Enhance CLI functionality with palette support and update exporters to use BlockPalette
This commit is contained in:
@@ -17,6 +17,8 @@ lib = { path = "../lib" }
|
||||
exporters = { path = "../exporters" }
|
||||
clap = { version = "4.6.0", features = ["derive"] }
|
||||
anyhow = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = "1"
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter"] }
|
||||
|
||||
@@ -2,26 +2,34 @@ use std::{fs, path::PathBuf};
|
||||
|
||||
use clap::Parser;
|
||||
use exporters::McFunctionExporter;
|
||||
use lib::{StructureExporter, TextBuilder, TtfFont};
|
||||
use lib::{BlockPalette, StructureExporter, TextBuilder, TtfFont};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Cli {
|
||||
/// The text you want to generate
|
||||
#[arg(short, long)]
|
||||
text: String,
|
||||
#[arg(short, long, required_unless_present = "list_palettes")]
|
||||
text: Option<String>,
|
||||
|
||||
/// Path to the .ttf font file
|
||||
#[arg(short, long)]
|
||||
font: PathBuf,
|
||||
#[arg(short, long, required_unless_present = "list_palettes")]
|
||||
font: Option<PathBuf>,
|
||||
|
||||
/// How many blocks deep the text should be
|
||||
#[arg(short, long, default_value_t = 1)]
|
||||
depth: u32,
|
||||
|
||||
/// The Minecraft block ID to use for the text body
|
||||
#[arg(short, long, default_value = "minecraft:quartz_block")]
|
||||
block: String,
|
||||
/// Name of a built-in palette preset (from the palettes/ directory)
|
||||
#[arg(short, long, conflicts_with = "palette_file")]
|
||||
palette: Option<String>,
|
||||
|
||||
/// Path to a JSON palette file
|
||||
#[arg(long)]
|
||||
palette_file: Option<PathBuf>,
|
||||
|
||||
/// List available palette presets and exit
|
||||
#[arg(long)]
|
||||
list_palettes: bool,
|
||||
|
||||
/// Output file path (without extension)
|
||||
#[arg(short, long, default_value = "output")]
|
||||
@@ -32,26 +40,70 @@ struct Cli {
|
||||
size: f32,
|
||||
}
|
||||
|
||||
fn palettes_dir() -> PathBuf {
|
||||
std::env::current_exe()
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join("palettes")
|
||||
}
|
||||
|
||||
fn load_palette_by_name(name: &str) -> anyhow::Result<BlockPalette> {
|
||||
let path = palettes_dir().join(format!("{}.json", name));
|
||||
let json = fs::read_to_string(&path)
|
||||
.map_err(|_| anyhow::anyhow!("palette '{}' not found in {:?}", name, palettes_dir()))?;
|
||||
Ok(serde_json::from_str(&json)?)
|
||||
}
|
||||
|
||||
pub fn run() -> anyhow::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
tracing::info!("loading font from: {:?}", cli.font);
|
||||
let font_bytes = fs::read(&cli.font)?;
|
||||
if cli.list_palettes {
|
||||
let dir = palettes_dir();
|
||||
let entries = fs::read_dir(&dir)
|
||||
.map_err(|_| anyhow::anyhow!("palettes directory not found at {:?}", dir))?;
|
||||
println!("Available palettes:");
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
if path.extension().and_then(|e| e.to_str()) == Some("json") {
|
||||
if let Some(stem) = path.file_stem().and_then(|s| s.to_str()) {
|
||||
println!(" {}", stem);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let font = TtfFont::from_bytes(&font_bytes, cli.size)
|
||||
.map_err(|e| anyhow::anyhow!(e))?;
|
||||
let text = cli.text.unwrap();
|
||||
let font_path = cli.font.unwrap();
|
||||
|
||||
tracing::info!("generating voxel grid for text: '{}'", cli.text);
|
||||
let palette = if let Some(path) = cli.palette_file {
|
||||
let json = fs::read_to_string(&path)
|
||||
.map_err(|e| anyhow::anyhow!("failed to read palette file {:?}: {}", path, e))?;
|
||||
serde_json::from_str(&json)?
|
||||
} else {
|
||||
let name = cli.palette.as_deref().unwrap_or("default");
|
||||
load_palette_by_name(name)?
|
||||
};
|
||||
|
||||
tracing::info!("using palette: {}", palette.name);
|
||||
tracing::info!("loading font from: {:?}", font_path);
|
||||
let font_bytes = fs::read(&font_path)?;
|
||||
|
||||
let font = TtfFont::from_bytes(&font_bytes, cli.size).map_err(|e| anyhow::anyhow!(e))?;
|
||||
|
||||
tracing::info!("generating voxel grid for text: '{}'", text);
|
||||
let builder = TextBuilder::new(&font).with_depth(cli.depth);
|
||||
let grid = builder.generate(&cli.text);
|
||||
let grid = builder.generate(&text);
|
||||
|
||||
tracing::info!(
|
||||
"grid generated: {}x{}x{}",
|
||||
grid.width, grid.height, grid.depth
|
||||
grid.width,
|
||||
grid.height,
|
||||
grid.depth
|
||||
);
|
||||
|
||||
let exporter = McFunctionExporter::new(&cli.block, "minecraft:obsidian");
|
||||
|
||||
let exporter = McFunctionExporter::new(&palette);
|
||||
let output_bytes = exporter.export(&grid)?;
|
||||
|
||||
let mut out_path = cli.out.clone();
|
||||
|
||||
Reference in New Issue
Block a user