mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added default sprite attribute state
This commit is contained in:
parent
ad8965fdd7
commit
4a89d88e9b
@ -156,50 +156,44 @@ impl Block {
|
|||||||
|
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
|
|
||||||
// TODO: Rename to `filled`
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(kind: BlockKind, color: Rgb<u8>) -> Self {
|
pub(super) const fn from_raw(kind: BlockKind, data: [u8; 3]) -> Self { Self { kind, data } }
|
||||||
// TODO: we should probably assert this, overwriting the data fields with a
|
|
||||||
// colour is bad news
|
|
||||||
/*
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
assert!(kind.is_filled());
|
|
||||||
*/
|
|
||||||
|
|
||||||
Self {
|
// TODO: Rename to `filled`, make caller guarantees stronger
|
||||||
kind,
|
#[inline]
|
||||||
// Colours are only valid for non-fluids
|
#[track_caller]
|
||||||
data: if kind.is_filled() {
|
pub const fn new(kind: BlockKind, color: Rgb<u8>) -> Self {
|
||||||
[color.r, color.g, color.b]
|
if kind.is_filled() {
|
||||||
|
Self::from_raw(kind, [color.r, color.g, color.b])
|
||||||
} else {
|
} else {
|
||||||
[0; 3]
|
// Works because `SpriteKind::Empty` has no attributes
|
||||||
},
|
let data = (SpriteKind::Empty as u32).to_be_bytes();
|
||||||
|
Self::from_raw(kind, [data[1], data[2], data[3]])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only valid if `block_kind` is unfilled, so this is just a private utility
|
// Only valid if `block_kind` is unfilled, so this is just a private utility
|
||||||
// method
|
// method
|
||||||
#[inline]
|
#[inline]
|
||||||
const fn unfilled(kind: BlockKind, sprite: SpriteKind) -> Self {
|
pub fn unfilled(kind: BlockKind, sprite: SpriteKind) -> Self {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
assert!(!kind.is_filled());
|
assert!(!kind.is_filled());
|
||||||
|
|
||||||
let sprite_bytes = (sprite as u32).to_be_bytes();
|
Self::from_raw(kind, sprite.to_initial_bytes())
|
||||||
|
|
||||||
Self {
|
|
||||||
kind,
|
|
||||||
data: [sprite_bytes[1], sprite_bytes[2], sprite_bytes[3]],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn air(sprite: SpriteKind) -> Self { Self::unfilled(BlockKind::Air, sprite) }
|
pub fn air(sprite: SpriteKind) -> Self { Self::unfilled(BlockKind::Air, sprite) }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn empty() -> Self { Self::air(SpriteKind::Empty) }
|
pub const fn empty() -> Self {
|
||||||
|
// Works because `SpriteKind::Empty` has no attributes
|
||||||
|
let data = (SpriteKind::Empty as u32).to_be_bytes();
|
||||||
|
Self::from_raw(BlockKind::Air, [data[1], data[2], data[3]])
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn water(sprite: SpriteKind) -> Self { Self::unfilled(BlockKind::Water, sprite) }
|
pub fn water(sprite: SpriteKind) -> Self { Self::unfilled(BlockKind::Water, sprite) }
|
||||||
|
|
||||||
/* Sprite decoding */
|
/* Sprite decoding */
|
||||||
|
|
||||||
@ -258,6 +252,9 @@ impl Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(super) const fn data(&self) -> [u8; 3] { self.data }
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(super) const fn with_data(mut self, data: [u8; 3]) -> Self {
|
pub(super) const fn with_data(mut self, data: [u8; 3]) -> Self {
|
||||||
self.data = data;
|
self.data = data;
|
||||||
@ -428,12 +425,12 @@ impl Block {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.get_attr::<sprite::LightDisabled>()
|
.get_attr::<sprite::LightEnabled>()
|
||||||
.map_or(false, |l| l.0)
|
.map_or(true, |l| l.0)
|
||||||
{
|
{
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(glow_level)
|
Some(glow_level)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,7 +633,7 @@ impl Block {
|
|||||||
|
|
||||||
/// Apply a light toggle to this block, if possible
|
/// Apply a light toggle to this block, if possible
|
||||||
pub fn with_toggle_light(self, enable: bool) -> Option<Self> {
|
pub fn with_toggle_light(self, enable: bool) -> Option<Self> {
|
||||||
self.with_attr(sprite::LightDisabled(!enable)).ok()
|
self.with_attr(sprite::LightEnabled(enable)).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -662,7 +659,7 @@ impl Block {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn into_vacant(self) -> Self {
|
pub fn into_vacant(self) -> Self {
|
||||||
if self.is_fluid() {
|
if self.is_fluid() {
|
||||||
Block::new(self.kind(), Rgb::zero())
|
Block::unfilled(self.kind(), SpriteKind::Empty)
|
||||||
} else {
|
} else {
|
||||||
// FIXME: Figure out if there's some sensible way to determine what medium to
|
// FIXME: Figure out if there's some sensible way to determine what medium to
|
||||||
// replace a filled block with if it's removed.
|
// replace a filled block with if it's removed.
|
||||||
@ -698,7 +695,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn convert_u32() {
|
fn convert_u32() {
|
||||||
for bk in BlockKind::iter() {
|
for bk in BlockKind::iter() {
|
||||||
let block = Block::new(bk, Rgb::new(165, 90, 204)); // Pretty unique bit patterns
|
let block = Block::from_raw(bk, [165, 90, 204]); // Pretty unique bit patterns
|
||||||
if bk.is_filled() {
|
if bk.is_filled() {
|
||||||
assert_eq!(Block::from_u32(block.to_u32()), Some(block));
|
assert_eq!(Block::from_u32(block.to_u32()), Some(block));
|
||||||
} else {
|
} else {
|
||||||
|
@ -286,7 +286,7 @@ impl TerrainChunk {
|
|||||||
pub fn water(sea_level: i32) -> TerrainChunk {
|
pub fn water(sea_level: i32) -> TerrainChunk {
|
||||||
TerrainChunk::new(
|
TerrainChunk::new(
|
||||||
sea_level,
|
sea_level,
|
||||||
Block::new(BlockKind::Water, Rgb::zero()),
|
Block::water(SpriteKind::Empty),
|
||||||
Block::air(SpriteKind::Empty),
|
Block::air(SpriteKind::Empty),
|
||||||
TerrainChunkMeta::void(),
|
TerrainChunkMeta::void(),
|
||||||
)
|
)
|
||||||
|
@ -349,7 +349,7 @@ sprites! {
|
|||||||
SeaDecorPillar = 0x1E,
|
SeaDecorPillar = 0x1E,
|
||||||
MagicalSeal = 0x1F,
|
MagicalSeal = 0x1F,
|
||||||
},
|
},
|
||||||
Lamp = 7 has Ori, LightDisabled {
|
Lamp = 7 has Ori, LightEnabled {
|
||||||
// Standalone lights
|
// Standalone lights
|
||||||
Lantern = 0,
|
Lantern = 0,
|
||||||
StreetLamp = 1,
|
StreetLamp = 1,
|
||||||
@ -362,20 +362,28 @@ sprites! {
|
|||||||
attributes! {
|
attributes! {
|
||||||
Ori { bits: 4, err: Infallible, from: |bits| Ok(Self(bits as u8)), into: |Ori(x)| x as u16 },
|
Ori { bits: 4, err: Infallible, from: |bits| Ok(Self(bits as u8)), into: |Ori(x)| x as u16 },
|
||||||
Growth { bits: 4, err: Infallible, from: |bits| Ok(Self(bits as u8)), into: |Growth(x)| x as u16 },
|
Growth { bits: 4, err: Infallible, from: |bits| Ok(Self(bits as u8)), into: |Growth(x)| x as u16 },
|
||||||
LightDisabled { bits: 1, err: Infallible, from: |bits| Ok(Self(bits == 1)), into: |LightDisabled(x)| x as u16 },
|
LightEnabled { bits: 1, err: Infallible, from: |bits| Ok(Self(bits == 1)), into: |LightEnabled(x)| x as u16 },
|
||||||
}
|
}
|
||||||
|
|
||||||
// The orientation of the sprite, 0..16
|
// The orientation of the sprite, 0..16
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
|
||||||
pub struct Ori(pub u8);
|
pub struct Ori(pub u8);
|
||||||
|
|
||||||
// The growth of the plant, 0..16
|
// The growth of the plant, 0..16
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Growth(pub u8);
|
pub struct Growth(pub u8);
|
||||||
|
|
||||||
// Whether a light has been toggled off.
|
impl Default for Growth {
|
||||||
|
fn default() -> Self { Self(15) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whether a light has been toggled on or off.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct LightDisabled(pub bool);
|
pub struct LightEnabled(pub bool);
|
||||||
|
|
||||||
|
impl Default for LightEnabled {
|
||||||
|
fn default() -> Self { Self(true) }
|
||||||
|
}
|
||||||
|
|
||||||
impl SpriteKind {
|
impl SpriteKind {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -158,6 +158,15 @@ macro_rules! sprites {
|
|||||||
},)*
|
},)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline] pub(super) fn to_initial_bytes(self) -> [u8; 3] {
|
||||||
|
let sprite_bytes = (*self as u32).to_be_bytes();
|
||||||
|
let block = Block::from_raw(super::BlockKind::Air, [sprite_bytes[1], sprite_bytes[2], sprite_bytes[3]]);
|
||||||
|
match self.category() {
|
||||||
|
$(Category::$category_name => block$($(.with_attr($attr::default()).unwrap())*)?,)*
|
||||||
|
}
|
||||||
|
.data()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -170,12 +179,14 @@ pub enum AttributeError<E> {
|
|||||||
Attribute(E),
|
Attribute(E),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Attribute: Sized {
|
pub trait Attribute: Default + Sized {
|
||||||
/// The unique index assigned to this attribute, used to index offset arrays
|
/// The unique index assigned to this attribute, used to index offset
|
||||||
|
/// arrays.
|
||||||
const INDEX: usize;
|
const INDEX: usize;
|
||||||
/// The number of bits required to represent this attribute
|
/// The number of bits required to represent this attribute.
|
||||||
const BITS: u8;
|
const BITS: u8;
|
||||||
type Error;
|
/// The error that might occur when decoding the attribute from bits.
|
||||||
|
type Error: core::fmt::Debug;
|
||||||
fn from_bits(bits: u16) -> Result<Self, Self::Error>;
|
fn from_bits(bits: u16) -> Result<Self, Self::Error>;
|
||||||
fn into_bits(self) -> u16;
|
fn into_bits(self) -> u16;
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ pub fn generate_mesh<'a>(
|
|||||||
let d = d + 2;
|
let d = d + 2;
|
||||||
let flat = {
|
let flat = {
|
||||||
let mut volume = vol.cached();
|
let mut volume = vol.cached();
|
||||||
const AIR: Block = Block::air(common::terrain::sprite::SpriteKind::Empty);
|
const AIR: Block = Block::empty();
|
||||||
// TODO: Once we can manage it sensibly, consider using something like
|
// TODO: Once we can manage it sensibly, consider using something like
|
||||||
// Option<Block> instead of just assuming air.
|
// Option<Block> instead of just assuming air.
|
||||||
let mut flat = vec![AIR; (w * h * d) as usize];
|
let mut flat = vec![AIR; (w * h * d) as usize];
|
||||||
|
@ -142,8 +142,8 @@ impl BlocksOfInterest {
|
|||||||
_ => {
|
_ => {
|
||||||
if let Some(sprite) = block.get_sprite() {
|
if let Some(sprite) = block.get_sprite() {
|
||||||
if sprite.category() == sprite::Category::Lamp {
|
if sprite.category() == sprite::Category::Lamp {
|
||||||
if let Ok(sprite::LightDisabled(disabled)) = block.get_attr() {
|
if let Ok(sprite::LightEnabled(enabled)) = block.get_attr() {
|
||||||
interactables.push((pos, Interaction::LightToggle(disabled)));
|
interactables.push((pos, Interaction::LightToggle(!enabled)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ pub struct Colors {
|
|||||||
pub vein: (u8, u8, u8),
|
pub vein: (u8, u8, u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
const EMPTY_AIR: Block = Block::air(SpriteKind::Empty);
|
const EMPTY_AIR: Block = Block::empty();
|
||||||
|
|
||||||
pub struct PathLocals {
|
pub struct PathLocals {
|
||||||
pub riverless_alt: f32,
|
pub riverless_alt: f32,
|
||||||
|
@ -167,7 +167,7 @@ impl Archetype for Keep {
|
|||||||
make_block(colors.pole.0, colors.pole.1, colors.pole.2).with_priority(important_layer);
|
make_block(colors.pole.0, colors.pole.1, colors.pole.2).with_priority(important_layer);
|
||||||
let flag =
|
let flag =
|
||||||
make_block(flag_color.0, flag_color.1, flag_color.2).with_priority(important_layer);
|
make_block(flag_color.0, flag_color.1, flag_color.2).with_priority(important_layer);
|
||||||
const AIR: Block = Block::air(SpriteKind::Empty);
|
const AIR: Block = Block::empty();
|
||||||
const EMPTY: BlockMask = BlockMask::nothing();
|
const EMPTY: BlockMask = BlockMask::nothing();
|
||||||
let internal = BlockMask::new(AIR, internal_layer);
|
let internal = BlockMask::new(AIR, internal_layer);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user