Fix IMPORT naming, messages and 3D Studio limits

STEP assemblies: a link that closes a loop in the assembly is dropped,
so no block inserts itself; the walk is iterative. Each imported block
gets a name the drawing does not use yet instead of silently reusing an
existing definition, inserts are pointed at the names the blocks got,
and an insert of a block that could not be defined is left out with
the error reported.

Names that come from files (STEP products, 3D Studio objects, materials
and cameras, WMF font faces) go through a new shared
scene::sanitized_table_name, which applies the block-name rules
(reserved and control characters, 255 characters).

3D Studio: meshes with more vertices than a polyface mesh can index are
split over several meshes. Single-layer mode uses the current layer.
Materials are only created when the drawing has a material dictionary.
Camera views get the current view's proportions and the perspective
flag.

Messages show paths as given, the file-not-found and read-failure
messages are plain text of our own, and the "Press Esc" line is gone
since the import cannot be cancelled. The true-colour packing is
shared. "Select ACIS File" and "Import WMF" get catalog entries and
keys in all 22 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-10-16 23:20:03 +03:00
1 parent dbc428b237
commit a0ed20df28
28 files changed
+205 -88

No files matched your search

+2
View File
@@ -1250,6 +1250,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = اختيار ملف ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6683,6 +6684,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = استيراد WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1237,6 +1237,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Избор на ACIS файл
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6671,6 +6672,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Импортиране на WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1237,6 +1237,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Vybrat soubor ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6668,6 +6669,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Importovat WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1238,6 +1238,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = ACIS-Datei auswählen
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6669,6 +6670,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = WMF importieren
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1239,6 +1239,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Επιλογή αρχείου ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6671,6 +6672,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Εισαγωγή WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1236,6 +1236,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Select ACIS File
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = Select External Reference File .select-external-reference-file = Select External Reference File
.cad-files = CAD Files .cad-files = CAD Files
@@ -6670,6 +6671,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Import WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1238,6 +1238,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Seleccionar archivo ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6671,6 +6672,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Importar WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1237,6 +1237,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Valitse ACIS-tiedosto
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6668,6 +6669,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Tuo WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1238,6 +1238,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Sélectionner un fichier ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6671,6 +6672,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Importer un WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1226,6 +1226,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = ACIS फ़ाइल चुनें
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6659,6 +6660,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = WMF आयात करें
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1242,6 +1242,7 @@ common =
.dgn-files = DGN-fájlok .dgn-files = DGN-fájlok
.select-dwf-file = DWF-fájl kiválasztása .select-dwf-file = DWF-fájl kiválasztása
.select-dgn-file = DGN-fájl kiválasztása .select-dgn-file = DGN-fájl kiválasztása
.select-acis-file = ACIS-fájl kiválasztása
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6655,6 +6656,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = WMF importálása
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1237,6 +1237,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Seleziona file ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6670,6 +6671,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Importa WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1228,6 +1228,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = ACIS ファイルを選択
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6659,6 +6660,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = WMF を読み込み
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1237,6 +1237,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = ACIS 파일 선택
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6670,6 +6671,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = WMF 가져오기
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1243,6 +1243,7 @@ common =
.dgn-files = ໄຟລ໌ DGN .dgn-files = ໄຟລ໌ DGN
.select-dwf-file = ເລືອກໄຟລ໌ DWF .select-dwf-file = ເລືອກໄຟລ໌ DWF
.select-dgn-file = ເລືອກໄຟລ໌ DGN .select-dgn-file = ເລືອກໄຟລ໌ DGN
.select-acis-file = ເລືອກໄຟລ໌ ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = ເລືອກໄຟລ໌ອ້າງອີງພາຍນອກ .select-external-reference-file = ເລືອກໄຟລ໌ອ້າງອີງພາຍນອກ
.cad-files = ໄຟລ໌ CAD .cad-files = ໄຟລ໌ CAD
@@ -6671,6 +6672,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = ນຳເຂົ້າ WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1236,6 +1236,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = ACIS-bestand selecteren
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6669,6 +6670,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = WMF importeren
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1237,6 +1237,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Wybierz plik ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6670,6 +6671,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Importuj WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1238,6 +1238,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Selecionar arquivo ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6671,6 +6672,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Importar WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1241,6 +1241,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = Выбор файла ACIS
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6672,6 +6673,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = Импорт WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1224,6 +1224,7 @@ common =
.dgn-files = DGN Dosyaları .dgn-files = DGN Dosyaları
.select-dwf-file = DWF Dosyası Seç .select-dwf-file = DWF Dosyası Seç
.select-dgn-file = DGN Dosyası Seç .select-dgn-file = DGN Dosyası Seç
.select-acis-file = ACIS Dosyası Seç
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6592,6 +6593,7 @@ dgn-import =
.import-file = Dosya İçe Aktar .import-file = Dosya İçe Aktar
.dgn-import = DGN İçe Aktar .dgn-import = DGN İçe Aktar
.import-dgn-file = DGN Dosyası İçe Aktar .import-dgn-file = DGN Dosyası İçe Aktar
.import-wmf = WMF İçe Aktar
.help-dgn = DGN modelini çizim nesneleri olarak içe aktarır: seviyeler katman, hücreler blok olur. .help-dgn = DGN modelini çizim nesneleri olarak içe aktarır: seviyeler katman, hücreler blok olur.
.help-import = Seçilen biçimdeki dosyayı o biçimin içe aktarıcısıyla içe aktarır. .help-import = Seçilen biçimdeki dosyayı o biçimin içe aktarıcısıyla içe aktarır.
.blank = Dosya adı boş olamaz .blank = Dosya adı boş olamaz
+2
View File
@@ -1225,6 +1225,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = 选择 ACIS 文件
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6654,6 +6655,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = 导入 WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+2
View File
@@ -1237,6 +1237,7 @@ common =
.dgn-files = DGN Files .dgn-files = DGN Files
.select-dwf-file = Select DWF File .select-dwf-file = Select DWF File
.select-dgn-file = Select DGN File .select-dgn-file = Select DGN File
.select-acis-file = 選擇 ACIS 檔案
.pdfattach = PDFATTACH: __ocs_fmt_0__ .pdfattach = PDFATTACH: __ocs_fmt_0__
.select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files } .select-external-reference-file = { draw.select } · { properties.external-reference } · { common.files }
.cad-files = { common.files } (CAD) .cad-files = { common.files } (CAD)
@@ -6666,6 +6667,7 @@ dgn-import =
.import-file = Import File .import-file = Import File
.dgn-import = DGN Import .dgn-import = DGN Import
.import-dgn-file = Import DGN File .import-dgn-file = Import DGN File
.import-wmf = 匯入 WMF
.help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks. .help-dgn = Imports a DGN model as drawing objects: levels as layers, cells as blocks.
.help-import = Imports a file of the chosen format with the format's importer. .help-import = Imports a file of the chosen format with the format's importer.
.blank = Filename cannot be blank .blank = Filename cannot be blank
+53 -39
View File
@@ -3,6 +3,8 @@
//! as one undo step. //! as one undo step.
use super::*; use super::*;
use std::collections::HashMap;
use crate::io::model_import::{self, ModelFormat}; use crate::io::model_import::{self, ModelFormat};
impl OpenCADStudio { impl OpenCADStudio {
@@ -36,9 +38,8 @@ impl OpenCADStudio {
let here = std::env::current_dir() let here = std::env::current_dir()
.map(|d| d.display().to_string()) .map(|d| d.display().to_string())
.unwrap_or_default(); .unwrap_or_default();
self.command_line.push_error(&format!( self.command_line
"\"{name}\": Can't find file in search path:\n {here}\\ (current directory)" .push_error(&format!("\"{name}\": file not found in the current directory, {here}"));
));
return Some(Task::none()); return Some(Task::none());
} }
Some(self.import_model(i, rest, ModelFormat::Sat)) Some(self.import_model(i, rest, ModelFormat::Sat))
@@ -82,40 +83,48 @@ impl OpenCADStudio {
.push_error(&format!("File {path} does not exist.")); .push_error(&format!("File {path} does not exist."));
return Task::none(); return Task::none();
}; };
// The translated formats report the job as they run.
let translated = format != ModelFormat::Sat; let translated = format != ModelFormat::Sat;
if translated {
self.command_line
.push_output("Import job in progress. Press Esc key to cancel.");
}
let drawing_mm = crate::app::properties::insunits_to_mm( let drawing_mm = crate::app::properties::insunits_to_mm(
self.tabs[i].scene.document.header.insertion_units, self.tabs[i].scene.document.header.insertion_units,
); );
let Some(imported) = model_import::read(format, &bytes, drawing_mm) else { let Some(imported) = model_import::read(format, &bytes, drawing_mm) else {
let shown = path.replace('/', "\\"); self.command_line
match format { .push_error(&format!("Import failed: {path} has no model the importer reads."));
ModelFormat::Sat => {
self.command_line.push_error("Modeling Operation Error:");
self.command_line.push_error("Error Code Number is 58000");
self.command_line
.push_error(&format!("Unable to read the ACIS file {shown}."));
}
_ => self
.command_line
.push_error(&format!("Import failed: {shown} has no model the importer reads.")),
}
return Task::none(); return Task::none();
}; };
self.push_undo_snapshot(i, "IMPORT"); self.push_undo_snapshot(i, "IMPORT");
let scene = &mut self.tabs[i].scene; let scene = &mut self.tabs[i].scene;
// A block the drawing already has keeps its definition and is // Each block goes under a name the drawing does not use yet (a
// inserted as it is. // product named like a block already there gets a new name, not the
// old definition), and the inserts are pointed at the names the
// blocks got. An insert of a block that could not be made is left
// out.
fn retarget(entities: Vec<codec::EntityType>, defined: &HashMap<String, String>) -> Vec<codec::EntityType> {
entities
.into_iter()
.filter_map(|entity| match entity {
codec::EntityType::Insert(mut insert) => {
insert.block_name = defined.get(&insert.block_name)?.clone();
Some(codec::EntityType::Insert(insert))
}
other => Some(other),
})
.collect()
}
let mut taken: Vec<String> = scene.document.block_records.iter().map(|b| b.name.clone()).collect();
let mut defined: HashMap<String, String> = HashMap::new();
for (name, entities) in imported.blocks { for (name, entities) in imported.blocks {
if scene.document.block_records.get(&name).is_none() { let unique = crate::modules::insert::xattach::unique_block_name(&name, &taken);
let _ = scene.define_block_from_owned_entities(entities, &name, glam::DVec3::ZERO); let entities = retarget(entities, &defined);
match scene.define_block_from_owned_entities(entities, &unique, glam::DVec3::ZERO) {
Ok(_) => {
taken.push(unique.clone());
defined.insert(name, unique);
}
Err(error) => self.command_line.push_error(&format!("{name}: {error}")),
} }
} }
for entity in imported.entities { for entity in retarget(imported.entities, &defined) {
scene.add_entity(entity); scene.add_entity(entity);
} }
self.tabs[i].dirty = true; self.tabs[i].dirty = true;
@@ -140,7 +149,7 @@ impl OpenCADStudio {
crate::io::wmf_import::read(&bytes, [0.5 * size[0], 0.5 * size[1]]) crate::io::wmf_import::read(&bytes, [0.5 * size[0], 0.5 * size[1]])
else { else {
self.command_line self.command_line
.push_error(&format!("{} is not a valid Windows metafile.", path.replace('/', "\\"))); .push_error(&format!("{path} is not a valid Windows metafile."));
return Task::none(); return Task::none();
}; };
self.push_undo_snapshot(i, if prompt { "WMFIN" } else { "IMPORT" }); self.push_undo_snapshot(i, if prompt { "WMFIN" } else { "IMPORT" });
@@ -152,7 +161,8 @@ impl OpenCADStudio {
let mut styles: Vec<String> = Vec::new(); let mut styles: Vec<String> = Vec::new();
for (k, face) in picture.fonts.iter().enumerate() { for (k, face) in picture.fonts.iter().enumerate() {
let n = picture.fonts[..k].iter().filter(|f| f.name == face.name).count(); let n = picture.fonts[..k].iter().filter(|f| f.name == face.name).count();
let name = format!("WMF-{}{n}", face.name); // The face name comes from the file.
let name = crate::scene::sanitized_table_name(&format!("WMF-{}{n}", face.name), "WMF");
if !scene.document.text_styles.contains(&name) { if !scene.document.text_styles.contains(&name) {
let mut style = codec::tables::TextStyle::new(name.as_str()); let mut style = codec::tables::TextStyle::new(name.as_str());
style.handle = scene.document.allocate_handle(); style.handle = scene.document.allocate_handle();
@@ -210,7 +220,7 @@ impl OpenCADStudio {
pub(in crate::app) fn open_tds_import_dialog(&mut self, path: &str) -> Result<(), String> { pub(in crate::app) fn open_tds_import_dialog(&mut self, path: &str) -> Result<(), String> {
let scene = crate::scene::model::pdf_raster::source_bytes(path) let scene = crate::scene::model::pdf_raster::source_bytes(path)
.and_then(|bytes| crate::io::tds_import::read(&bytes)) .and_then(|bytes| crate::io::tds_import::read(&bytes))
.ok_or_else(|| format!("{} is not a valid 3D Studio file.", path.replace('/', "\\")))?; .ok_or_else(|| format!("{path} is not a valid 3D Studio file."))?;
let mut objects: Vec<(String, &'static str, usize)> = scene let mut objects: Vec<(String, &'static str, usize)> = scene
.objects .objects
.iter() .iter()
@@ -322,10 +332,8 @@ impl OpenCADStudio {
let Some(scene) = crate::scene::model::pdf_raster::source_bytes(&request.path) let Some(scene) = crate::scene::model::pdf_raster::source_bytes(&request.path)
.and_then(|bytes| crate::io::tds_import::read(&bytes)) .and_then(|bytes| crate::io::tds_import::read(&bytes))
else { else {
self.command_line.push_error(&format!( self.command_line
"{} is not a valid 3D Studio file.", .push_error(&format!("{} is not a valid 3D Studio file.", request.path));
request.path.replace('/', "\\")
));
return; return;
}; };
let import = crate::io::tds_import::convert( let import = crate::io::tds_import::convert(
@@ -335,10 +343,18 @@ impl OpenCADStudio {
layers: request.layers, layers: request.layers,
multi: request.multi.clone(), multi: request.multi.clone(),
compact: request.compact, compact: request.compact,
single_layer: self.tabs[i].scene.document.header.current_layer_name.clone(),
}, },
); );
// Named views take the current view's proportions.
let (_, size, _) = self.tabs[i].scene.view_window();
let aspect = if size[0] > 0.0 && size[1] > 0.0 { size[0] / size[1] } else { 1.0 };
self.push_undo_snapshot(i, "IMPORT"); self.push_undo_snapshot(i, "IMPORT");
let document = &mut self.tabs[i].scene.document; let document = &mut self.tabs[i].scene.document;
// Materials live in the material dictionary; a drawing without one
// imports the meshes without materials.
let dictionary = document.header.acad_material_dict_handle;
let has_dictionary = matches!(document.objects.get(&dictionary), Some(ObjectType::Dictionary(_)));
// Materials by name: the drawing's own when it has one, else one // Materials by name: the drawing's own when it has one, else one
// made from the file's colours. // made from the file's colours.
let mut materials: std::collections::HashMap<String, codec::Handle> = Default::default(); let mut materials: std::collections::HashMap<String, codec::Handle> = Default::default();
@@ -349,20 +365,18 @@ impl OpenCADStudio {
}); });
let handle = match existing { let handle = match existing {
Some(h) => h, Some(h) => h,
None if !has_dictionary => continue,
None => { None => {
let source = scene.materials.iter().find(|m| m.name == *name); let source = scene.materials.iter().find(|m| m.name == *name);
let mut material = codec::objects::Material::new(); let mut material = codec::objects::Material::new();
material.handle = document.allocate_handle(); material.handle = document.allocate_handle();
material.owner = document.header.acad_material_dict_handle; material.owner = dictionary;
material.name = name.clone(); material.name = name.clone();
let color = |rgb: Option<[u8; 3]>| match rgb { let color = |rgb: Option<[u8; 3]>| match rgb {
Some([r, g, b]) => codec::objects::MaterialColor { Some([r, g, b]) => codec::objects::MaterialColor {
flag: 1, flag: 1,
factor: 1.0, factor: 1.0,
rgb: Some( rgb: Some(crate::scene::convert::acis_import::packed_true_colour(r, g, b)),
((0xC2u32 << 24) | (u32::from(r) << 16) | (u32::from(g) << 8) | u32::from(b))
as i32,
),
}, },
None => codec::objects::MaterialColor::default(), None => codec::objects::MaterialColor::default(),
}; };
@@ -370,7 +384,6 @@ impl OpenCADStudio {
material.diffuse_color = color(source.and_then(|m| m.diffuse)); material.diffuse_color = color(source.and_then(|m| m.diffuse));
material.specular_color = color(source.and_then(|m| m.specular)); material.specular_color = color(source.and_then(|m| m.specular));
let handle = material.handle; let handle = material.handle;
let dictionary = document.header.acad_material_dict_handle;
if let Some(ObjectType::Dictionary(dictionary)) = document.objects.get_mut(&dictionary) { if let Some(ObjectType::Dictionary(dictionary)) = document.objects.get_mut(&dictionary) {
dictionary.add_entry(name.clone(), handle); dictionary.add_entry(name.clone(), handle);
} }
@@ -393,8 +406,9 @@ impl OpenCADStudio {
named.direction = named.direction =
codec::types::Vector3::new(view.direction[0], view.direction[1], view.direction[2]); codec::types::Vector3::new(view.direction[0], view.direction[1], view.direction[2]);
named.height = view.height; named.height = view.height;
named.width = view.height; named.width = view.height * aspect;
named.lens_length = view.lens; named.lens_length = view.lens;
named.perspective = true;
named.handle = match document.views.get(&view.name) { named.handle = match document.views.get(&view.name) {
Some(old) => old.handle, Some(old) => old.handle,
None => document.allocate_handle(), None => document.allocate_handle(),
+39 -21
View File
@@ -30,19 +30,14 @@ fn ratio(file_mm: f64, drawing_mm: Option<f64>) -> f64 {
/// A block name from a product's, with the characters names cannot hold /// A block name from a product's, with the characters names cannot hold
/// replaced. /// replaced.
fn block_name(name: &str) -> String { fn block_name(name: &str) -> String {
let name: String = name crate::scene::sanitized_table_name(name, "Part")
.trim()
.chars()
.map(|c| if "<>/\\\":;?*|,=`".contains(c) { '_' } else { c })
.collect();
if name.is_empty() { "Part".to_string() } else { name }
} }
/// A STEP presentation colour as the drawing colour it imports as: the /// A STEP presentation colour as the drawing colour it imports as: the
/// standard index colour it is close to — red, yellow, green, cyan, blue, /// standard index colour it is close to — red, yellow, green, cyan, blue,
/// magenta, white, or the dark grey 250 (which black also becomes) — and /// magenta, white, or the dark grey 250 (which black also becomes) — and
/// otherwise the true colour. /// otherwise the true colour.
// ponytail: the closeness bands are fitted to measured imports (saturation // ponytail: the closeness bands are fitted to sample files (saturation
// at least 0.75, value at least 0.825 and hue within 7.5 degrees for the six // at least 0.75, value at least 0.825 and hue within 7.5 degrees for the six
// hues; greys from 0.16 to 0.39 for 250 and from 0.935 for white); refit // hues; greys from 0.16 to 0.39 for 250 and from 0.935 for white); refit
// them if a colour on a band edge comes out differently. // them if a colour on a band edge comes out differently.
@@ -114,22 +109,43 @@ fn step_blocks(model: crate::io::step_import::StepModel, scale: f64) -> Imported
} }
names.push(name); names.push(name);
} }
// Children before parents. // Children before parents. A link that closes a loop in the file's
// assembly (a product that would contain itself) is dropped, so no
// block ends up inserting itself.
let mut order = Vec::new(); let mut order = Vec::new();
let mut dropped: std::collections::HashSet<(usize, usize)> = Default::default();
let mut state = vec![0u8; model.products.len()]; let mut state = vec![0u8; model.products.len()];
fn visit(k: usize, model: &crate::io::step_import::StepModel, state: &mut [u8], order: &mut Vec<usize>) {
if state[k] != 0 {
return;
}
state[k] = 1;
for (child, _) in &model.products[k].children {
visit(*child, model, state, order);
}
state[k] = 2;
order.push(k);
}
for &root in &model.roots { for &root in &model.roots {
visit(root, &model, &mut state, &mut order); if state[root] != 0 {
continue;
}
state[root] = 1;
// Each product being walked and the next of its children to visit.
let mut stack = vec![(root, 0usize)];
while let Some((k, next)) = stack.last_mut() {
let k = *k;
match model.products[k].children.get(*next) {
Some(&(child, _)) => {
let link = (k, *next);
*next += 1;
match state[child] {
0 => {
state[child] = 1;
stack.push((child, 0));
}
1 => {
dropped.insert(link);
}
_ => {}
}
}
None => {
state[k] = 2;
order.push(k);
stack.pop();
}
}
}
} }
let blocks = order let blocks = order
.iter() .iter()
@@ -147,7 +163,9 @@ fn step_blocks(model: crate::io::step_import::StepModel, scale: f64) -> Imported
product product
.children .children
.iter() .iter()
.map(|(child, placement)| { .enumerate()
.filter(|(n, _)| !dropped.contains(&(k, *n)))
.map(|(_, (child, placement))| {
let mut insert = placed_insert(&names[*child], placement); let mut insert = placed_insert(&names[*child], placement);
insert.common_mut().color = Color::ByBlock; insert.common_mut().color = Color::ByBlock;
insert insert
+42 -21
View File
@@ -8,6 +8,8 @@ use std::collections::HashMap;
use codec::entities::{PolyfaceFace, PolyfaceMesh, PolyfaceVertex}; use codec::entities::{PolyfaceFace, PolyfaceMesh, PolyfaceVertex};
use codec::types::Vector3; use codec::types::Vector3;
use crate::scene::sanitized_table_name;
pub struct TdsMaterial { pub struct TdsMaterial {
pub name: String, pub name: String,
pub ambient: Option<[u8; 3]>, pub ambient: Option<[u8; 3]>,
@@ -258,6 +260,8 @@ pub struct TdsOptions {
/// they first use them — as they do when the import splits by /// they first use them — as they do when the import splits by
/// material or asks — rather than the file's vertex list. /// material or asks — rather than the file's vertex list.
pub compact: bool, pub compact: bool,
/// The layer every mesh goes on with [`LayerMode::Single`].
pub single_layer: String,
} }
/// One imported mesh. /// One imported mesh.
@@ -284,14 +288,24 @@ pub struct TdsImport {
pub messages: Vec<String>, pub messages: Vec<String>,
} }
/// A polyface mesh of `faces` of `mesh`: its vertices in file order, or /// Polyface meshes of `faces` of `mesh`: its vertices in file order, or
/// (`compact`) only those the faces use, in the order they first use them. /// (`compact`) only those the faces use, in the order they first use them.
fn polyface(mesh: &TdsMesh, faces: &[usize], compact: bool) -> PolyfaceMesh { /// A polyface mesh numbers its vertices in 16 bits, so a mesh with more
let mut out = PolyfaceMesh::new(); /// vertices than that is always compact, and the faces that need further
/// vertices go on further meshes.
fn polyfaces(mesh: &TdsMesh, faces: &[usize], compact: bool) -> Vec<PolyfaceMesh> {
const MAX_VERTICES: usize = i16::MAX as usize;
let compact = compact || mesh.vertices.len() > MAX_VERTICES;
let vertex = |v: usize| {
let p = mesh.vertices[v];
PolyfaceVertex::new(Vector3::new(p[0], p[1], p[2]))
};
let mut out = Vec::new();
let mut current = PolyfaceMesh::new();
let mut index: HashMap<usize, i16> = HashMap::new(); let mut index: HashMap<usize, i16> = HashMap::new();
if !compact { if !compact {
for (k, v) in mesh.vertices.iter().enumerate() { for k in 0..mesh.vertices.len() {
index.insert(k, out.add_vertex(PolyfaceVertex::new(Vector3::new(v[0], v[1], v[2])))); index.insert(k, current.add_vertex(vertex(k)));
} }
} }
for &f in faces { for &f in faces {
@@ -299,14 +313,15 @@ fn polyface(mesh: &TdsMesh, faces: &[usize], compact: bool) -> PolyfaceMesh {
if face.iter().any(|v| *v >= mesh.vertices.len()) { if face.iter().any(|v| *v >= mesh.vertices.len()) {
continue; continue;
} }
let ids = face.map(|v| { let new = face.iter().filter(|v| !index.contains_key(v)).count();
*index.entry(v).or_insert_with(|| { if current.vertices.len() + new > MAX_VERTICES {
let p = mesh.vertices[v]; out.push(std::mem::replace(&mut current, PolyfaceMesh::new()));
out.add_vertex(PolyfaceVertex::new(Vector3::new(p[0], p[1], p[2]))) index.clear();
}) }
}); let ids = face.map(|v| *index.entry(v).or_insert_with(|| current.add_vertex(vertex(v))));
out.add_face(PolyfaceFace::triangle(ids[0], ids[1], ids[2])); current.add_face(PolyfaceFace::triangle(ids[0], ids[1], ids[2]));
} }
out.push(current);
out out
} }
@@ -365,24 +380,30 @@ pub fn convert(scene: &TdsScene, options: &TdsOptions) -> TdsImport {
out.materials.push(m.clone()); out.materials.push(m.clone());
} }
} }
// Object and material names come from the file, so they
// are made fit to name a layer.
let layer = match options.layers { let layer = match options.layers {
LayerMode::ByObject => name.to_uppercase(), LayerMode::ByObject => sanitized_table_name(&name.to_uppercase(), "0"),
LayerMode::ByMaterial => material.as_deref().unwrap_or("0").to_uppercase(), LayerMode::ByMaterial => {
sanitized_table_name(&material.as_deref().unwrap_or("0").to_uppercase(), "0")
}
LayerMode::ByObjectColor => match mesh.color { LayerMode::ByObjectColor => match mesh.color {
Some(c) => format!("COLOR{c:02}"), Some(c) => format!("COLOR{c:02}"),
None => "COLORNONE".to_string(), None => "COLORNONE".to_string(),
}, },
LayerMode::Single => "AVLAYER".to_string(), LayerMode::Single => options.single_layer.clone(),
}; };
out.parts.push(TdsPart { for polyface in polyfaces(mesh, &faces, compact) {
layer, out.parts.push(TdsPart {
material, layer: layer.clone(),
mesh: polyface(mesh, &faces, compact), material: material.clone(),
}); mesh: polyface,
});
}
} }
} }
TdsObject::Camera(camera) => { TdsObject::Camera(camera) => {
let name = name.to_uppercase(); let name = sanitized_table_name(&name.to_uppercase(), "CAMERA");
out.messages.push(format!("Creating camera {name}")); out.messages.push(format!("Creating camera {name}"));
let direction = [0, 1, 2].map(|k| camera.position[k] - camera.target[k]); let direction = [0, 1, 2].map(|k| camera.position[k] - camera.target[k]);
let distance = direction.iter().map(|d| d * d).sum::<f64>().sqrt(); let distance = direction.iter().map(|d| d * d).sum::<f64>().sqrt();
+2
View File
@@ -3501,6 +3501,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
"Import File" => Some(("dgn-import", "import-file")), "Import File" => Some(("dgn-import", "import-file")),
"DGN Import" => Some(("dgn-import", "dgn-import")), "DGN Import" => Some(("dgn-import", "dgn-import")),
"Import DGN File" => Some(("dgn-import", "import-dgn-file")), "Import DGN File" => Some(("dgn-import", "import-dgn-file")),
"Import WMF" => Some(("dgn-import", "import-wmf")),
"Imports a DGN model as drawing objects: levels as layers, cells as blocks." => Some(("dgn-import", "help-dgn")), "Imports a DGN model as drawing objects: levels as layers, cells as blocks." => Some(("dgn-import", "help-dgn")),
"Imports a file of the chosen format with the format's importer." => Some(("dgn-import", "help-import")), "Imports a file of the chosen format with the format's importer." => Some(("dgn-import", "help-import")),
"Filename cannot be blank" => Some(("dgn-import", "blank")), "Filename cannot be blank" => Some(("dgn-import", "blank")),
@@ -4425,6 +4426,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
"DGN Files" => Some(("common", "dgn-files")), "DGN Files" => Some(("common", "dgn-files")),
"Select DWF File" => Some(("common", "select-dwf-file")), "Select DWF File" => Some(("common", "select-dwf-file")),
"Select DGN File" => Some(("common", "select-dgn-file")), "Select DGN File" => Some(("common", "select-dgn-file")),
"Select ACIS File" => Some(("common", "select-acis-file")),
"PDFATTACH: {e}" => Some(("common", "pdfattach")), "PDFATTACH: {e}" => Some(("common", "pdfattach")),
"Select External Reference File" => Some(("common", "select-external-reference-file")), "Select External Reference File" => Some(("common", "select-external-reference-file")),
"CAD Files" => Some(("common", "cad-files")), "CAD Files" => Some(("common", "cad-files")),
+11 -7
View File
@@ -1,8 +1,7 @@
//! ACIS text (SAT) files and kernel bodies as drawing objects. //! ACIS text (SAT) files and kernel bodies as drawing objects.
//! //!
//! Each body of a file becomes one object: a closed solid a 3DSOLID, a sheet //! Each body of a file becomes one object: a closed solid a 3DSOLID, a sheet
//! whose faces all lie on planes a REGION, any other sheet a SURFACE — the //! whose faces all lie on planes a REGION, any other sheet a SURFACE.
//! classes the ACIS import of the reference application produces.
use codec::entities::acis::{SatDocument, SatFace, Sidedness}; use codec::entities::acis::{SatDocument, SatFace, Sidedness};
use codec::entities::{AcisData, Region, Solid3D, Surface, SurfaceKind}; use codec::entities::{AcisData, Region, Solid3D, Surface, SurfaceKind};
@@ -82,14 +81,19 @@ fn attribute_index(color: codec::types::Color) -> i64 {
} }
} }
/// A true colour packed as a 32-bit colour value: the true-colour flag
/// byte, then red, green and blue.
pub(crate) fn packed_true_colour(r: u8, g: u8, b: u8) -> i32 {
((0xC2u32 << 24) | (u32::from(r) << 16) | (u32::from(g) << 8) | u32::from(b)) as i32
}
/// Hangs colour attributes on a record: a true colour first, then its /// Hangs colour attributes on a record: a true colour first, then its
/// index, as imported models carry them. /// index, as imported models carry them.
fn paint_record(document: &mut codec::entities::acis::SatDocument, owner: usize, color: codec::types::Color) { fn paint_record(document: &mut codec::entities::acis::SatDocument, owner: usize, color: codec::types::Color) {
use codec::entities::acis::{SatPointer, SatRecord, SatToken}; use codec::entities::acis::{SatPointer, SatRecord, SatToken};
let mut chain: Vec<(&str, i64)> = Vec::new(); let mut chain: Vec<(&str, i64)> = Vec::new();
if let codec::types::Color::Rgb { r, g, b } = color { if let codec::types::Color::Rgb { r, g, b } = color {
let packed = (0xC2u32 << 24) | (u32::from(r) << 16) | (u32::from(g) << 8) | u32::from(b); chain.push(("truecolor-adesk-attrib", i64::from(packed_true_colour(r, g, b))));
chain.push(("truecolor-adesk-attrib", i64::from(packed as i32)));
} }
chain.push(("color-adesk-attrib", attribute_index(color))); chain.push(("color-adesk-attrib", attribute_index(color)));
let Some(existing) = document.record(owner).map(|record| record.attribute) else { let Some(existing) = document.record(owner).map(|record| record.attribute) else {
@@ -116,9 +120,9 @@ fn paint_record(document: &mut codec::entities::acis::SatDocument, owner: usize,
} }
/// A kernel body as its drawing object in `colour` (by block when `None`), /// A kernel body as its drawing object in `colour` (by block when `None`),
/// with the faces given a colour of their own carrying it — and the edges /// with the faces given a colour of their own carrying it, and the edges
/// bounding them too, as the reference modeler stores them. A `sheet` is a /// bounding those faces carrying it too. A `sheet` is a SURFACE however
/// SURFACE however flat it is. /// flat it is.
pub fn painted_body_entity( pub fn painted_body_entity(
body: &kernel::brep::Body, body: &kernel::brep::Body,
colour: Option<codec::types::Color>, colour: Option<codec::types::Color>,
+14
View File
@@ -1208,6 +1208,20 @@ pub(crate) fn valid_block_name(name: &str) -> bool {
}) })
} }
/// `raw` made fit to name a table entry (a block, layer, style or view):
/// characters [`valid_block_name`] refuses become `_`, the name is cut to
/// 255 characters, and `fallback` stands in when nothing is left. For names
/// that come from outside files.
pub(crate) fn sanitized_table_name(raw: &str, fallback: &str) -> String {
let name: String = raw
.trim()
.chars()
.map(|c| if valid_block_name(c.encode_utf8(&mut [0; 4])) { c } else { '_' })
.take(255)
.collect();
block_service::validate_block_name(&name).unwrap_or_else(|_| fallback.to_string())
}
/// Pre-built entity caches returned by [`build_derived_caches`]. /// Pre-built entity caches returned by [`build_derived_caches`].
/// Produced in the file-load background task so the UI thread only assigns. /// Produced in the file-load background task so the UI thread only assigns.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]