added an all layer option to exports
This commit is contained in:
+62
-23
@@ -136,8 +136,13 @@ fn collect_scene_data(layout: &DungeonLayout, settings: &UiSettings) -> SceneDat
|
|||||||
|
|
||||||
// Open a dialog to select an export destination.
|
// Open a dialog to select an export destination.
|
||||||
pub fn select_export_target(settings: &UiSettings) -> Result<ExportTarget, String> {
|
pub fn select_export_target(settings: &UiSettings) -> Result<ExportTarget, String> {
|
||||||
if settings.export_format == ExportFormat::Folder {
|
if settings.export_format == ExportFormat::Folder || settings.export_level_index == 999 {
|
||||||
let mut dialog = FileDialog::new().set_title("Export composite masks folder");
|
let title = if settings.export_level_index == 999 {
|
||||||
|
"Select export folder for all levels"
|
||||||
|
} else {
|
||||||
|
"Export composite masks folder"
|
||||||
|
};
|
||||||
|
let mut dialog = FileDialog::new().set_title(title);
|
||||||
if let Some(ref last_path) = settings.last_export_path {
|
if let Some(ref last_path) = settings.last_export_path {
|
||||||
dialog = dialog.set_directory(last_path);
|
dialog = dialog.set_directory(last_path);
|
||||||
}
|
}
|
||||||
@@ -173,40 +178,74 @@ pub fn select_export_target(settings: &UiSettings) -> Result<ExportTarget, Strin
|
|||||||
|
|
||||||
// Export the current layout to the chosen file or folder target.
|
// Export the current layout to the chosen file or folder target.
|
||||||
pub fn export_to_target(
|
pub fn export_to_target(
|
||||||
layout: &DungeonLayout,
|
layouts: &[DungeonLayout],
|
||||||
settings: &UiSettings,
|
settings: &UiSettings,
|
||||||
target: ExportTarget,
|
target: ExportTarget,
|
||||||
) -> Result<PathBuf, String> {
|
) -> Result<PathBuf, String> {
|
||||||
|
let export_indices: Vec<usize> = if settings.export_level_index == 999 {
|
||||||
|
(0..layouts.len()).collect()
|
||||||
|
} else {
|
||||||
|
let idx = settings
|
||||||
|
.export_level_index
|
||||||
|
.min(layouts.len().saturating_sub(1));
|
||||||
|
vec![idx]
|
||||||
|
};
|
||||||
|
|
||||||
match target {
|
match target {
|
||||||
ExportTarget::Folder(folder) => {
|
ExportTarget::Folder(folder) => {
|
||||||
export_composite_masks(layout, settings, &folder)?;
|
for &idx in &export_indices {
|
||||||
|
let layout = &layouts[idx];
|
||||||
|
if settings.export_format == ExportFormat::Folder {
|
||||||
|
let subfolder = if settings.export_level_index == 999 {
|
||||||
|
folder.join(format!("level {}", idx + 1))
|
||||||
|
} else {
|
||||||
|
folder.clone()
|
||||||
|
};
|
||||||
|
export_composite_masks(layout, settings, &subfolder)?;
|
||||||
|
} else {
|
||||||
|
let ext = settings.export_format.extension();
|
||||||
|
let filename = format!("level{}.{ext}", idx + 1);
|
||||||
|
let path = folder.join(filename);
|
||||||
|
save_layout_to_file(layout, settings, &path)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(folder)
|
Ok(folder)
|
||||||
}
|
}
|
||||||
ExportTarget::File(path) => {
|
ExportTarget::File(path) => {
|
||||||
match settings.export_format {
|
let idx = export_indices[0];
|
||||||
ExportFormat::Svg => {
|
save_layout_to_file(&layouts[idx], settings, &path)?;
|
||||||
let svg = build_svg(layout, settings);
|
|
||||||
std::fs::write(&path, svg).map_err(|e| format!("Failed writing SVG: {e}"))?;
|
|
||||||
}
|
|
||||||
ExportFormat::Png | ExportFormat::Jpeg | ExportFormat::Webp => {
|
|
||||||
let pixmap = render_pixmap(layout, settings)?;
|
|
||||||
let img = raster_image_from_pixmap(&pixmap, settings)?;
|
|
||||||
let format = match settings.export_format {
|
|
||||||
ExportFormat::Png => ImageFormat::Png,
|
|
||||||
ExportFormat::Jpeg => ImageFormat::Jpeg,
|
|
||||||
ExportFormat::Webp => ImageFormat::WebP,
|
|
||||||
ExportFormat::Svg | ExportFormat::Folder => unreachable!(),
|
|
||||||
};
|
|
||||||
img.save_with_format(&path, format)
|
|
||||||
.map_err(|e| format!("Failed writing image: {e}"))?;
|
|
||||||
}
|
|
||||||
ExportFormat::Folder => unreachable!(),
|
|
||||||
}
|
|
||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn save_layout_to_file(
|
||||||
|
layout: &DungeonLayout,
|
||||||
|
settings: &UiSettings,
|
||||||
|
path: &std::path::Path,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
match settings.export_format {
|
||||||
|
ExportFormat::Svg => {
|
||||||
|
let svg = build_svg(layout, settings);
|
||||||
|
std::fs::write(path, svg).map_err(|e| format!("Failed writing SVG: {e}"))?;
|
||||||
|
}
|
||||||
|
ExportFormat::Png | ExportFormat::Jpeg | ExportFormat::Webp => {
|
||||||
|
let pixmap = render_pixmap(layout, settings)?;
|
||||||
|
let img = raster_image_from_pixmap(&pixmap, settings)?;
|
||||||
|
let format = match settings.export_format {
|
||||||
|
ExportFormat::Png => ImageFormat::Png,
|
||||||
|
ExportFormat::Jpeg => ImageFormat::Jpeg,
|
||||||
|
ExportFormat::Webp => ImageFormat::WebP,
|
||||||
|
ExportFormat::Svg | ExportFormat::Folder => unreachable!(),
|
||||||
|
};
|
||||||
|
img.save_with_format(path, format)
|
||||||
|
.map_err(|e| format!("Failed writing image: {e}"))?;
|
||||||
|
}
|
||||||
|
ExportFormat::Folder => unreachable!(),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// Render the dungeon layout to a pixmap.
|
// Render the dungeon layout to a pixmap.
|
||||||
fn render_pixmap(layout: &DungeonLayout, settings: &UiSettings) -> Result<Pixmap, String> {
|
fn render_pixmap(layout: &DungeonLayout, settings: &UiSettings) -> Result<Pixmap, String> {
|
||||||
let g = ExportGeometry::new(settings.cols, settings.rows);
|
let g = ExportGeometry::new(settings.cols, settings.rows);
|
||||||
|
|||||||
+8
-14
@@ -223,20 +223,14 @@ impl eframe::App for DungeonApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let export_idx = self
|
let layouts = self.levels.clone();
|
||||||
.settings
|
let settings = self.settings.clone();
|
||||||
.export_level_index
|
let (tx, rx) = mpsc::channel();
|
||||||
.min(self.levels.len().saturating_sub(1));
|
thread::spawn(move || {
|
||||||
if export_idx < self.levels.len() {
|
let result = exporter::export_to_target(&layouts, &settings, target);
|
||||||
let layout = self.levels[export_idx].clone();
|
let _ = tx.send(result);
|
||||||
let settings = self.settings.clone();
|
});
|
||||||
let (tx, rx) = mpsc::channel();
|
self.export_rx = Some(rx);
|
||||||
thread::spawn(move || {
|
|
||||||
let result = exporter::export_to_target(&layout, &settings, target);
|
|
||||||
let _ = tx.send(result);
|
|
||||||
});
|
|
||||||
self.export_rx = Some(rx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(rx) = &self.export_rx {
|
if let Some(rx) = &self.export_rx {
|
||||||
|
|||||||
@@ -432,14 +432,20 @@ fn draw_generate_tab(
|
|||||||
let level_count = num_levels;
|
let level_count = num_levels;
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label("Level");
|
ui.label("Level");
|
||||||
|
let selected_text = if settings.export_level_index == 999 {
|
||||||
|
"All Levels".to_string()
|
||||||
|
} else {
|
||||||
|
format!("Level {}", settings.export_level_index + 1)
|
||||||
|
};
|
||||||
egui::ComboBox::from_id_salt("export_level")
|
egui::ComboBox::from_id_salt("export_level")
|
||||||
.selected_text(format!("Level {}", settings.export_level_index))
|
.selected_text(selected_text)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
|
ui.selectable_value(&mut settings.export_level_index, 999, "All Levels");
|
||||||
for i in 0..level_count {
|
for i in 0..level_count {
|
||||||
ui.selectable_value(
|
ui.selectable_value(
|
||||||
&mut settings.export_level_index,
|
&mut settings.export_level_index,
|
||||||
i,
|
i,
|
||||||
format!("Level {}", i),
|
format!("Level {}", i + 1),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user