mirror of
https://gitlab.com/veloren/veloren
synced 2026-08-16 16:26:07 -04:00
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:
commit
af7e38c58e
39 changed files with 1246 additions and 1048 deletions
|
|
@ -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
1
Cargo.lock
generated
|
|
@ -8616,6 +8616,7 @@ dependencies = [
|
|||
"csv",
|
||||
"dot_vox",
|
||||
"enum-map",
|
||||
"enumset",
|
||||
"fxhash",
|
||||
"hashbrown 0.16.0",
|
||||
"indexmap 2.12.0",
|
||||
|
|
|
|||
|
|
@ -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 = [
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 _: () = {
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
566
common/src/util/cardinal_directions.rs
Normal file
566
common/src/util/cardinal_directions.rs
Normal 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() }
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue