use std::fmt;
use exhaust::Exhaust;
use all_is_cubes::block::{Block, Resolution::*, AIR};
use all_is_cubes::content::load_image::{default_srgb, space_from_image};
use all_is_cubes::content::palette;
use all_is_cubes::drawing::embedded_graphics::mono_font::iso_8859_1 as font;
use all_is_cubes::drawing::VoxelBrush;
#[cfg(doc)]
use all_is_cubes::inv::Tool;
use all_is_cubes::inv::TOOL_SELECTIONS;
use all_is_cubes::linking::{BlockModule, BlockProvider};
use all_is_cubes::math::GridRotation;
use all_is_cubes::universe::Universe;
use all_is_cubes::util::YieldProgress;
use all_is_cubes::{include_image, rgba_const};
use crate::vui::widgets::{ActionButtonVisualState, ButtonBase, ToggleButtonVisualState};
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Exhaust)]
#[doc(hidden)] #[non_exhaustive]
pub enum UiBlocks {
Crosshair,
ToolbarSlotFrame,
ToolbarPointer([ToolbarButtonState; TOOL_SELECTIONS]),
BackButton(ActionButtonVisualState),
AboutButton(ToggleButtonVisualState),
PauseButton(ToggleButtonVisualState),
MouselookButton(ToggleButtonVisualState),
FullscreenButton(ToggleButtonVisualState),
AntialiasButton(ToggleButtonVisualState),
DebugInfoTextButton(ToggleButtonVisualState),
DebugBehaviorsButton(ToggleButtonVisualState),
DebugChunkBoxesButton(ToggleButtonVisualState),
DebugCollisionBoxesButton(ToggleButtonVisualState),
DebugLightRaysButton(ToggleButtonVisualState),
}
impl BlockModule for UiBlocks {
fn namespace() -> &'static str {
"all-is-cubes/vui/blocks"
}
}
impl fmt::Display for UiBlocks {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
UiBlocks::Crosshair => write!(f, "crosshair"),
UiBlocks::ToolbarSlotFrame => write!(f, "toolbar-slot-frame"),
UiBlocks::ToolbarPointer([b0, b1, b2]) => {
write!(f, "toolbar-pointer/{b0}-{b1}-{b2}")
}
UiBlocks::BackButton(state) => write!(f, "back-button/{state}"),
UiBlocks::AboutButton(state) => write!(f, "about-button/{state}"),
UiBlocks::PauseButton(state) => write!(f, "pause-button/{state}"),
UiBlocks::MouselookButton(state) => write!(f, "mouselook-button/{state}"),
UiBlocks::FullscreenButton(state) => write!(f, "fullscreen-button/{state}"),
UiBlocks::AntialiasButton(state) => write!(f, "antialias-button/{state}"),
UiBlocks::DebugInfoTextButton(state) => write!(f, "debug-info-text-button/{state}"),
UiBlocks::DebugBehaviorsButton(state) => write!(f, "debug-behaviors-button/{state}"),
UiBlocks::DebugChunkBoxesButton(state) => {
write!(f, "debug-chunk-boxes-button/{state}")
}
UiBlocks::DebugCollisionBoxesButton(state) => {
write!(f, "debug-collision-boxes-button/{state}")
}
UiBlocks::DebugLightRaysButton(state) => write!(f, "debug-light-rays-button/{state}"),
}
}
}
impl UiBlocks {
pub async fn new(universe: &mut Universe, p: YieldProgress) -> BlockProvider<UiBlocks> {
BlockProvider::new(p, |key| {
Ok(match key {
UiBlocks::Crosshair => Block::builder()
.display_name("Crosshair")
.voxels_ref(
R64, universe.insert_anonymous(space_from_image(
include_image!("icons/crosshair.png"),
GridRotation::RXyZ,
default_srgb,
)?),
)
.build(),
UiBlocks::ToolbarSlotFrame => {
Block::builder()
.display_name("Toolbar Slot Frame")
.voxels_ref(
R64,
universe.insert_anonymous(space_from_image(
include_image!("icons/toolbar-slot.png"),
GridRotation::RXZY,
|pixel| default_srgb(pixel).translate([0, 16 - 1, 0]),
)?),
)
.build()
}
#[rustfmt::skip] UiBlocks::ToolbarPointer([
ToolbarButtonState::Unmapped,
ToolbarButtonState::Unmapped,
ToolbarButtonState::Unmapped,
]) => AIR,
UiBlocks::ToolbarPointer(buttons) => Block::builder()
.display_name("Selected")
.voxels_ref(
R32, universe.insert_anonymous(space_from_image(
include_image!("icons/toolbar-sel-cursor.png"),
GridRotation::RXyZ,
|color| match color {
image::Rgba([255, 0, 0, 255]) => buttons[0].brush(),
image::Rgba([0, 255, 0, 255]) => buttons[1].brush(),
image::Rgba([0, 0, 255, 255]) => buttons[2].brush(),
_ => default_srgb(color),
},
)?),
)
.build(),
UiBlocks::BackButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder.draw_icon(include_image!("icons/button-back.png"))?;
button_builder.build(universe, "Back")
}
UiBlocks::AboutButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder.draw_text(&font::FONT_10X20, "?")?;
button_builder.build(universe, "About")
}
UiBlocks::PauseButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder.draw_icon(include_image!("icons/button-pause.png"))?;
button_builder.build(universe, "Pause")
}
UiBlocks::MouselookButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder.draw_icon(include_image!("icons/button-mouselook.png"))?;
button_builder.build(universe, "Mouselook")
}
UiBlocks::FullscreenButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder.draw_icon(include_image!("icons/button-fullscreen.png"))?;
button_builder.build(universe, "Mouselook")
}
UiBlocks::AntialiasButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder.draw_icon(include_image!("icons/button-antialias.png"))?;
button_builder.build(universe, "Antialiasing")
}
UiBlocks::DebugInfoTextButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder.draw_icon(include_image!("icons/button-debug-info-text.png"))?;
button_builder.build(universe, "Debug: Info Text")
}
UiBlocks::DebugChunkBoxesButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder
.draw_icon(include_image!("icons/button-debug-chunk-boxes.png"))?;
button_builder.build(universe, "Debug: Chunk Boxes")
}
UiBlocks::DebugBehaviorsButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder.draw_icon(include_image!("icons/button-debug-behaviors.png"))?;
button_builder.build(universe, "Debug: Behaviors")
}
UiBlocks::DebugCollisionBoxesButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder
.draw_icon(include_image!("icons/button-debug-collision-boxes.png"))?;
button_builder.build(universe, "Debug: Collision Boxes")
}
UiBlocks::DebugLightRaysButton(state) => {
let mut button_builder = state.button_builder()?;
button_builder
.draw_icon(include_image!("icons/button-debug-light-rays.png"))?;
button_builder.build(universe, "Debug: Light Rays at Cursor")
}
})
})
.await
.unwrap()
}
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Exhaust)]
#[doc(hidden)] #[allow(clippy::exhaustive_enums)]
pub enum ToolbarButtonState {
Unmapped,
Mapped,
Pressed,
}
impl ToolbarButtonState {
fn brush(self) -> VoxelBrush<'static> {
match self {
Self::Unmapped => VoxelBrush::with_thickness(palette::HUD_TOOLBAR_BACK, 0..1),
Self::Mapped => VoxelBrush::with_thickness(palette::BUTTON_BACK, 0..3),
Self::Pressed => VoxelBrush::with_thickness(rgba_const!(0.1, 0.1, 0.1, 1.0), 0..2),
}
}
}
impl fmt::Display for ToolbarButtonState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unmapped => "u",
Self::Mapped => "m",
Self::Pressed => "p",
}
.fmt(f)
}
}
#[cfg(test)]
mod tests {
use super::*;
use futures_executor::block_on;
#[test]
fn blocks_smoke_test() {
block_on(UiBlocks::new(&mut Universe::new(), YieldProgress::noop()));
}
}