Skip to content

Commit

Permalink
Redefine Provider::install() to use transactions.
Browse files Browse the repository at this point in the history
  • Loading branch information
kpreid committed Jan 13, 2024
1 parent 5804e49 commit da5275e
Show file tree
Hide file tree
Showing 16 changed files with 239 additions and 156 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

- `block::BlockAttributes::tick_action` can now specify a time period rather than always occurring on the next tick.

- `linking::Provider` is `BlockProvider` but generalized to non-block types.

- `math::Axis` is an enum of coordinate axes.

- `math::Cube` represents a unit cube on the grid; it replaces many previous uses of `GridPoint` to identify cubes.
Expand Down Expand Up @@ -62,6 +64,8 @@
- `camera::HeadlessRenderer` now returns a custom image container type `Rendering` instead of using `image::RgbaImage`.
(This way, no dependency on `image` is needed.)

- `linking::BlockProvider::install()` now requires a `&mut UniverseTransaction` instead of a `&mut Universe`.

- `drawing::VoxelBrush::transform()` is renamed to `rotate()` and only accepts a rotation.
This avoids confusion between points in space and cube-identifying coordinates.
- Renamed `raytracer::PixelBuf` trait to `Accumulate`.
Expand Down
48 changes: 26 additions & 22 deletions all-is-cubes-content/src/atrium.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use all_is_cubes::math::{
};
use all_is_cubes::space::{SetCubeError, Space, SpacePhysics, SpaceTransaction};
use all_is_cubes::transaction::{self, Transaction as _};
use all_is_cubes::universe::Universe;
use all_is_cubes::universe::{Universe, UniverseTransaction};
use all_is_cubes::util::YieldProgress;
use all_is_cubes::{rgb_const, rgba_const};

