Skip to content

Commit

Permalink
Add a Schedule to Modifier::Move.
Browse files Browse the repository at this point in the history
I’m not entirely sure this is the right plan — will anyone want an
intentionally slower animation? Perhaps for performance, or perhaps not,
but what this does do is give a reference for the modifier’s `velocity`.
That is, anything with a `Schedule` in it is obviously something that
is dependent on the universe’s `TickSchedule`, and there's a systematic
way to update/validate those (at least, if we do something like
extending `VisitHandles` to visit other things).
  • Loading branch information
kpreid committed Aug 1, 2024
1 parent 51c4ad1 commit 0725bd4
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 17 deletions.
40 changes: 30 additions & 10 deletions all-is-cubes/src/block/modifier/move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::block::{
};
use crate::math::{Face6, GridAab, GridCoordinate, GridVector, Vol};
use crate::op::Operation;
use crate::time;
use crate::universe;

/// Data for [`Modifier::Move`]; displaces the block out of the grid, cropping it.
Expand All @@ -23,12 +24,18 @@ use crate::universe;
pub struct Move {
/// The direction in which the block is displaced.
pub direction: Face6,

/// The distance, in 1/256ths, by which it is displaced.
pub distance: u16,
/// The velocity **per tick** with which the displacement is changing.
///
/// TODO: "Per tick" is a bad unit.

/// The amount by which `self.distance` is changing every time
/// `self.schedule` fires.
pub velocity: i16,

/// When to apply the velocity.
///
/// If `self.velocity` is zero, this is ignored.
pub schedule: time::Schedule,
}

impl Move {
Expand All @@ -38,6 +45,7 @@ impl Move {
direction,
distance,
velocity,
schedule: time::Schedule::EVERY_TICK,
}
}

Expand All @@ -64,6 +72,7 @@ impl Move {
direction: self.direction.opposite(),
distance: 256 - self.distance,
velocity: -self.velocity,
schedule: self.schedule,
}
}

Expand All @@ -79,6 +88,7 @@ impl Move {
direction,
distance,
velocity,
schedule,
} = *self;

// Apply Quote to ensure that the block's own `tick_action` and other effects
Expand All @@ -104,9 +114,9 @@ impl Move {
.translate(translation_in_res)
.intersection_cubes(GridAab::for_block(effective_resolution));

let animation_action: Option<TickAction> = if displaced_bounds.is_none() && velocity >= 0 {
let animation_op: Option<Operation> = if displaced_bounds.is_none() && velocity >= 0 {
// Displaced to invisibility; turn into just plain air.
Some(TickAction::from(Operation::Become(AIR)))
Some(Operation::Become(AIR))
} else if translation_in_res == GridVector::zero() && velocity == 0
|| distance == 0 && velocity < 0
{
Expand All @@ -116,7 +126,7 @@ impl Move {
);
let mut new_block = block.clone();
new_block.modifiers_mut().remove(this_modifier_index); // TODO: What if other modifiers want to do things?
Some(TickAction::from(Operation::Become(new_block)))
Some(Operation::Become(new_block))
} else if velocity != 0 {
// Movement in progress.
assert!(
Expand All @@ -133,13 +143,13 @@ impl Move {
.try_into()
.unwrap(/* clamped to range */);
}
Some(TickAction::from(Operation::Become(new_block)))
Some(Operation::Become(new_block))
} else {
// Stationary displacement; take no action
None
};

let animation_hint = if animation_action.is_some() {
let animation_hint = if animation_op.is_some() {
input.attributes.animation_hint
| block::AnimationHint::replacement(block::AnimationChange::Shape)
} else {
Expand All @@ -148,7 +158,10 @@ impl Move {

let attributes = BlockAttributes {
animation_hint,
tick_action: animation_action,
tick_action: animation_op.map(|operation| TickAction {
operation,
schedule,
}),
..input.attributes
};

Expand Down Expand Up @@ -204,6 +217,7 @@ impl universe::VisitHandles for Move {
direction: _,
distance: _,
velocity: _,
schedule: _,
} = self;
}
}
Expand All @@ -215,7 +229,6 @@ mod tests {
use crate::content::make_some_blocks;
use crate::math::{notnan, rgba_const, FaceMap, GridPoint, OpacityCategory, Rgb, Rgba};
use crate::space::Space;
use crate::time;
use crate::universe::Universe;
use ordered_float::NotNan;
use pretty_assertions::assert_eq;
Expand All @@ -228,6 +241,7 @@ mod tests {
direction: Face6::PY,
distance: 128, // distance 1/2 block × scale factor of 256
velocity: 0,
schedule: time::Schedule::EVERY_TICK,
});

let expected_bounds = GridAab::from_lower_size([0, 8, 0], [16, 8, 16]);
Expand Down Expand Up @@ -279,6 +293,7 @@ mod tests {
direction: Face6::PY,
distance: 128, // distance 1/2 block × scale factor of 256
velocity: 0,
schedule: time::Schedule::EVERY_TICK,
});

let expected_bounds = GridAab::from_lower_size([0, 1, 0], [2, 1, 2]);
Expand Down Expand Up @@ -328,6 +343,7 @@ mod tests {
direction: Face6::PY,
distance: 128,
velocity: 0,
schedule: time::Schedule::EVERY_TICK,
});

assert_eq!(moved.evaluate().unwrap().attributes.tick_action, None);
Expand Down Expand Up @@ -393,6 +409,7 @@ mod tests {
direction: Face6::PX,
distance: 10,
velocity: 10,
schedule: time::Schedule::EVERY_TICK,
})
.with_modifier(composite.clone());

Expand All @@ -402,6 +419,7 @@ mod tests {
direction: Face6::PX,
distance: 20,
velocity: 10,
schedule: time::Schedule::EVERY_TICK,
})
.with_modifier(composite);

