forked from 1b-agent/opencadstudio-upstream
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 <noreply@anthropic.com>
This commit is contained in:
1 parent
1cbcc8f4c5
commit
1eae36e726
43 files changed
+152
-34
No files matched your search
Generated
+4
-4
@@ -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",
|
||||
]
|
||||
|
||||
+4
-5
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
|
||||
@@ -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 = تعذر حفظ الرسم
|
||||
|
||||
@@ -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 = Чертежът не може да бъде запазен
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = Αδυναμία αποθήκευσης σχεδίου
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ड्रॉइंग सहेजी नहीं जा सकी
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = 図面を保存できません
|
||||
|
||||
@@ -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 = 도면을 저장할 수 없습니다
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = Не удалось сохранить чертёж
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = 无法保存图形
|
||||
|
||||
@@ -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 = 無法儲存圖形
|
||||
|
||||
Generated
+1
-1
@@ -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",
|
||||
|
||||
@@ -3,7 +3,25 @@ use super::*;
|
||||
impl OpenCADStudio {
|
||||
pub(super) fn dispatch_fileops(&mut self, cmd: &str, i: usize) -> Option<Task<Message>> {
|
||||
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.
|
||||
|
||||
@@ -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 <name> shortcut for restore
|
||||
_ => {
|
||||
|
||||
@@ -850,6 +850,7 @@ inventory::submit!(crate::command::CommandRegistration {
|
||||
"CHSPACE",
|
||||
"NAVVCUBE",
|
||||
"NEW",
|
||||
"QNEW",
|
||||
"OBJIMPORT",
|
||||
"OPEN",
|
||||
"ORTHO",
|
||||
|
||||
+6
-1
@@ -149,7 +149,12 @@ impl OpenCADStudio {
|
||||
}
|
||||
let doc = &self.tabs[i].scene.document;
|
||||
|
||||
let text_names: Vec<String> = doc.text_styles.iter().map(|s| s.name.clone()).collect();
|
||||
let text_names: Vec<String> = 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
|
||||
|
||||
@@ -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<std::path::PathBuf>),
|
||||
/// 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.
|
||||
|
||||
@@ -27,7 +27,7 @@ pub(super) fn default_bindings() -> BTreeMap<String, String> {
|
||||
("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"),
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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")
|
||||
};
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -1152,7 +1152,9 @@ impl OpenCADStudio {
|
||||
let mut lt_opts: Vec<String> = vec!["ByBlock".to_string()];
|
||||
lt_opts.extend(doc.line_types.iter().map(|lt| lt.name.clone()));
|
||||
let mut textstyle_opts: Vec<String> = 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<codec::types::Handle>| -> String {
|
||||
match h {
|
||||
Some(h) => doc
|
||||
@@ -1416,7 +1418,11 @@ impl OpenCADStudio {
|
||||
let mut lt_opts: Vec<String> = vec!["ByBlock".to_string()];
|
||||
lt_opts.extend(doc.line_types.iter().map(|lt| lt.name.clone()));
|
||||
let text_style_opts: Vec<String> =
|
||||
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)
|
||||
|
||||
+12
-5
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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")),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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()))
|
||||
|
||||
Reference in new issue
Block a user