From 1eae36e7267442231a5816042c2698d8381c50f6 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 6 Oct 2026 18:32:43 +0300 Subject: [PATCH] Cargo: codec 76d2a1c, kernel e652b4d, graph 0545fa9; text styles, templates, solid edges - Text styles keep their TrueType typeface through save and reopen (codec reads and writes the STYLE record's ACAD extended data) (#1633) - Unnamed shape-file entries no longer show in text style lists (#1634) - Save As offers DWT 2018; NEW asks for the template to start from, while Ctrl+N and the quick-access New run QNEW with the default template (#1635) - An edge next to an earlier fillet of the same radius rounds together with it (kernel); the solid stays drawn and pickable while edges are chosen (#1625, #1107) - A full cache rebuild drops the B-rep cache too, so an undone fillet does not come back with the next edge operation (#1107) - Selected solids in shaded styles highlight only their visible edges (#1031) - VIEW ISO / SWISO / SEISO / NEISO / NWISO snap to the isometric corners Co-Authored-By: Claude Opus 5.5 --- Cargo.lock | 8 ++++---- Cargo.toml | 9 ++++----- crates/ocs_plugin_api/Cargo.toml | 4 ++-- crates/ocs_web_worker/Cargo.toml | 2 +- locales/ar-SA/opencadstudio.ftl | 1 + locales/bg-BG/opencadstudio.ftl | 1 + locales/cs-CZ/opencadstudio.ftl | 1 + locales/de-DE/opencadstudio.ftl | 1 + locales/el-GR/opencadstudio.ftl | 1 + locales/en-US/opencadstudio.ftl | 1 + locales/es-ES/opencadstudio.ftl | 1 + locales/fi-FI/opencadstudio.ftl | 1 + locales/fr-FR/opencadstudio.ftl | 1 + locales/hi-IN/opencadstudio.ftl | 1 + locales/hu-HU/opencadstudio.ftl | 1 + locales/it-IT/opencadstudio.ftl | 1 + locales/ja-JP/opencadstudio.ftl | 1 + locales/ko-KR/opencadstudio.ftl | 1 + locales/nl-NL/opencadstudio.ftl | 1 + locales/pl-PL/opencadstudio.ftl | 1 + locales/pt-BR/opencadstudio.ftl | 1 + locales/ru-RU/opencadstudio.ftl | 1 + locales/tr-TR/opencadstudio.ftl | 1 + locales/zh-CN/opencadstudio.ftl | 1 + locales/zh-TW/opencadstudio.ftl | 1 + plugins/opencad-python/Cargo.lock | 2 +- src/app/commands/fileops.rs | 20 +++++++++++++++++++- src/app/commands/layerprops.rs | 21 +++++++++++++++++++-- src/app/commands/mod.rs | 1 + src/app/layers.rs | 7 ++++++- src/app/mod.rs | 2 ++ src/app/shortcuts.rs | 2 +- src/app/style_ops.rs | 9 ++++++++- src/app/update/file.rs | 2 ++ src/app/update/mod.rs | 16 ++++++++++++++++ src/app/view/modal.rs | 10 ++++++++-- src/io/mod.rs | 17 ++++++++++++----- src/locale_catalog.rs | 1 + src/modules/model/edge_cmd.rs | 10 +++++++++- src/scene/entity.rs | 4 ++++ src/scene/pipeline/mod.rs | 13 ++++++++----- src/ui/ribbon/mod.rs | 2 +- src/ui/window/options.rs | 3 ++- 43 files changed, 152 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66a68575d..e119430a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4205,7 +4205,7 @@ dependencies = [ [[package]] name = "opencadcodec" version = "0.6.0" -source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=aad7053#aad70533211bd9192545729f7eb3bccb827bcf30" +source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=76d2a1c#76d2a1c66702d9aaf3ef8d4ff7dc06f4a025da82" dependencies = [ "anyhow", "bitflags 2.13.1", @@ -4228,7 +4228,7 @@ dependencies = [ [[package]] name = "opencadgraph" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=263de59#263de5924e3fffcbb78377db5ed1117f50620666" +source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=0545fa9#0545fa9a9944160ac1a941c91ba3d4501de80a88" dependencies = [ "opencadkernel", "serde_json", @@ -4237,7 +4237,7 @@ dependencies = [ [[package]] name = "opencadkernel" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=1a52eaf#1a52eaf237949a4492a7b56907922218ab2d1ea9" +source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=e652b4d#e652b4dfcd8b1055a113a5818ecfa9af5e420be4" dependencies = [ "cavalier_contours", "opencadcodec", @@ -4248,7 +4248,7 @@ dependencies = [ [[package]] name = "opencadkernel-constraints" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=1a52eaf#1a52eaf237949a4492a7b56907922218ab2d1ea9" +source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=e652b4d#e652b4dfcd8b1055a113a5818ecfa9af5e420be4" dependencies = [ "nalgebra", ] diff --git a/Cargo.toml b/Cargo.toml index d328e0698..89ca17284 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,10 +34,10 @@ rfd = "0.17" clap = { version = "4", features = ["derive", "string"] } env_logger = "0.11" log = "0.4" -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "aad7053", features = ["serde"] } -kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "1a52eaf", features = ["acis", "offset"] } -kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "1a52eaf" } -graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "263de59" } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "76d2a1c", features = ["serde"] } +kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "e652b4d", features = ["acis", "offset"] } +kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "e652b4d" } +graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "0545fa9" } dwg-thumbnailer = { path = "crates/dwg-thumbnailer" } flate2 = "1" image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] } @@ -181,4 +181,3 @@ harness = false [[test]] name = "integration" path = "tests/integration.rs" - diff --git a/crates/ocs_plugin_api/Cargo.toml b/crates/ocs_plugin_api/Cargo.toml index 9ffb949a5..58e17f2b9 100644 --- a/crates/ocs_plugin_api/Cargo.toml +++ b/crates/ocs_plugin_api/Cargo.toml @@ -15,7 +15,7 @@ serde_json = { version = "1", optional = true } # Pulled in only by the `host` feature, which adds the `opencadcodec`-typed # `HostApi` runtime surface. The default crate stays dependency-free so engine # crates and external tooling can depend on the manifest/ribbon contract cheaply. -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "aad7053", optional = true, features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "76d2a1c", optional = true, features = ["serde"] } # Runtime IPC and serialization (host feature only). interprocess = { version = "2", optional = true } @@ -39,7 +39,7 @@ serde_json = "1" serde = { version = "1", features = ["derive"] } cargo-lock = "11" # opencadcodec is scanned at build time to generate the embedded type registry. -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "aad7053", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "76d2a1c", features = ["serde"] } [dev-dependencies] serde_json = "1" diff --git a/crates/ocs_web_worker/Cargo.toml b/crates/ocs_web_worker/Cargo.toml index c57e180c2..3da241eb1 100644 --- a/crates/ocs_web_worker/Cargo.toml +++ b/crates/ocs_web_worker/Cargo.toml @@ -8,7 +8,7 @@ publish = false crate-type = ["cdylib"] [dependencies] -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "aad7053", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "76d2a1c", features = ["serde"] } bincode = "1.3" serde = { version = "1", features = ["derive"] } console_error_panic_hook = "0.1" diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index d7ddef4f1..9fe9d9e73 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -2348,6 +2348,7 @@ common = .chspace-no-viewport = CHSPACE: لا توجد نافذة عرض مسقطية لتغيير الفضاء من خلالها. .chspace-to-paper = CHSPACE: تم نقل __ocs_fmt_0__ كائن إلى فضاء الورق. .chspace-to-model = CHSPACE: تم نقل __ocs_fmt_0__ كائن إلى فضاء النموذج. + .select-template-title = تحديد قالب errors = .save-warning = تحذير الحفظ .unable-to-save-drawing = تعذر حفظ الرسم diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index 1c951e903..88d257df5 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -2335,6 +2335,7 @@ common = .chspace-no-viewport = CHSPACE: Няма прозорец в план, през който да се смени пространството. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ обекта преместени в пространството на листа. .chspace-to-model = CHSPACE: __ocs_fmt_0__ обекта преместени в пространството на модела. + .select-template-title = Избор на шаблон errors = .save-warning = Предупреждение при запазване .unable-to-save-drawing = Чертежът не може да бъде запазен diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index a1adf8088..a0b004045 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -2335,6 +2335,7 @@ common = .chspace-no-viewport = CHSPACE: Není výřez v půdorysném pohledu, přes který změnit prostor. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ objektů přesunuto do výkresového prostoru. .chspace-to-model = CHSPACE: __ocs_fmt_0__ objektů přesunuto do modelového prostoru. + .select-template-title = Vybrat šablonu errors = .save-warning = Uložit varování .unable-to-save-drawing = Nákres nelze uložit diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 113bb8981..b4303789d 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -2336,6 +2336,7 @@ common = .chspace-no-viewport = CHSPACE: Kein Ansichtsfenster in Draufsicht zum Wechseln des Bereichs. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ Objekt(e) in den Papierbereich verschoben. .chspace-to-model = CHSPACE: __ocs_fmt_0__ Objekt(e) in den Modellbereich verschoben. + .select-template-title = Vorlage auswählen errors = .save-warning = Warnhinweise speichern .unable-to-save-drawing = Zeichnung konnte nicht gespeichert werden diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index f316b9d5e..20506457b 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -2335,6 +2335,7 @@ common = .chspace-no-viewport = CHSPACE: Δεν υπάρχει παράθυρο προβολής κάτοψης για αλλαγή χώρου. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ αντικείμενα μεταφέρθηκαν στον χώρο χαρτιού. .chspace-to-model = CHSPACE: __ocs_fmt_0__ αντικείμενα μεταφέρθηκαν στον χώρο μοντέλου. + .select-template-title = Επιλογή προτύπου errors = .save-warning = Προειδοποίηση αποθήκευσης .unable-to-save-drawing = Αδυναμία αποθήκευσης σχεδίου diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index ca46303af..56ee9179a 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -2336,6 +2336,7 @@ common = .chspace-no-viewport = CHSPACE: No plan-view viewport to change space through. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ object(s) changed to paper space. .chspace-to-model = CHSPACE: __ocs_fmt_0__ object(s) changed to model space. + .select-template-title = Select Template errors = .save-warning = Save Warning .unable-to-save-drawing = Unable to Save Drawing diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 2cf8237be..8695475e0 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -2336,6 +2336,7 @@ common = .chspace-no-viewport = CHSPACE: No hay ventana gráfica en vista en planta para cambiar de espacio. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ objeto(s) pasado(s) al espacio papel. .chspace-to-model = CHSPACE: __ocs_fmt_0__ objeto(s) pasado(s) al espacio modelo. + .select-template-title = Seleccionar plantilla errors = .save-warning = Advertencia de guardado .unable-to-save-drawing = No se puede guardar el dibujo diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index c44d1f1c2..36e88e99f 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -2335,6 +2335,7 @@ common = .chspace-no-viewport = CHSPACE: Ei tasokuvan näkymäikkunaa tilan vaihtoon. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ objektia siirretty paperitilaan. .chspace-to-model = CHSPACE: __ocs_fmt_0__ objektia siirretty mallitilaan. + .select-template-title = Valitse malli errors = .save-warning = Tallenna varoitus .unable-to-save-drawing = Piirustusta ei voi tallentaa diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index dfeb98f84..ebbad5798 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -2336,6 +2336,7 @@ common = .chspace-no-viewport = CHSPACE : aucune fenêtre en vue en plan pour changer d'espace. .chspace-to-paper = CHSPACE : __ocs_fmt_0__ objet(s) déplacé(s) dans l'espace papier. .chspace-to-model = CHSPACE : __ocs_fmt_0__ objet(s) déplacé(s) dans l'espace objet. + .select-template-title = Sélectionner un gabarit errors = .save-warning = Enregistrer l' avertissement .unable-to-save-drawing = Impossible de sauvegarder le dessin diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index fe5621a45..ef13bc3b3 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -2324,6 +2324,7 @@ common = .chspace-no-viewport = CHSPACE: स्पेस बदलने के लिए कोई प्लान-व्यू व्यूपोर्ट नहीं। .chspace-to-paper = CHSPACE: __ocs_fmt_0__ ऑब्जेक्ट पेपर स्पेस में बदले गए। .chspace-to-model = CHSPACE: __ocs_fmt_0__ ऑब्जेक्ट मॉडल स्पेस में बदले गए। + .select-template-title = टेम्पलेट चुनें errors = .save-warning = चेतावनी सहेजें .unable-to-save-drawing = ड्रॉइंग सहेजी नहीं जा सकी diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 041e9061e..d8996fbff 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -2335,6 +2335,7 @@ common = .chspace-no-viewport = CHSPACE: Nincs felülnézeti nézetablak a tér váltásához. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ objektum papírtérbe helyezve. .chspace-to-model = CHSPACE: __ocs_fmt_0__ objektum modelltérbe helyezve. + .select-template-title = Sablon kiválasztása errors = .save-warning = Figyelmeztetés mentése .unable-to-save-drawing = Nem sikerült menteni a rajzot diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index a1df56f45..ab3cff89e 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -2335,6 +2335,7 @@ common = .chspace-no-viewport = CHSPACE: nessuna finestra in vista in pianta attraverso cui cambiare spazio. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ oggetto/i spostato/i nello spazio carta. .chspace-to-model = CHSPACE: __ocs_fmt_0__ oggetto/i spostato/i nello spazio modello. + .select-template-title = Seleziona modello errors = .save-warning = Salva avviso .unable-to-save-drawing = Impossibile salvare il disegno diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index ade38d6d5..32bfca35e 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -2326,6 +2326,7 @@ common = .chspace-no-viewport = CHSPACE: 空間を変更できる平面ビューのビューポートがありません。 .chspace-to-paper = CHSPACE: __ocs_fmt_0__ 個のオブジェクトをペーパー空間に移動しました。 .chspace-to-model = CHSPACE: __ocs_fmt_0__ 個のオブジェクトをモデル空間に移動しました。 + .select-template-title = テンプレートを選択 errors = .save-warning = 保存の警告 .unable-to-save-drawing = 図面を保存できません diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 939c2e0c2..1981cebce 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -2335,6 +2335,7 @@ common = .chspace-no-viewport = CHSPACE: 공간을 변경할 평면 뷰포트가 없습니다. .chspace-to-paper = CHSPACE: 객체 __ocs_fmt_0__개를 도면 공간으로 옮겼습니다. .chspace-to-model = CHSPACE: 객체 __ocs_fmt_0__개를 모형 공간으로 옮겼습니다. + .select-template-title = 템플릿 선택 errors = .save-warning = 경고 저장 .unable-to-save-drawing = 도면을 저장할 수 없습니다 diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index a7e3748bc..cfd5a9ef2 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -2336,6 +2336,7 @@ common = .chspace-no-viewport = CHSPACE: geen viewport in bovenaanzicht om de ruimte via te wisselen. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ object(en) naar de papierruimte verplaatst. .chspace-to-model = CHSPACE: __ocs_fmt_0__ object(en) naar de modelruimte verplaatst. + .select-template-title = Sjabloon selecteren errors = .save-warning = Waarschuwing opslaan .unable-to-save-drawing = Kan tekening niet opslaan diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index 0331ad907..f6193a88b 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -2335,6 +2335,7 @@ common = .chspace-no-viewport = CHSPACE: brak rzutni w widoku z góry do zmiany obszaru. .chspace-to-paper = CHSPACE: przeniesiono obiekty do obszaru papieru: __ocs_fmt_0__. .chspace-to-model = CHSPACE: przeniesiono obiekty do obszaru modelu: __ocs_fmt_0__. + .select-template-title = Wybierz szablon errors = .save-warning = Zapisz ostrzeżenie .unable-to-save-drawing = Nie można zapisać rysunku diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index f2d153fad..461c90074 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -2336,6 +2336,7 @@ common = .chspace-no-viewport = CHSPACE: nenhuma janela de vista em planta para mudar de espaço. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ objeto(s) movido(s) para o espaço do papel. .chspace-to-model = CHSPACE: __ocs_fmt_0__ objeto(s) movido(s) para o espaço do modelo. + .select-template-title = Selecionar modelo errors = .save-warning = Aviso de salvamento .unable-to-save-drawing = Não foi possível salvar o desenho diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 213aa7a0a..34cee593c 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -2339,6 +2339,7 @@ common = .chspace-no-viewport = CHSPACE: нет видового экрана в плане для смены пространства. .chspace-to-paper = CHSPACE: перенесено в пространство листа объектов: __ocs_fmt_0__. .chspace-to-model = CHSPACE: перенесено в пространство модели объектов: __ocs_fmt_0__. + .select-template-title = Выбор шаблона errors = .save-warning = Спасти предостережение .unable-to-save-drawing = Не удалось сохранить чертёж diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index 6974aef5c..ca21b0681 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -2320,6 +2320,7 @@ common = .chspace-no-viewport = CHSPACE: Alan değiştirmek için plan görünümlü görünüm penceresi yok. .chspace-to-paper = CHSPACE: __ocs_fmt_0__ nesne kağıt alanına taşındı. .chspace-to-model = CHSPACE: __ocs_fmt_0__ nesne model alanına taşındı. + .select-template-title = Şablon Seç errors = .save-warning = Kaydetme Uyarısı .unable-to-save-drawing = Çizim Kaydedilemiyor diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index 768db134b..e46fff4f3 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -2323,6 +2323,7 @@ common = .chspace-no-viewport = CHSPACE: 没有可用于更改空间的平面视图视口。 .chspace-to-paper = CHSPACE: 已将 __ocs_fmt_0__ 个对象移到图纸空间。 .chspace-to-model = CHSPACE: 已将 __ocs_fmt_0__ 个对象移到模型空间。 + .select-template-title = 选择样板 errors = .save-warning = 保存警告 .unable-to-save-drawing = 无法保存图形 diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index 57a0647ee..2516309b2 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -2335,6 +2335,7 @@ common = .chspace-no-viewport = CHSPACE: 沒有可用於變更空間的平面視圖視埠。 .chspace-to-paper = CHSPACE: 已將 __ocs_fmt_0__ 個物件移到圖紙空間。 .chspace-to-model = CHSPACE: 已將 __ocs_fmt_0__ 個物件移到模型空間。 + .select-template-title = 選取樣板 errors = .save-warning = 儲存警告 .unable-to-save-drawing = 無法儲存圖形 diff --git a/plugins/opencad-python/Cargo.lock b/plugins/opencad-python/Cargo.lock index 75aab19a9..007c79458 100644 --- a/plugins/opencad-python/Cargo.lock +++ b/plugins/opencad-python/Cargo.lock @@ -1264,7 +1264,7 @@ dependencies = [ [[package]] name = "opencadcodec" version = "0.6.0" -source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=aad7053#aad70533211bd9192545729f7eb3bccb827bcf30" +source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=76d2a1c#76d2a1c66702d9aaf3ef8d4ff7dc06f4a025da82" dependencies = [ "anyhow", "bitflags", diff --git a/src/app/commands/fileops.rs b/src/app/commands/fileops.rs index 4dd2ed284..ffe41dcfa 100644 --- a/src/app/commands/fileops.rs +++ b/src/app/commands/fileops.rs @@ -3,7 +3,25 @@ use super::*; impl OpenCADStudio { pub(super) fn dispatch_fileops(&mut self, cmd: &str, i: usize) -> Option> { match cmd { - "NEW" => return Some(Task::done(Message::TabNew)), + // QNEW starts from the default template (Options > Files); NEW + // asks which template to start from (#1635). + "QNEW" => return Some(Task::done(Message::TabNew)), + "NEW" => { + return Some(Task::perform( + async { + crate::sys::file_dialog() + .set_title(crate::t!("Select Template").as_ref()) + .add_filter( + crate::t!("Drawing Template (*.dwt)").as_ref(), + &["dwt", "DWT", "dwg", "DWG", "dxf", "DXF"], + ) + .pick_file() + .await + .map(|handle| crate::sys::handle_path(&handle)) + }, + Message::NewFromTemplate, + )); + } "OPEN" => return Some(Task::done(Message::OpenFile)), "SAVE" | "QSAVE" => return Some(Task::done(Message::SaveFile)), // SAVEALL — write every open drawing that already has a file path. diff --git a/src/app/commands/layerprops.rs b/src/app/commands/layerprops.rs index c899c281e..99858ea5c 100644 --- a/src/app/commands/layerprops.rs +++ b/src/app/commands/layerprops.rs @@ -875,8 +875,25 @@ impl OpenCADStudio { crate::scene::CubeRegion::Face(face), ))); } - "ISO" | "ISOMETRIC" | "SWISO" => { - return Some(Task::done(Message::ViewCubeHome)); + // Isometric presets snap to the matching ViewCube corner; + // ISO alone is the south-west one. + "ISO" | "ISOMETRIC" | "SWISO" | "SEISO" | "NEISO" | "NWISO" => { + let (x, y) = match sub.as_str() { + "SEISO" => (1.0, -1.0), + "NEISO" => (1.0, 1.0), + "NWISO" => (-1.0, 1.0), + _ => (-1.0, -1.0), + }; + let want = glam::Vec3::new(x, y, 1.0).normalize(); + let corner = (18..26) + .map(crate::scene::CubeRegion::Corner) + .max_by(|a, b| { + a.snap_direction() + .dot(want) + .total_cmp(&b.snap_direction().dot(want)) + }) + .expect("the cube has corners"); + return Some(Task::done(Message::ViewCubeSnap(corner))); } // VIEW shortcut for restore _ => { diff --git a/src/app/commands/mod.rs b/src/app/commands/mod.rs index 0e1df27d3..4e28bdc66 100644 --- a/src/app/commands/mod.rs +++ b/src/app/commands/mod.rs @@ -850,6 +850,7 @@ inventory::submit!(crate::command::CommandRegistration { "CHSPACE", "NAVVCUBE", "NEW", + "QNEW", "OBJIMPORT", "OPEN", "ORTHO", diff --git a/src/app/layers.rs b/src/app/layers.rs index 4bedc8968..7ec119470 100644 --- a/src/app/layers.rs +++ b/src/app/layers.rs @@ -149,7 +149,12 @@ impl OpenCADStudio { } let doc = &self.tabs[i].scene.document; - let text_names: Vec = doc.text_styles.iter().map(|s| s.name.clone()).collect(); + let text_names: Vec = doc + .text_styles + .iter() + .filter(|s| !s.is_shape_file) + .map(|s| s.name.clone()) + .collect(); let active_text = doc.header.current_text_style_name.clone(); let active_text = if text_names.contains(&active_text) { active_text diff --git a/src/app/mod.rs b/src/app/mod.rs index 258eef13d..211db1f9d 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -2299,6 +2299,8 @@ pub enum Message { /// Options → Files: the default template for new drawings. QnewTemplateChanged(String), QnewTemplateBrowse, + /// NEW: the picked template a new drawing starts from (`None` = cancelled). + NewFromTemplate(Option), /// Set the default type/version used when first saving a new drawing. DefaultSaveFormatChanged(String), /// Select one of Iced's built-in themes or the editable Custom theme. diff --git a/src/app/shortcuts.rs b/src/app/shortcuts.rs index dfb79bbe4..4f0d342df 100644 --- a/src/app/shortcuts.rs +++ b/src/app/shortcuts.rs @@ -27,7 +27,7 @@ pub(super) fn default_bindings() -> BTreeMap { ("F12".to_string(), "DYNINPUT"), (format!("{ACCEL}+0"), "CLEANSCREEN"), (format!("{ACCEL}+1"), "PROPERTIES"), - (format!("{ACCEL}+N"), "NEW"), + (format!("{ACCEL}+N"), "QNEW"), (format!("{ACCEL}+O"), "OPEN"), (format!("{ACCEL}+P"), "PLOT"), (format!("{ACCEL}+Q"), "QUIT"), diff --git a/src/app/style_ops.rs b/src/app/style_ops.rs index 89f2bb49f..841f1b91f 100644 --- a/src/app/style_ops.rs +++ b/src/app/style_ops.rs @@ -234,7 +234,14 @@ impl OpenCADStudio { v }; match kind { - StyleKind::Text => doc.text_styles.iter().map(|s| s.name.clone()).collect(), + // Shape-file entries (complex linetype glyphs) are not text styles to + // pick or edit; they have no name (#1634). + StyleKind::Text => doc + .text_styles + .iter() + .filter(|s| !s.is_shape_file) + .map(|s| s.name.clone()) + .collect(), StyleKind::Dim => doc.dim_styles.iter().map(|s| s.name.clone()).collect(), StyleKind::Table => from_objects(|o| match o { ObjectType::TableStyle(s) => Some(s.name.as_str()), diff --git a/src/app/update/file.rs b/src/app/update/file.rs index 935bb7dff..d876c13fb 100644 --- a/src/app/update/file.rs +++ b/src/app/update/file.rs @@ -3137,6 +3137,8 @@ impl OpenCADStudio { let default_name = filename; let (filter_label, filter_ext): (&str, &str) = if ext.eq_ignore_ascii_case("dxf") { ("DXF Files", "dxf") + } else if ext.eq_ignore_ascii_case("dwt") { + ("Drawing Template (*.dwt)", "dwt") } else { ("DWG Files", "dwg") }; diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index b598c2c87..849d66a45 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -8028,6 +8028,22 @@ impl OpenCADStudio { self.persist_settings_if_changed(); Task::none() } + Message::NewFromTemplate(Some(path)) => { + let task = self.update(Message::TabNew); + let idx = self.active_tab; + match self.apply_template(&path.to_string_lossy()) { + Ok(_) => { + self.tabs[idx].dirty = false; + self.refresh_layer_panel(); + self.sync_ribbon_styles(); + } + Err(error) => self + .command_line + .push_error(error["error"].as_str().unwrap_or("template")), + } + task + } + Message::NewFromTemplate(None) => Task::none(), Message::QnewTemplateBrowse => Task::perform( async { crate::sys::file_dialog() diff --git a/src/app/view/modal.rs b/src/app/view/modal.rs index 4426936dd..af15e9254 100644 --- a/src/app/view/modal.rs +++ b/src/app/view/modal.rs @@ -1152,7 +1152,9 @@ impl OpenCADStudio { let mut lt_opts: Vec = vec!["ByBlock".to_string()]; lt_opts.extend(doc.line_types.iter().map(|lt| lt.name.clone())); let mut textstyle_opts: Vec = vec!["None".to_string()]; - textstyle_opts.extend(doc.text_styles.iter().map(|t| t.name.clone())); + textstyle_opts.extend( + doc.text_styles.iter().filter(|t| !t.is_shape_file).map(|t| t.name.clone()), + ); let opt_block = |h: Option| -> String { match h { Some(h) => doc @@ -1416,7 +1418,11 @@ impl OpenCADStudio { let mut lt_opts: Vec = vec!["ByBlock".to_string()]; lt_opts.extend(doc.line_types.iter().map(|lt| lt.name.clone())); let text_style_opts: Vec = - doc.text_styles.iter().map(|style| style.name.clone()).collect(); + doc.text_styles + .iter() + .filter(|style| !style.is_shape_file) + .map(|style| style.name.clone()) + .collect(); let text_style_fixed_height = doc .text_styles .get(&self.ds_dimtxsty) diff --git a/src/io/mod.rs b/src/io/mod.rs index 6ff41327a..2a2e0c761 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -1402,7 +1402,7 @@ pub const DEFAULT_SAVE_FORMAT: &str = "DWG 2018"; pub const SAVE_FORMAT_OPTIONS: &[&str] = &[ "DWG 2018", "DWG 2013", "DWG 2010", "DWG 2007", "DWG 2004", "DWG 2000", "DWG R14", "DXF 2018", - "DXF 2013", "DXF 2010", "DXF 2007", "DXF 2004", "DXF 2000", "DXF R14", + "DXF 2013", "DXF 2010", "DXF 2007", "DXF 2004", "DXF 2000", "DXF R14", "DWT 2018", ]; pub fn canonical_save_format(format: &str) -> &'static str { @@ -1432,7 +1432,14 @@ pub fn parse_save_format(format: &str) -> (&'static str, codec::DxfVersion) { use codec::DxfVersion; let f = format.to_ascii_uppercase(); let is_dxf = f.starts_with("DXF"); - let ext = if is_dxf { "dxf" } else { "dwg" }; + // A drawing template (.dwt) is a DWG under another extension (#1635). + let ext = if is_dxf { + "dxf" + } else if f.starts_with("DWT") { + "dwt" + } else { + "dwg" + }; let version = if f.contains("2013") { DxfVersion::AC1027 } else if f.contains("2010") { @@ -1611,14 +1618,14 @@ impl std::fmt::Display for SaveFailure { impl std::error::Error for SaveFailure {} -const SUPPORTED_SAVE_FORMATS: &str = ".dwg, .dxf"; +const SUPPORTED_SAVE_FORMATS: &str = ".dwg, .dxf, .dwt"; fn validate_save_extension(path: &Path) -> Result<(), SaveFailure> { let extension = path .extension() .map(|value| value.to_string_lossy().to_lowercase()) .unwrap_or_default(); - if matches!(extension.as_str(), "dwg" | "dxf" | "sv$") { + if matches!(extension.as_str(), "dwg" | "dxf" | "dwt" | "sv$") { return Ok(()); } @@ -1684,7 +1691,7 @@ mod save_failure_tests { assert_eq!( error, - "unsupported output format .pdf; supported formats: .dwg, .dxf" + "unsupported output format .pdf; supported formats: .dwg, .dxf, .dwt" ); assert!(!path.exists(), "unsupported export created an output file"); } diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 617a655ec..be44a3ebd 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -4878,6 +4878,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "Unknown command: {}" => Some(("command", "unknown-command-cmd")), "Unsaved changes will be discarded." => Some(("common", "unsaved-changes-will-be-discarded")), "Discard & close" => Some(("common", "discard-close")), + "Select Template" => Some(("common", "select-template-title")), "CHSPACE: Command not allowed in the Model tab." => Some(("common", "chspace-model-tab")), "CHSPACE: No plan-view viewport to change space through." => Some(("common", "chspace-no-viewport")), "CHSPACE: {count} object(s) changed to paper space." => Some(("common", "chspace-to-paper")), diff --git a/src/modules/model/edge_cmd.rs b/src/modules/model/edge_cmd.rs index a3428304a..41fbca524 100644 --- a/src/modules/model/edge_cmd.rs +++ b/src/modules/model/edge_cmd.rs @@ -230,7 +230,15 @@ impl SolidEdgeCommand { self.preview_for_values(self.default_value, self.other_value) { self.preview_wires = wires; - self.preview_hidden.push(handle); + // While edges are still being picked the source stays drawn: a + // hidden solid leaves the pick meshes, so the next edge could not + // be selected (#1625). The preview overlays it until confirmed. + if !matches!( + self.step, + EdgeStep::Selecting | EdgeStep::PickingLoop | EdgeStep::LoopConfirm + ) { + self.preview_hidden.push(handle); + } } } diff --git a/src/scene/entity.rs b/src/scene/entity.rs index 3a5cb2094..0d0f1e8d0 100644 --- a/src/scene/entity.rs +++ b/src/scene/entity.rs @@ -2575,6 +2575,10 @@ impl Scene { if !incremental { self.meshes.clear(); self.block_meshes.clear(); + // The B-rep cache follows the entities too: an undo that rebuilds + // everything left the undone fillet's body here, and the next + // edge operation brought it back (#1107). Restored on demand. + self.solid_models.clear(); } // BLOCK-entity handles of the layout (model + paper) blocks. A solid // owned by one of these is top-level; anything else lives in a block diff --git a/src/scene/pipeline/mod.rs b/src/scene/pipeline/mod.rs index 984d98f39..772bfe134 100644 --- a/src/scene/pipeline/mod.rs +++ b/src/scene/pipeline/mod.rs @@ -4960,7 +4960,10 @@ analytic={:.1} regular={:.1} blocks={:.1}", // ── Pass 7: selection overlay pass ─────────────────────────────── // Redraws selected wires and text with depth_compare=Always so both - // appear on top of all other geometry at full brightness. + // appear on top of all other geometry at full brightness — unless + // faces are drawn: then edges behind a surface stay hidden while + // selected, as they are when not (#1031). + let occluded = hidden_line || !mesh_wireframe; let have_text_highlight = (!self.text_highlight_gpu.is_empty()) || !self.block_text_highlight_gpu.is_empty(); @@ -4997,7 +5000,7 @@ analytic={:.1} regular={:.1} blocks={:.1}", pass.set_bind_group(0, &self.uniform_bind_group, &[]); pass.set_stencil_reference(stencil_ref); if !self.gpu_selected_wires.is_empty() { - pass.set_pipeline(if hidden_line { + pass.set_pipeline(if occluded { &self.wire_pipeline } else { &self.wire_xray_pipeline @@ -5016,7 +5019,7 @@ analytic={:.1} regular={:.1} blocks={:.1}", } } if !self.gpu_selected_block_wires.is_empty() { - pass.set_pipeline(if hidden_line { + pass.set_pipeline(if occluded { &self.block_wire_pipeline } else { &self.block_wire_xray_pipeline @@ -5029,7 +5032,7 @@ analytic={:.1} regular={:.1} blocks={:.1}", } } if !self.gpu_selected_circles.is_empty() { - pass.set_pipeline(if hidden_line { + pass.set_pipeline(if occluded { &self.circle_pipeline } else { &self.circle_xray_pipeline @@ -5043,7 +5046,7 @@ analytic={:.1} regular={:.1} blocks={:.1}", } } if !self.gpu_selected_ellipses.is_empty() { - pass.set_pipeline(if hidden_line { + pass.set_pipeline(if occluded { &self.ellipse_pipeline } else { &self.ellipse_xray_pipeline diff --git a/src/ui/ribbon/mod.rs b/src/ui/ribbon/mod.rs index 245af7c9e..835c0550a 100644 --- a/src/ui/ribbon/mod.rs +++ b/src/ui/ribbon/mod.rs @@ -521,7 +521,7 @@ impl Ribbon { ) -> Element<'_, Message> { // ── Quick-access file commands + undo/redo, one merged flow ──────── let lead = iced::widget::Row::with_children(vec![ - quick_access_btn(crate::ui::icons::DOC_NEW, "New", "NEW").into(), + quick_access_btn(crate::ui::icons::DOC_NEW, "New", "QNEW").into(), quick_access_btn(crate::ui::icons::FOLDER_OPEN, "Open", "OPEN").into(), quick_access_btn(crate::ui::icons::SAVE, "Save", "SAVE").into(), quick_access_btn(crate::ui::icons::FILE_EXPORT, "Save As", "SAVEAS").into(), diff --git a/src/ui/window/options.rs b/src/ui/window/options.rs index 777c255a8..4f0b019f2 100644 --- a/src/ui/window/options.rs +++ b/src/ui/window/options.rs @@ -425,7 +425,8 @@ pub fn view_window<'a>( text(crate::tr!("options", "default-save-format-label")).size(12).width(150), iced::widget::pick_list( selected_format, - crate::io::SAVE_FORMAT_OPTIONS, + // Drawings, not the template entry (the list's last). + &crate::io::SAVE_FORMAT_OPTIONS[..crate::io::SAVE_FORMAT_OPTIONS.len() - 1], |value| value.to_string(), ) .on_select(|format: &str| Message::DefaultSaveFormatChanged(format.to_string()))