Expand All @@ -31,8 +31,13 @@ pub(crate) async fn atrium(
universe: &mut Universe,
progress: YieldProgress,
) -> Result<Space, InGenError> {
// TODO: subdivide progress
let blocks = install_atrium_blocks(universe, progress).await?;
// TODO: subdivide and report further progress
let blocks = {
let mut install_txn = UniverseTransaction::default();
let blocks = install_atrium_blocks(&mut install_txn, progress).await?;
install_txn.execute(universe, &mut transaction::no_outputs)?;
blocks
};

let ceiling_height = 6;
let between_small_arches = 3;
Expand Down Expand Up @@ -464,7 +469,7 @@ impl BannerColor {
}

async fn install_atrium_blocks(
universe: &mut Universe,
txn: &mut UniverseTransaction,
progress: YieldProgress,
) -> Result<BlockProvider<AtriumBlocks>, InGenError> {
let resolution = Resolution::R16;
Expand Down Expand Up @@ -564,7 +569,7 @@ async fn install_atrium_blocks(
let one_diagonal = GridVector::new(1, 1, 1);
let center_point_doubled = (one_diagonal * resolution_g).to_point();

BlockProvider::<AtriumBlocks>::new(progress, |key| {
Ok(BlockProvider::<AtriumBlocks>::new(progress, |key| {
Ok(match key {
AtriumBlocks::Sun => Block::builder()
.display_name("Sun")
Expand All @@ -581,7 +586,7 @@ async fn install_atrium_blocks(
brick_pattern(p)
}
})?
.build_into(universe),
.build_txn(txn),
AtriumBlocks::UpperFloor => Block::builder()
.display_name("Atrium Upper Floor")
.voxels_fn(resolution, |p| {
Expand All @@ -592,16 +597,16 @@ async fn install_atrium_blocks(
brick_pattern(p)
}
})?
.build_into(universe),
.build_txn(txn),
AtriumBlocks::SolidBricks => Block::builder()
.display_name("Atrium Wall Bricks")
.voxels_fn(resolution, brick_pattern)?
.build_into(universe),
.build_txn(txn),
AtriumBlocks::GroundArch => {
generate_arch(universe, &stone_range, brick_pattern, resolution, 7, 3)?
generate_arch(txn, &stone_range, brick_pattern, resolution, 7, 3)?
}
AtriumBlocks::UpperArch => {
generate_arch(universe, &stone_range, brick_pattern, resolution, 3, 2)?
generate_arch(txn, &stone_range, brick_pattern, resolution, 3, 2)?
}
AtriumBlocks::GroundColumn => Block::builder()
.display_name("Large Atrium Column")
Expand All @@ -614,7 +619,7 @@ async fn install_atrium_blocks(
&AIR
}
})?
.build_into(universe),
.build_txn(txn),
AtriumBlocks::SquareColumn => Block::builder()
.display_name("Square Atrium Column")
.rotation_rule(RotationPlacementRule::Attach { by: Face6::NY })
Expand All @@ -626,7 +631,7 @@ async fn install_atrium_blocks(
&AIR
}
})?
.build_into(universe),
.build_txn(txn),
AtriumBlocks::SmallColumn => Block::builder()
.display_name("Round Atrium Column")
.rotation_rule(RotationPlacementRule::Attach { by: Face6::NY })
Expand All @@ -638,12 +643,12 @@ async fn install_atrium_blocks(
&AIR
}
})?
.build_into(universe),
.build_txn(txn),
AtriumBlocks::Molding => Block::builder()
.display_name("Atrium Top Edge Molding")
// TODO: rotation rule
.voxels_fn(resolution, molding_fn)?
.build_into(universe),
.build_txn(txn),

AtriumBlocks::Banner(color) => Block::builder()
.display_name(format!("Atrium Banner {color}"))
Expand All @@ -656,7 +661,7 @@ async fn install_atrium_blocks(
AIR
}
})?
.build_into(universe),
.build_txn(txn),
AtriumBlocks::BannerBottomAccent => {
let accent_color = Block::from(rgba_const!(0.95, 0.89, 0.05, 1.0));
Block::builder()
Expand All @@ -668,13 +673,13 @@ async fn install_atrium_blocks(
&AIR
}
})?
.build_into(universe)
.build_txn(txn)
}

AtriumBlocks::Pole => Block::builder()
.display_name("Pole")
.voxels_fn((Resolution::R16 * MULTIBLOCK_SCALE).unwrap(), &pole_fn)?
.build_into(universe),
.build_txn(txn),
AtriumBlocks::Firepot => Block::builder()
.display_name("Firepot")
.voxels_ref(resolution, {
Expand Down Expand Up @@ -712,20 +717,19 @@ async fn install_atrium_blocks(
.execute(&mut space, &mut transaction::no_outputs)
.unwrap();
}
universe.insert_anonymous(space)
txn.insert_anonymous(space)
})
.build(),
})
})
.await?
.install(universe)?;
Ok(BlockProvider::<AtriumBlocks>::using(universe)?)
.install(txn)?)
}

const MULTIBLOCK_SCALE: Resolution = Resolution::R8;

