From 601910d557db24538a293ebe6dfa15680c51d9dd Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sat, 21 Sep 2024 16:28:43 -0700 Subject: [PATCH] content: Use `Primitive::Text` in `make_some_voxel_blocks()`. This removes one of the direct uses of `embedded_graphics`. See . A disadvantage is that now evaluating the block is more expensive. We could fix that by adding a `BlockDef` wrapper, or by making a way to turn a `Block` evaluation into the contents of a `Space` (which we'll probably want someday as an editing tool anyway). --- all-is-cubes/src/block/modifier/zoom.rs | 22 ++++---- all-is-cubes/src/content.rs | 71 +++++++++++++++---------- 2 files changed, 55 insertions(+), 38 deletions(-) diff --git a/all-is-cubes/src/block/modifier/zoom.rs b/all-is-cubes/src/block/modifier/zoom.rs index 32ae7b617..4d2914b91 100644 --- a/all-is-cubes/src/block/modifier/zoom.rs +++ b/all-is-cubes/src/block/modifier/zoom.rs @@ -183,16 +183,17 @@ mod tests { let [original_block] = make_some_voxel_blocks(&mut universe); let ev_original = original_block.evaluate().unwrap(); + assert_eq!(ev_original.resolution(), Resolution::R16); + let scale = R2; // scale up by two = divide resolution by two let zoom_resolution = ev_original.resolution().halve().unwrap(); let original_voxels = &ev_original.voxels; // Try zoom at multiple offset steps. for x in 0i32..2 { dbg!(x); - let zoomed = original_block.clone().with_modifier(Zoom::new( - R2, // scale up by two = divide resolution by two - point3(x, 0, 0), - )); + let zoomed = original_block + .clone() + .with_modifier(Zoom::new(scale, point3(x, 0, 0))); let ev_zoomed = zoomed.evaluate().unwrap(); assert_eq!( ev_zoomed, @@ -203,9 +204,8 @@ mod tests { ev_original.attributes.clone(), Evoxels::from_one(Evoxel::from_color(Rgba::TRANSPARENT)), block::Cost { - components: 3, // Primitive + display_name + Zoom - voxels: 16u32.pow(3), // counts evaluation of Recur - recursion: 0, + components: ev_original.cost.components + 1, + ..ev_original.cost }, ) } else { @@ -223,9 +223,11 @@ mod tests { }), ), block::Cost { - components: 3, - voxels: 16u32.pow(3) + 8u32.pow(3), // Recur + Zoom - recursion: 0, + components: ev_original.cost.components + 1, + // 8 = 16 (original) / 2 (zoom level) + voxels: ev_original.cost.voxels + + u32::from((ev_original.resolution() / scale).unwrap()).pow(3), + ..ev_original.cost }, ) } diff --git a/all-is-cubes/src/content.rs b/all-is-cubes/src/content.rs index e26ff41f0..3091dee55 100644 --- a/all-is-cubes/src/content.rs +++ b/all-is-cubes/src/content.rs @@ -6,19 +6,13 @@ use alloc::string::ToString; use alloc::vec::Vec; -use embedded_graphics::mono_font::iso_8859_1::FONT_9X15_BOLD; -use embedded_graphics::mono_font::MonoTextStyle; -use embedded_graphics::prelude::{Drawable, Point}; -use embedded_graphics::text::Alignment; -use embedded_graphics::text::Baseline; -use embedded_graphics::text::Text; -use embedded_graphics::text::TextStyleBuilder; - use crate::arcstr::{literal, ArcStr}; -use crate::block::{Block, Resolution, Resolution::R16, RotationPlacementRule}; +use crate::block::{self, Block, Resolution, Resolution::R16, RotationPlacementRule}; use crate::color_block; use crate::inv::{Slot, Tool}; -use crate::math::{rgb_const, Cube, Face6, FaceMap, GridAab, GridCoordinate, GridSize, Rgb, Rgba}; +use crate::math::{ + rgb_const, Cube, Face6, FaceMap, GridAab, GridCoordinate, GridSize, GridVector, Rgb, Rgba, +}; use crate::space::{SetCubeError, Space}; use crate::transaction::Transactional as _; use crate::universe::{Universe, UniverseTransaction}; @@ -93,31 +87,52 @@ pub fn make_some_voxel_blocks_txn( #[inline(never)] // discourage unnecessarily repeated code fn make_one_voxel_block(transaction: &mut UniverseTransaction, i: usize, n: usize) -> Block { + use crate::block::text; + let resolution = R16; let color = color_for_make_blocks(i, n); + let label_voxel = Block::from(palette::ALMOST_BLACK); + let label = arcstr::format!("{i}"); + let mut block_space = Space::for_block(resolution) .filled_with(Block::from(color)) .build(); axes(&mut block_space).unwrap(); - for face in Face6::ALL { - Text::with_text_style( - &i.to_string(), - Point::new(i32::from(resolution) / 2, i32::from(resolution) / 2), - MonoTextStyle::new(&FONT_9X15_BOLD, palette::ALMOST_BLACK), - TextStyleBuilder::new() - .baseline(Baseline::Middle) - .alignment(Alignment::Center) - .build(), - ) - .draw( - &mut block_space.draw_target(face.face_transform(GridCoordinate::from(resolution) - 1)), - ) - .unwrap(); - } - Block::builder() - .display_name(i.to_string()) + + let base_block = Block::builder() + .display_name(label.clone()) .voxels_handle(resolution, transaction.insert_anonymous(block_space)) - .build() + .build(); + + let text_block = Block::from(block::Primitive::Text { + text: text::Text::builder() + .string(label.clone()) + .font(text::Font::Logo) // legacy compatibility choice + .foreground(label_voxel.clone()) + .positioning(text::Positioning { + x: text::PositioningX::Center, + line_y: text::PositioningY::BodyMiddle, + z: text::PositioningZ::Front, + }) + .layout_bounds( + resolution, + GridAab::for_block(resolution) + // legacy compatibility -- nudge downward 1 voxel to keep the old text layout. + // Not sure why this is different but we'll be revisiting text layout in the future anyway. + .shrink(FaceMap::splat(0).with(Face6::PY, 1)) + .unwrap(), + ) + .build(), + offset: GridVector::zero(), + }); + + block::Composite::stack( + base_block, + Face6::ALL + .iter() + .map(|face| text_block.clone().rotate(face.rotation_from_nz())) + .map(|text_block| block::Composite::new(text_block, block::CompositeOperator::Over)), + ) } fn color_for_make_blocks(i: usize, n: usize) -> Rgba {