From 1065b06cad27e0905fa4667fc4cf5ba5cd9554b3 Mon Sep 17 00:00:00 2001 From: Isse Date: Wed, 1 Apr 2026 11:19:23 +0200 Subject: [PATCH] Add a sprite adjecency requirement for sprites that's checked on block changes --- CHANGELOG.md | 1 + Cargo.lock | 1 + Cargo.toml | 1 + common/Cargo.toml | 1 + common/src/terrain/block.rs | 34 +- common/src/terrain/sprite/magic.rs | 12 + common/src/terrain/sprite/mod.rs | 37 ++ common/src/util/cardinal_directions.rs | 566 +++++++++++++++++ common/src/util/mod.rs | 2 + common/state/src/state.rs | 116 +++- rtsim/src/rule/npc_ai/mod.rs | 4 +- world/Cargo.toml | 2 +- world/src/site/generation.rs | 34 +- world/src/site/mod.rs | 26 +- world/src/site/plot/adlet.rs | 92 +-- world/src/site/plot/airship_dock.rs | 10 +- world/src/site/plot/bridge.rs | 12 +- world/src/site/plot/cliff_tower.rs | 2 +- world/src/site/plot/coastal_house.rs | 4 +- world/src/site/plot/cultist.rs | 12 +- .../src/site/plot/desert_city_airship_dock.rs | 4 +- world/src/site/plot/desert_city_arena.rs | 67 ++- world/src/site/plot/desert_city_multiplot.rs | 18 +- world/src/site/plot/glider_platform.rs | 17 +- world/src/site/plot/glider_ring.rs | 27 +- world/src/site/plot/gnarling.rs | 38 +- world/src/site/plot/haniwa.rs | 24 +- world/src/site/plot/house.rs | 308 +++++----- world/src/site/plot/jungle_ruin.rs | 2 +- world/src/site/plot/myrmidon_arena.rs | 28 +- world/src/site/plot/myrmidon_house.rs | 4 +- world/src/site/plot/plaza.rs | 10 +- world/src/site/plot/road.rs | 12 +- world/src/site/plot/savannah_hut.rs | 2 +- world/src/site/plot/tavern.rs | 91 +-- world/src/site/plot/vampire_castle.rs | 8 +- world/src/site/tile.rs | 4 +- world/src/site/util/mod.rs | 567 ------------------ world/src/site/util/sprites.rs | 94 +-- 39 files changed, 1246 insertions(+), 1048 deletions(-) create mode 100644 common/src/util/cardinal_directions.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 934a2d1e68..55c32eefb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `GradientBrick` fill allows structures to have a brick pattern while also having a gradient between two colors - Moon phases - CLI Command to list every available graphics devices +- Some sprites are now destroyed instead of left floating after block changes. ### Changed diff --git a/Cargo.lock b/Cargo.lock index 280f6223be..b208e7743a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8616,6 +8616,7 @@ dependencies = [ "csv", "dot_vox", "enum-map", + "enumset", "fxhash", "hashbrown 0.16.0", "indexmap 2.12.0", diff --git a/Cargo.toml b/Cargo.toml index c8a01ed4d6..85b23a32b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -164,6 +164,7 @@ criterion = { version = "0.8", default-features = false, features = [ crossbeam-channel = { version = "0.5.15" } crossbeam-utils = { version = "0.8.7" } enum-map = { version = "2.4" } +enumset = "1.1.3" futures-util = { version = "0.3.7", default-features = false } fxhash = { version = "0.2.1" } hashbrown = { version = "0.16", default-features = false, features = [ diff --git a/common/Cargo.toml b/common/Cargo.toml index b581e490f5..0ca10f6d04 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -31,6 +31,7 @@ serde = { workspace = true, features = ["rc"] } # Util enum-map = { workspace = true, features = ["serde"] } +enumset = { workspace = true } vek = { workspace = true } chrono = { workspace = true } chrono-tz = { workspace = true } diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 43cdf97dfa..1761e97bab 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -137,12 +137,30 @@ impl BlockKind { /// Why is the sprite ID at the end? Simply put, it makes masking faster and /// easier, which is important because extracting the `SpriteKind` is a more /// commonly performed operation than extracting attributes. -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct Block { kind: BlockKind, data: [u8; 3], } +impl std::fmt::Debug for Block { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut s = f.debug_struct("Block"); + + s.field("kind", &self.kind); + + if let Some(sprite) = super::StructureSprite::from_block(self) { + s.field("sprite", &sprite); + } + + if self.is_filled() { + s.field("color", &self.data); + } + + s.finish() + } +} + impl FilledVox for Block { fn default_non_filled() -> Self { Block::air(SpriteKind::Empty) } @@ -253,6 +271,20 @@ impl Block { } } + pub fn rotation_mat(&self) -> Mat3 { + let dir = crate::util::Dir2::from_sprite_ori( + self.get_attr::().unwrap_or_default().0, + ) + .map(|(d, _)| d) + .unwrap_or(crate::util::Dir2::X); + + let mut rot_mat = dir.to_mat3(); + + rot_mat.cols *= self.sprite_mirror_vec().map(|f| f as i32); + + rot_mat + } + pub fn sprite_z_rot(&self) -> Option { self.get_attr::() .ok() diff --git a/common/src/terrain/sprite/magic.rs b/common/src/terrain/sprite/magic.rs index e8994bff8f..fa524f7851 100644 --- a/common/src/terrain/sprite/magic.rs +++ b/common/src/terrain/sprite/magic.rs @@ -183,6 +183,10 @@ macro_rules! sprites { Ok(()) } + pub fn from_block(_block: &Block) -> Self { + Self $(($(_block.get_attr::<$attr>().unwrap_or_default()),*))? + } + pub fn visitor<'de, O, F: FnOnce($category_name) -> O>(f: F, expecting: &str) -> Visitor<'_, 'de, O, F> { Visitor { f, @@ -217,6 +221,14 @@ macro_rules! sprites { )*)* } } + + pub fn from_block(block: &Block) -> Option { + let sprite = block.get_sprite()?; + + Some(match sprite { + $($(SpriteKind::$sprite_name => Self::$sprite_name(categories::$category_name::from_block(block)),)*)* + }) + } } const _: () = { diff --git a/common/src/terrain/sprite/mod.rs b/common/src/terrain/sprite/mod.rs index 037198850f..338356512f 100644 --- a/common/src/terrain/sprite/mod.rs +++ b/common/src/terrain/sprite/mod.rs @@ -97,6 +97,10 @@ impl StructureSprite { pub fn apply_to_block(self, block: Block) -> Result { self.0.apply_to_block(block) } + + pub fn from_block(block: &Block) -> Option { + StructureSpriteKind::from_block(block).map(Self) + } } sprites! { @@ -636,6 +640,14 @@ pub struct Damage(pub u8); #[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Deserialize)] pub struct SnowCovered(pub bool); +#[derive(Clone, Copy, Debug)] +pub enum SpriteAdjecencyRequirement { + /// Considers sprite rotation + AllSolid(&'static [Vec3]), + /// Considers sprite rotation + AnySolid(&'static [Vec3]), +} + impl SpriteKind { #[inline] //#[tweak_fn] @@ -901,6 +913,31 @@ impl SpriteKind { }) } + pub const fn adjecency_requirement(&self) -> Option { + use SpriteAdjecencyRequirement::*; + const NEG_X: Vec3 = Vec3::new(-1, 0, 0); + const Z: Vec3 = Vec3::new(0, 0, 1); + const NEG_Z: Vec3 = Vec3::new(0, 0, -1); + + Some(match self { + Self::Beehive + | Self::CeilingMushroom + | Self::CeilingLanternPlant + | Self::CeilingLanternFlower + | Self::CeilingJungleLeafyPlant => AllSolid(&[Z]), + Self::Apple | Self::Coconut => AnySolid(&[Z, NEG_Z]), + + _ if matches!(self.category(), Category::Plant) => AllSolid(&[NEG_Z]), + Self::Lantern | Self::LanternpostWoodBase | Self::LanternpostWoodUpper | Self::Bomb => { + AllSolid(&[NEG_Z]) + }, + + Self::LanternpostWoodLantern => AllSolid(&[NEG_X]), + + _ => return None, + }) + } + pub fn valid_collision_dir( &self, entity_aabb: Aabb, diff --git a/common/src/util/cardinal_directions.rs b/common/src/util/cardinal_directions.rs new file mode 100644 index 0000000000..9f493ae441 --- /dev/null +++ b/common/src/util/cardinal_directions.rs @@ -0,0 +1,566 @@ +use std::ops::{Add, Sub}; + +use rand::RngExt; +use vek::{Aabb, Aabr, Mat3, Vec2, Vec3}; + +/// A 2d cardinal direction. +#[derive(Debug, enum_map::Enum, strum::EnumIter, enumset::EnumSetType)] +pub enum Dir2 { + X, + Y, + NegX, + NegY, +} + +impl Dir2 { + pub const ALL: [Dir2; 4] = [Dir2::X, Dir2::Y, Dir2::NegX, Dir2::NegY]; + + pub fn choose(rng: &mut impl RngExt) -> Dir2 { + match rng.random_range(0..4) { + 0 => Dir2::X, + 1 => Dir2::Y, + 2 => Dir2::NegX, + _ => Dir2::NegY, + } + } + + pub fn from_vec2(vec: Vec2) -> Dir2 { + if vec.x.abs() > vec.y.abs() { + if vec.x > 0 { Dir2::X } else { Dir2::NegX } + } else if vec.y > 0 { + Dir2::Y + } else { + Dir2::NegY + } + } + + pub fn to_dir3(self) -> Dir3 { Dir3::from_dir(self) } + + #[must_use] + pub fn opposite(self) -> Dir2 { + match self { + Dir2::X => Dir2::NegX, + Dir2::NegX => Dir2::X, + Dir2::Y => Dir2::NegY, + Dir2::NegY => Dir2::Y, + } + } + + /// Rotate the direction anti clock wise + #[must_use] + pub fn rotated_ccw(self) -> Dir2 { + match self { + Dir2::X => Dir2::Y, + Dir2::NegX => Dir2::NegY, + Dir2::Y => Dir2::NegX, + Dir2::NegY => Dir2::X, + } + } + + /// Rotate the direction clock wise + #[must_use] + pub fn rotated_cw(self) -> Dir2 { self.rotated_ccw().opposite() } + + #[must_use] + pub fn orthogonal(self) -> Dir2 { + match self { + Dir2::X | Dir2::NegX => Dir2::Y, + Dir2::Y | Dir2::NegY => Dir2::X, + } + } + + #[must_use] + pub fn abs(self) -> Dir2 { + match self { + Dir2::X | Dir2::NegX => Dir2::X, + Dir2::Y | Dir2::NegY => Dir2::Y, + } + } + + #[must_use] + pub fn signum(self) -> i32 { + match self { + Dir2::X | Dir2::Y => 1, + Dir2::NegX | Dir2::NegY => -1, + } + } + + pub fn to_vec2(self) -> Vec2 { + match self { + Dir2::X => Vec2::new(1, 0), + Dir2::NegX => Vec2::new(-1, 0), + Dir2::Y => Vec2::new(0, 1), + Dir2::NegY => Vec2::new(0, -1), + } + } + + /// The diagonal to the left of `self`, this is equal to this dir plus this + /// dir rotated counter clockwise. + pub fn diagonal(self) -> Vec2 { self.to_vec2() + self.rotated_ccw().to_vec2() } + + pub fn to_vec3(self) -> Vec3 { + match self { + Dir2::X => Vec3::new(1, 0, 0), + Dir2::NegX => Vec3::new(-1, 0, 0), + Dir2::Y => Vec3::new(0, 1, 0), + Dir2::NegY => Vec3::new(0, -1, 0), + } + } + + /// Create a vec2 where x is in the direction of `self`, and y is anti + /// clockwise of `self`. + pub fn vec2(self, x: i32, y: i32) -> Vec2 { + match self { + Dir2::X => Vec2::new(x, y), + Dir2::NegX => Vec2::new(-x, -y), + Dir2::Y => Vec2::new(y, x), + Dir2::NegY => Vec2::new(-y, -x), + } + } + + /// Create a vec2 where x is in the direction of `self`, and y is orthogonal + /// version of self. + pub fn vec2_abs(self, x: T, y: T) -> Vec2 { + match self { + Dir2::X => Vec2::new(x, y), + Dir2::NegX => Vec2::new(x, y), + Dir2::Y => Vec2::new(y, x), + Dir2::NegY => Vec2::new(y, x), + } + } + + /// Returns a 3x3 matrix that rotates Vec3(1, 0, 0) to the direction you get + /// in to_vec3. Inteded to be used with Primitive::Rotate. + /// + /// Example: + /// ``` + /// use vek::Vec3; + /// use veloren_common::util::Dir2; + /// let dir = Dir2::X; + /// + /// assert_eq!(dir.to_mat3() * Vec3::new(1, 0, 0), dir.to_vec3()); + /// + /// let dir = Dir2::NegX; + /// + /// assert_eq!(dir.to_mat3() * Vec3::new(1, 0, 0), dir.to_vec3()); + /// + /// let dir = Dir2::Y; + /// + /// assert_eq!(dir.to_mat3() * Vec3::new(1, 0, 0), dir.to_vec3()); + /// + /// let dir = Dir2::NegY; + /// + /// assert_eq!(dir.to_mat3() * Vec3::new(1, 0, 0), dir.to_vec3()); + /// ``` + pub fn to_mat3(self) -> Mat3 { + match self { + Dir2::X => Mat3::new(1, 0, 0, 0, 1, 0, 0, 0, 1), + Dir2::NegX => Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1), + Dir2::Y => Mat3::new(0, -1, 0, 1, 0, 0, 0, 0, 1), + Dir2::NegY => Mat3::new(0, 1, 0, -1, 0, 0, 0, 0, 1), + } + } + + /// Creates a matrix that tranforms an upwards facing vector to this + /// direction. + pub fn from_z_mat3(self) -> Mat3 { + match self { + Dir2::X => Mat3::new(0, 0, -1, 0, 1, 0, 1, 0, 0), + Dir2::NegX => Mat3::new(0, 0, 1, 0, 1, 0, -1, 0, 0), + Dir2::Y => Mat3::new(1, 0, 0, 0, 0, -1, 0, 1, 0), + Dir2::NegY => Mat3::new(1, 0, 0, 0, 0, 1, 0, -1, 0), + } + } + + /// Translates this direction to worldspace as if it was relative to the + /// other direction + #[must_use] + pub fn relative_to(self, other: Dir2) -> Dir2 { + match other { + Dir2::X => self, + Dir2::NegX => self.opposite(), + Dir2::Y => self.rotated_cw(), + Dir2::NegY => self.rotated_ccw(), + } + } + + /// Is this direction parallel to x + pub fn is_x(self) -> bool { matches!(self, Dir2::X | Dir2::NegX) } + + /// Is this direction parallel to y + pub fn is_y(self) -> bool { matches!(self, Dir2::Y | Dir2::NegY) } + + pub fn is_positive(self) -> bool { matches!(self, Dir2::X | Dir2::Y) } + + pub fn is_negative(self) -> bool { !self.is_positive() } + + /// Returns the component that the direction is parallell to + pub fn select(self, vec: impl Into>) -> i32 { + let vec = vec.into(); + match self { + Dir2::X | Dir2::NegX => vec.x, + Dir2::Y | Dir2::NegY => vec.y, + } + } + + /// Select one component the direction is parallel to from vec and select + /// the other component from other + pub fn select_with(self, vec: impl Into>, other: impl Into>) -> Vec2 { + let vec = vec.into(); + let other = other.into(); + match self { + Dir2::X | Dir2::NegX => Vec2::new(vec.x, other.y), + Dir2::Y | Dir2::NegY => Vec2::new(other.x, vec.y), + } + } + + /// Returns the side of an aabr that the direction is pointing to + pub fn select_aabr(self, aabr: Aabr) -> T { + match self { + Dir2::X => aabr.max.x, + Dir2::NegX => aabr.min.x, + Dir2::Y => aabr.max.y, + Dir2::NegY => aabr.min.y, + } + } + + /// Select one component from the side the direction is pointing to from + /// aabr and select the other component from other + pub fn select_aabr_with(self, aabr: Aabr, other: impl Into>) -> Vec2 { + let other = other.into(); + match self { + Dir2::X => Vec2::new(aabr.max.x, other.y), + Dir2::NegX => Vec2::new(aabr.min.x, other.y), + Dir2::Y => Vec2::new(other.x, aabr.max.y), + Dir2::NegY => Vec2::new(other.x, aabr.min.y), + } + } + + /// The equivelant sprite direction of the direction + pub fn sprite_ori(self) -> u8 { + match self { + Dir2::X => 0, + Dir2::Y => 2, + Dir2::NegX => 4, + Dir2::NegY => 6, + } + } + + /// Returns (Dir, rest) + /// + /// Returns None if `ori` isn't a valid sprite Ori. + pub fn from_sprite_ori(ori: u8) -> Option<(Dir2, u8)> { + let dir = match ori / 2 { + 0 => Dir2::X, + 1 => Dir2::Y, + 2 => Dir2::NegX, + 3 => Dir2::NegY, + _ => return None, + }; + let rest = ori % 2; + + Some((dir, rest)) + } + + /// Legacy version of `sprite_ori`, so prefer using that over this. + pub fn sprite_ori_legacy(self) -> u8 { + match self { + Dir2::X => 2, + Dir2::NegX => 6, + Dir2::Y => 4, + Dir2::NegY => 0, + } + } + + pub fn split_aabr_offset(self, aabr: Aabr, offset: T) -> [Aabr; 2] + where + T: Copy + PartialOrd + Add + Sub, + { + match self { + Dir2::X => aabr.split_at_x(aabr.min.x + offset), + Dir2::Y => aabr.split_at_y(aabr.min.y + offset), + Dir2::NegX => { + let res = aabr.split_at_x(aabr.max.x - offset); + [res[1], res[0]] + }, + Dir2::NegY => { + let res = aabr.split_at_y(aabr.max.y - offset); + [res[1], res[0]] + }, + } + } + + pub fn trim_aabr(self, aabr: Aabr, amount: i32) -> Aabr { + (-self).extend_aabr(aabr, -amount) + } + + pub fn extend_aabr(self, aabr: Aabr, amount: i32) -> Aabr { + let offset = self.to_vec2() * amount; + match self { + _ if self.is_positive() => Aabr { + min: aabr.min, + max: aabr.max + offset, + }, + _ => Aabr { + min: aabr.min + offset, + max: aabr.max, + }, + } + } +} + +impl std::ops::Neg for Dir2 { + type Output = Dir2; + + fn neg(self) -> Self::Output { self.opposite() } +} + +/// A 3d direction. +#[derive(Debug, enum_map::Enum, strum::EnumIter, enumset::EnumSetType)] +pub enum Dir3 { + X, + Y, + Z, + NegX, + NegY, + NegZ, +} + +impl Dir3 { + pub const ALL: [Dir2; 4] = [Dir2::X, Dir2::Y, Dir2::NegX, Dir2::NegY]; + + pub fn choose(rng: &mut impl RngExt) -> Dir3 { + match rng.random_range(0..6) { + 0 => Dir3::X, + 1 => Dir3::Y, + 2 => Dir3::Z, + 3 => Dir3::NegX, + 4 => Dir3::NegY, + _ => Dir3::NegZ, + } + } + + pub fn from_dir(dir: Dir2) -> Dir3 { + match dir { + Dir2::X => Dir3::X, + Dir2::Y => Dir3::Y, + Dir2::NegX => Dir3::NegX, + Dir2::NegY => Dir3::NegY, + } + } + + pub fn to_dir(self) -> Option { + match self { + Dir3::X => Some(Dir2::X), + Dir3::Y => Some(Dir2::Y), + Dir3::NegX => Some(Dir2::NegX), + Dir3::NegY => Some(Dir2::NegY), + _ => None, + } + } + + pub fn from_vec3(vec: Vec3) -> Dir3 { + if vec.x.abs() > vec.y.abs() && vec.x.abs() > vec.z.abs() { + if vec.x > 0 { Dir3::X } else { Dir3::NegX } + } else if vec.y.abs() > vec.z.abs() { + if vec.y > 0 { Dir3::Y } else { Dir3::NegY } + } else if vec.z > 0 { + Dir3::Z + } else { + Dir3::NegZ + } + } + + #[must_use] + pub fn opposite(self) -> Dir3 { + match self { + Dir3::X => Dir3::NegX, + Dir3::NegX => Dir3::X, + Dir3::Y => Dir3::NegY, + Dir3::NegY => Dir3::Y, + Dir3::Z => Dir3::NegZ, + Dir3::NegZ => Dir3::Z, + } + } + + /// Rotate counter clockwise around an axis by 90 degrees. + pub fn rotate_axis_ccw(self, axis: Dir3) -> Dir3 { + match axis { + Dir3::X | Dir3::NegX => match self { + Dir3::Y => Dir3::Z, + Dir3::NegY => Dir3::NegZ, + Dir3::Z => Dir3::NegY, + Dir3::NegZ => Dir3::Y, + x => x, + }, + Dir3::Y | Dir3::NegY => match self { + Dir3::X => Dir3::Z, + Dir3::NegX => Dir3::NegZ, + Dir3::Z => Dir3::NegX, + Dir3::NegZ => Dir3::X, + y => y, + }, + Dir3::Z | Dir3::NegZ => match self { + Dir3::X => Dir3::Y, + Dir3::NegX => Dir3::NegY, + Dir3::Y => Dir3::NegX, + Dir3::NegY => Dir3::X, + z => z, + }, + } + } + + /// Rotate clockwise around an axis by 90 degrees. + pub fn rotate_axis_cw(self, axis: Dir3) -> Dir3 { self.rotate_axis_ccw(axis).opposite() } + + /// Get a direction that is orthogonal to both directions, always a positive + /// direction. + pub fn cross(self, other: Dir3) -> Dir3 { + match (self, other) { + (Dir3::X | Dir3::NegX, Dir3::Y | Dir3::NegY) + | (Dir3::Y | Dir3::NegY, Dir3::X | Dir3::NegX) => Dir3::Z, + (Dir3::X | Dir3::NegX, Dir3::Z | Dir3::NegZ) + | (Dir3::Z | Dir3::NegZ, Dir3::X | Dir3::NegX) => Dir3::Y, + (Dir3::Z | Dir3::NegZ, Dir3::Y | Dir3::NegY) + | (Dir3::Y | Dir3::NegY, Dir3::Z | Dir3::NegZ) => Dir3::X, + (Dir3::X | Dir3::NegX, Dir3::X | Dir3::NegX) => Dir3::Y, + (Dir3::Y | Dir3::NegY, Dir3::Y | Dir3::NegY) => Dir3::X, + (Dir3::Z | Dir3::NegZ, Dir3::Z | Dir3::NegZ) => Dir3::Y, + } + } + + #[must_use] + pub fn abs(self) -> Dir3 { + match self { + Dir3::X | Dir3::NegX => Dir3::X, + Dir3::Y | Dir3::NegY => Dir3::Y, + Dir3::Z | Dir3::NegZ => Dir3::Z, + } + } + + #[must_use] + pub fn signum(self) -> i32 { + match self { + Dir3::X | Dir3::Y | Dir3::Z => 1, + Dir3::NegX | Dir3::NegY | Dir3::NegZ => -1, + } + } + + pub fn to_vec3(self) -> Vec3 { + match self { + Dir3::X => Vec3::new(1, 0, 0), + Dir3::NegX => Vec3::new(-1, 0, 0), + Dir3::Y => Vec3::new(0, 1, 0), + Dir3::NegY => Vec3::new(0, -1, 0), + Dir3::Z => Vec3::new(0, 0, 1), + Dir3::NegZ => Vec3::new(0, 0, -1), + } + } + + /// Is this direction parallel to x + pub fn is_x(self) -> bool { matches!(self, Dir3::X | Dir3::NegX) } + + /// Is this direction parallel to y + pub fn is_y(self) -> bool { matches!(self, Dir3::Y | Dir3::NegY) } + + /// Is this direction parallel to z + pub fn is_z(self) -> bool { matches!(self, Dir3::Z | Dir3::NegZ) } + + pub fn is_positive(self) -> bool { matches!(self, Dir3::X | Dir3::Y | Dir3::Z) } + + pub fn is_negative(self) -> bool { !self.is_positive() } + + /// Returns the component that the direction is parallell to + pub fn select(self, vec: impl Into>) -> i32 { + let vec = vec.into(); + match self { + Dir3::X | Dir3::NegX => vec.x, + Dir3::Y | Dir3::NegY => vec.y, + Dir3::Z | Dir3::NegZ => vec.z, + } + } + + /// Select one component the direction is parallel to from vec and select + /// the other components from other + pub fn select_with(self, vec: impl Into>, other: impl Into>) -> Vec3 { + let vec = vec.into(); + let other = other.into(); + match self { + Dir3::X | Dir3::NegX => Vec3::new(vec.x, other.y, other.z), + Dir3::Y | Dir3::NegY => Vec3::new(other.x, vec.y, other.z), + Dir3::Z | Dir3::NegZ => Vec3::new(other.x, other.y, vec.z), + } + } + + /// Returns the side of an aabb that the direction is pointing to + pub fn select_aabb(self, aabb: Aabb) -> T { + match self { + Dir3::X => aabb.max.x, + Dir3::NegX => aabb.min.x, + Dir3::Y => aabb.max.y, + Dir3::NegY => aabb.min.y, + Dir3::Z => aabb.max.z, + Dir3::NegZ => aabb.min.z, + } + } + + /// Select one component from the side the direction is pointing to from + /// aabr and select the other components from other + pub fn select_aabb_with(self, aabb: Aabb, other: impl Into>) -> Vec3 { + let other = other.into(); + match self { + Dir3::X => Vec3::new(aabb.max.x, other.y, other.z), + Dir3::NegX => Vec3::new(aabb.min.x, other.y, other.z), + Dir3::Y => Vec3::new(other.x, aabb.max.y, other.z), + Dir3::NegY => Vec3::new(other.x, aabb.min.y, other.z), + Dir3::Z => Vec3::new(other.x, other.y, aabb.max.z), + Dir3::NegZ => Vec3::new(other.x, other.y, aabb.min.z), + } + } + + pub fn split_aabb_offset(self, aabb: Aabb, offset: T) -> [Aabb; 2] + where + T: Copy + PartialOrd + Add + Sub, + { + match self { + Dir3::X => aabb.split_at_x(aabb.min.x + offset), + Dir3::NegX => { + let res = aabb.split_at_x(aabb.max.x - offset); + [res[1], res[0]] + }, + Dir3::Y => aabb.split_at_y(aabb.min.y + offset), + Dir3::NegY => { + let res = aabb.split_at_y(aabb.max.y - offset); + [res[1], res[0]] + }, + Dir3::Z => aabb.split_at_z(aabb.min.z + offset), + Dir3::NegZ => { + let res = aabb.split_at_z(aabb.max.z - offset); + [res[1], res[0]] + }, + } + } + + pub fn trim_aabb(self, aabb: Aabb, amount: i32) -> Aabb { + (-self).extend_aabb(aabb, -amount) + } + + pub fn extend_aabb(self, aabb: Aabb, amount: i32) -> Aabb { + let offset = self.to_vec3() * amount; + match self { + _ if self.is_positive() => Aabb { + min: aabb.min, + max: aabb.max + offset, + }, + _ => Aabb { + min: aabb.min + offset, + max: aabb.max, + }, + } + } +} +impl std::ops::Neg for Dir3 { + type Output = Dir3; + + fn neg(self) -> Self::Output { self.opposite() } +} diff --git a/common/src/util/mod.rs b/common/src/util/mod.rs index 172861dbb4..ec660e927b 100644 --- a/common/src/util/mod.rs +++ b/common/src/util/mod.rs @@ -1,3 +1,4 @@ +mod cardinal_directions; mod color; pub mod dir; pub mod div; @@ -45,6 +46,7 @@ fn append_date(version: &str, timestamp: i64) -> String { } } +pub use cardinal_directions::*; pub use color::*; pub use dir::*; pub use grid_hasher::GridHasher; diff --git a/common/state/src/state.rs b/common/state/src/state.rs index 76790a075b..68acef4352 100644 --- a/common/state/src/state.rs +++ b/common/state/src/state.rs @@ -8,7 +8,7 @@ use common::uid::IdMaps; use common::{ calendar::Calendar, comp::{self, gizmos::RtsimGizmos}, - event::{EventBus, LocalEvent}, + event::{BonkEvent, EventBus, LocalEvent}, interaction, link::Is, mounting::{Mount, Rider, VolumeRider, VolumeRiders}, @@ -19,10 +19,11 @@ use common::{ }, shared_server_config::ServerConstants, slowjob::SlowJobPool, - terrain::{Block, MapSizeLg, TerrainChunk, TerrainGrid}, + terrain::{Block, MapSizeLg, TerrainChunk, TerrainGrid, sprite::SpriteAdjecencyRequirement}, tether, time::DayPeriod, trade::Trades, + util::Dir2, vol::{ReadVol, WriteVol}, weather::{Weather, WeatherGrid}, }; @@ -655,6 +656,10 @@ impl State { // Apply block modifications // Only include in `TerrainChanges` if successful let mut updated_blocks = Vec::with_capacity(modified_blocks.len()); + + // All positions that should recieve a block update. + let mut block_updates = HashSet::>::default(); + modified_blocks.retain(|wpos, new| { let res = terrain.map(*wpos, |old| { updated_blocks.push(BlockDiff { @@ -664,6 +669,7 @@ impl State { }); *new }); + if let (&Ok(old), true) = (&res, during_tick) { // NOTE: If the changes are applied during the tick, we push the *old* value as // the modified block (since it otherwise can't be recovered after the tick). @@ -671,6 +677,28 @@ impl State { // value. *new = old; } + + if let (&Ok(old), false) = (&res, during_tick) { + let h = old + .get_sprite() + .and_then(|s| s.solid_height()) + .unwrap_or(1.0) + .max( + new.get_sprite() + .and_then(|s| s.solid_height()) + .unwrap_or(1.0), + ) + .ceil() as i32; + + block_updates.extend((-1..=h + 1).map(|z| wpos + Vec3::unit_z() * z).chain( + (0..=h).flat_map(|z| { + Dir2::ALL + .iter() + .map(move |d| wpos + Vec3::unit_z() * z + d.to_vec2()) + }), + )); + }; + res.is_ok() }); @@ -678,6 +706,90 @@ impl State { block_update(&self.ecs, updated_blocks); } + // Only do block updates not during the tick since that's when actual + // terrain changes are applied. + // + // Clients will get these changes since they're just normal block updates + // next tick. + if !during_tick { + prof_span!(_guard, "Indirectly modified sprites"); + + // Collects all blocks that are neighbors with a modified block, + // where the `adjecency_requirement` is no longer upheld. + let indirectly_modified = block_updates + .into_iter() + // Filter for blocks that have an adjecency requirement. + .filter_map(|wpos| { + let block = terrain.get(wpos).ok()?; + Some((wpos, block.get_sprite()?.adjecency_requirement()?, block)) + }) + // Check if said adjecency requirement is upheld. + .filter(|(wpos, adjecency_requirement, block)| { + let rot_mat = block.rotation_mat(); + // Tries to find a solid block for the given adjecent block. + let find_solid = |adj: Vec3| { + let wpos = wpos + adj; + + let res = terrain.get(wpos).copied().unwrap_or(Block::empty()); + + // Don't check for sprites if we're checking for a block + // directly above. + let not_above = adj.z <= 0 || adj.x != 0 || adj.y != 0; + + if not_above && !res.is_solid() { + // Sprites can be taller than 1 block. + for z in 1..=Block::MAX_HEIGHT.ceil() as i32 { + if let Ok(block) = terrain.get(wpos - Vec3::unit_z() * z) + && let Some(sprite) = block.get_sprite() + && let Some(h) = sprite.solid_height() + && h.ceil() as i32 > z + { + return *block; + } + } + } + + res + }; + + // Same as `find_solid` but first rotates with the sprites rotation + // and mirroring. + let rel_solid = |adj: Vec3| find_solid(rot_mat * adj); + + let valid = match adjecency_requirement { + SpriteAdjecencyRequirement::AllSolid(v) => { + v.iter().all(|v| rel_solid(*v).is_solid()) + }, + SpriteAdjecencyRequirement::AnySolid(v) => { + v.iter().any(|v| rel_solid(*v).is_solid()) + }, + }; + + !valid + }) + .map(|(wpos, _, block)| (wpos, block)) + .collect::>(); + + // If the sprite is bonkable, bonk it. + let bonk_event_bus = self.ecs.write_resource::>(); + let mut bonk_emitter = bonk_event_bus.emitter(); + + let mut block_change = self.ecs.write_resource::(); + + for (wpos, block) in indirectly_modified { + if block.is_bonkable() { + bonk_emitter.emit(BonkEvent { + pos: wpos.as_::() + 0.5, + // TODO: Pass who destroyed the block? + owner: None, + target: None, + }); + } else { + block_change.blocks.insert(wpos, block.into_vacant()); + } + } + } + self.ecs.write_resource::().modified_blocks = modified_blocks; } diff --git a/rtsim/src/rule/npc_ai/mod.rs b/rtsim/src/rule/npc_ai/mod.rs index f4a7851325..02027b26e1 100644 --- a/rtsim/src/rule/npc_ai/mod.rs +++ b/rtsim/src/rule/npc_ai/mod.rs @@ -67,7 +67,7 @@ use common::{ store::Id, terrain::{CoordinateConversions, TerrainChunkSize, sprite}, time::DayPeriod, - util::Dir, + util::{Dir, Dir2}, }; use core::ops::ControlFlow; use fxhash::FxHasher64; @@ -1089,7 +1089,7 @@ fn go_to_tavern(site_id: SiteId, tavern_plot: Id) -> impl Action { - let side = site::util::Dir::from_vec2( + let side = Dir2::from_vec2( room.bounds.center().xy() - aabr.center(), ); let pos = side.select_aabr_with(*aabr, aabr.center()) + side.to_vec2(); diff --git a/world/Cargo.toml b/world/Cargo.toml index cdf0814c55..19a025d63d 100644 --- a/world/Cargo.toml +++ b/world/Cargo.toml @@ -40,7 +40,7 @@ common-dynlib = { package = "veloren-common-dynlib", path = "../common/dynlib", bincode = { workspace = true } bitvec = "1.0.1" enum-map = { workspace = true } -enumset = "1.1.3" +enumset = { workspace = true } fxhash = { workspace = true } image = { workspace = true } itertools = { workspace = true } diff --git a/world/src/site/generation.rs b/world/src/site/generation.rs index 3c92fe9b89..49726a8279 100644 --- a/world/src/site/generation.rs +++ b/world/src/site/generation.rs @@ -6,7 +6,6 @@ use crate::{ CanvasInfo, ColumnSample, block::block_from_structure, column::ColInfo, - site::util::Dir, util::{RandomField, Sampler}, }; use common::{ @@ -16,6 +15,7 @@ use common::{ Block, BlockKind, SpriteCfg, structure::{Structure as PrefabStructure, StructureBlock}, }, + util::Dir2, vol::ReadVol, }; use num::cast::AsPrimitive; @@ -39,13 +39,13 @@ pub enum Primitive { Ramp { aabb: Aabb, inset: i32, - dir: Dir, + dir: Dir2, }, Gable { aabb: Aabb, inset: i32, // X axis parallel or Y axis parallel - dir: Dir, + dir: Dir2, }, Cylinder(Aabb), Cone(Aabb), @@ -308,19 +308,19 @@ impl Fill { Primitive::Ramp { aabb, inset, dir } => { let inset = (*inset).max(aabb.size().reduce_min()); let inner = match dir { - Dir::X => Aabr { + Dir2::X => Aabr { min: Vec2::new(aabb.min.x - 1 + inset, aabb.min.y), max: Vec2::new(aabb.max.x, aabb.max.y), }, - Dir::NegX => Aabr { + Dir2::NegX => Aabr { min: Vec2::new(aabb.min.x, aabb.min.y), max: Vec2::new(aabb.max.x - inset, aabb.max.y), }, - Dir::Y => Aabr { + Dir2::Y => Aabr { min: Vec2::new(aabb.min.x, aabb.min.y - 1 + inset), max: Vec2::new(aabb.max.x, aabb.max.y), }, - Dir::NegY => Aabr { + Dir2::NegY => Aabr { min: Vec2::new(aabb.min.x, aabb.min.y), max: Vec2::new(aabb.max.x, aabb.max.y - inset), }, @@ -949,7 +949,7 @@ impl Painter { /// Returns a `PrimitiveRef` of the largest horizontal cylinder that fits in /// the provided Aabb. - pub fn horizontal_cylinder(&self, aabb: Aabb, dir: Dir) -> PrimitiveRef<'_> { + pub fn horizontal_cylinder(&self, aabb: Aabb, dir: Dir2) -> PrimitiveRef<'_> { let aabr = Aabr::from(aabb); let length = dir.select(aabr.size()); let height = aabb.max.z - aabb.min.z; @@ -1159,12 +1159,12 @@ impl Painter { /// Returns a `PrimitiveRef` of an Aabb with a slope cut into it. The /// `inset` governs the slope. The `dir` determines which direction the /// ramp points. - pub fn ramp_inset(&self, aabb: Aabb, inset: i32, dir: Dir) -> PrimitiveRef<'_> { + pub fn ramp_inset(&self, aabb: Aabb, inset: i32, dir: Dir2) -> PrimitiveRef<'_> { let aabb = aabb.made_valid(); self.prim(Primitive::Ramp { aabb, inset, dir }) } - pub fn ramp(&self, aabb: Aabb, dir: Dir) -> PrimitiveRef<'_> { + pub fn ramp(&self, aabb: Aabb, dir: Dir2) -> PrimitiveRef<'_> { let aabb = aabb.made_valid(); self.prim(Primitive::Ramp { aabb, @@ -1176,7 +1176,7 @@ impl Painter { /// Returns a `PrimitiveRef` of a triangular prism with the base being /// vertical. A gable is a tent shape. The `inset` governs the slope of /// the gable. The `dir` determines which way the gable points. - pub fn gable(&self, aabb: Aabb, inset: i32, dir: Dir) -> PrimitiveRef<'_> { + pub fn gable(&self, aabb: Aabb, inset: i32, dir: Dir2) -> PrimitiveRef<'_> { let aabb = aabb.made_valid(); self.prim(Primitive::Gable { aabb, inset, dir }) } @@ -1245,22 +1245,22 @@ impl Painter { self.prim(Primitive::Ramp { aabb, inset, - dir: Dir::X, + dir: Dir2::X, }) .intersect(self.prim(Primitive::Ramp { aabb, inset, - dir: Dir::NegX, + dir: Dir2::NegX, })) .intersect(self.prim(Primitive::Ramp { aabb, inset, - dir: Dir::Y, + dir: Dir2::Y, })) .intersect(self.prim(Primitive::Ramp { aabb, inset, - dir: Dir::NegY, + dir: Dir2::NegY, })) } @@ -1297,7 +1297,7 @@ impl Painter { /// |_____|/ /// ``` /// A horizontal half cylinder on top of an `Aabb`. - pub fn vault(&self, aabb: Aabb, dir: Dir) -> PrimitiveRef<'_> { + pub fn vault(&self, aabb: Aabb, dir: Dir2) -> PrimitiveRef<'_> { let h = dir.orthogonal().select(Vec3::from(aabb.size()).xy()); let mut prim = self.horizontal_cylinder( @@ -1347,7 +1347,7 @@ impl Painter { &self, aabb: Aabb, thickness: i32, - start_dir: Dir, + start_dir: Dir2, ) -> PrimitiveRef<'_> { let mut forward = start_dir; let mut z = aabb.max.z - 1; diff --git a/world/src/site/mod.rs b/world/src/site/mod.rs index 8daa53668b..1f5433de44 100644 --- a/world/src/site/mod.rs +++ b/world/src/site/mod.rs @@ -13,7 +13,6 @@ pub use self::{ genstat::{GenStatPlotKind, GenStatSiteKind, SitesGenMeta}, plot::{Plot, PlotKind, foreach_plot}, tile::TileKind, - util::Dir, }; use crate::{ Canvas, IndexRef, Land, @@ -34,6 +33,7 @@ use common::{ Block, BlockKind, SiteKindMeta, SpriteKind, TerrainChunkSize, site::{DungeonKindMeta, SettlementKindMeta}, }, + util::Dir2, vol::RectVolSize, }; use hashbrown::DefaultHashBuilder; @@ -1340,13 +1340,13 @@ impl Site { }); let wall_north = Tile { - kind: TileKind::Wall(Dir::Y), + kind: TileKind::Wall(Dir2::Y), plot: Some(plot), hard_alt: Some(castle_alt), }; let wall_east = Tile { - kind: TileKind::Wall(Dir::X), + kind: TileKind::Wall(Dir2::X), plot: Some(plot), hard_alt: Some(castle_alt), }; @@ -1429,7 +1429,7 @@ impl Site { max: aabr.center() + 3, }, Tile { - kind: TileKind::Wall(Dir::Y), + kind: TileKind::Wall(Dir2::Y), plot: Some(plot), hard_alt: Some(castle_alt), }, @@ -1522,7 +1522,7 @@ impl Site { &mut reseed(&mut rng), &site, door_tile, - Dir::from_vec2(door_dir), + Dir2::from_vec2(door_dir), aabr, alt, ); @@ -1595,11 +1595,11 @@ impl Site { } } let dir = match cardinal { - 0 => Dir::X, - 1 => Dir::Y, - 2 => Dir::NegX, - 3 => Dir::NegY, - _ => Dir::X, + 0 => Dir2::X, + 1 => Dir2::Y, + 2 => Dir2::NegX, + 3 => Dir2::NegY, + _ => Dir2::X, }; let size = 2.0; @@ -1699,7 +1699,7 @@ impl Site { // Point each ring after 1 towards the next ring // This provides a subtle guide through the course let dir = if i > 1 { - Dir::from_vec2(next_pos - pos) + Dir2::from_vec2(next_pos - pos) } else { dir }; @@ -1729,7 +1729,7 @@ impl Site { // last ring (ring 9) and finish platform // Separate condition due to window iterator to ensure // the finish platform is generated - let dir = Dir::from_vec2(next_pos - pos); + let dir = Dir2::from_vec2(next_pos - pos); let aabr = Aabr { min: Vec2::broadcast(-size as i32) + tile_pos, max: Vec2::broadcast(size as i32) + tile_pos, @@ -2989,7 +2989,7 @@ impl Site { if let Some(PlotKind::Road(road)) = tile.plot.map(|p| &self.plot(p).kind) { let start = road.path.nodes[a as usize]; let end = road.path.nodes[b as usize]; - let dir = Dir::from_vec2(end - start); + let dir = Dir2::from_vec2(end - start); let orth = dir.orthogonal(); let aabr = Aabr { min: self.tile_center_wpos(start) diff --git a/world/src/site/plot/adlet.rs b/world/src/site/plot/adlet.rs index 00074addf3..5c9603744f 100644 --- a/world/src/site/plot/adlet.rs +++ b/world/src/site/plot/adlet.rs @@ -2,7 +2,7 @@ use super::*; use crate::{ IndexRef, Land, assets::AssetHandle, - site::{generation::PrimitiveTransform, util::Dir}, + site::generation::PrimitiveTransform, util::{ FastNoise, NEIGHBORS, NEIGHBORS3, RandomField, attempt, sampler::Sampler, within_distance, }, @@ -25,14 +25,14 @@ pub struct AdletStronghold { surface_radius: i32, // Structure indicates the kind of structure it is, vec2 is relative position of structure // compared to wall_center, dir tells which way structure should face - outer_structures: Vec<(AdletStructure, Vec2, Dir)>, + outer_structures: Vec<(AdletStructure, Vec2, Dir2)>, tunnel_length: i32, cavern_center: Vec2, cavern_alt: f32, cavern_radius: i32, // Structure indicates the kind of structure it is, vec2 is relative position of structure // compared to cavern_center, dir tells which way structure should face - cavern_structures: Vec<(AdletStructure, Vec2, Dir)>, + cavern_structures: Vec<(AdletStructure, Vec2, Dir2)>, } #[derive(Copy, Clone)] @@ -129,9 +129,9 @@ impl AdletStronghold { let cavern_alt = (land.get_alt_approx(cavern_center) - cavern_radius as f32) .min(land.get_alt_approx(entrance)); - let mut outer_structures = Vec::<(AdletStructure, Vec2, Dir)>::new(); + let mut outer_structures = Vec::<(AdletStructure, Vec2, Dir2)>::new(); - let entrance_dir = Dir::from_vec2(entrance - cavern_center); + let entrance_dir = Dir2::from_vec2(entrance - cavern_center); outer_structures.push((AdletStructure::TunnelEntrance, Vec2::zero(), entrance_dir)); let desired_structures = surface_radius.pow(2) / 100; @@ -178,7 +178,7 @@ impl AdletStronghold { Some((structure_center, structure_kind)) } }) { - let dir_to_wall = Dir::from_vec2(rpos); + let dir_to_wall = Dir2::from_vec2(rpos); let door_rng: u32 = rng.random_range(0..9); let door_dir = match door_rng { 0..=3 => dir_to_wall, @@ -191,10 +191,10 @@ impl AdletStronghold { } } - let mut cavern_structures = Vec::<(AdletStructure, Vec2, Dir)>::new(); + let mut cavern_structures = Vec::<(AdletStructure, Vec2, Dir2)>::new(); fn valid_cavern_struct_pos( - structures: &[(AdletStructure, Vec2, Dir)], + structures: &[(AdletStructure, Vec2, Dir2)], structure: AdletStructure, rpos: Vec2, ) -> bool { @@ -217,7 +217,7 @@ impl AdletStronghold { .then_some(rpos) }) { // Dir doesn't matter since these are directionless - cavern_structures.push((AdletStructure::SpeleothemCluster, rpos, Dir::X)); + cavern_structures.push((AdletStructure::SpeleothemCluster, rpos, Dir2::X)); let desired_adjacent_clusters = rng.random_range(1..5); for _ in 0..desired_adjacent_clusters { // Choose a relative position adjacent to initial speleothem cluster @@ -235,7 +235,7 @@ impl AdletStronghold { cavern_structures.push(( AdletStructure::SpeleothemCluster, adj_rpos, - Dir::X, + Dir2::X, )); // Set new rpos to next cluster is adjacent to most recently placed rpos = adj_rpos; @@ -272,7 +272,7 @@ impl AdletStronghold { }) }) { // Direction doesn't matter for boss bonehut - cavern_structures.push((AdletStructure::BossBoneHut, rpos, Dir::X)); + cavern_structures.push((AdletStructure::BossBoneHut, rpos, Dir2::X)); } // Attempt to place yetipit near the cavern edge @@ -299,7 +299,7 @@ impl AdletStronghold { }) }) { // Direction doesn't matter for yetipit - cavern_structures.push((AdletStructure::YetiPit, rpos, Dir::X)); + cavern_structures.push((AdletStructure::YetiPit, rpos, Dir2::X)); } // Attempt to place big bonfire @@ -313,7 +313,7 @@ impl AdletStronghold { .then_some(rpos) }) { // Direction doesn't matter for central bonfire - cavern_structures.push((AdletStructure::Bonfire, rpos, Dir::X)); + cavern_structures.push((AdletStructure::Bonfire, rpos, Dir2::X)); } // Attempt to place some rock huts around the outer edge @@ -329,7 +329,7 @@ impl AdletStronghold { .then_some(rpos) }) { // Rock huts need no direction - cavern_structures.push((AdletStructure::RockHut, rpos, Dir::X)); + cavern_structures.push((AdletStructure::RockHut, rpos, Dir2::X)); } } @@ -354,7 +354,7 @@ impl AdletStronghold { .then_some((structure, rpos)) }) { // Direction facing the central bonfire - let dir = Dir::from_vec2(rpos).opposite(); + let dir = Dir2::from_vec2(rpos).opposite(); cavern_structures.push((structure, rpos, dir)); } } @@ -495,12 +495,12 @@ impl Structure for AdletStronghold { // Tunnel let dist: f32 = self.cavern_center.as_().distance(self.entrance.as_()); - let dir = Dir::from_vec2(self.entrance - self.cavern_center); + let dir = Dir2::from_vec2(self.entrance - self.cavern_center); let tunnel_start: Vec3 = match dir { - Dir::X => Vec2::new(self.entrance.x + 7, self.entrance.y), - Dir::Y => Vec2::new(self.entrance.x, self.entrance.y + 7), - Dir::NegX => Vec2::new(self.entrance.x - 7, self.entrance.y), - Dir::NegY => Vec2::new(self.entrance.x, self.entrance.y - 7), + Dir2::X => Vec2::new(self.entrance.x + 7, self.entrance.y), + Dir2::Y => Vec2::new(self.entrance.x, self.entrance.y + 7), + Dir2::NegX => Vec2::new(self.entrance.x - 7, self.entrance.y), + Dir2::NegY => Vec2::new(self.entrance.x, self.entrance.y - 7), } .as_() .with_z(self.cavern_alt - 1.0); @@ -512,10 +512,10 @@ impl Structure for AdletStronghold { let offset = 15.0; let tunnel_end = match dir { - Dir::X => Vec3::new(raw_tunnel_end.x - offset, tunnel_start.y, raw_tunnel_end.z), - Dir::Y => Vec3::new(tunnel_start.x, raw_tunnel_end.y - offset, raw_tunnel_end.z), - Dir::NegX => Vec3::new(raw_tunnel_end.x + offset, tunnel_start.y, raw_tunnel_end.z), - Dir::NegY => Vec3::new(tunnel_start.x, raw_tunnel_end.y + offset, raw_tunnel_end.z), + Dir2::X => Vec3::new(raw_tunnel_end.x - offset, tunnel_start.y, raw_tunnel_end.z), + Dir2::Y => Vec3::new(tunnel_start.x, raw_tunnel_end.y - offset, raw_tunnel_end.z), + Dir2::NegX => Vec3::new(raw_tunnel_end.x + offset, tunnel_start.y, raw_tunnel_end.z), + Dir2::NegY => Vec3::new(tunnel_start.x, raw_tunnel_end.y + offset, raw_tunnel_end.z), }; // Platform painter @@ -569,17 +569,17 @@ impl Structure for AdletStronghold { .line( tunnel_start + match dir { - Dir::X => Vec3::new(0.0, 4.0, 7.0), - Dir::Y => Vec3::new(4.0, 0.0, 7.0), - Dir::NegX => Vec3::new(0.0, 4.0, 7.0), - Dir::NegY => Vec3::new(4.0, 0.0, 7.0), + Dir2::X => Vec3::new(0.0, 4.0, 7.0), + Dir2::Y => Vec3::new(4.0, 0.0, 7.0), + Dir2::NegX => Vec3::new(0.0, 4.0, 7.0), + Dir2::NegY => Vec3::new(4.0, 0.0, 7.0), }, tunnel_end + match dir { - Dir::X => Vec3::new(0.0, 4.0, 7.0), - Dir::Y => Vec3::new(4.0, 0.0, 7.0), - Dir::NegX => Vec3::new(0.0, 4.0, 7.0), - Dir::NegY => Vec3::new(4.0, 0.0, 7.0), + Dir2::X => Vec3::new(0.0, 4.0, 7.0), + Dir2::Y => Vec3::new(4.0, 0.0, 7.0), + Dir2::NegX => Vec3::new(0.0, 4.0, 7.0), + Dir2::NegY => Vec3::new(4.0, 0.0, 7.0), }, 8.0, ) @@ -589,17 +589,17 @@ impl Structure for AdletStronghold { .line( tunnel_start + match dir { - Dir::X => Vec3::new(0.0, -4.0, 7.0), - Dir::Y => Vec3::new(-4.0, 0.0, 7.0), - Dir::NegX => Vec3::new(0.0, -4.0, 7.0), - Dir::NegY => Vec3::new(-4.0, 0.0, 7.0), + Dir2::X => Vec3::new(0.0, -4.0, 7.0), + Dir2::Y => Vec3::new(-4.0, 0.0, 7.0), + Dir2::NegX => Vec3::new(0.0, -4.0, 7.0), + Dir2::NegY => Vec3::new(-4.0, 0.0, 7.0), }, tunnel_end + match dir { - Dir::X => Vec3::new(0.0, -4.0, 7.0), - Dir::Y => Vec3::new(-4.0, 0.0, 7.0), - Dir::NegX => Vec3::new(0.0, -4.0, 7.0), - Dir::NegY => Vec3::new(-4.0, 0.0, 7.0), + Dir2::X => Vec3::new(0.0, -4.0, 7.0), + Dir2::Y => Vec3::new(-4.0, 0.0, 7.0), + Dir2::NegX => Vec3::new(0.0, -4.0, 7.0), + Dir2::NegY => Vec3::new(-4.0, 0.0, 7.0), }, 8.0, ) @@ -2099,7 +2099,7 @@ impl Structure for AdletStronghold { } struct RibCageGenerator { - dir: Dir, + dir: Dir2, length: u32, spine_height: f32, spine_radius: f32, @@ -2212,12 +2212,12 @@ impl RibCageGenerator { ); let rotation_origin = Vec3::new(spine_start.x, spine_start.y + 0.5, spine_start.z); - let rotate = |prim: PrimitiveRef<'a>, dir: &Dir| -> PrimitiveRef<'a> { + let rotate = |prim: PrimitiveRef<'a>, dir: &Dir2| -> PrimitiveRef<'a> { match dir { - Dir::X => prim, - Dir::Y => prim.rotate_about(Mat3::rotation_z(0.5 * PI).as_(), rotation_origin), - Dir::NegX => prim.rotate_about(Mat3::rotation_z(PI).as_(), rotation_origin), - Dir::NegY => prim.rotate_about(Mat3::rotation_z(1.5 * PI).as_(), rotation_origin), + Dir2::X => prim, + Dir2::Y => prim.rotate_about(Mat3::rotation_z(0.5 * PI).as_(), rotation_origin), + Dir2::NegX => prim.rotate_about(Mat3::rotation_z(PI).as_(), rotation_origin), + Dir2::NegY => prim.rotate_about(Mat3::rotation_z(1.5 * PI).as_(), rotation_origin), } }; diff --git a/world/src/site/plot/airship_dock.rs b/world/src/site/plot/airship_dock.rs index 5824dfb007..a8404b77f2 100644 --- a/world/src/site/plot/airship_dock.rs +++ b/world/src/site/plot/airship_dock.rs @@ -1026,20 +1026,20 @@ impl Structure for AirshipDock { let edge = painter.aabb(edge_fill); let stair_cap_even = painter - .ramp(stair, Dir::X) - .intersect(painter.ramp(stair, Dir::X).rotate_about( + .ramp(stair, Dir2::X) + .intersect(painter.ramp(stair, Dir2::X).rotate_about( Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, -1), center.with_z(stairtop - 4), )); let stair_cap_odd = stair_cap_even.rotate_about(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1), stair.center()); let stair_base_even = painter - .ramp(stair, Dir::X) - .intersect(painter.ramp(stair, Dir::X).translate(Vec3::new(1, 0, 0))) + .ramp(stair, Dir2::X) + .intersect(painter.ramp(stair, Dir2::X).translate(Vec3::new(1, 0, 0))) .union(painter.aabb(middirt)) .union( painter - .ramp(stair, Dir::X) + .ramp(stair, Dir2::X) .rotate_about( Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, -1), center.with_z(stairtop - 4), diff --git a/world/src/site/plot/bridge.rs b/world/src/site/plot/bridge.rs index c452cf5cd4..ce1829a6e1 100644 --- a/world/src/site/plot/bridge.rs +++ b/world/src/site/plot/bridge.rs @@ -144,7 +144,7 @@ fn render_short(bridge: &Bridge, painter: &Painter) { // let outset = 7; - let up_ramp = |point: Vec3, dir: Dir, side_len: i32| { + let up_ramp = |point: Vec3, dir: Dir2, side_len: i32| { let forward = dir.to_vec2(); let side = dir.orthogonal().to_vec2() * side_len; let ramp_in = top - point.z; @@ -367,7 +367,7 @@ fn render_heightened_viaduct(bridge: &Bridge, painter: &Painter, data: &Heighten .dir .split_aabr_offset(bridge_aabr, bridge.dir.select(bridge_aabr.size()) / 2); - let ramp_in_aabr = |aabr: Aabr, dir: Dir, zmin, zmax| { + let ramp_in_aabr = |aabr: Aabr, dir: Dir2, zmin, zmax| { let inset = dir.select(aabr.size()); painter.ramp_inset( aabb(aabr.min.with_z(zmin), aabr.max.with_z(zmax)), @@ -646,7 +646,7 @@ fn render_tower(bridge: &Bridge, painter: &Painter, roof_kind: &RoofKind) { for i in 1..=n { let c = tower_aabr.center().with_z(bridge.start.z + i * p); - for dir in Dir::ALL { + for dir in Dir2::ALL { painter.rotated_sprite( c + dir.to_vec2(), SpriteKind::WallSconce, @@ -896,7 +896,7 @@ pub struct Bridge { pub(crate) start: Vec3, pub(crate) end: Vec3, - pub(crate) dir: Dir, + pub(crate) dir: Dir2, center: Vec3, kind: BridgeKind, biome: BiomeKind, @@ -918,7 +918,7 @@ impl Bridge { let min_water_dist = 5; let find_edge = |start: Vec2, end: Vec2| { let mut test_start = start; - let dir = Dir::from_vec2(end - start).to_vec2(); + let dir = Dir2::from_vec2(end - start).to_vec2(); let mut last_alt = if let Some(col) = land.column_sample(start, index) { col.alt as i32 } else { @@ -975,7 +975,7 @@ impl Bridge { start, end, center, - dir: Dir::from_vec2(end.xy() - start.xy()), + dir: Dir2::from_vec2(end.xy() - start.xy()), kind: bridge, biome: land .get_chunk_wpos(center.xy()) diff --git a/world/src/site/plot/cliff_tower.rs b/world/src/site/plot/cliff_tower.rs index 0d722acfd9..bc22206ce3 100644 --- a/world/src/site/plot/cliff_tower.rs +++ b/world/src/site/plot/cliff_tower.rs @@ -544,7 +544,7 @@ impl Structure for CliffTower { .with_z(floor_level + 5), }) .clear(); - let dir = Dir::from_vec2(plot_center - pos); + let dir = Dir2::from_vec2(plot_center - pos); match (RandomField::new(0).get(pos.with_z(floor_level - d))) % 3 { diff --git a/world/src/site/plot/coastal_house.rs b/world/src/site/plot/coastal_house.rs index 2be53369c7..8ea3e8bcc3 100644 --- a/world/src/site/plot/coastal_house.rs +++ b/world/src/site/plot/coastal_house.rs @@ -371,7 +371,7 @@ impl Structure for CoastalHouse { let random_index_1 = (RandomField::new(0).get(center.with_z(base + s)) % 4) as usize; let random_index_2 = 3 - random_index_1; // add beds and tables at random corners - for (d, dir) in Dir::iter().enumerate() { + for (d, dir) in Dir2::iter().enumerate() { let diagonal = dir.diagonal(); let bed_pos = center + diagonal * ((length / 2) - 2); let table_pos = Vec2::new( @@ -385,7 +385,7 @@ impl Structure for CoastalHouse { painter.rotated_sprite(table_pos.with_z(alt), SpriteKind::TableCoastalLarge, 2); painter.sprite(table_pos.with_z(alt + 1), SpriteKind::JugAndCupsCoastal); - for dir in Dir::iter() { + for dir in Dir2::iter() { let vec = dir.to_vec2(); let bench_pos = Vec2::new(table_pos.x + vec.x * 2, table_pos.y + vec.y); painter.rotated_sprite( diff --git a/world/src/site/plot/cultist.rs b/world/src/site/plot/cultist.rs index 776ef41ccd..7fedba67d0 100644 --- a/world/src/site/plot/cultist.rs +++ b/world/src/site/plot/cultist.rs @@ -241,7 +241,7 @@ impl Structure for Cultist { max: Vec2::new(tower_center.x + 8 + size, tower_center.y + 4 + size) .with_z(room_base + height), }, - Dir::X, + Dir2::X, ) .clear(); @@ -253,7 +253,7 @@ impl Structure for Cultist { max: Vec2::new(tower_center.x + 4 + size, tower_center.y + 8 + size) .with_z(room_base + height), }, - Dir::Y, + Dir2::Y, ) .clear(); // vault carves floor 1 @@ -271,7 +271,7 @@ impl Structure for Cultist { ) .with_z(room_base + 10 + height + 5 + (height / 4) + (size / 2)), }, - Dir::X, + Dir2::X, ) .clear(); @@ -289,7 +289,7 @@ impl Structure for Cultist { ) .with_z(room_base + 10 + height + 5 + (height / 4) + (size / 2)), }, - Dir::Y, + Dir2::Y, ) .clear(); } @@ -439,7 +439,7 @@ impl Structure for Cultist { + ((room_size / 3) * f), ), }, - Dir::Y, + Dir2::Y, ) .clear(); @@ -504,7 +504,7 @@ impl Structure for Cultist { + ((room_size / 3) * f), ), }, - Dir::X, + Dir2::X, ) .clear(); diff --git a/world/src/site/plot/desert_city_airship_dock.rs b/world/src/site/plot/desert_city_airship_dock.rs index c37d41f602..4083dbccc8 100644 --- a/world/src/site/plot/desert_city_airship_dock.rs +++ b/world/src/site/plot/desert_city_airship_dock.rs @@ -292,7 +292,7 @@ impl Structure for DesertCityAirshipDock { ) .with_z(bldg_base + height - 1), }, - Dir::X, + Dir2::X, ) .intersect(clear_limit_1) .clear(); @@ -310,7 +310,7 @@ impl Structure for DesertCityAirshipDock { ) .with_z(bldg_base + height - 1), }, - Dir::Y, + Dir2::Y, ) .intersect(clear_limit_2) .clear(); diff --git a/world/src/site/plot/desert_city_arena.rs b/world/src/site/plot/desert_city_arena.rs index 4996814584..8f73350cad 100644 --- a/world/src/site/plot/desert_city_arena.rs +++ b/world/src/site/plot/desert_city_arena.rs @@ -2,12 +2,13 @@ use std::{f32::consts::TAU, sync::Arc}; use crate::{ Land, - site::{Dir, Fill, Painter, Site, Structure, generation::spiral_staircase}, + site::{Fill, Painter, Site, Structure, generation::spiral_staircase}, util::{CARDINALS, DIAGONALS, RandomField, Sampler}, }; use common::{ generation::{EntityInfo, SpecialEntity}, terrain::{Block, BlockKind, SpriteKind}, + util::Dir2, }; use rand::RngExt; use vek::*; @@ -303,7 +304,7 @@ impl Structure for DesertCityArena { ) .with_z(base + pillar_height), }, - Dir::X, + Dir2::X, ) .fill(sandstone.clone()); painter @@ -320,7 +321,7 @@ impl Structure for DesertCityArena { ) .with_z(base + pillar_height - 1), }, - Dir::X, + Dir2::X, ) .clear(); @@ -339,7 +340,7 @@ impl Structure for DesertCityArena { ) .with_z(base + pillar_height), }, - Dir::Y, + Dir2::Y, ) .fill(sandstone.clone()); painter @@ -356,7 +357,7 @@ impl Structure for DesertCityArena { ) .with_z(base + pillar_height - 1), }, - Dir::Y, + Dir2::Y, ) .clear(); } @@ -376,7 +377,7 @@ impl Structure for DesertCityArena { ) .with_z(base + (4 * pillar_size) + 2), }, - Dir::Y, + Dir2::Y, ) .fill(sandstone.clone()); painter @@ -393,7 +394,7 @@ impl Structure for DesertCityArena { ) .with_z(base + (4 * pillar_size)), }, - Dir::Y, + Dir2::Y, ) .clear(); // a2 @@ -411,7 +412,7 @@ impl Structure for DesertCityArena { ) .with_z(base + (4 * pillar_size)), }, - Dir::Y, + Dir2::Y, ) .fill(sandstone.clone()); painter @@ -428,7 +429,7 @@ impl Structure for DesertCityArena { ) .with_z(base + (4 * pillar_size) - 2), }, - Dir::Y, + Dir2::Y, ) .clear(); // b1 @@ -446,7 +447,7 @@ impl Structure for DesertCityArena { ) .with_z(base + (4 * pillar_size) + 2), }, - Dir::X, + Dir2::X, ) .fill(sandstone.clone()); painter @@ -463,7 +464,7 @@ impl Structure for DesertCityArena { ) .with_z(base + (4 * pillar_size)), }, - Dir::X, + Dir2::X, ) .clear(); // b2 @@ -481,7 +482,7 @@ impl Structure for DesertCityArena { ) .with_z(base + (4 * pillar_size)), }, - Dir::X, + Dir2::X, ) .fill(sandstone.clone()); painter @@ -498,7 +499,7 @@ impl Structure for DesertCityArena { ) .with_z(base + (4 * pillar_size) - 2), }, - Dir::X, + Dir2::X, ) .clear(); // top @@ -667,7 +668,7 @@ impl Structure for DesertCityArena { max: Vec2::new(center.x + (length / 2) + wall_th, center.y + 10) .with_z(base + (height / 2) + 8), }, - Dir::X, + Dir2::X, ) .fill(sandstone.clone()); painter @@ -678,7 +679,7 @@ impl Structure for DesertCityArena { max: Vec2::new(center.x + 10, center.y + (width / 2) + corner + wall_th) .with_z(base + (height / 2) + 8), }, - Dir::Y, + Dir2::Y, ) .fill(sandstone.clone()); painter @@ -689,7 +690,7 @@ impl Structure for DesertCityArena { max: Vec2::new(center.x + (length / 2) + wall_th, center.y + 10 - wall_th) .with_z(base + (height / 2) + 8 - wall_th), }, - Dir::X, + Dir2::X, ) .clear(); painter @@ -706,7 +707,7 @@ impl Structure for DesertCityArena { ) .with_z(base + (height / 2) + 8 - wall_th), }, - Dir::Y, + Dir2::Y, ) .clear(); // center clear @@ -765,7 +766,7 @@ impl Structure for DesertCityArena { ) .with_z(base + height + wall_th + top_height - 1), }, - Dir::Y, + Dir2::Y, ) .fill(sandstone.clone()); painter @@ -792,7 +793,7 @@ impl Structure for DesertCityArena { ) .with_z(base + height + wall_th + top_height - 1), }, - Dir::Y, + Dir2::Y, ) .clear(); painter @@ -819,7 +820,7 @@ impl Structure for DesertCityArena { ) .with_z(base + height + wall_th + top_height - 2), }, - Dir::Y, + Dir2::Y, ) .fill(color.clone()); painter @@ -846,7 +847,7 @@ impl Structure for DesertCityArena { ) .with_z(base + height + wall_th + top_height - 2), }, - Dir::Y, + Dir2::Y, ) .clear(); } @@ -876,7 +877,7 @@ impl Structure for DesertCityArena { ) .with_z(base + height + wall_th + top_height - 1), }, - Dir::X, + Dir2::X, ) .fill(sandstone.clone()); painter @@ -903,7 +904,7 @@ impl Structure for DesertCityArena { ) .with_z(base + height + wall_th + top_height - 1), }, - Dir::X, + Dir2::X, ) .clear(); painter @@ -930,7 +931,7 @@ impl Structure for DesertCityArena { ) .with_z(base + height + wall_th + top_height - 2), }, - Dir::X, + Dir2::X, ) .fill(color.clone()); painter @@ -957,7 +958,7 @@ impl Structure for DesertCityArena { ) .with_z(base + height + wall_th + top_height - 2), }, - Dir::X, + Dir2::X, ) .clear(); } @@ -1036,7 +1037,7 @@ impl Structure for DesertCityArena { .with_z(base + (length / 16) - 1 + floor), }, length / 16, - Dir::NegY, + Dir2::NegY, ) .fill(color.clone()); painter @@ -1051,7 +1052,7 @@ impl Structure for DesertCityArena { .with_z(base + (length / 16) - 1 + floor), }, length / 16, - Dir::NegY, + Dir2::NegY, ) .fill(sandstone.clone()); painter @@ -1066,7 +1067,7 @@ impl Structure for DesertCityArena { .with_z(base + (length / 16) - 1 + floor), }, length / 16, - Dir::Y, + Dir2::Y, ) .fill(color.clone()); @@ -1082,7 +1083,7 @@ impl Structure for DesertCityArena { .with_z(base + (length / 16) - 1 + floor), }, length / 16, - Dir::Y, + Dir2::Y, ) .fill(sandstone.clone()); painter @@ -1097,7 +1098,7 @@ impl Structure for DesertCityArena { .with_z(base + (length / 16) - 1 + floor), }, length / 16, - Dir::NegX, + Dir2::NegX, ) .fill(color.clone()); painter @@ -1112,7 +1113,7 @@ impl Structure for DesertCityArena { .with_z(base + (length / 16) - 1 + floor), }, length / 16, - Dir::NegX, + Dir2::NegX, ) .fill(sandstone.clone()); painter @@ -1127,7 +1128,7 @@ impl Structure for DesertCityArena { .with_z(base + (length / 16) - 1 + floor), }, length / 16, - Dir::X, + Dir2::X, ) .fill(color.clone()); painter @@ -1142,7 +1143,7 @@ impl Structure for DesertCityArena { .with_z(base + (length / 16) - 1 + floor), }, length / 16, - Dir::X, + Dir2::X, ) .fill(sandstone.clone()); } diff --git a/world/src/site/plot/desert_city_multiplot.rs b/world/src/site/plot/desert_city_multiplot.rs index bbb7d3d58f..f5352decb4 100644 --- a/world/src/site/plot/desert_city_multiplot.rs +++ b/world/src/site/plot/desert_city_multiplot.rs @@ -11,6 +11,7 @@ use crate::{ use common::{ generation::{EntityInfo, SpecialEntity}, terrain::{Block, BlockKind, SpriteKind, Structure as PrefabStructure, StructuresGroup}, + util::Dir2, }; use lazy_static::lazy_static; use rand::prelude::*; @@ -383,7 +384,7 @@ impl Structure for DesertCityMultiPlot { .with_z(floor_level + room_height), }, 2 * room_length, - Dir::X, + Dir2::X, ) .fill(sandstone.clone()); //interior room compartment with entries @@ -1054,7 +1055,7 @@ impl Structure for DesertCityMultiPlot { .with_z(floor_level + room_height), }, 2 * room_length, - Dir::X, + Dir2::X, ) .fill(sandstone.clone()); // Carve Roof Terrace @@ -1285,7 +1286,8 @@ impl Structure for DesertCityMultiPlot { subplot_center.y - room_length + 4, ); - painter.bed_desert(bed_pos.with_z(floor_level), Dir::X); + painter + .bed_desert(bed_pos.with_z(floor_level), Dir2::X); for d in 0..2 { // other sprites @@ -1580,22 +1582,22 @@ impl Structure for DesertCityMultiPlot { .sprite(sprite_pos, SpriteKind::CoatrackWoodWoodland), 4 => painter.mirrored2( sprite_pos, - Dir::X, + Dir2::X, SpriteKind::BenchWoodWoodland, ), 5 => painter.mirrored2( sprite_pos, - Dir::X, + Dir2::X, SpriteKind::BenchWoodWoodlandGreen1, ), 6 => painter.mirrored2( sprite_pos, - Dir::X, + Dir2::X, SpriteKind::BenchWoodWoodlandGreen2, ), 7 => painter.mirrored2( sprite_pos, - Dir::X, + Dir2::X, SpriteKind::BenchWoodWoodlandGreen3, ), _ => painter.sprite( @@ -1693,7 +1695,7 @@ impl Structure for DesertCityMultiPlot { ) .with_z(base + tower_height + 1), }, - Dir::NegX, + Dir2::NegX, ) .fill(sandstone.clone()); // Library Top Room diff --git a/world/src/site/plot/glider_platform.rs b/world/src/site/plot/glider_platform.rs index 4dd0dc6174..e9787eaa19 100644 --- a/world/src/site/plot/glider_platform.rs +++ b/world/src/site/plot/glider_platform.rs @@ -1,8 +1,5 @@ use super::*; -use crate::{ - Land, - site::{generation::PrimitiveTransform, util::Dir}, -}; +use crate::{Land, site::generation::PrimitiveTransform}; use common::terrain::BlockKind; use rand::prelude::*; use vek::*; @@ -11,7 +8,7 @@ use vek::*; pub struct GliderPlatform { /// Location of center of ring post center: Vec2, - direction: Dir, + direction: Dir2, /// Approximate altitude of the door tile pub(crate) alt: i32, } @@ -22,7 +19,7 @@ impl GliderPlatform { _rng: &mut impl Rng, _site: &Site, wpos: Vec2, - direction: Dir, + direction: Dir2, ) -> Self { // FIXME this should be fed into this function Self { @@ -40,10 +37,10 @@ impl Structure for GliderPlatform { #[cfg_attr(feature = "be-dyn-lib", unsafe(export_name = "render_glider_platform"))] fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) { let rotate_turns = match self.direction { - Dir::X => 0, - Dir::Y => 1, - Dir::NegX => 2, - Dir::NegY => 3, + Dir2::X => 0, + Dir2::Y => 1, + Dir2::NegX => 2, + Dir2::NegY => 3, }; let rotation_center = Vec3::new(self.center.x, self.center.y, self.alt); diff --git a/world/src/site/plot/glider_ring.rs b/world/src/site/plot/glider_ring.rs index 1af392496e..6df8584a2c 100644 --- a/world/src/site/plot/glider_ring.rs +++ b/world/src/site/plot/glider_ring.rs @@ -1,8 +1,5 @@ use super::*; -use crate::{ - Land, - site::{generation::PrimitiveTransform, util::Dir}, -}; +use crate::{Land, site::generation::PrimitiveTransform}; use common::terrain::BlockKind; use rand::prelude::*; use vek::*; @@ -12,7 +9,7 @@ pub struct GliderRing { /// Location of center of ring post center: Vec2, /// Represents the direction the ring is facing - direction: Dir, + direction: Dir2, /// The numeral on the ring sign number: usize, /// Starting altitude @@ -32,7 +29,7 @@ impl GliderRing { _site: &Site, wpos: &Vec2, number: usize, - direction: Dir, + direction: Dir2, ) -> Self { Self { center: *wpos, @@ -53,10 +50,10 @@ impl Structure for GliderRing { #[cfg_attr(feature = "be-dyn-lib", unsafe(export_name = "render_glider_ring"))] fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) { let rotate_turns = match self.direction { - Dir::X => 0, - Dir::Y => 1, - Dir::NegX => 2, - Dir::NegY => 3, + Dir2::X => 0, + Dir2::Y => 1, + Dir2::NegX => 2, + Dir2::NegY => 3, }; let rotation_center = Vec3::new(self.center.x, self.center.y, self.base); @@ -83,7 +80,7 @@ impl Structure for GliderRing { .with_z(ring_base), max: Vec2::new(self.center.x, self.center.y + self.ring_radius).with_z(ring_top), }, - Dir::X, + Dir2::X, ); let red_ring = painter.horizontal_cylinder( Aabb { @@ -91,7 +88,7 @@ impl Structure for GliderRing { max: Vec2::new(self.center.x + 2, self.center.y + self.ring_radius) .with_z(ring_top), }, - Dir::X, + Dir2::X, ); let front_white_ring = painter.horizontal_cylinder( Aabb { @@ -106,7 +103,7 @@ impl Structure for GliderRing { ) .with_z(ring_top - self.ring_thickness + 1), }, - Dir::X, + Dir2::X, ); let back_white_ring = painter.horizontal_cylinder( Aabb { @@ -121,7 +118,7 @@ impl Structure for GliderRing { ) .with_z(ring_top - self.ring_thickness + 1), }, - Dir::X, + Dir2::X, ); let mut black_fills = Vec::new(); for y in self.center.y - self.ring_radius + self.ring_thickness - 1 @@ -169,7 +166,7 @@ impl Structure for GliderRing { ) .with_z(ring_top - self.ring_thickness), }, - Dir::X, + Dir2::X, ); // Sign let sign_base = ring_top - self.ring_thickness - 1; diff --git a/world/src/site/plot/gnarling.rs b/world/src/site/plot/gnarling.rs index ad265fc9c2..f33c53c48b 100644 --- a/world/src/site/plot/gnarling.rs +++ b/world/src/site/plot/gnarling.rs @@ -2,7 +2,7 @@ use super::*; use crate::{ Land, assets::AssetHandle, - site::{generation::PrimitiveTransform, util::Dir}, + site::generation::PrimitiveTransform, util::{RandomField, attempt, sampler::Sampler, within_distance}, }; use common::{ @@ -25,7 +25,7 @@ pub struct GnarlingFortification { wall_towers: Vec>, // Structure indicates the kind of structure it is, vec2 is relative position of a hut compared // to origin, ori tells which way structure should face - structure_locations: Vec<(GnarlingStructure, Vec3, Dir)>, + structure_locations: Vec<(GnarlingStructure, Vec3, Dir2)>, tunnels: Tunnels, } @@ -168,7 +168,7 @@ impl GnarlingFortification { ]; let desired_structures = wall_radius.pow(2) / 100; - let mut structure_locations = Vec::<(GnarlingStructure, Vec3, Dir)>::new(); + let mut structure_locations = Vec::<(GnarlingStructure, Vec3, Dir2)>::new(); for _ in 0..desired_structures { if let Some((hut_loc, kind)) = attempt(50, || { // Choose structure kind @@ -235,7 +235,7 @@ impl GnarlingFortification { )) } }) { - let dir_to_center = Dir::from_vec2(hut_loc.xy()).opposite(); + let dir_to_center = Dir2::from_vec2(hut_loc.xy()).opposite(); let door_rng: u32 = rng.random_range(0..9); let door_dir = match door_rng { 0..=3 => dir_to_center, @@ -260,7 +260,7 @@ impl GnarlingFortification { let chieftain_hut_loc = ((inner_tower_locs[0] + inner_tower_locs[1]) + 2 * outer_wall_corners[chieftain_indices[1]]) / 4; - let chieftain_hut_ori = Dir::from_vec2(chieftain_hut_loc).opposite(); + let chieftain_hut_ori = Dir2::from_vec2(chieftain_hut_loc).opposite(); structure_locations.push(( GnarlingStructure::ChieftainHut, chieftain_hut_loc.with_z(rpos_height(chieftain_hut_loc)), @@ -281,7 +281,7 @@ impl GnarlingFortification { structure_locations.push(( GnarlingStructure::WatchTower, loc.with_z(rpos_height(*loc)), - Dir::Y, + Dir2::Y, )); }); @@ -406,19 +406,19 @@ impl GnarlingFortification { let x_offset; let y_offset; match _ori { - Dir::X => { + Dir2::X => { x_offset = 8; y_offset = 8; }, - Dir::NegX => { + Dir2::NegX => { x_offset = -8; y_offset = 8; }, - Dir::Y => { + Dir2::Y => { x_offset = 8; y_offset = -8; }, - Dir::NegY => { + Dir2::NegY => { x_offset = -8; y_offset = -8; }, @@ -474,8 +474,8 @@ impl GnarlingFortification { const GROUND_OFFSET: i32 = 24; let height = wpos.z + GROUND_HEIGHT; let x_or_y = match _ori { - Dir::X | Dir::NegX => true, - Dir::Y | Dir::NegY => false, + Dir2::X | Dir2::NegX => true, + Dir2::Y | Dir2::NegY => false, }; for pm in plus_minus { let mut pos_ori = @@ -861,7 +861,7 @@ impl Structure for GnarlingFortification { painter: &Painter, wpos: Vec2, alt: i32, - door_dir: Dir, + door_dir: Dir2, hut_radius: f32, hut_wall_height: f32, door_height: i32, @@ -905,15 +905,15 @@ impl Structure for GnarlingFortification { // Door let aabb_min = |dir| { match dir { - Dir::X | Dir::Y => wpos - Vec2::one(), - Dir::NegX | Dir::NegY => wpos + randx / 5 + 1, + Dir2::X | Dir2::Y => wpos - Vec2::one(), + Dir2::NegX | Dir2::NegY => wpos + randx / 5 + 1, } .with_z(alt + 1) }; let aabb_max = |dir| { (match dir { - Dir::X | Dir::Y => wpos + randx / 5 + 1, - Dir::NegX | Dir::NegY => wpos - Vec2::one(), + Dir2::X | Dir2::Y => wpos + randx / 5 + 1, + Dir2::NegX | Dir2::NegY => wpos - Vec2::one(), } + dir.to_vec2() * hut_radius as i32) .with_z(alt + 1 + door_height) }; @@ -1656,7 +1656,7 @@ impl Structure for GnarlingFortification { max: (wpos + 9).with_z(alt + roof_height + 4), }, 0, - Dir::Y, + Dir2::Y, ) .without( painter.gable( @@ -1667,7 +1667,7 @@ impl Structure for GnarlingFortification { .with_z(alt + roof_height + 3), }, 0, - Dir::Y, + Dir2::Y, ), ); diff --git a/world/src/site/plot/haniwa.rs b/world/src/site/plot/haniwa.rs index c3a3a79145..622a06a619 100644 --- a/world/src/site/plot/haniwa.rs +++ b/world/src/site/plot/haniwa.rs @@ -187,7 +187,7 @@ impl Structure for Haniwa { max: Vec2::new(center.x + (outside_radius / 2) + 8, center.y + 16) .with_z(base + 28), }, - Dir::X, + Dir2::X, ) .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) .fill(grass.clone()); @@ -198,7 +198,7 @@ impl Structure for Haniwa { max: Vec2::new(center.x + (outside_radius / 2) + 8, center.y + 16) .with_z(base + 27), }, - Dir::X, + Dir2::X, ) .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) .fill(rock_broken.clone()); @@ -317,7 +317,7 @@ impl Structure for Haniwa { min: Vec2::new(center.x + (diameter / 4), center.y - 12).with_z(base - 5), max: Vec2::new(center.x + (diameter / 2) + 9, center.y + 12).with_z(base + 22), }, - Dir::X, + Dir2::X, ) .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) .fill(rock_broken.clone()); @@ -330,7 +330,7 @@ impl Structure for Haniwa { max: Vec2::new(center.x + (diameter / 2) + 9 + v, center.y + 10 - v) .with_z(base + 22 - v), }, - Dir::X, + Dir2::X, ) .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) .fill(rock_broken.clone()); @@ -341,7 +341,7 @@ impl Structure for Haniwa { min: Vec2::new(center.x + (diameter / 4), center.y - 4).with_z(base), max: Vec2::new(center.x + (diameter / 2) + 25, center.y + 4).with_z(base + 16), }, - Dir::X, + Dir2::X, ) .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) .clear(); @@ -455,7 +455,7 @@ impl Structure for Haniwa { ) .with_z(floor + (room_size / 8)), }, - Dir::X, + Dir2::X, ) .clear(); painter @@ -472,7 +472,7 @@ impl Structure for Haniwa { ) .with_z(floor + (room_size / 8)), }, - Dir::Y, + Dir2::Y, ) .clear(); // room lanterns inner @@ -720,7 +720,7 @@ impl Structure for Haniwa { max: Vec2::new(stairs_start.x + s, stairs_start.y + 4) .with_z(stairs_floor + 12 - s + 2), }, - Dir::X, + Dir2::X, ) .fill(rock_broken.clone()); } @@ -733,7 +733,7 @@ impl Structure for Haniwa { max: Vec2::new(stairs_start.x + s, stairs_start.y + 2) .with_z(stairs_floor + 10 - s), }, - Dir::X, + Dir2::X, ) .clear(); painter @@ -763,7 +763,7 @@ impl Structure for Haniwa { max: Vec2::new(stairs_start.x + s, stairs_start.y + 2) .with_z(stairs_floor + 10 - s), }, - Dir::X, + Dir2::X, ) .fill(key_door.clone()); painter @@ -796,7 +796,7 @@ impl Structure for Haniwa { max: Vec2::new(center.x + (diameter / 4) - s, center.y + 5) .with_z(base + 16 - s + 1), }, - Dir::X, + Dir2::X, ) .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) .fill(rock_broken.clone()); @@ -809,7 +809,7 @@ impl Structure for Haniwa { max: Vec2::new(center.x + (diameter / 4) - s, center.y + 4) .with_z(base + 16 - s), }, - Dir::X, + Dir2::X, ) .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) .clear(); diff --git a/world/src/site/plot/house.rs b/world/src/site/plot/house.rs index 8b086431a2..906b41c389 100644 --- a/world/src/site/plot/house.rs +++ b/world/src/site/plot/house.rs @@ -2,7 +2,7 @@ use super::*; use crate::{ Land, all::ForestKind, - site::util::{Dir, sprites::PainterSpriteExt}, + site::util::sprites::PainterSpriteExt, util::{DIRS, RandomField, Sampler}, }; use common::{ @@ -48,7 +48,7 @@ pub struct House { overhang: i32, /// Color of the roof roof_color: Rgb, - front: Dir, + front: Dir2, christmas_decorations: bool, lower_style: Style, upper_style: Style, @@ -73,10 +73,10 @@ impl House { }; let front = match door_dir { - dir if dir.y < 0 => Dir::NegY, - dir if dir.x < 0 => Dir::NegX, - dir if dir.y > 0 => Dir::Y, - _ => Dir::X, + dir if dir.y < 0 => Dir2::NegY, + dir if dir.x < 0 => Dir2::NegX, + dir if dir.y > 0 => Dir2::Y, + _ => Dir2::X, }; let christmas_decorations = calendar.is_some_and(|c| c.is_event(CalendarEvent::Christmas)); @@ -197,7 +197,7 @@ impl Structure for House { + 1; let (roof_primitive, roof_empty) = match self.front { - Dir::Y => { + Dir2::Y => { ( painter.prim(Primitive::Gable { aabb: Aabb { @@ -212,7 +212,7 @@ impl Structure for House { .with_z(alt + roof + roof_height), }, inset: roof_height, - dir: Dir::Y, + dir: Dir2::Y, }), painter.prim(Primitive::Gable { aabb: Aabb { @@ -229,11 +229,11 @@ impl Structure for House { .with_z(alt + roof + roof_height - 1), }, inset: roof_height - 1, - dir: Dir::Y, + dir: Dir2::Y, }), ) }, - Dir::X => { + Dir2::X => { ( painter.prim(Primitive::Gable { aabb: Aabb { @@ -248,7 +248,7 @@ impl Structure for House { .with_z(alt + roof + roof_height), }, inset: roof_height, - dir: Dir::X, + dir: Dir2::X, }), painter.prim(Primitive::Gable { aabb: Aabb { @@ -265,11 +265,11 @@ impl Structure for House { .with_z(alt + roof + roof_height - 1), }, inset: roof_height - 1, - dir: Dir::X, + dir: Dir2::X, }), ) }, - Dir::NegY => ( + Dir2::NegY => ( painter.prim(Primitive::Gable { aabb: Aabb { min: Vec2::new( @@ -284,7 +284,7 @@ impl Structure for House { .with_z(alt + roof + roof_height), }, inset: roof_height, - dir: Dir::Y, + dir: Dir2::Y, }), painter.prim(Primitive::Gable { aabb: Aabb { @@ -297,7 +297,7 @@ impl Structure for House { .with_z(alt + roof + roof_height - 1), }, inset: roof_height - 1, - dir: Dir::Y, + dir: Dir2::Y, }), ), _ => ( @@ -315,7 +315,7 @@ impl Structure for House { .with_z(alt + roof + roof_height), }, inset: roof_height, - dir: Dir::X, + dir: Dir2::X, }), painter.prim(Primitive::Gable { aabb: Aabb { @@ -331,13 +331,13 @@ impl Structure for House { .with_z(alt + roof + roof_height - 1), }, inset: roof_height - 1, - dir: Dir::X, + dir: Dir2::X, }), ), }; let (roof_front_wall, roof_rear_wall) = match self.front { - Dir::Y => ( + Dir2::Y => ( painter.prim(Primitive::Aabb(Aabb { min: (Vec2::new( self.bounds.min.x, @@ -356,7 +356,7 @@ impl Structure for House { .with_z(alt + roof + roof_height)), })), ), - Dir::X => ( + Dir2::X => ( painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.max.x + (self.levels as i32 - 1) * self.overhang, @@ -375,7 +375,7 @@ impl Structure for House { .with_z(alt + roof + roof_height), })), ), - Dir::NegY => ( + Dir2::NegY => ( painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x, @@ -425,7 +425,7 @@ impl Structure for House { painter.fill(roof_walls, wall_fill_gable.clone()); let max_overhang = (self.levels as i32 - 1) * self.overhang; let (roof_beam, roof_beam_right, roof_beam_left) = match self.front { - Dir::Y => ( + Dir2::Y => ( painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.min.x, self.bounds.min.y).with_z(alt + roof), max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1 + max_overhang) @@ -442,7 +442,7 @@ impl Structure for House { .with_z(alt + roof + 1), })), ), - Dir::X => ( + Dir2::X => ( painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.min.x, self.bounds.min.y).with_z(alt + roof), max: Vec2::new(self.bounds.max.x + max_overhang + 1, self.bounds.max.y + 1) @@ -459,7 +459,7 @@ impl Structure for House { .with_z(alt + roof + 1), })), ), - Dir::NegY => ( + Dir2::NegY => ( painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.min.x, self.bounds.min.y - max_overhang) .with_z(alt + roof), @@ -592,17 +592,17 @@ impl Structure for House { // Walls let inner_level = if self.overhang < -4 && i > 1 { match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: (self.bounds.min + 1).with_z(alt + previous_height), max: Vec2::new(self.bounds.max.x, self.bounds.max.y + storey_increase + 1) .with_z(alt + height), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: (self.bounds.min + 1).with_z(alt + previous_height), max: Vec2::new(self.bounds.max.x + storey_increase + 1, self.bounds.max.y) .with_z(alt + height), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x + 1, self.bounds.min.y - storey_increase + 1, @@ -621,17 +621,17 @@ impl Structure for House { } } else { match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: (self.bounds.min + 1).with_z(alt + previous_height), max: Vec2::new(self.bounds.max.x, self.bounds.max.y + storey_increase) .with_z(alt + height), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: (self.bounds.min + 1).with_z(alt + previous_height), max: (Vec2::new(self.bounds.max.x + storey_increase, self.bounds.max.y)) .with_z(alt + height), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x + 1, self.bounds.min.y - storey_increase + 1, @@ -650,7 +650,7 @@ impl Structure for House { } }; let outer_level = match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: self.bounds.min.with_z(alt + previous_height), max: (Vec2::new( self.bounds.max.x + 1, @@ -658,7 +658,7 @@ impl Structure for House { )) .with_z(alt + height), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: self.bounds.min.with_z(alt + previous_height), max: Vec2::new( self.bounds.max.x + storey_increase + 1, @@ -666,7 +666,7 @@ impl Structure for House { ) .with_z(alt + height), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.min.x, self.bounds.min.y - storey_increase) .with_z(alt + previous_height), max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1) @@ -707,7 +707,7 @@ impl Structure for House { for x in self.tile_aabr.min.x - 2..self.tile_aabr.max.x + 2 { if self.overhang >= 2 && self.front.is_y() { let temp = match self.front { - Dir::Y => site.tile_wpos(Vec2::new(x, self.tile_aabr.max.y)), + Dir2::Y => site.tile_wpos(Vec2::new(x, self.tile_aabr.max.y)), //2 => site.tile_wpos(Vec2::new(x, self.tile_aabr.min.y)), _ => Vec2::zero(), }; @@ -715,7 +715,7 @@ impl Structure for House { // something to do with AABBs with min and max not smaller in the right // order. The same thing is true for orientation 3. let support = match self.front { - Dir::Y => painter.line( + Dir2::Y => painter.line( Vec2::new( temp.x, self.bounds.max.y + storey_increase - self.overhang + 1, @@ -756,14 +756,14 @@ impl Structure for House { for y in self.tile_aabr.min.y - 2..self.tile_aabr.max.y + 2 { if self.overhang >= 2 && !self.front.is_y() { let temp = match self.front { - Dir::Y => Vec2::zero(), - Dir::X => site.tile_wpos(Vec2::new(self.tile_aabr.max.x, y)), - Dir::NegY => Vec2::zero(), + Dir2::Y => Vec2::zero(), + Dir2::X => site.tile_wpos(Vec2::new(self.tile_aabr.max.x, y)), + Dir2::NegY => Vec2::zero(), _ => site.tile_wpos(Vec2::new(self.tile_aabr.min.x, y)), }; let support = match self.front { - Dir::Y => painter.prim(Primitive::Empty), - Dir::X => painter.line( + Dir2::Y => painter.prim(Primitive::Empty), + Dir2::X => painter.line( Vec2::new( self.bounds.max.x + storey_increase - self.overhang + 1, temp.y, @@ -776,7 +776,7 @@ impl Structure for House { .with_z(alt + previous_height), 0.75, ), - Dir::NegY => painter.prim(Primitive::Empty), + Dir2::NegY => painter.prim(Primitive::Empty), _ => painter.line( Vec2::new( self.bounds.min.x - storey_increase + self.overhang - 1, @@ -810,7 +810,7 @@ impl Structure for House { painter.prim(Primitive::Empty) } else { match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x - 1, self.bounds.max.y + storey_increase, @@ -822,7 +822,7 @@ impl Structure for House { ) .with_z(alt + height), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.max.x + storey_increase, self.bounds.min.y - 1, @@ -834,7 +834,7 @@ impl Structure for House { ) .with_z(alt + height), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x - 1, self.bounds.min.y - storey_increase, @@ -868,7 +868,7 @@ impl Structure for House { let pillars2 = painter.prim(Primitive::intersect(pillars_x, pillars_y)); let pillars3 = painter.prim(Primitive::union(pillars1, pillars2)); let pillars4 = match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.min.x - 1, self.bounds.min.y - 1) .with_z(alt + previous_height), max: Vec2::new( @@ -877,7 +877,7 @@ impl Structure for House { ) .with_z(alt + previous_height + 1), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.min.x - 1, self.bounds.min.y - 1) .with_z(alt + previous_height), max: Vec2::new( @@ -886,7 +886,7 @@ impl Structure for House { ) .with_z(alt + previous_height + 1), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x - 1, self.bounds.min.y - storey_increase - 1, @@ -930,11 +930,11 @@ impl Structure for House { .with_z(alt + previous_height + 2 + window_height); let window = painter.prim(Primitive::Aabb(Aabb { min, max })); let add_windows = match self.front { - Dir::Y => { + Dir2::Y => { max.y < self.bounds.max.y + storey_increase && min.y > self.bounds.min.y }, - Dir::X => max.y < self.bounds.max.y && min.y > self.bounds.min.y, - Dir::NegY => { + Dir2::X => max.y < self.bounds.max.y && min.y > self.bounds.min.y, + Dir2::NegY => { max.y < self.bounds.max.y && min.y > self.bounds.min.y - storey_increase }, _ => max.y < self.bounds.max.y && min.y > self.bounds.min.y, @@ -994,11 +994,11 @@ impl Structure for House { .with_z(alt + previous_height + 2 + window_height); let window = painter.prim(Primitive::Aabb(Aabb { min, max })); let add_windows = match self.front { - Dir::Y => max.x < self.bounds.max.x && min.x > self.bounds.min.x, - Dir::X => { + Dir2::Y => max.x < self.bounds.max.x && min.x > self.bounds.min.x, + Dir2::X => { max.x < self.bounds.max.x + storey_increase && min.x > self.bounds.min.x }, - Dir::NegY => max.x < self.bounds.max.x && min.x > self.bounds.min.x, + Dir2::NegY => max.x < self.bounds.max.x && min.x > self.bounds.min.x, _ => { max.x < self.bounds.max.x && min.x > self.bounds.min.x - storey_increase }, @@ -1050,7 +1050,7 @@ impl Structure for House { // Shed roof on negative overhangs if self.overhang < -4 && i > 1 { let shed = match self.front { - Dir::Y => painter.prim(Primitive::Ramp { + Dir2::Y => painter.prim(Primitive::Ramp { aabb: Aabb { min: Vec2::new( self.bounds.min.x - 1, @@ -1064,9 +1064,9 @@ impl Structure for House { .with_z(alt + height), }, inset: storey, - dir: Dir::NegY, + dir: Dir2::NegY, }), - Dir::X => painter.prim(Primitive::Ramp { + Dir2::X => painter.prim(Primitive::Ramp { aabb: Aabb { min: Vec2::new( self.bounds.max.x + storey_increase + 1, @@ -1080,9 +1080,9 @@ impl Structure for House { .with_z(alt + height), }, inset: storey, - dir: Dir::NegX, + dir: Dir2::NegX, }), - Dir::NegY => painter.prim(Primitive::Ramp { + Dir2::NegY => painter.prim(Primitive::Ramp { aabb: Aabb { min: Vec2::new( self.bounds.min.x - 1, @@ -1096,7 +1096,7 @@ impl Structure for House { .with_z(alt + height), }, inset: storey, - dir: Dir::Y, + dir: Dir2::Y, }), _ => painter.prim(Primitive::Ramp { aabb: Aabb { @@ -1112,11 +1112,11 @@ impl Structure for House { .with_z(alt + height), }, inset: storey, - dir: Dir::X, + dir: Dir2::X, }), }; let shed_empty = match self.front { - Dir::Y => painter.prim(Primitive::Ramp { + Dir2::Y => painter.prim(Primitive::Ramp { aabb: Aabb { min: Vec2::new( self.bounds.min.x - 1, @@ -1130,9 +1130,9 @@ impl Structure for House { .with_z(alt + height - 1), }, inset: storey - 1, - dir: Dir::NegY, + dir: Dir2::NegY, }), - Dir::X => painter.prim(Primitive::Ramp { + Dir2::X => painter.prim(Primitive::Ramp { aabb: Aabb { min: Vec2::new( self.bounds.max.x + storey_increase + 1, @@ -1146,9 +1146,9 @@ impl Structure for House { .with_z(alt + height - 1), }, inset: storey - 1, - dir: Dir::NegX, + dir: Dir2::NegX, }), - Dir::NegY => painter.prim(Primitive::Ramp { + Dir2::NegY => painter.prim(Primitive::Ramp { aabb: Aabb { min: Vec2::new( self.bounds.min.x - 1, @@ -1162,7 +1162,7 @@ impl Structure for House { .with_z(alt + height), }, inset: storey - 1, - dir: Dir::Y, + dir: Dir2::Y, }), _ => painter.prim(Primitive::Ramp { aabb: Aabb { @@ -1178,13 +1178,13 @@ impl Structure for House { .with_z(alt + height), }, inset: storey - 1, - dir: Dir::X, + dir: Dir2::X, }), }; painter.fill(shed, Fill::Brick(BlockKind::Wood, self.roof_color, 24)); painter.fill(shed_empty, Fill::Block(Block::empty())); let shed_left_wall = match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.min.x, self.bounds.max.y + storey_increase + 1) .with_z(alt + previous_height), max: Vec2::new( @@ -1193,7 +1193,7 @@ impl Structure for House { ) .with_z(alt + height - 1), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.max.x + storey_increase + 1, self.bounds.min.y) .with_z(alt + previous_height), max: Vec2::new( @@ -1202,7 +1202,7 @@ impl Structure for House { ) .with_z(alt + height - 1), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.max.x, self.bounds.min.y - storey_increase - self.overhang.abs() + 1, @@ -1228,7 +1228,7 @@ impl Structure for House { })), }; let shed_right_wall = match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.max.x, self.bounds.max.y + storey_increase + 1) .with_z(alt + previous_height), max: Vec2::new( @@ -1237,7 +1237,7 @@ impl Structure for House { ) .with_z(alt + height - 1), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.max.x + storey_increase + 1, self.bounds.max.y) .with_z(alt + previous_height), max: Vec2::new( @@ -1246,7 +1246,7 @@ impl Structure for House { ) .with_z(alt + height - 1), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x, self.bounds.min.y - storey_increase - self.overhang.abs() + 1, @@ -1272,7 +1272,7 @@ impl Structure for House { })), }; let shed_wall_beams = match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.min.x, self.bounds.max.y + storey_increase + 1) .with_z(alt + previous_height), max: Vec2::new( @@ -1281,7 +1281,7 @@ impl Structure for House { ) .with_z(alt + previous_height + 1), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.max.x + storey_increase + 1, self.bounds.min.y) .with_z(alt + previous_height), max: Vec2::new( @@ -1290,7 +1290,7 @@ impl Structure for House { ) .with_z(alt + previous_height + 1), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x, self.bounds.min.y - storey_increase - self.overhang.abs() + 1, @@ -1333,13 +1333,13 @@ impl Structure for House { }; for n in range { let temp = match self.front { - Dir::Y => site.tile_wpos(Vec2::new(n, self.tile_aabr.max.y)) - 4, - Dir::X => site.tile_wpos(Vec2::new(self.tile_aabr.max.x, n)) - 4, - Dir::NegY => site.tile_wpos(Vec2::new(n, self.tile_aabr.min.y)) - 4, + Dir2::Y => site.tile_wpos(Vec2::new(n, self.tile_aabr.max.y)) - 4, + Dir2::X => site.tile_wpos(Vec2::new(self.tile_aabr.max.x, n)) - 4, + Dir2::NegY => site.tile_wpos(Vec2::new(n, self.tile_aabr.min.y)) - 4, _ => site.tile_wpos(Vec2::new(self.tile_aabr.min.x, n)) - 4, }; let dormer_box = match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(temp.x - 1, self.bounds.max.y + storey_increase + 1) .with_z(alt + previous_height), max: Vec2::new( @@ -1348,7 +1348,7 @@ impl Structure for House { ) .with_z(alt + height - 1), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.max.x + storey_increase + 1, temp.y - 1) .with_z(alt + previous_height), max: Vec2::new( @@ -1357,7 +1357,7 @@ impl Structure for House { ) .with_z(alt + height - 1), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( temp.x - 1, self.bounds.min.y - storey_increase - self.overhang.abs() + 1, @@ -1377,7 +1377,7 @@ impl Structure for House { })), }; let dormer_roof = match self.front { - Dir::Y => painter.prim(Primitive::Gable { + Dir2::Y => painter.prim(Primitive::Gable { aabb: Aabb { min: Vec2::new(temp.x - 1, self.bounds.max.y + storey_increase + 1) .with_z(alt + height - 2), @@ -1388,9 +1388,9 @@ impl Structure for House { .with_z(alt + height + 1), }, inset: 3, - dir: Dir::Y, + dir: Dir2::Y, }), - Dir::X => painter.prim(Primitive::Gable { + Dir2::X => painter.prim(Primitive::Gable { aabb: Aabb { min: Vec2::new(self.bounds.max.x + storey_increase + 1, temp.y - 1) .with_z(alt + height - 2), @@ -1401,9 +1401,9 @@ impl Structure for House { .with_z(alt + height + 1), }, inset: 3, - dir: Dir::X, + dir: Dir2::X, }), - Dir::NegY => painter.prim(Primitive::Gable { + Dir2::NegY => painter.prim(Primitive::Gable { aabb: Aabb { min: Vec2::new( temp.x - 1, @@ -1414,7 +1414,7 @@ impl Structure for House { .with_z(alt + height + 1), }, inset: 3, - dir: Dir::Y, + dir: Dir2::Y, }), _ => painter.prim(Primitive::Gable { aabb: Aabb { @@ -1427,21 +1427,21 @@ impl Structure for House { .with_z(alt + height + 1), }, inset: 3, - dir: Dir::X, + dir: Dir2::X, }), }; let window_min = match self.front { - Dir::Y => Vec2::new( + Dir2::Y => Vec2::new( temp.x, self.bounds.max.y + storey_increase + self.overhang.abs() - 1, ) .with_z(alt + previous_height + 2), - Dir::X => Vec2::new( + Dir2::X => Vec2::new( self.bounds.max.x + storey_increase + self.overhang.abs() - 1, temp.y, ) .with_z(alt + previous_height + 2), - Dir::NegY => Vec2::new( + Dir2::NegY => Vec2::new( temp.x, self.bounds.min.y - storey_increase - self.overhang.abs() + 1, ) @@ -1453,17 +1453,17 @@ impl Structure for House { .with_z(alt + previous_height + 2), }; let window_max = match self.front { - Dir::Y => Vec2::new( + Dir2::Y => Vec2::new( temp.x + 3, self.bounds.max.y + storey_increase + self.overhang.abs(), ) .with_z(alt + previous_height + 2 + window_height), - Dir::X => Vec2::new( + Dir2::X => Vec2::new( self.bounds.max.x + storey_increase + self.overhang.abs(), temp.y + 3, ) .with_z(alt + previous_height + 2 + window_height), - Dir::NegY => Vec2::new( + Dir2::NegY => Vec2::new( temp.x + 3, self.bounds.min.y - storey_increase - self.overhang.abs() + 2, ) @@ -1479,7 +1479,7 @@ impl Structure for House { max: window_max, })); let window_cavity = match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(temp.x, self.bounds.max.y + storey_increase) .with_z(alt + previous_height), max: Vec2::new( @@ -1488,7 +1488,7 @@ impl Structure for House { ) .with_z(alt + previous_height + 2 + window_height), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.max.x + storey_increase, temp.y) .with_z(alt + previous_height), max: Vec2::new( @@ -1497,7 +1497,7 @@ impl Structure for House { ) .with_z(alt + previous_height + 2 + window_height), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( temp.x, self.bounds.min.y - storey_increase - self.overhang.abs() + 2, @@ -1549,7 +1549,7 @@ impl Structure for House { if i > 1 { let floor = if self.overhang < -1 && i > 1 { match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: (self.bounds.min + 1).with_z(alt + previous_height), max: Vec2::new( self.bounds.max.x, @@ -1557,7 +1557,7 @@ impl Structure for House { ) .with_z(alt + previous_height + 1), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1) .with_z(alt + previous_height), max: Vec2::new( @@ -1566,7 +1566,7 @@ impl Structure for House { ) .with_z(alt + previous_height + 1), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x + 1, self.bounds.min.y + 1 - storey_increase - self.overhang.abs(), @@ -1587,7 +1587,7 @@ impl Structure for House { } } else { match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: (self.bounds.min + 1).with_z(alt + previous_height), max: (Vec2::new( self.bounds.max.x, @@ -1595,7 +1595,7 @@ impl Structure for House { )) .with_z(alt + previous_height + 1), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: (self.bounds.min + 1).with_z(alt + previous_height), max: (Vec2::new( self.bounds.max.x + storey_increase, @@ -1603,7 +1603,7 @@ impl Structure for House { )) .with_z(alt + previous_height + 1), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new( self.bounds.min.x + 1, self.bounds.min.y + 1 - storey_increase, @@ -1634,8 +1634,8 @@ impl Structure for House { if i % 2 == 0 { // bedroom on even-leveled floors let bed_pos = match self.front { - Dir::X => Vec2::new(half_x, quarter_y), - Dir::NegY => Vec2::new(three_quarter_x, half_y), + Dir2::X => Vec2::new(half_x, quarter_y), + Dir2::NegY => Vec2::new(three_quarter_x, half_y), _ => Vec2::new(half_x, half_y), }; let bed_dir = self.front; @@ -1711,7 +1711,7 @@ impl Structure for House { table_pos.with_z(base), SpriteKind::DiningtableWoodWoodlandRound, ); - for dir in Dir::iter() { + for dir in Dir2::iter() { let chair_pos = table_pos + dir.to_vec2(); painter.rotated_sprite( chair_pos.with_z(base), @@ -1722,24 +1722,24 @@ impl Structure for House { } else { // room is bigger, so use large table + chair positions let table_pos = match self.front { - Dir::Y => Vec2::new(half_x, three_quarter_y), - Dir::X => Vec2::new(half_x, half_y), + Dir2::Y => Vec2::new(half_x, three_quarter_y), + Dir2::X => Vec2::new(half_x, half_y), _ => Vec2::new(quarter_x, half_y), } .with_z(base); let table_axis = if RandomField::new(0).chance(table_pos, 0.5) { - Dir::X + Dir2::X } else { - Dir::Y + Dir2::Y }; let table_bounds = painter.table_wood_fancy_woodland(table_pos, table_axis); painter.chairs_around(SpriteKind::ChairWoodWoodland, 1, table_bounds, base); } // drawer along a wall let (drawer_pos, drawer_ori) = match self.front { - Dir::Y => (Vec2::new(self.bounds.max.x - 1, self.bounds.max.y - 2), 6), - Dir::X => (Vec2::new(self.bounds.max.x - 2, self.bounds.max.y - 1), 0), - Dir::NegY => (Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 2), 6), + Dir2::Y => (Vec2::new(self.bounds.max.x - 1, self.bounds.max.y - 2), 6), + Dir2::X => (Vec2::new(self.bounds.max.x - 2, self.bounds.max.y - 1), 0), + Dir2::NegY => (Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 2), 6), _ => (Vec2::new(self.bounds.min.x + 2, self.bounds.max.y - 1), 0), }; painter.rotated_sprite( @@ -1754,9 +1754,9 @@ impl Structure for House { let stair_width = 3; let previous_floor_height = (storey * (i as i32 - 2)).max(0); let stair_origin = match self.front { - Dir::Y => self.bounds.min + 1, - Dir::X => self.bounds.min + 1, - Dir::NegY => { + Dir2::Y => self.bounds.min + 1, + Dir2::X => self.bounds.min + 1, + Dir2::NegY => { Vec2::new(self.bounds.max.x - 12, self.bounds.max.y - stair_width * 2) }, _ => Vec2::new(self.bounds.max.x - 12, self.bounds.min.y + 1), @@ -1772,7 +1772,7 @@ impl Structure for House { max: Vec2::new(stair_origin.x + 10, stair_origin.y + stair_width).with_z(alt + previous_height + 1), }, inset: storey, - dir: Dir::X, + dir: Dir2::X, }) /*}, 1 => { @@ -1851,7 +1851,7 @@ impl Structure for House { max: Vec2::new(stair_origin.x + 8, stair_origin.y + 2 * stair_width).with_z(alt + previous_height + 1), }, inset: storey, - dir: Dir::NegX, + dir: Dir2::NegX, }) /*}, 1 => { @@ -2048,13 +2048,13 @@ impl Structure for House { } } else */{ match self.front { - Dir::Y => { + Dir2::Y => { Vec2::new(half_x, self.bounds.min.y + 1) }, - Dir::X => { + Dir2::X => { Vec2::new(self.bounds.min.x + 1, half_y) }, - Dir::NegY => { + Dir2::NegY => { Vec2::new(half_x - 4, self.bounds.max.y - 3) }, _ => { @@ -2063,17 +2063,17 @@ impl Structure for House { } }; let chimney = match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(fireplace_origin.x, fireplace_origin.y).with_z(alt), max: Vec2::new(fireplace_origin.x + 4, fireplace_origin.y + 3) .with_z(alt + roof + roof_height + 2), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(fireplace_origin.x, fireplace_origin.y).with_z(alt), max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 4) .with_z(alt + roof + roof_height + 2), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(fireplace_origin.x, fireplace_origin.y).with_z(alt), max: Vec2::new(fireplace_origin.x + 4, fireplace_origin.y + 3) .with_z(alt + roof + roof_height + 2), @@ -2086,17 +2086,17 @@ impl Structure for House { }; let chimney_cavity = match self.front { - Dir::Y => painter.prim(Primitive::Aabb(Aabb { + Dir2::Y => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt), max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2) .with_z(alt + roof + roof_height + 2), })), - Dir::X => painter.prim(Primitive::Aabb(Aabb { + Dir2::X => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt), max: Vec2::new(fireplace_origin.x + 2, fireplace_origin.y + 3) .with_z(alt + roof + roof_height + 2), })), - Dir::NegY => painter.prim(Primitive::Aabb(Aabb { + Dir2::NegY => painter.prim(Primitive::Aabb(Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt), max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2) .with_z(alt + roof + roof_height + 2), @@ -2108,15 +2108,15 @@ impl Structure for House { })), }; let fire_embers = match self.front { - Dir::Y => Aabb { + Dir2::Y => Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt), max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2).with_z(alt + 1), }, - Dir::X => Aabb { + Dir2::X => Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt), max: Vec2::new(fireplace_origin.x + 2, fireplace_origin.y + 3).with_z(alt + 1), }, - Dir::NegY => Aabb { + Dir2::NegY => Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt), max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2).with_z(alt + 1), }, @@ -2126,15 +2126,15 @@ impl Structure for House { }, }; let fireplace_cavity = match self.front { - Dir::Y => Aabb { + Dir2::Y => Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt), max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 3).with_z(alt + 2), }, - Dir::X => Aabb { + Dir2::X => Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt), max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 3).with_z(alt + 2), }, - Dir::NegY => Aabb { + Dir2::NegY => Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y).with_z(alt), max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2).with_z(alt + 2), }, @@ -2165,16 +2165,16 @@ impl Structure for House { || self.bounds.max.y - self.bounds.min.y < 16 { match self.front { - Dir::Y => Vec2::new(self.bounds.min.x + 4, self.bounds.min.y + 2), - Dir::X => Vec2::new(self.bounds.min.x + 2, self.bounds.min.y + 4), - Dir::NegY => Vec2::new(self.bounds.max.x - 4, self.bounds.max.y - 2), + Dir2::Y => Vec2::new(self.bounds.min.x + 4, self.bounds.min.y + 2), + Dir2::X => Vec2::new(self.bounds.min.x + 2, self.bounds.min.y + 4), + Dir2::NegY => Vec2::new(self.bounds.max.x - 4, self.bounds.max.y - 2), _ => Vec2::new(self.bounds.max.x - 8, self.bounds.max.y - 2), } } else { match self.front { - Dir::Y => Vec2::new(self.bounds.max.x - 4, self.bounds.min.y + 2), - Dir::X => Vec2::new(self.bounds.min.x + 8, self.bounds.max.y - 2), - Dir::NegY => Vec2::new(self.bounds.max.x - 4, self.bounds.max.y - 2), + Dir2::Y => Vec2::new(self.bounds.max.x - 4, self.bounds.min.y + 2), + Dir2::X => Vec2::new(self.bounds.min.x + 8, self.bounds.max.y - 2), + Dir2::NegY => Vec2::new(self.bounds.max.x - 4, self.bounds.max.y - 2), _ => Vec2::new(self.bounds.max.x - 8, self.bounds.max.y - 2), } }; @@ -2185,7 +2185,7 @@ impl Structure for House { if self.christmas_decorations { let (wreath_pos, wreath_ori) = match self.front { - Dir::Y => ( + Dir2::Y => ( Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 3) .with_z(alt + 2), @@ -2194,7 +2194,7 @@ impl Structure for House { }, 4, ), - Dir::X => ( + Dir2::X => ( Aabb { min: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 1) .with_z(alt + 2), @@ -2203,7 +2203,7 @@ impl Structure for House { }, 2, ), - Dir::NegY => ( + Dir2::NegY => ( Aabb { min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y - 1) .with_z(alt + 2), @@ -2233,15 +2233,15 @@ impl Structure for House { // Door // Fill around the door with wall let doorway1 = match self.front { - Dir::Y => Aabb { + Dir2::Y => Aabb { min: Vec2::new(door_tile_wpos.x - 1, self.bounds.max.y).with_z(alt), max: Vec2::new(door_tile_wpos.x + 3, self.bounds.max.y + 1).with_z(alt + 4), }, - Dir::X => Aabb { + Dir2::X => Aabb { min: Vec2::new(self.bounds.max.x, door_tile_wpos.y - 1).with_z(alt), max: Vec2::new(self.bounds.max.x + 1, door_tile_wpos.y + 3).with_z(alt + 4), }, - Dir::NegY => Aabb { + Dir2::NegY => Aabb { min: Vec2::new(door_tile_wpos.x - 1, self.bounds.min.y).with_z(alt), max: Vec2::new(door_tile_wpos.x + 3, self.bounds.min.y + 1).with_z(alt + 4), }, @@ -2254,15 +2254,15 @@ impl Structure for House { // Carve out the doorway with air let doorway2 = match self.front { - Dir::Y => Aabb { + Dir2::Y => Aabb { min: Vec2::new(door_tile_wpos.x, self.bounds.max.y).with_z(alt), max: Vec2::new(door_tile_wpos.x + 2, self.bounds.max.y + 1).with_z(alt + 3), }, - Dir::X => Aabb { + Dir2::X => Aabb { min: Vec2::new(self.bounds.max.x, door_tile_wpos.y).with_z(alt), max: Vec2::new(self.bounds.max.x + 1, door_tile_wpos.y + 2).with_z(alt + 3), }, - Dir::NegY => Aabb { + Dir2::NegY => Aabb { min: Vec2::new(door_tile_wpos.x, self.bounds.min.y).with_z(alt), max: Vec2::new(door_tile_wpos.x + 2, self.bounds.min.y + 1).with_z(alt + 3), }, @@ -2278,7 +2278,7 @@ impl Structure for House { // Fill in the right and left side doors let (door_gap, door1, door1_ori, door2, door2_ori) = match self.front { - Dir::Y => ( + Dir2::Y => ( Aabb { min: Vec2::new(door_tile_wpos.x - 1, self.bounds.max.y + 1).with_z(alt), max: Vec2::new(door_tile_wpos.x + 3, self.bounds.max.y + 4).with_z(alt + 3), @@ -2294,7 +2294,7 @@ impl Structure for House { }, 4, ), - Dir::X => ( + Dir2::X => ( Aabb { min: Vec2::new(self.bounds.max.x + 1, door_tile_wpos.y - 1).with_z(alt), max: Vec2::new(self.bounds.max.x + 4, door_tile_wpos.y + 3).with_z(alt + 3), @@ -2310,7 +2310,7 @@ impl Structure for House { }, 6, ), - Dir::NegY => ( + Dir2::NegY => ( Aabb { min: Vec2::new(door_tile_wpos.x - 1, self.bounds.min.y - 4).with_z(alt), max: Vec2::new(door_tile_wpos.x + 3, self.bounds.min.y).with_z(alt + 3), @@ -2360,7 +2360,7 @@ impl Structure for House { let rng = RandomField::new(0).get(door_tile_wpos.with_z(alt + 3)); let right = (rng % 2) as i32; let (door_light_pos, door_light_ori) = match self.front { - Dir::Y => ( + Dir2::Y => ( Aabb { min: Vec2::new(door_tile_wpos.x + right, self.bounds.max.y + 1) .with_z(alt + 3), @@ -2369,7 +2369,7 @@ impl Structure for House { }, 4, ), - Dir::X => ( + Dir2::X => ( Aabb { min: Vec2::new(self.bounds.max.x + 1, door_tile_wpos.y + right) .with_z(alt + 3), @@ -2378,7 +2378,7 @@ impl Structure for House { }, 2, ), - Dir::NegY => ( + Dir2::NegY => ( Aabb { min: Vec2::new(door_tile_wpos.x + right, self.bounds.min.y - 1) .with_z(alt + 3), diff --git a/world/src/site/plot/jungle_ruin.rs b/world/src/site/plot/jungle_ruin.rs index e8e39fe0d7..9c7a2fa9ef 100644 --- a/world/src/site/plot/jungle_ruin.rs +++ b/world/src/site/plot/jungle_ruin.rs @@ -196,7 +196,7 @@ impl Structure for JungleRuin { .with_z(plot_base - height_handle - room_size + 1), max: Vec2::new(center.x, center.y + 3).with_z(plot_base), }, - Dir::NegX, + Dir2::NegX, ) .fill(stone_broken); let chest_pos = Vec2::new(center.x + room_size - 2, center.y - 3) diff --git a/world/src/site/plot/myrmidon_arena.rs b/world/src/site/plot/myrmidon_arena.rs index a84be339c9..b745c6828c 100644 --- a/world/src/site/plot/myrmidon_arena.rs +++ b/world/src/site/plot/myrmidon_arena.rs @@ -374,7 +374,7 @@ impl Structure for MyrmidonArena { max: Vec2::new(entry_pos.x + 15, entry_pos.y + 12) .with_z(base + platform_2_height), }, - Dir::Y, + Dir2::Y, ) .fill(sandstone.clone()); painter @@ -384,7 +384,7 @@ impl Structure for MyrmidonArena { max: Vec2::new(entry_pos.x + 10, entry_pos.y + 12) .with_z(base + platform_2_height - 5), }, - Dir::Y, + Dir2::Y, ) .clear(); let height_handle = 5; @@ -431,7 +431,7 @@ impl Structure for MyrmidonArena { .with_z(base + platform_2_height + 4 + height_handle), }, 16, - Dir::Y, + Dir2::Y, ) .fill(sandstone.clone()); @@ -444,7 +444,7 @@ impl Structure for MyrmidonArena { .with_z(base + platform_2_height + 5 + height_handle), }, 16, - Dir::Y, + Dir2::Y, ) .fill(roof_color.clone()); for g in 0..8 { @@ -457,7 +457,7 @@ impl Structure for MyrmidonArena { .with_z(base + platform_2_height + 6 + height_handle), }, 16, - Dir::Y, + Dir2::Y, ) .fill(roof_color.clone()); } @@ -468,7 +468,7 @@ impl Structure for MyrmidonArena { min: Vec2::new(entry_pos.x - 3, entry_pos.y - 19).with_z(base - 20), max: Vec2::new(entry_pos.x + 3, entry_pos.y + 5).with_z(base - 12), }, - Dir::Y, + Dir2::Y, ) .clear(); painter @@ -540,7 +540,7 @@ impl Structure for MyrmidonArena { min: Vec2::new(boss_pos.x - 4, boss_pos.y - 10).with_z(base - 22), max: Vec2::new(boss_pos.x + 4, boss_pos.y + 18).with_z(base - 12), }, - Dir::Y, + Dir2::Y, ) .clear(); painter @@ -549,7 +549,7 @@ impl Structure for MyrmidonArena { min: Vec2::new(boss_pos.x - 52, boss_pos.y - 4).with_z(base - 22), max: Vec2::new(boss_pos.x, boss_pos.y + 4).with_z(base - 12), }, - Dir::X, + Dir2::X, ) .clear(); painter @@ -558,7 +558,7 @@ impl Structure for MyrmidonArena { min: Vec2::new(boss_pos.x - 4, boss_pos.y - 4).with_z(base - 22), max: Vec2::new(boss_pos.x - 3, boss_pos.y + 4).with_z(base - 12), }, - Dir::X, + Dir2::X, ) .fill(Fill::Block(Block::air(SpriteKind::MyrmidonKeyDoor))); painter @@ -573,7 +573,7 @@ impl Structure for MyrmidonArena { min: Vec2::new(boss_pos.x - 4, boss_pos.y + 17).with_z(base - 20), max: Vec2::new(boss_pos.x + 4, boss_pos.y + 18).with_z(base - 12), }, - Dir::Y, + Dir2::Y, ) .fill(Fill::Block(Block::air(SpriteKind::MyrmidonKeyDoor))); painter @@ -582,7 +582,7 @@ impl Structure for MyrmidonArena { min: Vec2::new(boss_pos.x, boss_pos.y + 17).with_z(base - 18), max: Vec2::new(boss_pos.x + 1, boss_pos.y + 18).with_z(base - 17), }, - Dir::Y, + Dir2::Y, ) .fill(Fill::Block(Block::air(SpriteKind::MinotaurKeyhole))); @@ -651,7 +651,7 @@ impl Structure for MyrmidonArena { for s in 0..3 { let room_var = RandomField::new(0).get(room_pos.with_z(base + r + s)) % 6; - let room_dir = if room_var < 3 { Dir::Y } else { Dir::X }; + let room_dir = if room_var < 3 { Dir2::Y } else { Dir2::X }; let room = painter.vault( Aabb { min: (room_pos - (radius / 8)).with_z(base - 79 + (18 * s)), @@ -687,7 +687,7 @@ impl Structure for MyrmidonArena { min: (cyclops_pos_high - (radius / 8)).with_z(base - 40), max: (cyclops_pos_high + (radius / 8)).with_z(base - 25), }, - Dir::X, + Dir2::X, ) .clear(); painter.spawn(EntityInfo::at(cyclops_pos_high.as_()).with_asset_expect( @@ -702,7 +702,7 @@ impl Structure for MyrmidonArena { min: (cyclops_pos_low - (radius / 8)).with_z(base - 79), max: (cyclops_pos_low + (radius / 8)).with_z(base - 64), }, - Dir::X, + Dir2::X, ) .clear(); painter.spawn(EntityInfo::at(cyclops_pos_low.as_()).with_asset_expect( diff --git a/world/src/site/plot/myrmidon_house.rs b/world/src/site/plot/myrmidon_house.rs index 201066e4a3..bcbc9ca310 100644 --- a/world/src/site/plot/myrmidon_house.rs +++ b/world/src/site/plot/myrmidon_house.rs @@ -225,7 +225,7 @@ impl Structure for MyrmidonHouse { .with_z(base + bldg_height + 4), }) .fill(sandstone.clone()); - let roof_dir = if rand > 0 { Dir::X } else { Dir::Y }; + let roof_dir = if rand > 0 { Dir2::X } else { Dir2::Y }; painter .gable( Aabb { @@ -375,7 +375,7 @@ impl Structure for MyrmidonHouse { for s in 0..3 { let room_var = RandomField::new(0).get(room_pos.with_z(base + r + s)) % 6; - let room_dir = if room_var < 3 { Dir::Y } else { Dir::X }; + let room_dir = if room_var < 3 { Dir2::Y } else { Dir2::X }; let room = painter.vault( Aabb { diff --git a/world/src/site/plot/plaza.rs b/world/src/site/plot/plaza.rs index ba411fc9fe..85fad3a8bb 100644 --- a/world/src/site/plot/plaza.rs +++ b/world/src/site/plot/plaza.rs @@ -20,9 +20,9 @@ impl CornerMeta { pub struct Plaza { pub aabr: Aabr, pub kind: RoadKind, - corner_meta: EnumMap, + corner_meta: EnumMap, pub hard_alt: Option, - dir: Dir, + dir: Dir2, } impl Plaza { @@ -51,7 +51,7 @@ impl Plaza { let center = get_corner_meta(iaabr.center()); - let corner_meta: EnumMap = Dir::iter() + let corner_meta: EnumMap = Dir2::iter() .map(|d| { let o = d.rotated_cw(); let pos = d.select_aabr_with(iaabr, o.select_aabr(iaabr)); @@ -71,7 +71,7 @@ impl Plaza { None }, dir: *RandomField::new(51) - .choose(aabr.center().with_z(center.alt), &Dir::ALL) + .choose(aabr.center().with_z(center.alt), &Dir2::ALL) .expect("Dir::ALL has len 4"), } } @@ -121,7 +121,7 @@ impl Structure for Plaza { max: site.wpos_tile_pos(self.aabr.max) - 1, }; - for dir in Dir::iter() { + for dir in Dir2::iter() { let orth = dir.orthogonal(); for i in (orth.select(tile_aabr.min) + 1)..orth.select(tile_aabr.max) { diff --git a/world/src/site/plot/road.rs b/world/src/site/plot/road.rs index 3fb349cede..57159f00fd 100644 --- a/world/src/site/plot/road.rs +++ b/world/src/site/plot/road.rs @@ -32,7 +32,7 @@ pub struct RoadKind { impl RoadKind { /// Intended to be placed at `riverless_alt`. - pub fn place_light(&self, pos: Vec3, dir: Dir, painter: &Painter) { + pub fn place_light(&self, pos: Vec3, dir: Dir2, painter: &Painter) { let wood_corner = Fill::Brick(BlockKind::Wood, Rgb::new(86, 50, 50), 10); painter .column(pos.xy(), pos.z - 4..pos.z) @@ -44,7 +44,7 @@ impl RoadKind { } } - pub fn block(&self, col: &ColumnSample, wpos: Vec3, dir: Dir) -> Block { + pub fn block(&self, col: &ColumnSample, wpos: Vec3, dir: Dir2) -> Block { match self.material { RoadMaterial::Dirt => Block::new( BlockKind::Earth, @@ -107,11 +107,11 @@ impl Structure for Road { let center = site.tile_center_wpos(*p); - let light_wpos = |dir: Dir| { + let light_wpos = |dir: Dir2| { let width = w as i32 * 2 - 1 - (dir.signum() + 1) / 2; center + dir.to_vec2() * width }; - let available_dirs: EnumSet = Dir::iter() + let available_dirs: EnumSet = Dir2::iter() .filter(|dir| { let light_wpos = light_wpos(*dir); let tpos = site.wpos_tile_pos(light_wpos); @@ -178,7 +178,7 @@ impl Structure for Road { let is_end = *b == path.len() as u16 - 1; let a = path.nodes()[*a as usize]; let b = path.nodes()[*b as usize]; - let path_dir = Dir::from_vec2(b - a); + let path_dir = Dir2::from_vec2(b - a); Some(( LineSegment2 { start: site.tile_center_wpos(a) @@ -209,7 +209,7 @@ impl Structure for Road { if let Some((line, _)) = near_roads.find(|(line, w)| line.distance_to_point(wposf) < *w as f32 * 2.0) { - let dir = Dir::from_vec2((line.start - line.end).as_()); + let dir = Dir2::from_vec2((line.start - line.end).as_()); Some(self.kind.block(col, wpos.with_z(z), dir)) } else { None diff --git a/world/src/site/plot/savannah_hut.rs b/world/src/site/plot/savannah_hut.rs index d786dba577..ad793b9747 100644 --- a/world/src/site/plot/savannah_hut.rs +++ b/world/src/site/plot/savannah_hut.rs @@ -255,7 +255,7 @@ impl Structure for SavannahHut { // draws a random index let random_index = (RandomField::new(0).get(center.with_z(base)) % 4) as usize; // add bed at random diagonal - let dir = *Dir::ALL.get(random_index).unwrap(); + let dir = *Dir2::ALL.get(random_index).unwrap(); let diagonal = dir.diagonal(); let bed_pos = center + diagonal * (length - 9); painter.bed_savannah(bed_pos.with_z(base - 2), dir); diff --git a/world/src/site/plot/tavern.rs b/world/src/site/plot/tavern.rs index 37c2ec9285..22d172494c 100644 --- a/world/src/site/plot/tavern.rs +++ b/world/src/site/plot/tavern.rs @@ -5,6 +5,7 @@ use common::{ lottery::Lottery, store::{Id, Store}, terrain::{BlockKind, SpriteCfg, SpriteKind}, + util::Dir3, }; use enum_map::EnumMap; use enumset::EnumSet; @@ -18,7 +19,7 @@ use vek::*; use crate::{ IndexRef, Land, - site::{Dir, Fill, Site, Structure, generation::PrimitiveTransform, namegen, util::Dir3}, + site::{Dir2, Fill, Site, Structure, generation::PrimitiveTransform, namegen}, util::RandomField, }; @@ -31,13 +32,13 @@ pub struct Wall { top_alt: i32, from: Neighbor, to: Neighbor, - to_dir: Dir, + to_dir: Dir2, door: Option<(i32, i32)>, } impl Wall { pub fn door_pos(&self) -> Option> { - let wall_dir = Dir::from_vec2(self.end - self.start); + let wall_dir = Dir2::from_vec2(self.end - self.start); self.door.map(|(door_min, door_max)| { (self.start.as_() + wall_dir.to_vec2().as_() * (door_min + door_max) as f32 / 2.0 + 0.5) @@ -46,7 +47,7 @@ impl Wall { } pub fn door_bounds(&self) -> Option> { - let wall_dir = Dir::from_vec2(self.end - self.start); + let wall_dir = Dir2::from_vec2(self.end - self.start); self.door.map(|(door_min, door_max)| { Aabr { @@ -61,9 +62,9 @@ impl Wall { #[derive(Copy, Clone)] enum RoofStyle { Flat, - FlatBars { dir: Dir }, - LeanTo { dir: Dir, max_z: i32 }, - Gable { dir: Dir, max_z: i32 }, + FlatBars { dir: Dir2 }, + LeanTo { dir: Dir2, max_z: i32 }, + Gable { dir: Dir2, max_z: i32 }, Hip { max_z: i32 }, Floor, } @@ -72,7 +73,7 @@ struct Roof { bounds: Aabr, min_z: i32, style: RoofStyle, - stairs: Option<(Aabb, Dir)>, + stairs: Option<(Aabb, Dir2)>, } #[derive(Clone, Copy, EnumIter, enum_map::Enum)] @@ -217,7 +218,7 @@ pub enum Detail { }, Table { pos: Vec2, - chairs: EnumSet, + chairs: EnumSet, }, Stage { aabr: Aabr, @@ -229,7 +230,7 @@ pub struct Room { pub bounds: Aabb, kind: RoomKind, // stairs: Option>, - walls: EnumMap>>, + walls: EnumMap>>, floors: Vec>, roofs: Vec>, detail_areas: Vec>, @@ -283,7 +284,7 @@ impl Tavern { rng: &mut impl RngExt, site: &Site, door_tile: Vec2, - door_dir: Dir, + door_dir: Dir2, tile_aabr: Aabr, alt: Option, ) -> Self { @@ -324,7 +325,7 @@ impl Tavern { fn place_side_room( room: RoomKind, max_bounds: Aabr, - in_dir: Dir, + in_dir: Dir2, in_pos: Vec2, rng: &mut impl RngExt, ) -> Option> { @@ -377,7 +378,7 @@ impl Tavern { max_bounds.size().h, ); let target_size = Vec2::new(size_x, size_y); - let dir = Dir::choose(rng); + let dir = Dir2::choose(rng); let orth = *[dir.orthogonal(), dir.orthogonal().opposite()] .choose(rng) .unwrap(); @@ -412,7 +413,7 @@ impl Tavern { struct RoomMeta { id: Id, - free_walls: EnumSet, + free_walls: EnumSet, can_add_basement: bool, } @@ -460,7 +461,7 @@ impl Tavern { room_metas.push(RoomMeta { id: entrance_id, - free_walls: Dir::iter().filter(|d| *d != door_dir).collect(), + free_walls: Dir2::iter().filter(|d| *d != door_dir).collect(), can_add_basement: false, }); @@ -493,7 +494,7 @@ impl Tavern { min_z: i32, max_z: i32, mut max_bounds: Aabr, - mut max_shrink_dir: impl FnMut(Dir) -> Option, + mut max_shrink_dir: impl FnMut(Dir2) -> Option, ) -> Option> { // Take other rooms into account when calculating `max_bounds`. We don't care // about this room if it's the originating room or at another @@ -506,7 +507,7 @@ impl Tavern { let intersection = bounds.intersection(max_bounds); if intersection.is_valid() { // Find the direction to shrink in that yields the highest area. - let bounds = Dir::iter() + let bounds = Dir2::iter() .filter(|dir| { dir.select_aabr(intersection) * dir.signum() < dir.select_aabr(max_bounds) * dir.signum() @@ -679,7 +680,7 @@ impl Tavern { room_metas.push(RoomMeta { id, - free_walls: Dir::iter().filter(|d| *d != -in_dir).collect(), + free_walls: Dir2::iter().filter(|d| *d != -in_dir).collect(), can_add_basement: !room_kind.basement_rooms().is_empty(), }); room_counts[room_kind] += 1; @@ -749,14 +750,14 @@ impl Tavern { let room_bounds = to_aabr(rooms[from_id].bounds); let mut skip = HashSet::new(); skip.insert(from_id); - let mut wall_ranges = EnumMap::>::default(); - for dir in Dir::iter() { + let mut wall_ranges = EnumMap::>::default(); + for dir in Dir2::iter() { let orth = dir.orthogonal(); let range = (orth.select(room_bounds.min), orth.select(room_bounds.max)); wall_ranges[dir].push(range); } // Split the wall into parts. - let mut split_range = |dir: Dir, min: i32, max: i32| { + let mut split_range = |dir: Dir2, min: i32, max: i32| { debug_assert!(min <= max); let mut new_ranges = Vec::new(); wall_ranges[dir].retain_mut(|(r_min, r_max)| { @@ -783,7 +784,7 @@ impl Tavern { }); wall_ranges[dir].extend(new_ranges); }; - for dir in Dir::iter() { + for dir in Dir2::iter() { let connected_walls = &mut rooms[from_id].walls[dir]; skip.extend( connected_walls @@ -822,7 +823,7 @@ impl Tavern { let p1 = n_room_bounds.projected_point(room_bounds.center()); let p0 = room_bounds.projected_point(p1); - let to_dir = Dir::from_vec2(p1 - p0); + let to_dir = Dir2::from_vec2(p1 - p0); let intersection = to_dir .extend_aabr(room_bounds, 1) @@ -897,7 +898,7 @@ impl Tavern { let mut roof_bounds = to_aabr(room.bounds); roof_bounds.min -= 2; roof_bounds.max += 2; - let mut dirs = Vec::from(Dir::ALL); + let mut dirs = Vec::from(Dir2::ALL); let mut over_rooms = vec![room_id]; let mut under_rooms = vec![]; @@ -947,17 +948,17 @@ impl Tavern { // If we just have gardens, we can use FlatBars style. if gardens == over_rooms.len() { - let ratio = Dir::X.select(roof_bounds.size()) as f32 - / Dir::Y.select(roof_bounds.size()) as f32; + let ratio = Dir2::X.select(roof_bounds.size()) as f32 + / Dir2::Y.select(roof_bounds.size()) as f32; valid_styles.extend([ - (5.0 * ratio, RoofStyle::FlatBars { dir: Dir::X }), - (5.0 / ratio, RoofStyle::FlatBars { dir: Dir::Y }), + (5.0 * ratio, RoofStyle::FlatBars { dir: Dir2::X }), + (5.0 / ratio, RoofStyle::FlatBars { dir: Dir2::Y }), ]); } // Find heights of possible adjecent rooms. let mut dir_zs = EnumMap::default(); - for dir in Dir::iter() { + for dir in Dir2::iter() { let orth = dir.orthogonal(); for room in rooms.values() { let room_aabr = to_aabr(room.bounds); @@ -973,7 +974,7 @@ impl Tavern { } } - for dir in [Dir::X, Dir::Y] { + for dir in [Dir2::X, Dir2::Y] { if dir_zs[dir.orthogonal()].is_none() && dir_zs[-dir.orthogonal()].is_none() { let max_z = roof_min_z + (dir.orthogonal().select(roof_bounds.size()) / 2 - 1).min(7); @@ -995,7 +996,7 @@ impl Tavern { } } - for dir in Dir::iter() { + for dir in Dir2::iter() { if let (Some(h), None) = (dir_zs[dir], dir_zs[-dir]) { for max_z in roof_min_z + 2..=h { valid_styles.push((1.0, RoofStyle::LeanTo { dir, max_z })) @@ -1003,7 +1004,7 @@ impl Tavern { } } - if Dir::iter().all(|d| dir_zs[d].is_none()) { + if Dir2::iter().all(|d| dir_zs[d].is_none()) { for max_z in roof_min_z + 3..=roof_min_z + 7 { valid_styles.push((0.8, RoofStyle::Hip { max_z })) } @@ -1044,7 +1045,7 @@ impl Tavern { let in_aabr = to_aabr(in_room_bounds); let to_aabr = to_aabr(to_room_bounds); - let valid_dirs = Dir::iter().filter(move |dir| { + let valid_dirs = Dir2::iter().filter(move |dir| { dir.select_aabr(in_aabr) == dir.select_aabr(max_bounds) || dir.select_aabr(to_aabr) == dir.select_aabr(max_bounds) }); @@ -1199,7 +1200,7 @@ impl Tavern { let room_aabr = to_aabr(room.bounds); let table = |pos: Vec2, aabr: Aabr| Detail::Table { pos, - chairs: Dir::iter() + chairs: Dir2::iter() .filter(|dir| aabr.contains_point(pos + dir.to_vec2())) .collect(), }; @@ -1217,7 +1218,7 @@ impl Tavern { let mut best = None; let mut best_score = 0; for (i, aabr) in room.detail_areas.iter().enumerate() { - let edges = Dir::iter() + let edges = Dir2::iter() .filter(|dir| dir.select_aabr(*aabr) == dir.select_aabr(room_aabr)) .count() as i32; let test_score = edges * aabr.size().product(); @@ -1242,7 +1243,7 @@ impl Tavern { let mut best = None; let mut best_score = 0; for (i, aabr) in room.detail_areas.iter().enumerate() { - let test_score = Dir::iter() + let test_score = Dir2::iter() .any(|dir| dir.select_aabr(*aabr) == dir.select_aabr(room_aabr)) as i32 * aabr.size().product(); @@ -1567,7 +1568,7 @@ impl Structure for Tavern { min: wall.start.with_z(wall.base_alt), max: wall.end.with_z(wall.top_alt), }; - let wall_dir = Dir::from_vec2(wall.end - wall.start); + let wall_dir = Dir2::from_vec2(wall.end - wall.start); match (wall.from.map(get_kind), wall.to.map(get_kind)) { (Some(RoomKind::Garden), None) | (None, Some(RoomKind::Garden)) => { let hgt = wall_aabb.min.z..=wall_aabb.max.z; @@ -1660,7 +1661,7 @@ impl Structure for Tavern { RoomKind::Garden => {}, RoomKind::Cellar => { for aabr in room.detail_areas.iter().copied() { - for dir in Dir::iter() + for dir in Dir2::iter() .filter(|dir| dir.select_aabr(aabr) == dir.select_aabr(room_aabr)) { let pos = dir @@ -1693,7 +1694,7 @@ impl Structure for Tavern { }, RoomKind::Stage => { for aabr in room.detail_areas.iter().copied() { - for dir in Dir::iter().filter(|dir| { + for dir in Dir2::iter().filter(|dir| { dir.select_aabr(aabr) == dir.select_aabr(room_aabr) && dir.rotated_cw().select_aabr(aabr) == dir.rotated_cw().select_aabr(room_aabr) @@ -1708,7 +1709,7 @@ impl Structure for Tavern { }, RoomKind::Bar | RoomKind::Seating => { for aabr in room.detail_areas.iter().copied() { - for dir in Dir::iter() + for dir in Dir2::iter() .filter(|dir| dir.select_aabr(aabr) == dir.select_aabr(room_aabr)) { let pos = dir @@ -1734,7 +1735,7 @@ impl Structure for Tavern { }, RoomKind::Entrance => { for aabr in room.detail_areas.iter() { - let edges = Dir::iter() + let edges = Dir2::iter() .filter(|dir| dir.select_aabr(*aabr) == dir.select_aabr(room_aabr)) .count(); let hanger_pos = if edges == 2 { @@ -1745,7 +1746,7 @@ impl Structure for Tavern { None }; - for dir in Dir::iter() + for dir in Dir2::iter() .filter(|dir| dir.select_aabr(*aabr) == dir.select_aabr(room_aabr)) { let pos = dir @@ -1765,7 +1766,7 @@ impl Structure for Tavern { for detail in room.details.iter() { match *detail { Detail::Bar { aabr } => { - for dir in Dir::iter() { + for dir in Dir2::iter() { let edge = dir.select_aabr(aabr); let rot_dir = if field.chance(aabr.center().with_z(0), 0.5) { dir.rotated_cw() @@ -1825,7 +1826,7 @@ impl Structure for Tavern { max: (aabr.max - 1).with_z(room.bounds.min.z), })) .fill(wall_fill.clone()); - for dir in Dir::iter().filter(|dir| { + for dir in Dir2::iter().filter(|dir| { dir.select_aabr(aabr) != dir.select_aabr(room_aabr) && dir.rotated_cw().select_aabr(aabr) != dir.rotated_cw().select_aabr(room_aabr) @@ -1838,7 +1839,7 @@ impl Structure for Tavern { .column(pos, room.bounds.min.z..=room.bounds.max.z) .fill(wall_detail_fill.clone()); - for dir in Dir::iter() { + for dir in Dir2::iter() { painter.rotated_sprite( pos.with_z(room.bounds.center().z + 1) + dir.to_vec2(), SpriteKind::WallSconce, diff --git a/world/src/site/plot/vampire_castle.rs b/world/src/site/plot/vampire_castle.rs index 35b45eb0ec..7dc2a5088b 100644 --- a/world/src/site/plot/vampire_castle.rs +++ b/world/src/site/plot/vampire_castle.rs @@ -1166,7 +1166,7 @@ impl Structure for VampireCastle { max: Vec2::new(center.x - castle_length - 2, center.y + 5) .with_z(entry_base + 15), }, - Dir::NegX, + Dir2::NegX, ) .fill(onewaydoor.clone()); // castle cellar @@ -1959,7 +1959,7 @@ impl Structure for VampireCastle { ), }, (2 * side_bldg_length) + 20, - Dir::X, + Dir2::X, ) .fill(brick.clone()); painter @@ -1979,7 +1979,7 @@ impl Structure for VampireCastle { ), }, (2 * side_bldg_length) + 20, - Dir::NegX, + Dir2::NegX, ) .fill(brick.clone()); } @@ -2039,7 +2039,7 @@ impl Structure for VampireCastle { max: Vec2::new(side_bldg_pos_1.x + 5, side_bldg_pos_1.y + entry_side + 1) .with_z(side_bldg_base_raw + (2 * castle_height) + 7), }, - Dir::NegY, + Dir2::NegY, ) .fill(key_door.clone()); painter diff --git a/world/src/site/tile.rs b/world/src/site/tile.rs index d68ebb88ec..507dca0da4 100644 --- a/world/src/site/tile.rs +++ b/world/src/site/tile.rs @@ -185,7 +185,7 @@ pub enum TileKind { Path { closest_pos: Vec2, path: Path }, Building, Castle, - Wall(Dir), + Wall(Dir2), Tower(RoofKind), Keep(KeepKind), Gate, @@ -286,7 +286,7 @@ pub enum HazardKind { pub enum KeepKind { Middle, Corner, - Wall(Dir), + Wall(Dir2), } #[derive(Copy, Clone, PartialEq, Eq)] diff --git a/world/src/site/util/mod.rs b/world/src/site/util/mod.rs index 3679879b49..44a31ee0bd 100644 --- a/world/src/site/util/mod.rs +++ b/world/src/site/util/mod.rs @@ -1,569 +1,2 @@ pub mod gradient; pub mod sprites; - -use std::ops::{Add, Sub}; - -use rand::RngExt; -use vek::*; - -/// A 2d cardinal direction. -#[derive(Debug, enum_map::Enum, strum::EnumIter, enumset::EnumSetType)] -pub enum Dir { - X, - Y, - NegX, - NegY, -} - -impl Dir { - pub const ALL: [Dir; 4] = [Dir::X, Dir::Y, Dir::NegX, Dir::NegY]; - - pub fn choose(rng: &mut impl RngExt) -> Dir { - match rng.random_range(0..4) { - 0 => Dir::X, - 1 => Dir::Y, - 2 => Dir::NegX, - _ => Dir::NegY, - } - } - - pub fn from_vec2(vec: Vec2) -> Dir { - if vec.x.abs() > vec.y.abs() { - if vec.x > 0 { Dir::X } else { Dir::NegX } - } else if vec.y > 0 { - Dir::Y - } else { - Dir::NegY - } - } - - pub fn to_dir3(self) -> Dir3 { Dir3::from_dir(self) } - - #[must_use] - pub fn opposite(self) -> Dir { - match self { - Dir::X => Dir::NegX, - Dir::NegX => Dir::X, - Dir::Y => Dir::NegY, - Dir::NegY => Dir::Y, - } - } - - /// Rotate the direction anti clock wise - #[must_use] - pub fn rotated_ccw(self) -> Dir { - match self { - Dir::X => Dir::Y, - Dir::NegX => Dir::NegY, - Dir::Y => Dir::NegX, - Dir::NegY => Dir::X, - } - } - - /// Rotate the direction clock wise - #[must_use] - pub fn rotated_cw(self) -> Dir { self.rotated_ccw().opposite() } - - #[must_use] - pub fn orthogonal(self) -> Dir { - match self { - Dir::X | Dir::NegX => Dir::Y, - Dir::Y | Dir::NegY => Dir::X, - } - } - - #[must_use] - pub fn abs(self) -> Dir { - match self { - Dir::X | Dir::NegX => Dir::X, - Dir::Y | Dir::NegY => Dir::Y, - } - } - - #[must_use] - pub fn signum(self) -> i32 { - match self { - Dir::X | Dir::Y => 1, - Dir::NegX | Dir::NegY => -1, - } - } - - pub fn to_vec2(self) -> Vec2 { - match self { - Dir::X => Vec2::new(1, 0), - Dir::NegX => Vec2::new(-1, 0), - Dir::Y => Vec2::new(0, 1), - Dir::NegY => Vec2::new(0, -1), - } - } - - /// The diagonal to the left of `self`, this is equal to this dir plus this - /// dir rotated counter clockwise. - pub fn diagonal(self) -> Vec2 { self.to_vec2() + self.rotated_ccw().to_vec2() } - - pub fn to_vec3(self) -> Vec3 { - match self { - Dir::X => Vec3::new(1, 0, 0), - Dir::NegX => Vec3::new(-1, 0, 0), - Dir::Y => Vec3::new(0, 1, 0), - Dir::NegY => Vec3::new(0, -1, 0), - } - } - - /// Create a vec2 where x is in the direction of `self`, and y is anti - /// clockwise of `self`. - pub fn vec2(self, x: i32, y: i32) -> Vec2 { - match self { - Dir::X => Vec2::new(x, y), - Dir::NegX => Vec2::new(-x, -y), - Dir::Y => Vec2::new(y, x), - Dir::NegY => Vec2::new(-y, -x), - } - } - - /// Create a vec2 where x is in the direction of `self`, and y is orthogonal - /// version of self. - pub fn vec2_abs(self, x: T, y: T) -> Vec2 { - match self { - Dir::X => Vec2::new(x, y), - Dir::NegX => Vec2::new(x, y), - Dir::Y => Vec2::new(y, x), - Dir::NegY => Vec2::new(y, x), - } - } - - /// Returns a 3x3 matrix that rotates Vec3(1, 0, 0) to the direction you get - /// in to_vec3. Inteded to be used with Primitive::Rotate. - /// - /// Example: - /// ``` - /// use vek::Vec3; - /// use veloren_world::site::util::Dir; - /// let dir = Dir::X; - /// - /// assert_eq!(dir.to_mat3() * Vec3::new(1, 0, 0), dir.to_vec3()); - /// - /// let dir = Dir::NegX; - /// - /// assert_eq!(dir.to_mat3() * Vec3::new(1, 0, 0), dir.to_vec3()); - /// - /// let dir = Dir::Y; - /// - /// assert_eq!(dir.to_mat3() * Vec3::new(1, 0, 0), dir.to_vec3()); - /// - /// let dir = Dir::NegY; - /// - /// assert_eq!(dir.to_mat3() * Vec3::new(1, 0, 0), dir.to_vec3()); - /// ``` - pub fn to_mat3(self) -> Mat3 { - match self { - Dir::X => Mat3::new(1, 0, 0, 0, 1, 0, 0, 0, 1), - Dir::NegX => Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1), - Dir::Y => Mat3::new(0, -1, 0, 1, 0, 0, 0, 0, 1), - Dir::NegY => Mat3::new(0, 1, 0, -1, 0, 0, 0, 0, 1), - } - } - - /// Creates a matrix that tranforms an upwards facing vector to this - /// direction. - pub fn from_z_mat3(self) -> Mat3 { - match self { - Dir::X => Mat3::new(0, 0, -1, 0, 1, 0, 1, 0, 0), - Dir::NegX => Mat3::new(0, 0, 1, 0, 1, 0, -1, 0, 0), - Dir::Y => Mat3::new(1, 0, 0, 0, 0, -1, 0, 1, 0), - Dir::NegY => Mat3::new(1, 0, 0, 0, 0, 1, 0, -1, 0), - } - } - - /// Translates this direction to worldspace as if it was relative to the - /// other direction - #[must_use] - pub fn relative_to(self, other: Dir) -> Dir { - match other { - Dir::X => self, - Dir::NegX => self.opposite(), - Dir::Y => self.rotated_cw(), - Dir::NegY => self.rotated_ccw(), - } - } - - /// Is this direction parallel to x - pub fn is_x(self) -> bool { matches!(self, Dir::X | Dir::NegX) } - - /// Is this direction parallel to y - pub fn is_y(self) -> bool { matches!(self, Dir::Y | Dir::NegY) } - - pub fn is_positive(self) -> bool { matches!(self, Dir::X | Dir::Y) } - - pub fn is_negative(self) -> bool { !self.is_positive() } - - /// Returns the component that the direction is parallell to - pub fn select(self, vec: impl Into>) -> i32 { - let vec = vec.into(); - match self { - Dir::X | Dir::NegX => vec.x, - Dir::Y | Dir::NegY => vec.y, - } - } - - /// Select one component the direction is parallel to from vec and select - /// the other component from other - pub fn select_with(self, vec: impl Into>, other: impl Into>) -> Vec2 { - let vec = vec.into(); - let other = other.into(); - match self { - Dir::X | Dir::NegX => Vec2::new(vec.x, other.y), - Dir::Y | Dir::NegY => Vec2::new(other.x, vec.y), - } - } - - /// Returns the side of an aabr that the direction is pointing to - pub fn select_aabr(self, aabr: Aabr) -> T { - match self { - Dir::X => aabr.max.x, - Dir::NegX => aabr.min.x, - Dir::Y => aabr.max.y, - Dir::NegY => aabr.min.y, - } - } - - /// Select one component from the side the direction is pointing to from - /// aabr and select the other component from other - pub fn select_aabr_with(self, aabr: Aabr, other: impl Into>) -> Vec2 { - let other = other.into(); - match self { - Dir::X => Vec2::new(aabr.max.x, other.y), - Dir::NegX => Vec2::new(aabr.min.x, other.y), - Dir::Y => Vec2::new(other.x, aabr.max.y), - Dir::NegY => Vec2::new(other.x, aabr.min.y), - } - } - - /// The equivelant sprite direction of the direction - pub fn sprite_ori(self) -> u8 { - match self { - Dir::X => 0, - Dir::Y => 2, - Dir::NegX => 4, - Dir::NegY => 6, - } - } - - /// Returns (Dir, rest) - /// - /// Returns None if `ori` isn't a valid sprite Ori. - pub fn from_sprite_ori(ori: u8) -> Option<(Dir, u8)> { - let dir = match ori / 2 { - 0 => Dir::X, - 1 => Dir::Y, - 2 => Dir::NegX, - 3 => Dir::NegY, - _ => return None, - }; - let rest = ori % 2; - - Some((dir, rest)) - } - - /// Legacy version of `sprite_ori`, so prefer using that over this. - pub fn sprite_ori_legacy(self) -> u8 { - match self { - Dir::X => 2, - Dir::NegX => 6, - Dir::Y => 4, - Dir::NegY => 0, - } - } - - pub fn split_aabr_offset(self, aabr: Aabr, offset: T) -> [Aabr; 2] - where - T: Copy + PartialOrd + Add + Sub, - { - match self { - Dir::X => aabr.split_at_x(aabr.min.x + offset), - Dir::Y => aabr.split_at_y(aabr.min.y + offset), - Dir::NegX => { - let res = aabr.split_at_x(aabr.max.x - offset); - [res[1], res[0]] - }, - Dir::NegY => { - let res = aabr.split_at_y(aabr.max.y - offset); - [res[1], res[0]] - }, - } - } - - pub fn trim_aabr(self, aabr: Aabr, amount: i32) -> Aabr { - (-self).extend_aabr(aabr, -amount) - } - - pub fn extend_aabr(self, aabr: Aabr, amount: i32) -> Aabr { - let offset = self.to_vec2() * amount; - match self { - _ if self.is_positive() => Aabr { - min: aabr.min, - max: aabr.max + offset, - }, - _ => Aabr { - min: aabr.min + offset, - max: aabr.max, - }, - } - } -} - -impl std::ops::Neg for Dir { - type Output = Dir; - - fn neg(self) -> Self::Output { self.opposite() } -} - -/// A 3d direction. -#[derive(Debug, enum_map::Enum, strum::EnumIter, enumset::EnumSetType)] -pub enum Dir3 { - X, - Y, - Z, - NegX, - NegY, - NegZ, -} - -impl Dir3 { - pub const ALL: [Dir; 4] = [Dir::X, Dir::Y, Dir::NegX, Dir::NegY]; - - pub fn choose(rng: &mut impl RngExt) -> Dir3 { - match rng.random_range(0..6) { - 0 => Dir3::X, - 1 => Dir3::Y, - 2 => Dir3::Z, - 3 => Dir3::NegX, - 4 => Dir3::NegY, - _ => Dir3::NegZ, - } - } - - pub fn from_dir(dir: Dir) -> Dir3 { - match dir { - Dir::X => Dir3::X, - Dir::Y => Dir3::Y, - Dir::NegX => Dir3::NegX, - Dir::NegY => Dir3::NegY, - } - } - - pub fn to_dir(self) -> Option { - match self { - Dir3::X => Some(Dir::X), - Dir3::Y => Some(Dir::Y), - Dir3::NegX => Some(Dir::NegX), - Dir3::NegY => Some(Dir::NegY), - _ => None, - } - } - - pub fn from_vec3(vec: Vec3) -> Dir3 { - if vec.x.abs() > vec.y.abs() && vec.x.abs() > vec.z.abs() { - if vec.x > 0 { Dir3::X } else { Dir3::NegX } - } else if vec.y.abs() > vec.z.abs() { - if vec.y > 0 { Dir3::Y } else { Dir3::NegY } - } else if vec.z > 0 { - Dir3::Z - } else { - Dir3::NegZ - } - } - - #[must_use] - pub fn opposite(self) -> Dir3 { - match self { - Dir3::X => Dir3::NegX, - Dir3::NegX => Dir3::X, - Dir3::Y => Dir3::NegY, - Dir3::NegY => Dir3::Y, - Dir3::Z => Dir3::NegZ, - Dir3::NegZ => Dir3::Z, - } - } - - /// Rotate counter clockwise around an axis by 90 degrees. - pub fn rotate_axis_ccw(self, axis: Dir3) -> Dir3 { - match axis { - Dir3::X | Dir3::NegX => match self { - Dir3::Y => Dir3::Z, - Dir3::NegY => Dir3::NegZ, - Dir3::Z => Dir3::NegY, - Dir3::NegZ => Dir3::Y, - x => x, - }, - Dir3::Y | Dir3::NegY => match self { - Dir3::X => Dir3::Z, - Dir3::NegX => Dir3::NegZ, - Dir3::Z => Dir3::NegX, - Dir3::NegZ => Dir3::X, - y => y, - }, - Dir3::Z | Dir3::NegZ => match self { - Dir3::X => Dir3::Y, - Dir3::NegX => Dir3::NegY, - Dir3::Y => Dir3::NegX, - Dir3::NegY => Dir3::X, - z => z, - }, - } - } - - /// Rotate clockwise around an axis by 90 degrees. - pub fn rotate_axis_cw(self, axis: Dir3) -> Dir3 { self.rotate_axis_ccw(axis).opposite() } - - /// Get a direction that is orthogonal to both directions, always a positive - /// direction. - pub fn cross(self, other: Dir3) -> Dir3 { - match (self, other) { - (Dir3::X | Dir3::NegX, Dir3::Y | Dir3::NegY) - | (Dir3::Y | Dir3::NegY, Dir3::X | Dir3::NegX) => Dir3::Z, - (Dir3::X | Dir3::NegX, Dir3::Z | Dir3::NegZ) - | (Dir3::Z | Dir3::NegZ, Dir3::X | Dir3::NegX) => Dir3::Y, - (Dir3::Z | Dir3::NegZ, Dir3::Y | Dir3::NegY) - | (Dir3::Y | Dir3::NegY, Dir3::Z | Dir3::NegZ) => Dir3::X, - (Dir3::X | Dir3::NegX, Dir3::X | Dir3::NegX) => Dir3::Y, - (Dir3::Y | Dir3::NegY, Dir3::Y | Dir3::NegY) => Dir3::X, - (Dir3::Z | Dir3::NegZ, Dir3::Z | Dir3::NegZ) => Dir3::Y, - } - } - - #[must_use] - pub fn abs(self) -> Dir3 { - match self { - Dir3::X | Dir3::NegX => Dir3::X, - Dir3::Y | Dir3::NegY => Dir3::Y, - Dir3::Z | Dir3::NegZ => Dir3::Z, - } - } - - #[must_use] - pub fn signum(self) -> i32 { - match self { - Dir3::X | Dir3::Y | Dir3::Z => 1, - Dir3::NegX | Dir3::NegY | Dir3::NegZ => -1, - } - } - - pub fn to_vec3(self) -> Vec3 { - match self { - Dir3::X => Vec3::new(1, 0, 0), - Dir3::NegX => Vec3::new(-1, 0, 0), - Dir3::Y => Vec3::new(0, 1, 0), - Dir3::NegY => Vec3::new(0, -1, 0), - Dir3::Z => Vec3::new(0, 0, 1), - Dir3::NegZ => Vec3::new(0, 0, -1), - } - } - - /// Is this direction parallel to x - pub fn is_x(self) -> bool { matches!(self, Dir3::X | Dir3::NegX) } - - /// Is this direction parallel to y - pub fn is_y(self) -> bool { matches!(self, Dir3::Y | Dir3::NegY) } - - /// Is this direction parallel to z - pub fn is_z(self) -> bool { matches!(self, Dir3::Z | Dir3::NegZ) } - - pub fn is_positive(self) -> bool { matches!(self, Dir3::X | Dir3::Y | Dir3::Z) } - - pub fn is_negative(self) -> bool { !self.is_positive() } - - /// Returns the component that the direction is parallell to - pub fn select(self, vec: impl Into>) -> i32 { - let vec = vec.into(); - match self { - Dir3::X | Dir3::NegX => vec.x, - Dir3::Y | Dir3::NegY => vec.y, - Dir3::Z | Dir3::NegZ => vec.z, - } - } - - /// Select one component the direction is parallel to from vec and select - /// the other components from other - pub fn select_with(self, vec: impl Into>, other: impl Into>) -> Vec3 { - let vec = vec.into(); - let other = other.into(); - match self { - Dir3::X | Dir3::NegX => Vec3::new(vec.x, other.y, other.z), - Dir3::Y | Dir3::NegY => Vec3::new(other.x, vec.y, other.z), - Dir3::Z | Dir3::NegZ => Vec3::new(other.x, other.y, vec.z), - } - } - - /// Returns the side of an aabb that the direction is pointing to - pub fn select_aabb(self, aabb: Aabb) -> T { - match self { - Dir3::X => aabb.max.x, - Dir3::NegX => aabb.min.x, - Dir3::Y => aabb.max.y, - Dir3::NegY => aabb.min.y, - Dir3::Z => aabb.max.z, - Dir3::NegZ => aabb.min.z, - } - } - - /// Select one component from the side the direction is pointing to from - /// aabr and select the other components from other - pub fn select_aabb_with(self, aabb: Aabb, other: impl Into>) -> Vec3 { - let other = other.into(); - match self { - Dir3::X => Vec3::new(aabb.max.x, other.y, other.z), - Dir3::NegX => Vec3::new(aabb.min.x, other.y, other.z), - Dir3::Y => Vec3::new(other.x, aabb.max.y, other.z), - Dir3::NegY => Vec3::new(other.x, aabb.min.y, other.z), - Dir3::Z => Vec3::new(other.x, other.y, aabb.max.z), - Dir3::NegZ => Vec3::new(other.x, other.y, aabb.min.z), - } - } - - pub fn split_aabb_offset(self, aabb: Aabb, offset: T) -> [Aabb; 2] - where - T: Copy + PartialOrd + Add + Sub, - { - match self { - Dir3::X => aabb.split_at_x(aabb.min.x + offset), - Dir3::NegX => { - let res = aabb.split_at_x(aabb.max.x - offset); - [res[1], res[0]] - }, - Dir3::Y => aabb.split_at_y(aabb.min.y + offset), - Dir3::NegY => { - let res = aabb.split_at_y(aabb.max.y - offset); - [res[1], res[0]] - }, - Dir3::Z => aabb.split_at_z(aabb.min.z + offset), - Dir3::NegZ => { - let res = aabb.split_at_z(aabb.max.z - offset); - [res[1], res[0]] - }, - } - } - - pub fn trim_aabb(self, aabb: Aabb, amount: i32) -> Aabb { - (-self).extend_aabb(aabb, -amount) - } - - pub fn extend_aabb(self, aabb: Aabb, amount: i32) -> Aabb { - let offset = self.to_vec3() * amount; - match self { - _ if self.is_positive() => Aabb { - min: aabb.min, - max: aabb.max + offset, - }, - _ => Aabb { - min: aabb.min + offset, - max: aabb.max, - }, - } - } -} -impl std::ops::Neg for Dir3 { - type Output = Dir3; - - fn neg(self) -> Self::Output { self.opposite() } -} diff --git a/world/src/site/util/sprites.rs b/world/src/site/util/sprites.rs index 74fdab5f7b..b15250a92a 100644 --- a/world/src/site/util/sprites.rs +++ b/world/src/site/util/sprites.rs @@ -1,12 +1,14 @@ use crate::site::{Fill, Painter}; -use super::Dir; -use common::terrain::{ - Block, SpriteKind, - sprite::{MirrorX, Ori}, +use common::{ + terrain::{ + Block, SpriteKind, + sprite::{MirrorX, Ori}, + }, + util::Dir2, }; use enum_map::EnumMap; -use strum::IntoEnumIterator; +use strum::IntoEnumIterator as _; use vek::*; /// A struct to make it easier to create sprites that tile on a 2d plane. Both @@ -17,10 +19,10 @@ pub struct Tileable2 { alt: i32, bounds: Aabr, center: Block, - side: EnumMap, + side: EnumMap, /// The corner selected is `Dir::diagonal()`. - corner: EnumMap, - rotation: Dir, + corner: EnumMap, + rotation: Dir2, } impl Tileable2 { @@ -31,7 +33,7 @@ impl Tileable2 { center: Block::empty(), side: EnumMap::from_fn(|_| Block::empty()), corner: EnumMap::from_fn(|_| Block::empty()), - rotation: Dir::X, + rotation: Dir2::X, } } @@ -50,7 +52,7 @@ impl Tileable2 { .with_corner_sprite(corner) } - pub fn two_by(len: i32, pos: Vec3, dir: Dir) -> Self { + pub fn two_by(len: i32, pos: Vec3, dir: Dir2) -> Self { Self::empty() .with_rotation(dir) .with_center_size(pos, Vec2::new(len, 2)) @@ -103,12 +105,12 @@ impl Tileable2 { self } - pub fn with_side_dir(mut self, dir: Dir, sprite: SpriteKind) -> Self { + pub fn with_side_dir(mut self, dir: Dir2, sprite: SpriteKind) -> Self { self.side[dir] = self.side[dir].with_sprite(sprite); self } - pub fn with_side_axis(self, axis: Dir, sprite: SpriteKind) -> Self { + pub fn with_side_axis(self, axis: Dir2, sprite: SpriteKind) -> Self { self.with_side_dir(axis, sprite) .with_side_dir(-axis, sprite) } @@ -121,28 +123,28 @@ impl Tileable2 { } /// The corner selected is `Dir::diagonal()`. - pub fn with_corner_dir(mut self, dir: Dir, block: Block) -> Self { + pub fn with_corner_dir(mut self, dir: Dir2, block: Block) -> Self { self.corner[dir] = block; self } /// The corner selected is `Dir::diagonal()`. - pub fn with_corner_sprite_dir(mut self, dir: Dir, sprite: SpriteKind) -> Self { + pub fn with_corner_sprite_dir(mut self, dir: Dir2, sprite: SpriteKind) -> Self { self.corner[dir] = self.corner[dir].with_sprite(sprite); self } - pub fn with_corner_side(self, axis: Dir, sprite: Block) -> Self { + pub fn with_corner_side(self, axis: Dir2, sprite: Block) -> Self { self.with_corner_dir(axis, sprite) .with_corner_dir(axis.rotated_ccw(), sprite) } - pub fn with_corner_sprite_side(self, axis: Dir, sprite: SpriteKind) -> Self { + pub fn with_corner_sprite_side(self, axis: Dir2, sprite: SpriteKind) -> Self { self.with_corner_sprite_dir(axis, sprite) .with_corner_sprite_dir(axis.rotated_ccw(), sprite) } - pub fn with_rotation(mut self, dir: Dir) -> Self { + pub fn with_rotation(mut self, dir: Dir2) -> Self { self.rotation = dir; self } @@ -153,9 +155,9 @@ impl Tileable2 { pub fn center(&self) -> Block { self.center } - pub fn side(&self, dir: Dir) -> Block { self.side[dir.relative_to(self.rotation)] } + pub fn side(&self, dir: Dir2) -> Block { self.side[dir.relative_to(self.rotation)] } - pub fn corner(&self, dir: Dir) -> Block { self.corner[dir.relative_to(self.rotation)] } + pub fn corner(&self, dir: Dir2) -> Block { self.corner[dir.relative_to(self.rotation)] } } fn single_block(painter: &Painter, pos: Vec3, block: Block) { @@ -169,10 +171,10 @@ fn single_block(painter: &Painter, pos: Vec3, block: Block) { /// Only applies changes if the block can have the attributes `Ori` and /// `MirrorX`. -fn ori_mirror(mut block: Block, dir: Dir, x: bool, y: bool) -> Block { +fn ori_mirror(mut block: Block, dir: Dir2, x: bool, y: bool) -> Block { let dir_res = block.get_attr::().map(|old_ori| { let (old_dir, offset) = - Dir::from_sprite_ori(old_ori.0).expect("We got this from the Ori attr"); + Dir2::from_sprite_ori(old_ori.0).expect("We got this from the Ori attr"); let new_dir = dir.relative_to(old_dir); Ori(new_dir.sprite_ori() + offset) }); @@ -197,26 +199,26 @@ fn ori_mirror(mut block: Block, dir: Dir, x: bool, y: bool) -> Block { } pub trait PainterSpriteExt { - fn lanternpost_wood(&self, pos: Vec3, dir: Dir); + fn lanternpost_wood(&self, pos: Vec3, dir: Dir2); fn bed( &self, pos: Vec3, - dir: Dir, + dir: Dir2, head: SpriteKind, middle: SpriteKind, tail: SpriteKind, ) -> Aabr { let bed = Tileable2::two_by(3, pos, dir) - .with_corner_sprite_side(Dir::Y, head) - .with_corner_sprite_side(Dir::NegY, tail) + .with_corner_sprite_side(Dir2::Y, head) + .with_corner_sprite_side(Dir2::NegY, tail) .with_side_sprite(middle); self.tileable2(&bed); bed.bounds() } - fn bed_wood_woodland(&self, pos: Vec3, dir: Dir) -> Aabr { + fn bed_wood_woodland(&self, pos: Vec3, dir: Dir2) -> Aabr { self.bed( pos, dir, @@ -226,7 +228,7 @@ pub trait PainterSpriteExt { ) } - fn bed_desert(&self, pos: Vec3, dir: Dir) -> Aabr { + fn bed_desert(&self, pos: Vec3, dir: Dir2) -> Aabr { self.bed( pos, dir, @@ -236,7 +238,7 @@ pub trait PainterSpriteExt { ) } - fn bed_cliff(&self, pos: Vec3, dir: Dir) -> Aabr { + fn bed_cliff(&self, pos: Vec3, dir: Dir2) -> Aabr { self.bed( pos, dir, @@ -246,7 +248,7 @@ pub trait PainterSpriteExt { ) } - fn bed_savannah(&self, pos: Vec3, dir: Dir) -> Aabr { + fn bed_savannah(&self, pos: Vec3, dir: Dir2) -> Aabr { self.bed( pos, dir, @@ -256,7 +258,7 @@ pub trait PainterSpriteExt { ) } - fn bed_coastal(&self, pos: Vec3, dir: Dir) -> Aabr { + fn bed_coastal(&self, pos: Vec3, dir: Dir2) -> Aabr { self.bed( pos, dir, @@ -266,7 +268,7 @@ pub trait PainterSpriteExt { ) } - fn table_wood_fancy_woodland(&self, pos: Vec3, axis: Dir) -> Aabr { + fn table_wood_fancy_woodland(&self, pos: Vec3, axis: Dir2) -> Aabr { let table = Tileable2::two_by(3, pos, axis) .with_side_sprite(SpriteKind::TableWoodFancyWoodlandBody) .with_corner_sprite(SpriteKind::TableWoodFancyWoodlandCorner); @@ -285,14 +287,14 @@ pub trait PainterSpriteExt { fn tileable1( &self, pos: Vec3, - dir: Dir, + dir: Dir2, size: i32, middle_sprite: SpriteKind, side_sprite: SpriteKind, ); /// This will be placed with the "right side" looking forward at `pos`. - fn mirrored2(&self, pos: Vec3, dir: Dir, sprite: SpriteKind) { + fn mirrored2(&self, pos: Vec3, dir: Dir2, sprite: SpriteKind) { self.tileable1(pos, dir, 2, SpriteKind::Empty, sprite); } @@ -303,7 +305,7 @@ pub trait PainterSpriteExt { } impl PainterSpriteExt for Painter { - fn lanternpost_wood(&self, pos: Vec3, dir: Dir) { + fn lanternpost_wood(&self, pos: Vec3, dir: Dir2) { let sprite_ori = dir.sprite_ori(); self.rotated_sprite(pos, SpriteKind::LanternpostWoodBase, sprite_ori); self.column(pos.xy(), pos.z + 1..pos.z + 4).clear(); @@ -320,7 +322,7 @@ impl PainterSpriteExt for Painter { } fn chairs_around(&self, chair: SpriteKind, spacing: usize, bounds: Aabr, alt: i32) { - for dir in Dir::iter() { + for dir in Dir2::iter() { let s = dir.orthogonal().select(bounds.size()); // We skip small sides if s <= 2 && dir.select(bounds.size()) > s { @@ -349,7 +351,7 @@ impl PainterSpriteExt for Painter { fn tileable1( &self, pos: Vec3, - dir: Dir, + dir: Dir2, size: i32, middle_sprite: SpriteKind, side_sprite: SpriteKind, @@ -417,13 +419,13 @@ impl PainterSpriteExt for Painter { } if size.h > 2 { - let rot = Dir::NegY; + let rot = Dir2::NegY; self.aabb(Aabb { min: Vec3::new(bounds.min.x, bounds.min.y + 1, alt), max: Vec3::new(bounds.min.x, bounds.max.y - 1, alt) + 1, }) .fill(Fill::Sprite(ori_mirror( - tileable.side(Dir::NegX), + tileable.side(Dir2::NegX), rot, false, false, @@ -434,7 +436,7 @@ impl PainterSpriteExt for Painter { max: Vec3::new(bounds.max.x, bounds.max.y - 1, alt) + 1, }) .fill(Fill::Sprite(ori_mirror( - tileable.side(Dir::X), + tileable.side(Dir2::X), rot, false, // Mirror is applied before rotation so we mirror Y @@ -443,13 +445,13 @@ impl PainterSpriteExt for Painter { } if size.w > 2 { - let rot = Dir::X; + let rot = Dir2::X; self.aabb(Aabb { min: Vec3::new(bounds.min.x + 1, bounds.min.y, alt), max: Vec3::new(bounds.max.x - 1, bounds.min.y, alt) + 1, }) .fill(Fill::Sprite(ori_mirror( - tileable.side(Dir::NegY), + tileable.side(Dir2::NegY), rot, false, false, @@ -460,7 +462,7 @@ impl PainterSpriteExt for Painter { max: Vec3::new(bounds.max.x - 1, bounds.max.y, alt) + 1, }) .fill(Fill::Sprite(ori_mirror( - tileable.side(Dir::Y), + tileable.side(Dir2::Y), rot, false, true, @@ -473,7 +475,7 @@ impl PainterSpriteExt for Painter { self, bounds.min.with_z(alt), ori_mirror( - tileable.corner(Dir::NegX), + tileable.corner(Dir2::NegX), rot, rot.is_negative(), orth.is_negative(), @@ -483,7 +485,7 @@ impl PainterSpriteExt for Painter { self, Vec3::new(bounds.max.x, bounds.min.y, alt), ori_mirror( - tileable.corner(Dir::NegY), + tileable.corner(Dir2::NegY), rot, orth.is_positive(), rot.is_negative(), @@ -493,7 +495,7 @@ impl PainterSpriteExt for Painter { self, Vec3::new(bounds.min.x, bounds.max.y, alt), ori_mirror( - tileable.corner(Dir::Y), + tileable.corner(Dir2::Y), rot, orth.is_negative(), rot.is_positive(), @@ -503,7 +505,7 @@ impl PainterSpriteExt for Painter { self, bounds.max.with_z(alt), ori_mirror( - tileable.corner(Dir::X), + tileable.corner(Dir2::X), rot, rot.is_positive(), orth.is_positive(),