fn generate_arch<'b>(
universe: &mut Universe,
txn: &mut UniverseTransaction,
stone_range: &[Block], // TODO: clarify
brick_pattern: impl Fn(Cube) -> &'b Block,
resolution: Resolution,
Expand Down Expand Up @@ -785,7 +789,7 @@ fn generate_arch<'b>(
Some(brick_pattern(p))
}
})?;
universe.insert_anonymous(space)
txn.insert_anonymous(space)
};
Ok(Block::builder()
.display_name("Atrium Upper Floor Arch")
Expand Down
52 changes: 24 additions & 28 deletions all-is-cubes-content/src/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use all_is_cubes::math::{
};
use all_is_cubes::space::{Space, SpacePhysics, SpaceTransaction};
use all_is_cubes::transaction::{self, Transaction as _};
use all_is_cubes::universe::Universe;
use all_is_cubes::universe::UniverseTransaction;
use all_is_cubes::util::YieldProgress;
use all_is_cubes::{rgb_const, rgba_const};

Expand Down Expand Up @@ -75,7 +75,7 @@ impl fmt::Display for DemoBlocks {
///
/// [`LandscapeBlocks`]: crate::landscape::LandscapeBlocks
pub async fn install_demo_blocks(
universe: &mut Universe,
txn: &mut UniverseTransaction,
p: YieldProgress,
) -> Result<(), GenError> {
let resolution = R16;
Expand All @@ -90,7 +90,7 @@ pub async fn install_demo_blocks(
let center_point_doubled = (one_diagonal * resolution_g).to_point();

let [landscape_p, p] = p.split(0.5);
install_landscape_blocks(universe, resolution, landscape_p).await?;
install_landscape_blocks(txn, resolution, landscape_p).await?;
p.progress(0.0).await;

let curb_color: Block = Rgba::new(0.788, 0.765, 0.741, 1.0).into();
Expand Down Expand Up @@ -122,7 +122,7 @@ pub async fn install_demo_blocks(
let pedestal_voxel = Block::from(palette::STONE);

use DemoBlocks::*;
BlockProvider::<DemoBlocks>::new(p, |key| {
let provider_for_patch = BlockProvider::<DemoBlocks>::new(p, |key| {
Ok(match key {
GlassBlock => {
let glass_densities = [
Expand All @@ -147,7 +147,7 @@ pub async fn install_demo_blocks(
.dot(Vector3D::new(1.0, 1.0, 1.0));
gradient_lookup(&glass_densities, (1.0 - r as f32) * 2.0)
})?
.build_into(universe)
.build_txn(txn)
}

Road => {
Expand All @@ -172,7 +172,7 @@ pub async fn install_demo_blocks(
let x = rng.gen_range(range.clone());
palette_image.get_brush(x, y).origin_block().unwrap_or(&AIR)
})?
.build_into(universe)
.build_txn(txn)
}

Lamp => Block::builder()
Expand All @@ -187,7 +187,7 @@ pub async fn install_demo_blocks(
&AIR
}
})?
.build_into(universe),
.build_txn(txn),

LamppostSegment => Block::builder()
.display_name("Lamppost")
Expand All @@ -203,7 +203,7 @@ pub async fn install_demo_blocks(
&AIR
}
})?
.build_into(universe),
.build_txn(txn),

LamppostBase => Block::builder()
.display_name("Lamppost Base")
Expand All @@ -222,7 +222,7 @@ pub async fn install_demo_blocks(
&AIR
}
})?
.build_into(universe),
.build_txn(txn),

LamppostTop => Block::builder()
.display_name("Lamppost Top")
Expand All @@ -239,7 +239,7 @@ pub async fn install_demo_blocks(
&AIR
}
})?
.build_into(universe),
.build_txn(txn),

Sconce => Block::builder()
.display_name("Sconce")
Expand All @@ -261,7 +261,7 @@ pub async fn install_demo_blocks(
&AIR
}
})?
.build_into(universe),
.build_txn(txn),

