Merge branch 'isse/sprite-adjecency' into 'master'

Add a sprite adjecency requirement for sprites that's checked on block changes

See merge request veloren/veloren!5262
This commit is contained in:
Isse 2026-04-01 11:19:24 +02:00
commit af7e38c58e
39 changed files with 1246 additions and 1048 deletions

View file

@ -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

1
Cargo.lock generated
View file

@ -8616,6 +8616,7 @@ dependencies = [
"csv",
"dot_vox",
"enum-map",
"enumset",
"fxhash",
"hashbrown 0.16.0",
"indexmap 2.12.0",

View file

@ -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 = [

View file

@ -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 }

View file

@ -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<i32> {
let dir = crate::util::Dir2::from_sprite_ori(
self.get_attr::<sprite::Ori>().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<f32> {
self.get_attr::<sprite::Ori>()
.ok()

View file

@ -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<Self> {
let sprite = block.get_sprite()?;
Some(match sprite {
$($(SpriteKind::$sprite_name => Self::$sprite_name(categories::$category_name::from_block(block)),)*)*
})
}
}
const _: () = {

View file

@ -97,6 +97,10 @@ impl StructureSprite {
pub fn apply_to_block(self, block: Block) -> Result<Block, Block> {
self.0.apply_to_block(block)
}
pub fn from_block(block: &Block) -> Option<Self> {
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<i32>]),
/// Considers sprite rotation
AnySolid(&'static [Vec3<i32>]),
}
impl SpriteKind {
#[inline]
//#[tweak_fn]
@ -901,6 +913,31 @@ impl SpriteKind {
})
}
pub const fn adjecency_requirement(&self) -> Option<SpriteAdjecencyRequirement> {
use SpriteAdjecencyRequirement::*;
const NEG_X: Vec3<i32> = Vec3::new(-1, 0, 0);
const Z: Vec3<i32> = Vec3::new(0, 0, 1);
const NEG_Z: Vec3<i32> = 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<f32>,

View file

@ -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<i32>) -> 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<i32> {
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<i32> { self.to_vec2() + self.rotated_ccw().to_vec2() }
pub fn to_vec3(self) -> Vec3<i32> {
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<i32> {
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<T>(self, x: T, y: T) -> Vec2<T> {
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<i32> {
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<i32> {
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<Vec2<i32>>) -> 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<Vec2<i32>>, other: impl Into<Vec2<i32>>) -> Vec2<i32> {
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<T>(self, aabr: Aabr<T>) -> 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<T>(self, aabr: Aabr<T>, other: impl Into<Vec2<T>>) -> Vec2<T> {
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<T>(self, aabr: Aabr<T>, offset: T) -> [Aabr<T>; 2]
where
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
{
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<i32>, amount: i32) -> Aabr<i32> {
(-self).extend_aabr(aabr, -amount)
}
pub fn extend_aabr(self, aabr: Aabr<i32>, amount: i32) -> Aabr<i32> {
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<Dir2> {
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<i32>) -> 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<i32> {
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<Vec3<i32>>) -> 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<Vec3<i32>>, other: impl Into<Vec3<i32>>) -> Vec3<i32> {
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<T>(self, aabb: Aabb<T>) -> 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<T>(self, aabb: Aabb<T>, other: impl Into<Vec3<T>>) -> Vec3<T> {
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<T>(self, aabb: Aabb<T>, offset: T) -> [Aabb<T>; 2]
where
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
{
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<i32>, amount: i32) -> Aabb<i32> {
(-self).extend_aabb(aabb, -amount)
}
pub fn extend_aabb(self, aabb: Aabb<i32>, amount: i32) -> Aabb<i32> {
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() }
}

View file

@ -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;

View file

@ -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::<Vec3<i32>>::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<i32>| {
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<i32>| 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::<Vec<_>>();
// If the sprite is bonkable, bonk it.
let bonk_event_bus = self.ecs.write_resource::<EventBus<BonkEvent>>();
let mut bonk_emitter = bonk_event_bus.emitter();
let mut block_change = self.ecs.write_resource::<BlockChange>();
for (wpos, block) in indirectly_modified {
if block.is_bonkable() {
bonk_emitter.emit(BonkEvent {
pos: wpos.as_::<f32>() + 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::<TerrainChanges>().modified_blocks = modified_blocks;
}

View file

@ -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<site::Plot>) -> impl Action<Def
.flat_map(|room| {
room.details.iter().filter_map(|detail| match_some!(detail,
tavern::Detail::Bar { aabr } => {
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();

View file

@ -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 }

View file

@ -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<i32>,
inset: i32,
dir: Dir,
dir: Dir2,
},
Gable {
aabb: Aabb<i32>,
inset: i32,
// X axis parallel or Y axis parallel
dir: Dir,
dir: Dir2,
},
Cylinder(Aabb<i32>),
Cone(Aabb<i32>),
@ -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<i32>, dir: Dir) -> PrimitiveRef<'_> {
pub fn horizontal_cylinder(&self, aabb: Aabb<i32>, 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<i32>, inset: i32, dir: Dir) -> PrimitiveRef<'_> {
pub fn ramp_inset(&self, aabb: Aabb<i32>, inset: i32, dir: Dir2) -> PrimitiveRef<'_> {
let aabb = aabb.made_valid();
self.prim(Primitive::Ramp { aabb, inset, dir })
}
pub fn ramp(&self, aabb: Aabb<i32>, dir: Dir) -> PrimitiveRef<'_> {
pub fn ramp(&self, aabb: Aabb<i32>, 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<i32>, inset: i32, dir: Dir) -> PrimitiveRef<'_> {
pub fn gable(&self, aabb: Aabb<i32>, 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<i32>, dir: Dir) -> PrimitiveRef<'_> {
pub fn vault(&self, aabb: Aabb<i32>, 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<i32>,
thickness: i32,
start_dir: Dir,
start_dir: Dir2,
) -> PrimitiveRef<'_> {
let mut forward = start_dir;
let mut z = aabb.max.z - 1;

View file

@ -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)

View file

@ -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<i32>, Dir)>,
outer_structures: Vec<(AdletStructure, Vec2<i32>, Dir2)>,
tunnel_length: i32,
cavern_center: Vec2<i32>,
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<i32>, Dir)>,
cavern_structures: Vec<(AdletStructure, Vec2<i32>, 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<i32>, Dir)>::new();
let mut outer_structures = Vec::<(AdletStructure, Vec2<i32>, 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<i32>, Dir)>::new();
let mut cavern_structures = Vec::<(AdletStructure, Vec2<i32>, Dir2)>::new();
fn valid_cavern_struct_pos(
structures: &[(AdletStructure, Vec2<i32>, Dir)],
structures: &[(AdletStructure, Vec2<i32>, Dir2)],
structure: AdletStructure,
rpos: Vec2<i32>,
) -> 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<f32> = 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),
}
};

View file

@ -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),

View file

@ -144,7 +144,7 @@ fn render_short(bridge: &Bridge, painter: &Painter) {
// let outset = 7;
let up_ramp = |point: Vec3<i32>, dir: Dir, side_len: i32| {
let up_ramp = |point: Vec3<i32>, 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<i32>, dir: Dir, zmin, zmax| {
let ramp_in_aabr = |aabr: Aabr<i32>, 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<i32>,
pub(crate) end: Vec3<i32>,
pub(crate) dir: Dir,
pub(crate) dir: Dir2,
center: Vec3<i32>,
kind: BridgeKind,
biome: BiomeKind,
@ -918,7 +918,7 @@ impl Bridge {
let min_water_dist = 5;
let find_edge = |start: Vec2<i32>, end: Vec2<i32>| {
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())

View file

@ -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
{

View file

@ -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(

View file

@ -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();

View file

@ -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();

View file

@ -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());
}

View file

@ -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

View file

@ -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<i32>,
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<i32>,
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);

View file

@ -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<i32>,
/// 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<i32>,
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;

View file

@ -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<Vec3<i32>>,
// 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<i32>, Dir)>,
structure_locations: Vec<(GnarlingStructure, Vec3<i32>, Dir2)>,
tunnels: Tunnels,
}
@ -168,7 +168,7 @@ impl GnarlingFortification {
];
let desired_structures = wall_radius.pow(2) / 100;
let mut structure_locations = Vec::<(GnarlingStructure, Vec3<i32>, Dir)>::new();
let mut structure_locations = Vec::<(GnarlingStructure, Vec3<i32>, 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<i32>,
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,
),
);

View file

@ -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();

View file

@ -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<u8>,
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),

View file

@ -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)

View file

@ -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(

View file

@ -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 {

View file

@ -20,9 +20,9 @@ impl CornerMeta {
pub struct Plaza {
pub aabr: Aabr<i32>,
pub kind: RoadKind,
corner_meta: EnumMap<Dir, CornerMeta>,
corner_meta: EnumMap<Dir2, CornerMeta>,
pub hard_alt: Option<i32>,
dir: Dir,
dir: Dir2,
}
impl Plaza {
@ -51,7 +51,7 @@ impl Plaza {
let center = get_corner_meta(iaabr.center());
let corner_meta: EnumMap<Dir, CornerMeta> = Dir::iter()
let corner_meta: EnumMap<Dir2, CornerMeta> = 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) {

View file

@ -32,7 +32,7 @@ pub struct RoadKind {
impl RoadKind {
/// Intended to be placed at `riverless_alt`.
pub fn place_light(&self, pos: Vec3<i32>, dir: Dir, painter: &Painter) {
pub fn place_light(&self, pos: Vec3<i32>, 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<i32>, dir: Dir) -> Block {
pub fn block(&self, col: &ColumnSample, wpos: Vec3<i32>, 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> = Dir::iter()
let available_dirs: EnumSet<Dir2> = 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

View file

@ -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);

View file

@ -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<Vec3<f32>> {
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<Aabr<i32>> {
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<i32>,
min_z: i32,
style: RoofStyle,
stairs: Option<(Aabb<i32>, Dir)>,
stairs: Option<(Aabb<i32>, Dir2)>,
}
#[derive(Clone, Copy, EnumIter, enum_map::Enum)]
@ -217,7 +218,7 @@ pub enum Detail {
},
Table {
pos: Vec2<i32>,
chairs: EnumSet<Dir>,
chairs: EnumSet<Dir2>,
},
Stage {
aabr: Aabr<i32>,
@ -229,7 +230,7 @@ pub struct Room {
pub bounds: Aabb<i32>,
kind: RoomKind,
// stairs: Option<Id<Stairs>>,
walls: EnumMap<Dir, Vec<Id<Wall>>>,
walls: EnumMap<Dir2, Vec<Id<Wall>>>,
floors: Vec<Id<Roof>>,
roofs: Vec<Id<Roof>>,
detail_areas: Vec<Aabr<i32>>,
@ -283,7 +284,7 @@ impl Tavern {
rng: &mut impl RngExt,
site: &Site,
door_tile: Vec2<i32>,
door_dir: Dir,
door_dir: Dir2,
tile_aabr: Aabr<i32>,
alt: Option<i32>,
) -> Self {
@ -324,7 +325,7 @@ impl Tavern {
fn place_side_room(
room: RoomKind,
max_bounds: Aabr<i32>,
in_dir: Dir,
in_dir: Dir2,
in_pos: Vec2<i32>,
rng: &mut impl RngExt,
) -> Option<Aabr<i32>> {
@ -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<Room>,
free_walls: EnumSet<Dir>,
free_walls: EnumSet<Dir2>,
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<i32>,
mut max_shrink_dir: impl FnMut(Dir) -> Option<i32>,
mut max_shrink_dir: impl FnMut(Dir2) -> Option<i32>,
) -> Option<Aabr<i32>> {
// 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::<Dir, Vec<_>>::default();
for dir in Dir::iter() {
let mut wall_ranges = EnumMap::<Dir2, Vec<_>>::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<i32>, aabr: Aabr<i32>| 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,

View file

@ -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

View file

@ -185,7 +185,7 @@ pub enum TileKind {
Path { closest_pos: Vec2<f32>, 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)]

View file

@ -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<i32>) -> 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<i32> {
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<i32> { self.to_vec2() + self.rotated_ccw().to_vec2() }
pub fn to_vec3(self) -> Vec3<i32> {
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<i32> {
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<T>(self, x: T, y: T) -> Vec2<T> {
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<i32> {
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<i32> {
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<Vec2<i32>>) -> 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<Vec2<i32>>, other: impl Into<Vec2<i32>>) -> Vec2<i32> {
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<T>(self, aabr: Aabr<T>) -> 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<T>(self, aabr: Aabr<T>, other: impl Into<Vec2<T>>) -> Vec2<T> {
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<T>(self, aabr: Aabr<T>, offset: T) -> [Aabr<T>; 2]
where
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
{
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<i32>, amount: i32) -> Aabr<i32> {
(-self).extend_aabr(aabr, -amount)
}
pub fn extend_aabr(self, aabr: Aabr<i32>, amount: i32) -> Aabr<i32> {
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<Dir> {
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<i32>) -> 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<i32> {
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<Vec3<i32>>) -> 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<Vec3<i32>>, other: impl Into<Vec3<i32>>) -> Vec3<i32> {
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<T>(self, aabb: Aabb<T>) -> 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<T>(self, aabb: Aabb<T>, other: impl Into<Vec3<T>>) -> Vec3<T> {
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<T>(self, aabb: Aabb<T>, offset: T) -> [Aabb<T>; 2]
where
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
{
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<i32>, amount: i32) -> Aabb<i32> {
(-self).extend_aabb(aabb, -amount)
}
pub fn extend_aabb(self, aabb: Aabb<i32>, amount: i32) -> Aabb<i32> {
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() }
}

View file

@ -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<i32>,
center: Block,
side: EnumMap<Dir, Block>,
side: EnumMap<Dir2, Block>,
/// The corner selected is `Dir::diagonal()`.
corner: EnumMap<Dir, Block>,
rotation: Dir,
corner: EnumMap<Dir2, Block>,
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<i32>, dir: Dir) -> Self {
pub fn two_by(len: i32, pos: Vec3<i32>, 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<i32>, block: Block) {
@ -169,10 +171,10 @@ fn single_block(painter: &Painter, pos: Vec3<i32>, 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::<Ori>().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<i32>, dir: Dir);
fn lanternpost_wood(&self, pos: Vec3<i32>, dir: Dir2);
fn bed(
&self,
pos: Vec3<i32>,
dir: Dir,
dir: Dir2,
head: SpriteKind,
middle: SpriteKind,
tail: SpriteKind,
) -> Aabr<i32> {
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<i32>, dir: Dir) -> Aabr<i32> {
fn bed_wood_woodland(&self, pos: Vec3<i32>, dir: Dir2) -> Aabr<i32> {
self.bed(
pos,
dir,
@ -226,7 +228,7 @@ pub trait PainterSpriteExt {
)
}
fn bed_desert(&self, pos: Vec3<i32>, dir: Dir) -> Aabr<i32> {
fn bed_desert(&self, pos: Vec3<i32>, dir: Dir2) -> Aabr<i32> {
self.bed(
pos,
dir,
@ -236,7 +238,7 @@ pub trait PainterSpriteExt {
)
}
fn bed_cliff(&self, pos: Vec3<i32>, dir: Dir) -> Aabr<i32> {
fn bed_cliff(&self, pos: Vec3<i32>, dir: Dir2) -> Aabr<i32> {
self.bed(
pos,
dir,
@ -246,7 +248,7 @@ pub trait PainterSpriteExt {
)
}
fn bed_savannah(&self, pos: Vec3<i32>, dir: Dir) -> Aabr<i32> {
fn bed_savannah(&self, pos: Vec3<i32>, dir: Dir2) -> Aabr<i32> {
self.bed(
pos,
dir,
@ -256,7 +258,7 @@ pub trait PainterSpriteExt {
)
}
fn bed_coastal(&self, pos: Vec3<i32>, dir: Dir) -> Aabr<i32> {
fn bed_coastal(&self, pos: Vec3<i32>, dir: Dir2) -> Aabr<i32> {
self.bed(
pos,
dir,
@ -266,7 +268,7 @@ pub trait PainterSpriteExt {
)
}
fn table_wood_fancy_woodland(&self, pos: Vec3<i32>, axis: Dir) -> Aabr<i32> {
fn table_wood_fancy_woodland(&self, pos: Vec3<i32>, axis: Dir2) -> Aabr<i32> {
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<i32>,
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<i32>, dir: Dir, sprite: SpriteKind) {
fn mirrored2(&self, pos: Vec3<i32>, 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<i32>, dir: Dir) {
fn lanternpost_wood(&self, pos: Vec3<i32>, 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<i32>, 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<i32>,
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(),