IMPORT: 3D Studio files

A .3ds file opens the 3D Studio Import window: the file's objects with
their kind and material count, filtered by kind or name, checked one by
one or all at once, where to put them on layers and what a mesh with
several materials becomes. Checked meshes come in as polyface meshes on
the chosen layers with materials made from the file's colours, cameras
as named views; a mesh with several materials is split, given its first
material, given none, or asked about on the command line. Automation
drives the window with tds_import_dialog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ramox81andClaude Opus 5.5 committed 2026-10-16 20:12:16 +03:00
1 parent 9ddc103bcc
commit 78e429732e
35 files changed
+1893 -4

No files matched your search

+40
View File
@@ -110,6 +110,7 @@ pub(super) const NAMES: &[&str] = &[
"image_adjust",
"import_file_dialog",
"dgn_import_dialog",
"tds_import_dialog",
"refedit_dialog",
"pdf_shx_settings",
"pdf_layer_toggle",
@@ -2198,6 +2199,45 @@ impl OpenCADStudio {
_ => return Err(bad()),
})
}
// The 3D Studio Import window, one field per call: "check=<name>"
// and "uncheck=<name>" (the object's name, or "Global Settings"),
// "all", "clear", "filter=all|mesh|light|camera|general",
// "search=<text>", "layers=object|material|color|single",
// "multi=ask|split|first|none", "path=<file>" (as Change… picks
// it), "ok" or "cancel".
"tds_import_dialog" => {
use crate::ui::window::import_dialogs::ImportDialogMsg as I;
if self.active_modal != Some(crate::app::ModalKind::TdsImport) {
return Err(failure("no_dialog", "The 3D Studio Import window is not open"));
}
let spec = string(req, "value")?;
let (key, value) = spec.split_once('=').unwrap_or((spec, ""));
let bad = || failure("invalid_value", spec);
if key == "cancel" {
return Ok(Task::done(Message::CloseModal));
}
let pick = |options: &[&str]| options.iter().position(|o| *o == value).ok_or_else(bad);
Message::ImportDialog(match key {
"ok" => I::TdsOk,
"all" => I::TdsAll,
"clear" => I::TdsClear,
"check" | "uncheck" => {
let k = self
.import_dialogs
.tds
.as_ref()
.and_then(|s| s.objects.iter().position(|(name, _, _)| name.eq_ignore_ascii_case(value)))
.ok_or_else(bad)?;
I::TdsCheck(k, key == "check")
}
"filter" => I::TdsFilter(pick(&["all", "mesh", "light", "camera", "general"])?),
"search" => I::TdsSearch(value.to_string()),
"layers" => I::TdsLayers(pick(&["object", "material", "color", "single"])?),
"multi" => I::TdsMulti(pick(&["ask", "split", "first", "none"])?),
"path" => I::TdsPicked(Some(value.to_string())),
_ => return Err(bad()),
})
}
// The DGN Import window, one field per call: "path=<file>" (as
// Change… picks it), "model=<n>", "target=new|current",
// "conflict=prefix|ignore", "units=master|sub", "explode=on|off",