Arrow => {
let mut space = Space::for_block(resolution).build();
Expand Down Expand Up @@ -307,7 +307,7 @@ pub async fn install_demo_blocks(
Block::builder()
.display_name("Arrow")
.rotation_rule(RotationPlacementRule::Attach { by: Face6::NY })
.voxels_ref(resolution, universe.insert_anonymous(space))
.voxels_ref(resolution, txn.insert_anonymous(space))
.build()
}

Expand All @@ -316,7 +316,7 @@ pub async fn install_demo_blocks(
// TODO: rotation should specify curb line direction
.rotation_rule(RotationPlacementRule::Attach { by: Face6::NY })
.voxels_fn(resolution, curb_fn)?
.build_into(universe),
.build_txn(txn),

ExhibitBackground => {
let colors = [
Expand All @@ -328,7 +328,7 @@ pub async fn install_demo_blocks(
.voxels_fn(R4, |cube| {
&colors[(cube.x + cube.y + cube.z).rem_euclid(2) as usize]
})?
.build_into(universe)
.build_txn(txn)
}

Pedestal => Block::builder()
Expand All @@ -346,7 +346,7 @@ pub async fn install_demo_blocks(
&AIR
}
})?
.build_into(universe),
.build_txn(txn),

Signboard => {
let sign_board = Block::from(palette::PLANK);
Expand Down Expand Up @@ -400,7 +400,7 @@ pub async fn install_demo_blocks(
Block::builder()
.display_name("Signboard")
.rotation_rule(RotationPlacementRule::Attach { by: Face6::NY })
.voxels_ref(resolution, universe.insert_anonymous(space))
.voxels_ref(resolution, txn.insert_anonymous(space))
.build()
}

Expand All @@ -422,7 +422,7 @@ pub async fn install_demo_blocks(
.display_name("Clock")
.rotation_rule(RotationPlacementRule::Attach { by: Face6::NZ })
.animation_hint(AnimationHint::CONTINUOUS)
.voxels_ref(resolution, universe.insert_anonymous(space))
.voxels_ref(resolution, txn.insert_anonymous(space))
.build()
}

Expand All @@ -443,12 +443,7 @@ pub async fn install_demo_blocks(
})
})
.await?
.install(universe)?;

// Kludge: Grab the installed blocks to patch up inter-block cross-references
// TODO: This should be possible to do as a built-in feature of the "linking" system
let provider_for_patch = BlockProvider::using(universe)
.map_err(|e| GenError::failure(e, "TODO: dummy name".into()))?;
.install(txn)?;

// Join up blinker blocks
for state in bool::exhaust() {
Expand Down Expand Up @@ -550,10 +545,11 @@ mod tests {

#[tokio::test]
pub async fn install_demo_blocks_test() {
let mut universe = Universe::new();
install_demo_blocks(&mut universe, yield_progress_for_testing())
.await
.unwrap();
// TODO: assert what entries were created, once Universe has iteration
install_demo_blocks(
&mut UniverseTransaction::default(),
yield_progress_for_testing(),
)
.await
.unwrap();
}
}
12 changes: 7 additions & 5 deletions all-is-cubes-content/src/city.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,22 @@ pub(crate) async fn demo_city<I: Instant>(
// Also install blocks some exhibits want.
// We do this once so that if multiple exhibits end up wanting them there are no conflicts.
// TODO: We want a "module loading" system that allows expressing dependencies.
let mut install_txn = UniverseTransaction::default();
let widget_theme_progress = p.start_and_cut(0.05, "WidgetTheme").await;
all_is_cubes_ui::vui::widgets::WidgetTheme::new(universe, widget_theme_progress)
all_is_cubes_ui::vui::widgets::WidgetTheme::new(&mut install_txn, widget_theme_progress)
.await
.unwrap();
let ui_blocks_progress = p.start_and_cut(0.05, "UiBlocks").await;
all_is_cubes_ui::vui::blocks::UiBlocks::new(universe, ui_blocks_progress)
all_is_cubes_ui::vui::blocks::UiBlocks::new(&mut install_txn, ui_blocks_progress)
.await
.install(universe)
.install(&mut install_txn)
.unwrap();
let icons_blocks_progress = p.start_and_cut(0.05, "Icons").await;
all_is_cubes::inv::Icons::new(universe, icons_blocks_progress)
all_is_cubes::inv::Icons::new(&mut install_txn, icons_blocks_progress)
.await
.install(universe)
.install(&mut install_txn)
.unwrap();
install_txn.execute(universe, &mut transaction::no_outputs)?;

// Layout parameters
// TODO: move to CityPlanner
Expand Down
Loading

0 comments on commit da5275e

Please sign in to comment.