Expand All @@ -423,6 +441,7 @@ mod tests {
direction: Face6::PX,
distance: 10,
velocity: 10,
schedule: time::Schedule::EVERY_TICK,
}),
block::CompositeOperator::Over,
));
Expand All @@ -432,6 +451,7 @@ mod tests {
direction: Face6::PX,
distance: 10,
velocity: 10,
schedule: time::Schedule::EVERY_TICK,
}),
block::CompositeOperator::Over,
));
Expand Down
6 changes: 1 addition & 5 deletions all-is-cubes/src/block/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,11 +535,7 @@ mod eval {
let block = Block::builder()
.color(Rgba::new(1e28, 1e28, 1e28, 1e28))
// Modifier matters because it causes the block to become voxels
.modifier(Modifier::Move(modifier::Move {
direction: Face6::NX,
distance: 0,
velocity: 0,
}))
.modifier(Modifier::Move(modifier::Move::new(Face6::NX, 0, 0)))
.build();
block.evaluate().unwrap();
}
Expand Down
10 changes: 9 additions & 1 deletion all-is-cubes/src/save/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,12 @@ mod block {
direction,
distance,
velocity,
schedule,
}) => ModifierSer::MoveV1 {
direction,
distance,
velocity,
schedule,
},
Modifier::Inventory(ref inventory) => ModifierSer::BlockInventoryV1 {
inventory: Cow::Borrowed(inventory),
Expand Down Expand Up @@ -397,7 +399,13 @@ mod block {
direction,
distance,
velocity,
} => Modifier::Move(Move::new(direction, distance, velocity)),
schedule,
} => Modifier::Move(Move {
direction,
distance,
velocity,
schedule,
}),
ModifierSer::BlockInventoryV1 { inventory } => {
Modifier::Inventory(inventory.into_owned())
}
Expand Down
4 changes: 3 additions & 1 deletion all-is-cubes/src/save/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use serde::{Deserialize, Serialize};
use crate::block::Block;
use crate::math::{Aab, Face6, GridAab, GridCoordinate, GridRotation};
use crate::save::compress::{GzSerde, Leu16};
use crate::time::Schedule;
use crate::universe::Handle;
use crate::{behavior, block, character, inv, op, space, universe};

Expand Down Expand Up @@ -149,7 +150,7 @@ pub(crate) enum RotationPlacementRuleSer {
#[derive(Debug, Deserialize, Serialize)]
pub(crate) struct TickActionSer<'a> {
pub operation: Cow<'a, op::Operation>,
pub schedule: crate::time::Schedule,
pub schedule: Schedule,
}
#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(tag = "type")]
Expand Down Expand Up @@ -198,6 +199,7 @@ pub(crate) enum ModifierSer<'a> {
direction: Face6,
distance: u16,
velocity: i16,
schedule: Schedule,
},
/// This is called "`BlockInventory`" rather than "`Inventory`" so that the
/// variant tags are unique across the entire schema, which might be useful
Expand Down

0 comments on commit 0725bd4

Please sign in to comment.