forked from 1b-agent/opencadstudio-upstream
feat(bedit): author visibility states of dynamic blocks
In the Block Editor, BVSTATE makes a new visibility state, makes one current, renames or deletes one; BVHIDE and BVSHOW hide or show the picked objects in the current state (BVSHOW shows every object of the block while they are picked). The first use makes the block dynamic. The states are stored as the format keeps them: a BLOCKVISIBILITYPARAMETER in the block's ACAD_ENHANCEDBLOCK evaluation graph with its visibility grip and the grip's two location expressions, the round-trip purge preventer, AcDbDynamicBlockTrueName / AcDbDynamicBlockGUID / AcDbBlockRepETag on the definition and element tags on each of its objects. The definition shows its first state; a reference given another state gets its own evaluated *U copy, tagged AcDbBlockRepBTag and linked back through AcDbBlockRepresentation / AcDbRepData, so it shows that state and the other references do not change. Saving the block drops erased objects from the states. Checked: a block authored this way reads back with its states and reference link from DWG and DXF, and the ODA converter accepts the DWG. Closes #1566 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
353c1b0d0f
commit
da8e976a60
31 files changed
+1464
-1
No files matched your search
@@ -3133,6 +3133,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT حدد كتلة ذات سمات:
|
||||
.annotation-object-scale = مقياس كائن التعليق التوضيحي
|
||||
.bedit-select-block-reference-to-edit = BEDIT حدد مرجع الكتلة لتحريره:
|
||||
.bvstate-option = BVSTATE أدخل خيارًا [جديد/تعيين/إعادة تسمية/حذف] <تعيين>:
|
||||
.bvstate-new-name = BVSTATE أدخل اسم حالة الرؤية الجديدة:
|
||||
.bvstate-set = BVSTATE أدخل حالة الرؤية المراد جعلها الحالية <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE أدخل حالة الرؤية المراد إعادة تسميتها <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE أدخل الاسم الجديد:
|
||||
.bvstate-delete = BVSTATE أدخل حالة الرؤية المراد حذفها:
|
||||
.bvstate-not-found = لم يتم العثور على حالة الرؤية "__ocs_fmt_0__".
|
||||
.bvstate-exists = حالة الرؤية "__ocs_fmt_0__" موجودة بالفعل.
|
||||
.bvstate-last = لا يمكن حذف حالة الرؤية الوحيدة.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: افتح الكتلة أولاً في محرر الكتل (BEDIT).
|
||||
.bvstate-current = حالة الرؤية الحالية: __ocs_fmt_0__
|
||||
.bvhide-select = حدد الكائنات المراد إخفاؤها:
|
||||
.bvshow-select = حدد الكائنات المراد إظهارها:
|
||||
.arrayedit-select-array = ARRAYEDIT حدد المصفوفة:
|
||||
.arrayedit-options = ARRAYEDIT أدخل خيارًا [المصدر/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: الكائن المحدد ليس مصفوفة ترابطية.
|
||||
|
||||
@@ -3120,6 +3120,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Избери блок с атрибути:
|
||||
.annotation-object-scale = Мащаб на анотационен обект
|
||||
.bedit-select-block-reference-to-edit = BEDIT Избери препратка към блок за редактиране:
|
||||
.bvstate-option = BVSTATE Въведете опция [Ново/Задай/Преименувай/Изтрий] <Задай>:
|
||||
.bvstate-new-name = BVSTATE Въведете име на новото състояние на видимост:
|
||||
.bvstate-set = BVSTATE Въведете състоянието на видимост, което да стане текущо <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Въведете състоянието на видимост за преименуване <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Въведете новото име:
|
||||
.bvstate-delete = BVSTATE Въведете състоянието на видимост за изтриване:
|
||||
.bvstate-not-found = Състоянието на видимост "__ocs_fmt_0__" не е намерено.
|
||||
.bvstate-exists = Състоянието на видимост "__ocs_fmt_0__" вече съществува.
|
||||
.bvstate-last = Единственото състояние на видимост не може да бъде изтрито.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: първо отворете блока в редактора на блокове (BEDIT).
|
||||
.bvstate-current = Текущо състояние на видимост: __ocs_fmt_0__
|
||||
.bvhide-select = Изберете обекти за скриване:
|
||||
.bvshow-select = Изберете обекти за показване:
|
||||
.arrayedit-select-array = ARRAYEDIT Изберете масив:
|
||||
.arrayedit-options = ARRAYEDIT Въведете опция [Източник/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: избраният обект не е асоциативен масив.
|
||||
|
||||
@@ -3120,6 +3120,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Vyberte blok s atributy:
|
||||
.annotation-object-scale = Měřítko objektu anotace
|
||||
.bedit-select-block-reference-to-edit = BEDIT Vyberte referenci bloku, kterou chcete upravit:
|
||||
.bvstate-option = BVSTATE Zadejte možnost [Nový/Nastavit/Přejmenovat/Odstranit] <Nastavit>:
|
||||
.bvstate-new-name = BVSTATE Zadejte název nového stavu viditelnosti:
|
||||
.bvstate-set = BVSTATE Zadejte stav viditelnosti, který se stane aktuálním <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Zadejte stav viditelnosti k přejmenování <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Zadejte nový název:
|
||||
.bvstate-delete = BVSTATE Zadejte stav viditelnosti k odstranění:
|
||||
.bvstate-not-found = Stav viditelnosti "__ocs_fmt_0__" nebyl nalezen.
|
||||
.bvstate-exists = Stav viditelnosti "__ocs_fmt_0__" již existuje.
|
||||
.bvstate-last = Jediný stav viditelnosti nelze odstranit.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: nejprve otevřete blok v editoru bloků (BEDIT).
|
||||
.bvstate-current = Aktuální stav viditelnosti: __ocs_fmt_0__
|
||||
.bvhide-select = Vyberte objekty ke skrytí:
|
||||
.bvshow-select = Vyberte objekty k zobrazení:
|
||||
.arrayedit-select-array = ARRAYEDIT Vyberte pole:
|
||||
.arrayedit-options = ARRAYEDIT Zadejte možnost [Zdroj/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: vybraný objekt není asociativní pole.
|
||||
|
||||
@@ -3121,6 +3121,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Block mit Attributen auswählen:
|
||||
.annotation-object-scale = Beschriftungsobjektmaßstab
|
||||
.bedit-select-block-reference-to-edit = BEDIT Blockreferenz zum Bearbeiten auswählen:
|
||||
.bvstate-option = BVSTATE Option eingeben [Neu/Setzen/Umbenennen/Löschen] <Setzen>:
|
||||
.bvstate-new-name = BVSTATE Namen des neuen Sichtbarkeitsstatus eingeben:
|
||||
.bvstate-set = BVSTATE Aktuell zu setzenden Sichtbarkeitsstatus eingeben <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Umzubenennenden Sichtbarkeitsstatus eingeben <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Neuen Namen eingeben:
|
||||
.bvstate-delete = BVSTATE Zu löschenden Sichtbarkeitsstatus eingeben:
|
||||
.bvstate-not-found = Sichtbarkeitsstatus "__ocs_fmt_0__" nicht gefunden.
|
||||
.bvstate-exists = Sichtbarkeitsstatus "__ocs_fmt_0__" existiert bereits.
|
||||
.bvstate-last = Der einzige Sichtbarkeitsstatus kann nicht gelöscht werden.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: Öffnen Sie den Block zuerst im Blockeditor (BEDIT).
|
||||
.bvstate-current = Aktueller Sichtbarkeitsstatus: __ocs_fmt_0__
|
||||
.bvhide-select = Auszublendende Objekte wählen:
|
||||
.bvshow-select = Einzublendende Objekte wählen:
|
||||
.arrayedit-select-array = ARRAYEDIT Reihe wählen:
|
||||
.arrayedit-options = ARRAYEDIT Option eingeben [Quelle/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: das gewählte Objekt ist keine assoziative Reihe.
|
||||
|
||||
@@ -3121,6 +3121,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Επιλέξτε μπλοκ με χαρακτηριστικά:
|
||||
.annotation-object-scale = Κλίμακα αντικειμένου επισημείωσης
|
||||
.bedit-select-block-reference-to-edit = BEDIT Επιλέξτε αναφορά μπλοκ προς επεξεργασία:
|
||||
.bvstate-option = BVSTATE Δώστε επιλογή [Νέα/Ορισμός/Μετονομασία/Διαγραφή] <Ορισμός>:
|
||||
.bvstate-new-name = BVSTATE Δώστε όνομα νέας κατάστασης ορατότητας:
|
||||
.bvstate-set = BVSTATE Δώστε την κατάσταση ορατότητας που θα γίνει τρέχουσα <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Δώστε την κατάσταση ορατότητας προς μετονομασία <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Δώστε νέο όνομα:
|
||||
.bvstate-delete = BVSTATE Δώστε την κατάσταση ορατότητας προς διαγραφή:
|
||||
.bvstate-not-found = Η κατάσταση ορατότητας "__ocs_fmt_0__" δεν βρέθηκε.
|
||||
.bvstate-exists = Η κατάσταση ορατότητας "__ocs_fmt_0__" υπάρχει ήδη.
|
||||
.bvstate-last = Η μοναδική κατάσταση ορατότητας δεν μπορεί να διαγραφεί.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: ανοίξτε πρώτα το μπλοκ στον επεξεργαστή μπλοκ (BEDIT).
|
||||
.bvstate-current = Τρέχουσα κατάσταση ορατότητας: __ocs_fmt_0__
|
||||
.bvhide-select = Επιλέξτε αντικείμενα για απόκρυψη:
|
||||
.bvshow-select = Επιλέξτε αντικείμενα για εμφάνιση:
|
||||
.arrayedit-select-array = ARRAYEDIT Επιλέξτε διάταξη:
|
||||
.arrayedit-options = ARRAYEDIT Δώστε επιλογή [Πηγή/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: το επιλεγμένο αντικείμενο δεν είναι συσχετιστική διάταξη.
|
||||
|
||||
@@ -3121,6 +3121,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Select block with attributes:
|
||||
.annotation-object-scale = Annotation Object Scale
|
||||
.bedit-select-block-reference-to-edit = BEDIT Select block reference to edit:
|
||||
.bvstate-option = BVSTATE Enter an option [New/Set/Rename/Delete] <Set>:
|
||||
.bvstate-new-name = BVSTATE Enter name of new visibility state:
|
||||
.bvstate-set = BVSTATE Enter visibility state to make current <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Enter visibility state to rename <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Enter new name:
|
||||
.bvstate-delete = BVSTATE Enter visibility state to delete:
|
||||
.bvstate-not-found = Visibility state "__ocs_fmt_0__" not found.
|
||||
.bvstate-exists = Visibility state "__ocs_fmt_0__" already exists.
|
||||
.bvstate-last = The only visibility state cannot be deleted.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: open the block in the Block Editor first (BEDIT).
|
||||
.bvstate-current = Current visibility state: __ocs_fmt_0__
|
||||
.bvhide-select = Select objects to hide:
|
||||
.bvshow-select = Select objects to make visible:
|
||||
.arrayedit-select-array = ARRAYEDIT Select array:
|
||||
.arrayedit-options = ARRAYEDIT Enter an option [Source/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: the selected object is not an associative array.
|
||||
|
||||
@@ -3121,6 +3121,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Seleccione un bloque con atributos:
|
||||
.annotation-object-scale = Escala del objeto anotativo
|
||||
.bedit-select-block-reference-to-edit = BEDIT Seleccione la referencia de bloque que desea editar:
|
||||
.bvstate-option = BVSTATE Indique una opción [Nuevo/Establecer/Renombrar/Suprimir] <Establecer>:
|
||||
.bvstate-new-name = BVSTATE Indique el nombre del nuevo estado de visibilidad:
|
||||
.bvstate-set = BVSTATE Indique el estado de visibilidad que se hará actual <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Indique el estado de visibilidad que se renombrará <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Indique el nuevo nombre:
|
||||
.bvstate-delete = BVSTATE Indique el estado de visibilidad que se suprimirá:
|
||||
.bvstate-not-found = No se encuentra el estado de visibilidad "__ocs_fmt_0__".
|
||||
.bvstate-exists = El estado de visibilidad "__ocs_fmt_0__" ya existe.
|
||||
.bvstate-last = No se puede suprimir el único estado de visibilidad.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: abra primero el bloque en el Editor de bloques (BEDIT).
|
||||
.bvstate-current = Estado de visibilidad actual: __ocs_fmt_0__
|
||||
.bvhide-select = Seleccione los objetos que se ocultarán:
|
||||
.bvshow-select = Seleccione los objetos que se harán visibles:
|
||||
.arrayedit-select-array = ARRAYEDIT Seleccione la matriz:
|
||||
.arrayedit-options = ARRAYEDIT Indique una opción [Origen/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: el objeto seleccionado no es una matriz asociativa.
|
||||
|
||||
@@ -3120,6 +3120,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Valitse lohko määritteillä:
|
||||
.annotation-object-scale = Merkintäobjektin mittakaava
|
||||
.bedit-select-block-reference-to-edit = BEDIT Valitse muokattava lohkoviite:
|
||||
.bvstate-option = BVSTATE Anna vaihtoehto [Uusi/Aseta/Nimeä uudelleen/Poista] <Aseta>:
|
||||
.bvstate-new-name = BVSTATE Anna uuden näkyvyystilan nimi:
|
||||
.bvstate-set = BVSTATE Anna nykyiseksi asetettava näkyvyystila <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Anna uudelleennimettävä näkyvyystila <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Anna uusi nimi:
|
||||
.bvstate-delete = BVSTATE Anna poistettava näkyvyystila:
|
||||
.bvstate-not-found = Näkyvyystilaa "__ocs_fmt_0__" ei löydy.
|
||||
.bvstate-exists = Näkyvyystila "__ocs_fmt_0__" on jo olemassa.
|
||||
.bvstate-last = Ainoaa näkyvyystilaa ei voi poistaa.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: avaa lohko ensin lohkoeditorissa (BEDIT).
|
||||
.bvstate-current = Nykyinen näkyvyystila: __ocs_fmt_0__
|
||||
.bvhide-select = Valitse piilotettavat objektit:
|
||||
.bvshow-select = Valitse näytettävät objektit:
|
||||
.arrayedit-select-array = ARRAYEDIT Valitse sarja:
|
||||
.arrayedit-options = ARRAYEDIT Anna vaihtoehto [Lähde/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: valittu objekti ei ole assosiatiivinen sarja.
|
||||
|
||||
@@ -3121,6 +3121,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Sélectionner un bloc avec des attributs :
|
||||
.annotation-object-scale = Échelle d'objets d'annotation
|
||||
.bedit-select-block-reference-to-edit = BEDIT Sélectionnez la référence de bloc à modifier :
|
||||
.bvstate-option = BVSTATE Entrez une option [Nouveau/Définir/Renommer/Supprimer] <Définir> :
|
||||
.bvstate-new-name = BVSTATE Entrez le nom du nouvel état de visibilité :
|
||||
.bvstate-set = BVSTATE Entrez l'état de visibilité à rendre courant <__ocs_fmt_0__> :
|
||||
.bvstate-rename-from = BVSTATE Entrez l'état de visibilité à renommer <__ocs_fmt_0__> :
|
||||
.bvstate-rename-to = BVSTATE Entrez le nouveau nom :
|
||||
.bvstate-delete = BVSTATE Entrez l'état de visibilité à supprimer :
|
||||
.bvstate-not-found = État de visibilité "__ocs_fmt_0__" introuvable.
|
||||
.bvstate-exists = L'état de visibilité "__ocs_fmt_0__" existe déjà.
|
||||
.bvstate-last = Le seul état de visibilité ne peut pas être supprimé.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__ : ouvrez d'abord le bloc dans l'éditeur de blocs (BEDIT).
|
||||
.bvstate-current = État de visibilité courant : __ocs_fmt_0__
|
||||
.bvhide-select = Sélectionnez les objets à masquer :
|
||||
.bvshow-select = Sélectionnez les objets à rendre visibles :
|
||||
.arrayedit-select-array = ARRAYEDIT Sélectionnez le réseau :
|
||||
.arrayedit-options = ARRAYEDIT Entrez une option [Source/eXit] <eXit> :
|
||||
.arrayedit-not-an-array = ARRAYEDIT : l'objet sélectionné n'est pas un réseau associatif.
|
||||
|
||||
@@ -3109,6 +3109,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT विशेषताओं के साथ ब्लॉक का चयन करें:
|
||||
.annotation-object-scale = Annotation ऑब्जेक्ट स्केल
|
||||
.bedit-select-block-reference-to-edit = BEDIT संपादित करने के लिए ब्लॉक संदर्भ का चयन करें:
|
||||
.bvstate-option = BVSTATE विकल्प दर्ज करें [नया/सेट/नाम बदलें/हटाएँ] <सेट>:
|
||||
.bvstate-new-name = BVSTATE नई दृश्यता स्थिति का नाम दर्ज करें:
|
||||
.bvstate-set = BVSTATE वर्तमान बनाने के लिए दृश्यता स्थिति दर्ज करें <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE नाम बदलने के लिए दृश्यता स्थिति दर्ज करें <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE नया नाम दर्ज करें:
|
||||
.bvstate-delete = BVSTATE हटाने के लिए दृश्यता स्थिति दर्ज करें:
|
||||
.bvstate-not-found = दृश्यता स्थिति "__ocs_fmt_0__" नहीं मिली।
|
||||
.bvstate-exists = दृश्यता स्थिति "__ocs_fmt_0__" पहले से मौजूद है।
|
||||
.bvstate-last = एकमात्र दृश्यता स्थिति हटाई नहीं जा सकती।
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: पहले ब्लॉक को ब्लॉक एडिटर में खोलें (BEDIT)।
|
||||
.bvstate-current = वर्तमान दृश्यता स्थिति: __ocs_fmt_0__
|
||||
.bvhide-select = छिपाने के लिए ऑब्जेक्ट चुनें:
|
||||
.bvshow-select = दिखाने के लिए ऑब्जेक्ट चुनें:
|
||||
.arrayedit-select-array = ARRAYEDIT ऐरे चुनें:
|
||||
.arrayedit-options = ARRAYEDIT विकल्प दर्ज करें [स्रोत/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: चुना गया ऑब्जेक्ट सहयोगी ऐरे नहीं है।
|
||||
|
||||
@@ -3123,6 +3123,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Blokk kiválasztása attribútumokkal:
|
||||
.annotation-object-scale = Feliratozási objektum léptéke
|
||||
.bedit-select-block-reference-to-edit = BEDIT Válassza ki a szerkeszteni kívánt blokkreferenciát:
|
||||
.bvstate-option = BVSTATE Adjon meg egy lehetőséget [Új/Beállítás/Átnevezés/Törlés] <Beállítás>:
|
||||
.bvstate-new-name = BVSTATE Adja meg az új láthatósági állapot nevét:
|
||||
.bvstate-set = BVSTATE Adja meg az aktuálissá teendő láthatósági állapotot <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Adja meg az átnevezendő láthatósági állapotot <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Adja meg az új nevet:
|
||||
.bvstate-delete = BVSTATE Adja meg a törlendő láthatósági állapotot:
|
||||
.bvstate-not-found = "__ocs_fmt_0__" láthatósági állapot nem található.
|
||||
.bvstate-exists = "__ocs_fmt_0__" láthatósági állapot már létezik.
|
||||
.bvstate-last = Az egyetlen láthatósági állapot nem törölhető.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: előbb nyissa meg a blokkot a blokkszerkesztőben (BEDIT).
|
||||
.bvstate-current = Aktuális láthatósági állapot: __ocs_fmt_0__
|
||||
.bvhide-select = Jelölje ki az elrejtendő objektumokat:
|
||||
.bvshow-select = Jelölje ki a megjelenítendő objektumokat:
|
||||
.arrayedit-select-array = ARRAYEDIT Válassza ki a tömböt:
|
||||
.arrayedit-options = ARRAYEDIT Adjon meg egy lehetőséget [Forrás/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: a kijelölt objektum nem asszociatív tömb.
|
||||
|
||||
@@ -3120,6 +3120,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Seleziona blocco con attributi:
|
||||
.annotation-object-scale = Scala oggetto annotazione
|
||||
.bedit-select-block-reference-to-edit = BEDIT Selezionare il riferimento di blocco da modificare:
|
||||
.bvstate-option = BVSTATE Immettere un'opzione [Nuovo/Imposta/Rinomina/Elimina] <Imposta>:
|
||||
.bvstate-new-name = BVSTATE Immettere il nome del nuovo stato di visibilità:
|
||||
.bvstate-set = BVSTATE Immettere lo stato di visibilità da rendere corrente <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Immettere lo stato di visibilità da rinominare <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Immettere il nuovo nome:
|
||||
.bvstate-delete = BVSTATE Immettere lo stato di visibilità da eliminare:
|
||||
.bvstate-not-found = Stato di visibilità "__ocs_fmt_0__" non trovato.
|
||||
.bvstate-exists = Lo stato di visibilità "__ocs_fmt_0__" esiste già.
|
||||
.bvstate-last = L'unico stato di visibilità non può essere eliminato.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: aprire prima il blocco nell'Editor blocchi (BEDIT).
|
||||
.bvstate-current = Stato di visibilità corrente: __ocs_fmt_0__
|
||||
.bvhide-select = Selezionare gli oggetti da nascondere:
|
||||
.bvshow-select = Selezionare gli oggetti da rendere visibili:
|
||||
.arrayedit-select-array = ARRAYEDIT Selezionare la serie:
|
||||
.arrayedit-options = ARRAYEDIT Immettere un'opzione [Origine/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: l'oggetto selezionato non è una serie associativa.
|
||||
|
||||
@@ -3111,6 +3111,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT 属性付きブロックを選択:
|
||||
.annotation-object-scale = 注釈オブジェクト尺度
|
||||
.bedit-select-block-reference-to-edit = BEDIT 編集するブロック参照を選択:
|
||||
.bvstate-option = BVSTATE オプションを入力 [新規/設定/名前変更/削除] <設定>:
|
||||
.bvstate-new-name = BVSTATE 新しい可視性状態の名前を入力:
|
||||
.bvstate-set = BVSTATE 現在にする可視性状態を入力 <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE 名前を変更する可視性状態を入力 <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE 新しい名前を入力:
|
||||
.bvstate-delete = BVSTATE 削除する可視性状態を入力:
|
||||
.bvstate-not-found = 可視性状態「__ocs_fmt_0__」が見つかりません。
|
||||
.bvstate-exists = 可視性状態「__ocs_fmt_0__」は既に存在します。
|
||||
.bvstate-last = 唯一の可視性状態は削除できません。
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: 先にブロック エディタでブロックを開いてください (BEDIT)。
|
||||
.bvstate-current = 現在の可視性状態: __ocs_fmt_0__
|
||||
.bvhide-select = 非表示にするオブジェクトを選択:
|
||||
.bvshow-select = 表示するオブジェクトを選択:
|
||||
.arrayedit-select-array = ARRAYEDIT 配列複写を選択:
|
||||
.arrayedit-options = ARRAYEDIT オプションを入力 [元/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: 選択したオブジェクトは自動調整配列複写ではありません。
|
||||
|
||||
@@ -3120,6 +3120,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT 속성이 있는 블록 선택:
|
||||
.annotation-object-scale = 주석 객체 축척
|
||||
.bedit-select-block-reference-to-edit = BEDIT 편집할 블록 참조 선택:
|
||||
.bvstate-option = BVSTATE 옵션 입력 [새로 만들기/설정/이름 바꾸기/삭제] <설정>:
|
||||
.bvstate-new-name = BVSTATE 새 가시성 상태의 이름 입력:
|
||||
.bvstate-set = BVSTATE 현재로 설정할 가시성 상태 입력 <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE 이름을 바꿀 가시성 상태 입력 <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE 새 이름 입력:
|
||||
.bvstate-delete = BVSTATE 삭제할 가시성 상태 입력:
|
||||
.bvstate-not-found = 가시성 상태 "__ocs_fmt_0__"을(를) 찾을 수 없습니다.
|
||||
.bvstate-exists = 가시성 상태 "__ocs_fmt_0__"이(가) 이미 있습니다.
|
||||
.bvstate-last = 유일한 가시성 상태는 삭제할 수 없습니다.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: 먼저 블록 편집기에서 블록을 여십시오(BEDIT).
|
||||
.bvstate-current = 현재 가시성 상태: __ocs_fmt_0__
|
||||
.bvhide-select = 숨길 객체 선택:
|
||||
.bvshow-select = 표시할 객체 선택:
|
||||
.arrayedit-select-array = ARRAYEDIT 배열 선택:
|
||||
.arrayedit-options = ARRAYEDIT 옵션 입력 [원본/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: 선택한 객체는 연관 배열이 아닙니다.
|
||||
|
||||
@@ -3121,6 +3121,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT ເລືອກບລັອກທີ່ມີຄຸນລັກສະນະ:
|
||||
.annotation-object-scale = ມາດຕາສ່ວນວັດຖຸຄຳອະທິບາຍ
|
||||
.bedit-select-block-reference-to-edit = BEDIT ເລືອກການອ້າງອີງບລັອກທີ່ຈະແກ້ໄຂ:
|
||||
.bvstate-option = BVSTATE ປ້ອນທາງເລືອກ [ໃໝ່/ຕັ້ງ/ປ່ຽນຊື່/ລຶບ] <ຕັ້ງ>:
|
||||
.bvstate-new-name = BVSTATE ປ້ອນຊື່ສະຖານະການເບິ່ງເຫັນໃໝ່:
|
||||
.bvstate-set = BVSTATE ປ້ອນສະຖານະການເບິ່ງເຫັນທີ່ຈະເປັນປັດຈຸບັນ <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE ປ້ອນສະຖານະການເບິ່ງເຫັນທີ່ຈະປ່ຽນຊື່ <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE ປ້ອນຊື່ໃໝ່:
|
||||
.bvstate-delete = BVSTATE ປ້ອນສະຖານະການເບິ່ງເຫັນທີ່ຈະລຶບ:
|
||||
.bvstate-not-found = ບໍ່ພົບສະຖານະການເບິ່ງເຫັນ "__ocs_fmt_0__".
|
||||
.bvstate-exists = ສະຖານະການເບິ່ງເຫັນ "__ocs_fmt_0__" ມີຢູ່ແລ້ວ.
|
||||
.bvstate-last = ບໍ່ສາມາດລຶບສະຖານະການເບິ່ງເຫັນດຽວໄດ້.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: ເປີດບລັອກໃນຕົວແກ້ໄຂບລັອກກ່ອນ (BEDIT).
|
||||
.bvstate-current = ສະຖານະການເບິ່ງເຫັນປັດຈຸບັນ: __ocs_fmt_0__
|
||||
.bvhide-select = ເລືອກວັດຖຸທີ່ຈະເຊື່ອງ:
|
||||
.bvshow-select = ເລືອກວັດຖຸທີ່ຈະສະແດງ:
|
||||
.arrayedit-select-array = ARRAYEDIT ເລືອກອາເຣ:
|
||||
.arrayedit-options = ARRAYEDIT ປ້ອນທາງເລືອກ [ແຫຼ່ງ/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: ວັດຖຸທີ່ເລືອກບໍ່ແມ່ນອາເຣທີ່ເຊື່ອມໂຍງ.
|
||||
|
||||
@@ -3121,6 +3121,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Selecteer symbool met attributen:
|
||||
.annotation-object-scale = Annotatie objectschaal
|
||||
.bedit-select-block-reference-to-edit = BEDIT Selecteer symboolverwijzing naar bewerken:
|
||||
.bvstate-option = BVSTATE Geef een optie [Nieuw/Instellen/Hernoemen/Verwijderen] <Instellen>:
|
||||
.bvstate-new-name = BVSTATE Geef de naam van de nieuwe zichtbaarheidsstatus:
|
||||
.bvstate-set = BVSTATE Geef de zichtbaarheidsstatus die huidig wordt <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Geef de te hernoemen zichtbaarheidsstatus <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Geef de nieuwe naam:
|
||||
.bvstate-delete = BVSTATE Geef de te verwijderen zichtbaarheidsstatus:
|
||||
.bvstate-not-found = Zichtbaarheidsstatus "__ocs_fmt_0__" niet gevonden.
|
||||
.bvstate-exists = Zichtbaarheidsstatus "__ocs_fmt_0__" bestaat al.
|
||||
.bvstate-last = De enige zichtbaarheidsstatus kan niet worden verwijderd.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: open het blok eerst in de blokeditor (BEDIT).
|
||||
.bvstate-current = Huidige zichtbaarheidsstatus: __ocs_fmt_0__
|
||||
.bvhide-select = Selecteer te verbergen objecten:
|
||||
.bvshow-select = Selecteer zichtbaar te maken objecten:
|
||||
.arrayedit-select-array = ARRAYEDIT Selecteer de reeks:
|
||||
.arrayedit-options = ARRAYEDIT Geef een optie [Bron/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: het geselecteerde object is geen associatieve reeks.
|
||||
|
||||
@@ -3120,6 +3120,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Wybierz blok z atrybutami:
|
||||
.annotation-object-scale = Skala obiektu adnotacji
|
||||
.bedit-select-block-reference-to-edit = BEDIT Wybierz odniesienie do bloku do edycji:
|
||||
.bvstate-option = BVSTATE Podaj opcję [Nowy/Ustaw/Zmień nazwę/Usuń] <Ustaw>:
|
||||
.bvstate-new-name = BVSTATE Podaj nazwę nowego stanu widoczności:
|
||||
.bvstate-set = BVSTATE Podaj stan widoczności, który ma być bieżący <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Podaj stan widoczności do zmiany nazwy <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Podaj nową nazwę:
|
||||
.bvstate-delete = BVSTATE Podaj stan widoczności do usunięcia:
|
||||
.bvstate-not-found = Nie znaleziono stanu widoczności "__ocs_fmt_0__".
|
||||
.bvstate-exists = Stan widoczności "__ocs_fmt_0__" już istnieje.
|
||||
.bvstate-last = Nie można usunąć jedynego stanu widoczności.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: najpierw otwórz blok w edytorze bloków (BEDIT).
|
||||
.bvstate-current = Bieżący stan widoczności: __ocs_fmt_0__
|
||||
.bvhide-select = Wybierz obiekty do ukrycia:
|
||||
.bvshow-select = Wybierz obiekty do pokazania:
|
||||
.arrayedit-select-array = ARRAYEDIT Wybierz szyk:
|
||||
.arrayedit-options = ARRAYEDIT Podaj opcję [Źródło/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: wybrany obiekt nie jest szykiem skojarzonym.
|
||||
|
||||
@@ -3121,6 +3121,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Selecione um bloco com atributos:
|
||||
.annotation-object-scale = Escala de objeto de anotação
|
||||
.bedit-select-block-reference-to-edit = BEDIT Selecione a referência de bloco a editar:
|
||||
.bvstate-option = BVSTATE Digite uma opção [Novo/Definir/Renomear/Excluir] <Definir>:
|
||||
.bvstate-new-name = BVSTATE Digite o nome do novo estado de visibilidade:
|
||||
.bvstate-set = BVSTATE Digite o estado de visibilidade a tornar atual <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Digite o estado de visibilidade a renomear <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Digite o novo nome:
|
||||
.bvstate-delete = BVSTATE Digite o estado de visibilidade a excluir:
|
||||
.bvstate-not-found = Estado de visibilidade "__ocs_fmt_0__" não encontrado.
|
||||
.bvstate-exists = O estado de visibilidade "__ocs_fmt_0__" já existe.
|
||||
.bvstate-last = O único estado de visibilidade não pode ser excluído.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: abra primeiro o bloco no Editor de blocos (BEDIT).
|
||||
.bvstate-current = Estado de visibilidade atual: __ocs_fmt_0__
|
||||
.bvhide-select = Selecione os objetos a ocultar:
|
||||
.bvshow-select = Selecione os objetos a tornar visíveis:
|
||||
.arrayedit-select-array = ARRAYEDIT Selecione o arranjo:
|
||||
.arrayedit-options = ARRAYEDIT Digite uma opção [Origem/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: o objeto selecionado não é um arranjo associativo.
|
||||
|
||||
@@ -3124,6 +3124,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Выберите блок с атрибутами:
|
||||
.annotation-object-scale = Масштаб аннотативного объекта
|
||||
.bedit-select-block-reference-to-edit = BEDIT Выберите ссылку на блок для редактирования:
|
||||
.bvstate-option = BVSTATE Введите параметр [Новое/Установить/Переименовать/Удалить] <Установить>:
|
||||
.bvstate-new-name = BVSTATE Введите имя нового состояния видимости:
|
||||
.bvstate-set = BVSTATE Введите состояние видимости, которое станет текущим <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Введите состояние видимости для переименования <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Введите новое имя:
|
||||
.bvstate-delete = BVSTATE Введите состояние видимости для удаления:
|
||||
.bvstate-not-found = Состояние видимости "__ocs_fmt_0__" не найдено.
|
||||
.bvstate-exists = Состояние видимости "__ocs_fmt_0__" уже существует.
|
||||
.bvstate-last = Единственное состояние видимости нельзя удалить.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: сначала откройте блок в редакторе блоков (BEDIT).
|
||||
.bvstate-current = Текущее состояние видимости: __ocs_fmt_0__
|
||||
.bvhide-select = Выберите объекты, которые нужно скрыть:
|
||||
.bvshow-select = Выберите объекты, которые нужно показать:
|
||||
.arrayedit-select-array = ARRAYEDIT Выберите массив:
|
||||
.arrayedit-options = ARRAYEDIT Введите параметр [Исходные/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: выбранный объект не является ассоциативным массивом.
|
||||
|
||||
@@ -3102,6 +3102,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT Öznitelikleri olan bir blok seçin:
|
||||
.annotation-object-scale = Açıklama Nesnesi Ölçeği
|
||||
.bedit-select-block-reference-to-edit = BEDIT Düzenlenecek blok referansını seçin:
|
||||
.bvstate-option = BVSTATE Bir seçenek girin [Yeni/Ayarla/Yeniden adlandır/Sil] <Ayarla>:
|
||||
.bvstate-new-name = BVSTATE Yeni görünürlük durumunun adını girin:
|
||||
.bvstate-set = BVSTATE Geçerli yapılacak görünürlük durumunu girin <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE Yeniden adlandırılacak görünürlük durumunu girin <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE Yeni adı girin:
|
||||
.bvstate-delete = BVSTATE Silinecek görünürlük durumunu girin:
|
||||
.bvstate-not-found = "__ocs_fmt_0__" görünürlük durumu bulunamadı.
|
||||
.bvstate-exists = "__ocs_fmt_0__" görünürlük durumu zaten var.
|
||||
.bvstate-last = Tek görünürlük durumu silinemez.
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: önce bloğu Blok Düzenleyici'de açın (BEDIT).
|
||||
.bvstate-current = Geçerli görünürlük durumu: __ocs_fmt_0__
|
||||
.bvhide-select = Gizlenecek nesneleri seçin:
|
||||
.bvshow-select = Görünür yapılacak nesneleri seçin:
|
||||
.arrayedit-select-array = ARRAYEDIT Diziyi seçin:
|
||||
.arrayedit-options = ARRAYEDIT Bir seçenek girin [Kaynak/çıKış] <çıKış>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: seçilen nesne ilişkili bir dizi değil.
|
||||
|
||||
@@ -3108,6 +3108,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT 选择带属性的块:
|
||||
.annotation-object-scale = 注释对象比例
|
||||
.bedit-select-block-reference-to-edit = BEDIT 选择要编辑的块引用 :
|
||||
.bvstate-option = BVSTATE 输入选项 [新建/设置/重命名/删除] <设置>:
|
||||
.bvstate-new-name = BVSTATE 输入新可见性状态的名称:
|
||||
.bvstate-set = BVSTATE 输入要置为当前的可见性状态 <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE 输入要重命名的可见性状态 <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE 输入新名称:
|
||||
.bvstate-delete = BVSTATE 输入要删除的可见性状态:
|
||||
.bvstate-not-found = 找不到可见性状态“__ocs_fmt_0__”。
|
||||
.bvstate-exists = 可见性状态“__ocs_fmt_0__”已存在。
|
||||
.bvstate-last = 不能删除唯一的可见性状态。
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: 请先在块编辑器中打开该块 (BEDIT)。
|
||||
.bvstate-current = 当前可见性状态: __ocs_fmt_0__
|
||||
.bvhide-select = 选择要隐藏的对象:
|
||||
.bvshow-select = 选择要显示的对象:
|
||||
.arrayedit-select-array = ARRAYEDIT 选择阵列:
|
||||
.arrayedit-options = ARRAYEDIT 输入选项 [源/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: 所选对象不是关联阵列。
|
||||
|
||||
@@ -3120,6 +3120,19 @@ modify =
|
||||
.attedit-select-block-with-attributes = ATTEDIT 選擇帶屬性的圖塊:
|
||||
.annotation-object-scale = 註解物件比例
|
||||
.bedit-select-block-reference-to-edit = BEDIT 選擇要編輯的圖塊引用 :
|
||||
.bvstate-option = BVSTATE 輸入選項 [新建/設定/更名/刪除] <設定>:
|
||||
.bvstate-new-name = BVSTATE 輸入新可見性狀態的名稱:
|
||||
.bvstate-set = BVSTATE 輸入要設為目前的可見性狀態 <__ocs_fmt_0__>:
|
||||
.bvstate-rename-from = BVSTATE 輸入要更名的可見性狀態 <__ocs_fmt_0__>:
|
||||
.bvstate-rename-to = BVSTATE 輸入新名稱:
|
||||
.bvstate-delete = BVSTATE 輸入要刪除的可見性狀態:
|
||||
.bvstate-not-found = 找不到可見性狀態「__ocs_fmt_0__」。
|
||||
.bvstate-exists = 可見性狀態「__ocs_fmt_0__」已存在。
|
||||
.bvstate-last = 無法刪除唯一的可見性狀態。
|
||||
.bvstate-needs-bedit = __ocs_fmt_0__: 請先在圖塊編輯器中開啟圖塊 (BEDIT)。
|
||||
.bvstate-current = 目前可見性狀態: __ocs_fmt_0__
|
||||
.bvhide-select = 選取要隱藏的物件:
|
||||
.bvshow-select = 選取要顯示的物件:
|
||||
.arrayedit-select-array = ARRAYEDIT 選取陣列:
|
||||
.arrayedit-options = ARRAYEDIT 輸入選項 [來源/eXit] <eXit>:
|
||||
.arrayedit-not-an-array = ARRAYEDIT: 選取的物件不是關聯式陣列。
|
||||
|
||||
@@ -260,6 +260,14 @@ impl OpenCADStudio {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// A dynamic block leaves the editor showing its first visibility
|
||||
// state, with erased objects dropped from its states.
|
||||
let definition = session.br_handle;
|
||||
crate::scene::block_visibility::finish_editing(
|
||||
&mut self.tabs[i].scene.document,
|
||||
definition,
|
||||
);
|
||||
self.tabs[i].scene.visibility_states.remove(&definition);
|
||||
if let Some(delta) = self.block_edit_delta(i) {
|
||||
let mut history = self.tabs[i].block_edit_history.take().unwrap();
|
||||
std::mem::swap(&mut self.tabs[i].history, &mut history.main);
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
//! BVSTATE, BVHIDE and BVSHOW: the visibility states of the block open in
|
||||
//! the Block Editor (see `scene::block_visibility`).
|
||||
|
||||
use crate::app::{Message, OpenCADStudio};
|
||||
use crate::scene::block_visibility as visibility;
|
||||
use codec::{CadDocument, EntityType, Handle};
|
||||
use iced::Task;
|
||||
|
||||
impl OpenCADStudio {
|
||||
/// The block open in the Block Editor, or an error naming `command`.
|
||||
fn visibility_block(&mut self, i: usize, command: &str) -> Option<Handle> {
|
||||
let block = self.tabs[i]
|
||||
.active_block_edit_session()
|
||||
.map(|session| session.br_handle);
|
||||
if block.is_none() {
|
||||
self.command_line.push_error(
|
||||
crate::tf!("{}: open the block in the Block Editor first (BEDIT).", command)
|
||||
.as_ref(),
|
||||
);
|
||||
}
|
||||
block
|
||||
}
|
||||
|
||||
/// The block's visibility parameter, made when it has none: its grip
|
||||
/// sits on the block's base point.
|
||||
fn visibility_parameter(&mut self, i: usize, block: Handle) -> Option<Handle> {
|
||||
let document = &mut self.tabs[i].scene.document;
|
||||
let base = document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|record| record.handle == block)
|
||||
.and_then(|record| match document.get_entity(record.block_entity_handle) {
|
||||
Some(EntityType::Block(begin)) => Some(begin.base_point),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or(codec::types::Vector3::ZERO);
|
||||
visibility::create(document, block, base)
|
||||
}
|
||||
|
||||
/// The state the block shows in the editor.
|
||||
fn visibility_current(&self, i: usize, block: Handle) -> usize {
|
||||
let scene = &self.tabs[i].scene;
|
||||
scene.visibility_states.get(&block).copied().unwrap_or_else(|| {
|
||||
visibility::parameter(&scene.document, block)
|
||||
.map_or(0, |parameter| visibility::shown_state(&scene.document, parameter.handle))
|
||||
})
|
||||
}
|
||||
|
||||
fn show_visibility_state(&mut self, i: usize, block: Handle, parameter: Handle, state: usize) {
|
||||
visibility::apply_state(&mut self.tabs[i].scene.document, parameter, state);
|
||||
self.tabs[i].scene.visibility_states.insert(block, state);
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.tabs[i].dirty = true;
|
||||
if let Some(name) = visibility::state_names(&self.tabs[i].scene.document, parameter)
|
||||
.get(state)
|
||||
{
|
||||
self.command_line
|
||||
.push_output(crate::tf!("Current visibility state: {}", name).as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn dispatch_bvisibility(&mut self, cmd: &str, i: usize) -> Option<Task<Message>> {
|
||||
use crate::command::CadCommand;
|
||||
use crate::modules::draw::modify::bvstate::{BvStateCommand, SEP};
|
||||
match cmd {
|
||||
"BVSTATE" => {
|
||||
let block = self.visibility_block(i, "BVSTATE")?;
|
||||
let document = &self.tabs[i].scene.document;
|
||||
let names = visibility::parameter(document, block)
|
||||
.map(|parameter| visibility::state_names(document, parameter.handle))
|
||||
.unwrap_or_else(|| vec!["VisibilityState0".to_string()]);
|
||||
let current = self.visibility_current(i, block);
|
||||
if let Some(name) = names.get(current) {
|
||||
self.command_line
|
||||
.push_output(crate::tf!("Current visibility state: {}", name).as_ref());
|
||||
}
|
||||
let command = BvStateCommand::new(names, current);
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.command_line.set_step_options(command.options());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
Some(Task::none())
|
||||
}
|
||||
cmd if cmd.starts_with("_BVSTATE") => {
|
||||
let block = self.visibility_block(i, "BVSTATE")?;
|
||||
let fields: Vec<&str> = cmd.split(SEP).skip(1).collect();
|
||||
self.push_undo_snapshot(i, "BVSTATE");
|
||||
let parameter = self.visibility_parameter(i, block)?;
|
||||
let current = self.visibility_current(i, block);
|
||||
let document = &mut self.tabs[i].scene.document;
|
||||
let index = |document: &CadDocument, name: &str| {
|
||||
visibility::state_names(document, parameter)
|
||||
.iter()
|
||||
.position(|candidate| candidate.eq_ignore_ascii_case(name))
|
||||
};
|
||||
let shown = match fields.as_slice() {
|
||||
["NEW", name] => visibility::add_state(document, parameter, name, current),
|
||||
["SET", name] => index(document, name),
|
||||
["RENAME", from, to] => {
|
||||
if let Some(state) = index(document, from) {
|
||||
visibility::rename_state(document, parameter, state, to);
|
||||
}
|
||||
Some(current)
|
||||
}
|
||||
["DELETE", name] => index(document, name).map(|state| {
|
||||
visibility::delete_state(document, parameter, state);
|
||||
let count = visibility::state_names(document, parameter).len();
|
||||
if current == state || current >= count {
|
||||
0
|
||||
} else if current > state {
|
||||
current - 1
|
||||
} else {
|
||||
current
|
||||
}
|
||||
}),
|
||||
_ => None,
|
||||
};
|
||||
self.show_visibility_state(i, block, parameter, shown.unwrap_or(current));
|
||||
self.tabs[i].active_cmd = None;
|
||||
Some(Task::none())
|
||||
}
|
||||
"BVHIDE" | "BVSHOW" => {
|
||||
let block = self.visibility_block(i, cmd)?;
|
||||
let hide = cmd == "BVHIDE";
|
||||
if !hide {
|
||||
// Every object of the block shows while they are picked;
|
||||
// the state is put back once the pick ends.
|
||||
let document = &mut self.tabs[i].scene.document;
|
||||
let members: Vec<Handle> = document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|record| record.handle == block)
|
||||
.map(|record| record.entity_handles.clone())
|
||||
.unwrap_or_default();
|
||||
for handle in members {
|
||||
if let Some(entity) = document.get_entity_mut(handle) {
|
||||
entity.common_mut().invisible = false;
|
||||
}
|
||||
}
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
}
|
||||
let pending = if hide { "_BVHIDE" } else { "_BVSHOW" };
|
||||
if !self.tabs[i].scene.selected.is_empty() {
|
||||
return Some(self.dispatch_command(pending));
|
||||
}
|
||||
let prompt = if hide {
|
||||
"Select objects to hide:"
|
||||
} else {
|
||||
"Select objects to make visible:"
|
||||
};
|
||||
use crate::modules::draw::select::SelectObjectsCommand;
|
||||
let command = SelectObjectsCommand::with_prompt(cmd, pending, prompt);
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
Some(Task::none())
|
||||
}
|
||||
"_BVHIDE" | "_BVSHOW" => {
|
||||
let block = self.visibility_block(i, &cmd[1..])?;
|
||||
let handles: Vec<Handle> = self.tabs[i]
|
||||
.scene
|
||||
.selected_handles_in_order()
|
||||
.into_iter()
|
||||
.filter(|handle| {
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.get_entity(*handle)
|
||||
.is_some_and(|entity| entity.common().owner_handle == block)
|
||||
})
|
||||
.collect();
|
||||
self.push_undo_snapshot(i, &cmd[1..]);
|
||||
let parameter = self.visibility_parameter(i, block)?;
|
||||
let current = self.visibility_current(i, block);
|
||||
visibility::set_visible(
|
||||
&mut self.tabs[i].scene.document,
|
||||
parameter,
|
||||
current,
|
||||
&handles,
|
||||
cmd == "_BVSHOW",
|
||||
);
|
||||
self.tabs[i].scene.deselect_all();
|
||||
self.show_visibility_state(i, block, parameter, current);
|
||||
self.tabs[i].active_cmd = None;
|
||||
Some(Task::none())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use std::path::PathBuf;
|
||||
mod attdef;
|
||||
mod blocks;
|
||||
mod blockvars;
|
||||
mod bvisibility;
|
||||
mod count;
|
||||
mod dim;
|
||||
pub(crate) mod display;
|
||||
@@ -302,6 +303,9 @@ impl OpenCADStudio {
|
||||
if let Some(t) = self.dispatch_xref_attach(cmd, i) {
|
||||
return Some(t);
|
||||
}
|
||||
if let Some(t) = self.dispatch_bvisibility(cmd, i) {
|
||||
return Some(t);
|
||||
}
|
||||
if let Some(t) = self.dispatch_blocks(cmd, i) {
|
||||
return Some(t);
|
||||
}
|
||||
|
||||
+17
-1
@@ -186,6 +186,20 @@ impl OpenCADStudio {
|
||||
return;
|
||||
}
|
||||
|
||||
// A reference to the definition itself gets an evaluated copy first,
|
||||
// so the state picked for it leaves the definition alone.
|
||||
let direct = {
|
||||
let doc = &self.tabs[i].scene.document;
|
||||
matches!(doc.get_entity(insert_handle), Some(EntityType::Insert(ins))
|
||||
if doc.block_records.get(&ins.block_name).is_some_and(|record| {
|
||||
crate::scene::block_visibility::parameter(doc, record.handle).is_some()
|
||||
}))
|
||||
};
|
||||
if direct {
|
||||
self.push_undo_snapshot(i, "Visibility State");
|
||||
self.tabs[i].scene.visibility_representation(insert_handle);
|
||||
}
|
||||
|
||||
// Resolve everything against an immutable borrow first.
|
||||
let mapping = {
|
||||
let doc = &self.tabs[i].scene.document;
|
||||
@@ -202,7 +216,9 @@ impl OpenCADStudio {
|
||||
return;
|
||||
};
|
||||
|
||||
self.push_undo_snapshot(i, "Visibility State");
|
||||
if !direct {
|
||||
self.push_undo_snapshot(i, "Visibility State");
|
||||
}
|
||||
|
||||
// Apply invisibility flags to the anonymous block's members.
|
||||
{
|
||||
|
||||
@@ -832,6 +832,19 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"BACKGROUND colour [Default/Black/DarkGray/Gray/LightGray/White] or R G B (0–255):" => Some(("file", "background-colour-default-black-darkgray-gray")),
|
||||
"BASE Specify base point:" => Some(("insert", "base-specify-base-point")),
|
||||
"BEDIT Select block reference to edit:" => Some(("modify", "bedit-select-block-reference-to-edit")),
|
||||
"BVSTATE Enter an option [New/Set/Rename/Delete] <Set>:" => Some(("modify", "bvstate-option")),
|
||||
"BVSTATE Enter name of new visibility state:" => Some(("modify", "bvstate-new-name")),
|
||||
"BVSTATE Enter visibility state to make current <{}>:" => Some(("modify", "bvstate-set")),
|
||||
"BVSTATE Enter visibility state to rename <{}>:" => Some(("modify", "bvstate-rename-from")),
|
||||
"BVSTATE Enter new name:" => Some(("modify", "bvstate-rename-to")),
|
||||
"BVSTATE Enter visibility state to delete:" => Some(("modify", "bvstate-delete")),
|
||||
"Visibility state \"{}\" not found." => Some(("modify", "bvstate-not-found")),
|
||||
"Visibility state \"{}\" already exists." => Some(("modify", "bvstate-exists")),
|
||||
"The only visibility state cannot be deleted." => Some(("modify", "bvstate-last")),
|
||||
"{}: open the block in the Block Editor first (BEDIT)." => Some(("modify", "bvstate-needs-bedit")),
|
||||
"Current visibility state: {}" => Some(("modify", "bvstate-current")),
|
||||
"Select objects to hide:" => Some(("modify", "bvhide-select")),
|
||||
"Select objects to make visible:" => Some(("modify", "bvshow-select")),
|
||||
"ARRAYEDIT Select array:" => Some(("modify", "arrayedit-select-array")),
|
||||
"ARRAYEDIT Enter an option [Source/eXit] <eXit>:" => Some(("modify", "arrayedit-options")),
|
||||
"ARRAYEDIT: the selected object is not an associative array." => Some(("modify", "arrayedit-not-an-array")),
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
// BVSTATE — the visibility states of the block open in the Block Editor:
|
||||
// make a new one, make one current, rename or delete one. The first use in a
|
||||
// block makes it dynamic with a visibility parameter.
|
||||
|
||||
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind};
|
||||
use codec::Handle;
|
||||
use glam::DVec3;
|
||||
|
||||
/// Separates the fields of the `_BVSTATE` step the command hands over.
|
||||
pub const SEP: char = '\u{1f}';
|
||||
|
||||
enum Step {
|
||||
Option,
|
||||
NewName,
|
||||
SetName,
|
||||
RenameFrom,
|
||||
RenameTo(String),
|
||||
DeleteName,
|
||||
}
|
||||
|
||||
pub struct BvStateCommand {
|
||||
names: Vec<String>,
|
||||
current: usize,
|
||||
step: Step,
|
||||
}
|
||||
|
||||
impl BvStateCommand {
|
||||
pub fn new(names: Vec<String>, current: usize) -> Self {
|
||||
Self {
|
||||
names,
|
||||
current,
|
||||
step: Step::Option,
|
||||
}
|
||||
}
|
||||
|
||||
fn current_name(&self) -> String {
|
||||
self.names.get(self.current).cloned().unwrap_or_default()
|
||||
}
|
||||
|
||||
fn known(&self, name: &str) -> Option<String> {
|
||||
self.names
|
||||
.iter()
|
||||
.find(|candidate| candidate.eq_ignore_ascii_case(name))
|
||||
.cloned()
|
||||
}
|
||||
|
||||
fn done(parts: &[&str]) -> CmdResult {
|
||||
let mut command = String::from("_BVSTATE");
|
||||
for part in parts {
|
||||
command.push(SEP);
|
||||
command.push_str(part);
|
||||
}
|
||||
CmdResult::Dispatch(command)
|
||||
}
|
||||
|
||||
fn unknown(name: &str) -> CmdResult {
|
||||
CmdResult::ReportError(crate::tf!("Visibility state \"{}\" not found.", name).into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for BvStateCommand {
|
||||
fn name(&self) -> &'static str {
|
||||
"BVSTATE"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
Step::Option => {
|
||||
crate::t!("BVSTATE Enter an option [New/Set/Rename/Delete] <Set>:").into_owned()
|
||||
}
|
||||
Step::NewName => crate::t!("BVSTATE Enter name of new visibility state:").into_owned(),
|
||||
Step::SetName => crate::tf!(
|
||||
"BVSTATE Enter visibility state to make current <{}>:",
|
||||
self.current_name()
|
||||
)
|
||||
.into_owned(),
|
||||
Step::RenameFrom => crate::tf!(
|
||||
"BVSTATE Enter visibility state to rename <{}>:",
|
||||
self.current_name()
|
||||
)
|
||||
.into_owned(),
|
||||
Step::RenameTo(_) => crate::t!("BVSTATE Enter new name:").into_owned(),
|
||||
Step::DeleteName => {
|
||||
crate::t!("BVSTATE Enter visibility state to delete:").into_owned()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn options(&self) -> Vec<CmdOption> {
|
||||
match self.step {
|
||||
Step::Option => vec![
|
||||
CmdOption::new(crate::t!("New").as_ref(), "N"),
|
||||
CmdOption::new(crate::t!("Set").as_ref(), "S"),
|
||||
CmdOption::new(crate::t!("Rename").as_ref(), "R"),
|
||||
CmdOption::new(crate::t!("Delete").as_ref(), "D"),
|
||||
],
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn wants_text_input(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn input_kind(&self) -> InputKind {
|
||||
match self.step {
|
||||
Step::Option => InputKind::SingleToken,
|
||||
_ => InputKind::FreeText,
|
||||
}
|
||||
}
|
||||
|
||||
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
|
||||
let text = text.trim();
|
||||
match &self.step {
|
||||
Step::Option => {
|
||||
self.step = match text.trim_start_matches('_').to_ascii_uppercase().as_str() {
|
||||
"N" | "NEW" => Step::NewName,
|
||||
"" | "S" | "SET" => Step::SetName,
|
||||
"R" | "RENAME" => Step::RenameFrom,
|
||||
"D" | "DELETE" => Step::DeleteName,
|
||||
_ => {
|
||||
return Some(CmdResult::ReportError(
|
||||
crate::t!("Invalid option keyword.").into_owned(),
|
||||
))
|
||||
}
|
||||
};
|
||||
Some(CmdResult::NeedPoint)
|
||||
}
|
||||
Step::NewName if text.is_empty() => Some(CmdResult::NeedPoint),
|
||||
Step::NewName => match self.known(text) {
|
||||
Some(_) => Some(CmdResult::ReportError(
|
||||
crate::tf!("Visibility state \"{}\" already exists.", text).into_owned(),
|
||||
)),
|
||||
None => Some(Self::done(&["NEW", text])),
|
||||
},
|
||||
Step::SetName => {
|
||||
let name = if text.is_empty() {
|
||||
self.current_name()
|
||||
} else {
|
||||
text.to_string()
|
||||
};
|
||||
Some(match self.known(&name) {
|
||||
Some(name) => Self::done(&["SET", &name]),
|
||||
None => Self::unknown(&name),
|
||||
})
|
||||
}
|
||||
Step::RenameFrom => {
|
||||
let name = if text.is_empty() {
|
||||
self.current_name()
|
||||
} else {
|
||||
text.to_string()
|
||||
};
|
||||
match self.known(&name) {
|
||||
Some(name) => {
|
||||
self.step = Step::RenameTo(name);
|
||||
Some(CmdResult::NeedPoint)
|
||||
}
|
||||
None => Some(Self::unknown(&name)),
|
||||
}
|
||||
}
|
||||
Step::RenameTo(_) if text.is_empty() => Some(CmdResult::NeedPoint),
|
||||
Step::RenameTo(from) => {
|
||||
let taken = self
|
||||
.known(text)
|
||||
.is_some_and(|existing| !existing.eq_ignore_ascii_case(from));
|
||||
Some(if taken {
|
||||
CmdResult::ReportError(
|
||||
crate::tf!("Visibility state \"{}\" already exists.", text).into_owned(),
|
||||
)
|
||||
} else {
|
||||
Self::done(&["RENAME", from, text])
|
||||
})
|
||||
}
|
||||
Step::DeleteName if text.is_empty() => Some(CmdResult::NeedPoint),
|
||||
Step::DeleteName => Some(match self.known(text) {
|
||||
Some(_) if self.names.len() <= 1 => CmdResult::ReportError(
|
||||
crate::t!("The only visibility state cannot be deleted.").into_owned(),
|
||||
),
|
||||
Some(name) => Self::done(&["DELETE", &name]),
|
||||
None => Self::unknown(text),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, _handle: Handle, _pt: DVec3) -> CmdResult {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
self.on_text_input("").unwrap_or(CmdResult::Cancel)
|
||||
}
|
||||
}
|
||||
|
||||
inventory::submit!(crate::command::CommandRegistration {
|
||||
names: &["BVSTATE", "BVHIDE", "BVSHOW"]
|
||||
});
|
||||
@@ -5,6 +5,7 @@ pub mod attedit;
|
||||
pub mod blend;
|
||||
pub mod block_edit;
|
||||
pub mod break_cmd;
|
||||
pub mod bvstate;
|
||||
pub mod copy;
|
||||
pub mod delete;
|
||||
mod entity_index;
|
||||
|
||||
@@ -0,0 +1,742 @@
|
||||
//! Visibility states of a dynamic block, authored in the Block Editor and
|
||||
//! stored the way the format keeps them: a BLOCKVISIBILITYPARAMETER in the
|
||||
//! block's `ACAD_ENHANCEDBLOCK` evaluation graph (with its grip and the
|
||||
//! grip's two location expressions), `AcDbBlockRepETag` tags on the
|
||||
//! definition and on each of its objects, and, behind every reference that
|
||||
//! shows a state other than the definition's, an evaluated `*U` copy tagged
|
||||
//! `AcDbBlockRepBTag` and linked back by `AcDbBlockRepresentationData`.
|
||||
//!
|
||||
//! The definition itself shows the first state, so a reference to it needs
|
||||
//! no copy until another state is picked for it.
|
||||
|
||||
use codec::objects::{
|
||||
BlockElement, BlockEvalExpression, BlockEvalValue, BlockEvaluationEdge, BlockEvaluationGraph,
|
||||
BlockEvaluationNode, BlockGrip, BlockGripExpression, BlockParameterPropertyInfo,
|
||||
BlockRepresentationData, BlockVisibilityParameter, BlockVisibilityState, DynamicBlockData,
|
||||
DynamicBlockObject, ObjectType,
|
||||
};
|
||||
use codec::types::Vector3;
|
||||
use codec::xdata::{ExtendedDataRecord, XDataValue};
|
||||
use codec::{CadDocument, EntityType, Handle};
|
||||
|
||||
use super::Scene;
|
||||
|
||||
const ELEMENT_TAG: &str = "AcDbBlockRepETag";
|
||||
const REPRESENTATION_TAG: &str = "AcDbBlockRepBTag";
|
||||
const TRUE_NAME: &str = "AcDbDynamicBlockTrueName";
|
||||
const GUID: &str = "AcDbDynamicBlockGUID";
|
||||
|
||||
/// Object version the parameter, grip and expressions carry.
|
||||
const MAJOR: i32 = 33;
|
||||
const MINOR: i32 = 329;
|
||||
/// Value code of an expression that holds no value.
|
||||
const NO_VALUE: i16 = -9999;
|
||||
|
||||
/// (DXF name, class, DWG maintenance version) of the classes used here.
|
||||
const CLASSES: &[(&str, &str, i32)] = &[
|
||||
("ACAD_EVALUATION_GRAPH", "AcDbEvalGraph", 55),
|
||||
("BLOCKVISIBILITYPARAMETER", "AcDbBlockVisibilityParameter", 55),
|
||||
("BLOCKVISIBILITYGRIP", "AcDbBlockVisibilityGrip", 55),
|
||||
("BLOCKGRIPLOCATIONCOMPONENT", "AcDbBlockGripExpr", 20),
|
||||
("ACDB_DYNAMICBLOCKPURGEPREVENTER_VERSION", "AcDbDynamicBlockPurgePreventer", 61),
|
||||
("ACDB_BLOCKREPRESENTATION_DATA", "AcDbBlockRepresentationData", 58),
|
||||
];
|
||||
|
||||
/// Register the classes with the flags and versions the reference writes
|
||||
/// for them; a reader takes a class registered otherwise for a proxy.
|
||||
fn register_classes(document: &mut CadDocument) {
|
||||
for &(dxf_name, cpp_class_name, maintenance_version) in CLASSES {
|
||||
if let Some(existing) = document.classes.get_mut_by_name(dxf_name) {
|
||||
existing.proxy_flags = codec::classes::ProxyFlags(1153);
|
||||
existing.dwg_version = 25;
|
||||
existing.maintenance_version = maintenance_version;
|
||||
continue;
|
||||
}
|
||||
document.classes.add_or_update(codec::classes::DxfClass {
|
||||
dxf_name: dxf_name.to_string(),
|
||||
cpp_class_name: cpp_class_name.to_string(),
|
||||
application_name: "ObjectDBX Classes".to_string(),
|
||||
proxy_flags: codec::classes::ProxyFlags(1153),
|
||||
instance_count: 0,
|
||||
was_zombie: false,
|
||||
is_an_entity: false,
|
||||
class_number: 0,
|
||||
item_class_id: 0x1F3,
|
||||
dwg_version: 25,
|
||||
maintenance_version,
|
||||
unknown1: 0,
|
||||
unknown2: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_app_id(document: &mut CadDocument, name: &str) {
|
||||
if !document.app_ids.contains(name) {
|
||||
let mut app = codec::tables::AppId::new(name);
|
||||
app.handle = document.allocate_handle();
|
||||
let _ = document.app_ids.add(app);
|
||||
}
|
||||
}
|
||||
|
||||
fn expression(node_id: i32, value_code: i16, value: BlockEvalValue) -> BlockEvalExpression {
|
||||
BlockEvalExpression {
|
||||
parent_id: BlockEvalExpression::NO_PARENT,
|
||||
major: MAJOR,
|
||||
minor: MINOR,
|
||||
value_code,
|
||||
value,
|
||||
node_id,
|
||||
}
|
||||
}
|
||||
|
||||
fn dynamic(
|
||||
handle: Handle,
|
||||
owner: Handle,
|
||||
dxf_name: &str,
|
||||
cpp_class_name: &str,
|
||||
data: DynamicBlockData,
|
||||
) -> DynamicBlockObject {
|
||||
let mut object = DynamicBlockObject::new(dxf_name, cpp_class_name);
|
||||
object.handle = handle;
|
||||
object.owner = owner;
|
||||
object.data = data;
|
||||
object
|
||||
}
|
||||
|
||||
/// The visibility parameter of block definition `definition`.
|
||||
pub fn parameter(document: &CadDocument, definition: Handle) -> Option<&BlockVisibilityParameter> {
|
||||
document.block_visibility_param_for_def(definition)
|
||||
}
|
||||
|
||||
/// Store an edited parameter in the document and its lookup view.
|
||||
fn store(document: &mut CadDocument, parameter: BlockVisibilityParameter) {
|
||||
document
|
||||
.block_visibility_params
|
||||
.insert(parameter.handle, parameter.clone());
|
||||
document.objects.insert(
|
||||
parameter.handle,
|
||||
ObjectType::BlockVisibilityParameter(parameter),
|
||||
);
|
||||
}
|
||||
|
||||
/// The objects of a definition, block begin and end left out.
|
||||
fn members(document: &CadDocument, definition: Handle) -> Vec<Handle> {
|
||||
document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|record| record.handle == definition)
|
||||
.map(|record| {
|
||||
record
|
||||
.entity_handles
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|handle| {
|
||||
!matches!(
|
||||
document.get_entity(*handle),
|
||||
None | Some(EntityType::Block(_) | EntityType::BlockEnd(_))
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn element_tag(id: i32, handle: Handle) -> ExtendedDataRecord {
|
||||
let mut tag = ExtendedDataRecord::new(ELEMENT_TAG);
|
||||
tag.add_value(XDataValue::Integer16(1));
|
||||
tag.add_value(XDataValue::Integer32(id));
|
||||
tag.add_value(XDataValue::Handle(handle));
|
||||
tag
|
||||
}
|
||||
|
||||
fn element_id(entity: &EntityType) -> Option<i32> {
|
||||
entity
|
||||
.common()
|
||||
.extended_data
|
||||
.get_record(ELEMENT_TAG)?
|
||||
.values
|
||||
.iter()
|
||||
.find_map(|value| match value {
|
||||
XDataValue::Integer32(id) => Some(*id),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn set_entity_tag(document: &mut CadDocument, handle: Handle, record: ExtendedDataRecord) {
|
||||
let app = document
|
||||
.app_ids
|
||||
.get(&record.application_name)
|
||||
.map(|app| app.handle.value());
|
||||
if let Some(entity) = document.get_entity_mut(handle) {
|
||||
let xdata = &mut entity.common_mut().extended_data;
|
||||
// The fresh record, not bytes kept from a read, is what gets written.
|
||||
if let Some(app) = app {
|
||||
xdata.raw_dwg_eed.retain(|(owner, _)| *owner != app);
|
||||
}
|
||||
xdata.upsert_record(record);
|
||||
}
|
||||
}
|
||||
|
||||
/// Give every object of the definition its element tag, numbering the new
|
||||
/// ones after the highest id in use, and record the next id on the block.
|
||||
fn tag_members(document: &mut CadDocument, definition: Handle) {
|
||||
let members = members(document, definition);
|
||||
let mut next = members
|
||||
.iter()
|
||||
.filter_map(|handle| document.get_entity(*handle).and_then(element_id))
|
||||
.max()
|
||||
.map_or(0, |id| id + 1);
|
||||
for handle in members {
|
||||
let id = match document.get_entity(handle).and_then(element_id) {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
next += 1;
|
||||
next - 1
|
||||
}
|
||||
};
|
||||
set_entity_tag(document, handle, element_tag(id, handle));
|
||||
}
|
||||
let mut tag = ExtendedDataRecord::new(ELEMENT_TAG);
|
||||
tag.add_value(XDataValue::Integer16(1));
|
||||
tag.add_value(XDataValue::Integer32(next));
|
||||
document.set_object_xdata_record(definition, tag);
|
||||
}
|
||||
|
||||
/// A registry-format GUID for a new dynamic block.
|
||||
fn new_guid() -> String {
|
||||
let mut bytes = [0u8; 16];
|
||||
if getrandom::fill(&mut bytes).is_err() {
|
||||
let seed = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.map_or(0, |elapsed| elapsed.as_nanos());
|
||||
bytes = seed.to_le_bytes();
|
||||
}
|
||||
let hex: String = bytes.iter().map(|byte| format!("{byte:02X}")).collect();
|
||||
format!(
|
||||
"{{{}-{}-{}-{}-{}}}",
|
||||
&hex[0..8],
|
||||
&hex[8..12],
|
||||
&hex[12..16],
|
||||
&hex[16..20],
|
||||
&hex[20..32]
|
||||
)
|
||||
}
|
||||
|
||||
/// Make block definition `definition` dynamic with a visibility parameter
|
||||
/// whose grip sits at `location`, one state showing every object. Returns
|
||||
/// the parameter, or the one the block has already.
|
||||
pub fn create(document: &mut CadDocument, definition: Handle, location: Vector3) -> Option<Handle> {
|
||||
if let Some(existing) = parameter(document, definition) {
|
||||
return Some(existing.handle);
|
||||
}
|
||||
let name = document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|record| record.handle == definition)?
|
||||
.name
|
||||
.clone();
|
||||
register_classes(document);
|
||||
for app in [ELEMENT_TAG, REPRESENTATION_TAG, TRUE_NAME, GUID] {
|
||||
ensure_app_id(document, app);
|
||||
}
|
||||
let dictionary = document.ensure_extension_dictionary(definition);
|
||||
let [graph, parameter, grip, x, y, preventer] =
|
||||
[(); 6].map(|_| document.allocate_handle());
|
||||
|
||||
store(
|
||||
document,
|
||||
BlockVisibilityParameter {
|
||||
handle: parameter,
|
||||
owner: graph,
|
||||
eval_parent_id: BlockEvalExpression::NO_PARENT,
|
||||
eval_major: MAJOR,
|
||||
eval_minor: MINOR,
|
||||
eval_value_code: NO_VALUE,
|
||||
eval_value: BlockEvalValue::None,
|
||||
eval_node_id: 1,
|
||||
element_name: "Visibility State".to_string(),
|
||||
element_major: MAJOR,
|
||||
element_minor: MINOR,
|
||||
element_eed_1071: 0,
|
||||
show_properties: true,
|
||||
chain_actions: false,
|
||||
name: "Visibility1".to_string(),
|
||||
description: String::new(),
|
||||
def_point: location,
|
||||
property_info: [
|
||||
BlockParameterPropertyInfo::default(),
|
||||
BlockParameterPropertyInfo::default(),
|
||||
],
|
||||
property_info_count: 2,
|
||||
is_initialized: true,
|
||||
unknown_bool: false,
|
||||
all_blocks: Vec::new(),
|
||||
states: vec![BlockVisibilityState {
|
||||
name: "VisibilityState0".to_string(),
|
||||
..Default::default()
|
||||
}],
|
||||
},
|
||||
);
|
||||
let grip_object = dynamic(
|
||||
grip,
|
||||
graph,
|
||||
"BLOCKVISIBILITYGRIP",
|
||||
"AcDbBlockVisibilityGrip",
|
||||
DynamicBlockData::VisibilityGrip(BlockGrip {
|
||||
element: BlockElement {
|
||||
eval: expression(2, NO_VALUE, BlockEvalValue::None),
|
||||
name: "Grip".to_string(),
|
||||
major: MAJOR,
|
||||
minor: MINOR,
|
||||
eed_1071: 0,
|
||||
},
|
||||
flags_91: 3,
|
||||
flags_92: 4,
|
||||
location,
|
||||
insert_cycling: false,
|
||||
insert_cycling_weight: -1,
|
||||
}),
|
||||
);
|
||||
document
|
||||
.objects
|
||||
.insert(grip, ObjectType::DynamicBlock(grip_object));
|
||||
for (handle, node, axis) in [(x, 3, "UpdatedX"), (y, 4, "UpdatedY")] {
|
||||
let component = dynamic(
|
||||
handle,
|
||||
graph,
|
||||
"BLOCKGRIPLOCATIONCOMPONENT",
|
||||
"AcDbBlockGripExpr",
|
||||
DynamicBlockData::GripLocationComponent(BlockGripExpression {
|
||||
eval: expression(node, 40, BlockEvalValue::Real(0.0)),
|
||||
grip_type: 1,
|
||||
expression: axis.to_string(),
|
||||
}),
|
||||
);
|
||||
document
|
||||
.objects
|
||||
.insert(handle, ObjectType::DynamicBlock(component));
|
||||
}
|
||||
// The grip drives the parameter, whose position the two expressions
|
||||
// read: node 0 the parameter, 1 the grip, 2 and 3 the expressions.
|
||||
let node = |id: i32, expression: Handle, node_data: [i32; 4]| BlockEvaluationNode {
|
||||
id,
|
||||
edge_flags: 32,
|
||||
next_id: id + 1,
|
||||
expression,
|
||||
node_data,
|
||||
active_cycles: None,
|
||||
};
|
||||
let edge = |id: i32, source_node: i32, destination_node: i32, outgoing_edges| {
|
||||
BlockEvaluationEdge {
|
||||
id,
|
||||
next_id: 0,
|
||||
incoming_edge: 1,
|
||||
source_node,
|
||||
destination_node,
|
||||
outgoing_edges,
|
||||
}
|
||||
};
|
||||
let mut graph_object = dynamic(
|
||||
graph,
|
||||
dictionary,
|
||||
"ACAD_EVALUATION_GRAPH",
|
||||
"AcDbEvalGraph",
|
||||
DynamicBlockData::EvaluationGraph(BlockEvaluationGraph {
|
||||
first_node_id: 4,
|
||||
first_node_id_copy: 4,
|
||||
nodes: vec![
|
||||
node(0, parameter, [0, 0, 1, 2]),
|
||||
node(1, grip, [-1, -1, 0, 0]),
|
||||
node(2, x, [1, 1, -1, -1]),
|
||||
node(3, y, [2, 2, -1, -1]),
|
||||
],
|
||||
edges: vec![
|
||||
edge(0, 1, 0, [-1; 5]),
|
||||
edge(1, 0, 2, [-1, -1, -1, 2, -1]),
|
||||
edge(2, 0, 3, [-1, -1, 1, -1, -1]),
|
||||
],
|
||||
}),
|
||||
);
|
||||
graph_object.reactors.push(dictionary);
|
||||
document
|
||||
.objects
|
||||
.insert(graph, ObjectType::DynamicBlock(graph_object));
|
||||
let mut preventer_object = dynamic(
|
||||
preventer,
|
||||
dictionary,
|
||||
"ACDB_DYNAMICBLOCKPURGEPREVENTER_VERSION",
|
||||
"AcDbDynamicBlockPurgePreventer",
|
||||
DynamicBlockData::Representation(BlockRepresentationData {
|
||||
flags: 1,
|
||||
block: definition,
|
||||
}),
|
||||
);
|
||||
preventer_object.reactors.push(dictionary);
|
||||
document
|
||||
.objects
|
||||
.insert(preventer, ObjectType::DynamicBlock(preventer_object));
|
||||
if let Some(ObjectType::Dictionary(dictionary)) = document.objects.get_mut(&dictionary) {
|
||||
dictionary.add_entry("ACAD_ENHANCEDBLOCK", graph);
|
||||
dictionary.add_entry("AcDbDynamicBlockRoundTripPurgePreventer", preventer);
|
||||
}
|
||||
|
||||
let mut true_name = ExtendedDataRecord::new(TRUE_NAME);
|
||||
true_name.add_value(XDataValue::String(name));
|
||||
document.set_object_xdata_record(definition, true_name);
|
||||
let mut guid = ExtendedDataRecord::new(GUID);
|
||||
guid.add_value(XDataValue::String(new_guid()));
|
||||
document.set_object_xdata_record(definition, guid);
|
||||
tag_members(document, definition);
|
||||
Some(parameter)
|
||||
}
|
||||
|
||||
/// The names of the states of `parameter`, in list order.
|
||||
pub fn state_names(document: &CadDocument, parameter: Handle) -> Vec<String> {
|
||||
match document.objects.get(¶meter) {
|
||||
Some(ObjectType::BlockVisibilityParameter(parameter)) => {
|
||||
parameter.states.iter().map(|state| state.name.clone()).collect()
|
||||
}
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn edit<R>(
|
||||
document: &mut CadDocument,
|
||||
parameter: Handle,
|
||||
change: impl FnOnce(&mut BlockVisibilityParameter) -> R,
|
||||
) -> Option<R> {
|
||||
let Some(ObjectType::BlockVisibilityParameter(current)) = document.objects.get(¶meter)
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
let mut edited = current.clone();
|
||||
let result = change(&mut edited);
|
||||
store(document, edited);
|
||||
Some(result)
|
||||
}
|
||||
|
||||
/// Add state `name`, showing what state `like` shows. Returns its index, or
|
||||
/// `None` when the name is taken.
|
||||
pub fn add_state(
|
||||
document: &mut CadDocument,
|
||||
parameter: Handle,
|
||||
name: &str,
|
||||
like: usize,
|
||||
) -> Option<usize> {
|
||||
edit(document, parameter, |parameter| {
|
||||
if parameter
|
||||
.states
|
||||
.iter()
|
||||
.any(|state| state.name.eq_ignore_ascii_case(name))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let visible_blocks = parameter
|
||||
.states
|
||||
.get(like)
|
||||
.map(|state| state.visible_blocks.clone())
|
||||
.unwrap_or_default();
|
||||
parameter.states.push(BlockVisibilityState {
|
||||
name: name.to_string(),
|
||||
visible_blocks,
|
||||
visible_params: Vec::new(),
|
||||
});
|
||||
Some(parameter.states.len() - 1)
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Rename state `index`; false when the new name is taken.
|
||||
pub fn rename_state(
|
||||
document: &mut CadDocument,
|
||||
parameter: Handle,
|
||||
index: usize,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
edit(document, parameter, |parameter| {
|
||||
let taken = parameter
|
||||
.states
|
||||
.iter()
|
||||
.enumerate()
|
||||
.any(|(other, state)| other != index && state.name.eq_ignore_ascii_case(name));
|
||||
match parameter.states.get_mut(index) {
|
||||
Some(state) if !taken => {
|
||||
state.name = name.to_string();
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Delete state `index`; the last state stays.
|
||||
pub fn delete_state(document: &mut CadDocument, parameter: Handle, index: usize) -> bool {
|
||||
edit(document, parameter, |parameter| {
|
||||
if parameter.states.len() <= 1 || index >= parameter.states.len() {
|
||||
return false;
|
||||
}
|
||||
parameter.states.remove(index);
|
||||
true
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Show (`visible`) or hide `handles` in state `index`. An object the
|
||||
/// parameter did not govern yet is shown in every other state, as it was.
|
||||
pub fn set_visible(
|
||||
document: &mut CadDocument,
|
||||
parameter: Handle,
|
||||
index: usize,
|
||||
handles: &[Handle],
|
||||
visible: bool,
|
||||
) {
|
||||
let definition = owner_definition(document, parameter);
|
||||
edit(document, parameter, |parameter| {
|
||||
for &handle in handles {
|
||||
if !parameter.all_blocks.contains(&handle) {
|
||||
parameter.all_blocks.push(handle);
|
||||
for state in &mut parameter.states {
|
||||
state.visible_blocks.push(handle);
|
||||
}
|
||||
}
|
||||
let Some(state) = parameter.states.get_mut(index) else {
|
||||
continue;
|
||||
};
|
||||
state.visible_blocks.retain(|other| *other != handle);
|
||||
if visible {
|
||||
state.visible_blocks.push(handle);
|
||||
}
|
||||
}
|
||||
});
|
||||
if let Some(definition) = definition {
|
||||
tag_members(document, definition);
|
||||
}
|
||||
}
|
||||
|
||||
/// The block definition `parameter` belongs to (graph, dictionary, record).
|
||||
fn owner_definition(document: &CadDocument, parameter: Handle) -> Option<Handle> {
|
||||
let graph = match document.objects.get(¶meter)? {
|
||||
ObjectType::BlockVisibilityParameter(parameter) => parameter.owner,
|
||||
_ => return None,
|
||||
};
|
||||
let dictionary = match document.objects.get(&graph)? {
|
||||
ObjectType::DynamicBlock(graph) => graph.owner,
|
||||
_ => return None,
|
||||
};
|
||||
match document.objects.get(&dictionary)? {
|
||||
ObjectType::Dictionary(dictionary) => Some(dictionary.owner),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Show the definition's objects as state `index` does.
|
||||
pub fn apply_state(document: &mut CadDocument, parameter: Handle, index: usize) {
|
||||
let Some(ObjectType::BlockVisibilityParameter(current)) = document.objects.get(¶meter)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(state) = current.states.get(index) else {
|
||||
return;
|
||||
};
|
||||
let shown: Vec<(Handle, bool)> = current
|
||||
.all_blocks
|
||||
.iter()
|
||||
.map(|handle| (*handle, state.visible_blocks.contains(handle)))
|
||||
.collect();
|
||||
for (handle, visible) in shown {
|
||||
if let Some(entity) = document.get_entity_mut(handle) {
|
||||
entity.common_mut().invisible = !visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The state whose objects are the ones the definition shows now.
|
||||
pub fn shown_state(document: &CadDocument, parameter: Handle) -> usize {
|
||||
let Some(ObjectType::BlockVisibilityParameter(parameter)) = document.objects.get(¶meter)
|
||||
else {
|
||||
return 0;
|
||||
};
|
||||
parameter
|
||||
.states
|
||||
.iter()
|
||||
.position(|state| {
|
||||
parameter.all_blocks.iter().all(|handle| {
|
||||
let shown = document
|
||||
.get_entity(*handle)
|
||||
.is_some_and(|entity| !entity.common().invisible);
|
||||
shown == state.visible_blocks.contains(handle)
|
||||
})
|
||||
})
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// After the Block Editor: drop objects that were erased, tag new ones and
|
||||
/// leave the definition showing its first state.
|
||||
pub fn finish_editing(document: &mut CadDocument, definition: Handle) {
|
||||
let Some(handle) = parameter(document, definition).map(|parameter| parameter.handle) else {
|
||||
return;
|
||||
};
|
||||
let live: Vec<Handle> = members(document, definition);
|
||||
edit(document, handle, |parameter| {
|
||||
parameter.all_blocks.retain(|handle| live.contains(handle));
|
||||
for state in &mut parameter.states {
|
||||
state.visible_blocks.retain(|handle| live.contains(handle));
|
||||
}
|
||||
});
|
||||
tag_members(document, definition);
|
||||
apply_state(document, handle, 0);
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
/// Give a reference to a dynamic definition its own evaluated copy, so a
|
||||
/// state picked for it leaves the definition and the other references
|
||||
/// alone. Returns the copy's name; a reference already showing a copy,
|
||||
/// or not dynamic, keeps its block and gets `None`.
|
||||
pub fn visibility_representation(&mut self, insert: Handle) -> Option<String> {
|
||||
let Some(EntityType::Insert(reference)) = self.document.get_entity(insert) else {
|
||||
return None;
|
||||
};
|
||||
let definition = self.document.block_records.get(&reference.block_name)?.handle;
|
||||
parameter(&self.document, definition)?;
|
||||
let name = {
|
||||
let next = self
|
||||
.document
|
||||
.block_records
|
||||
.iter()
|
||||
.filter_map(|record| record.name.strip_prefix("*U")?.parse::<u64>().ok())
|
||||
.max()
|
||||
.map_or(1, |n| n + 1);
|
||||
format!("*U{next}")
|
||||
};
|
||||
let base = self
|
||||
.document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|record| record.handle == definition)
|
||||
.and_then(|record| match self.document.get_entity(record.block_entity_handle) {
|
||||
Some(EntityType::Block(block)) => Some(block.base_point),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or(Vector3::ZERO);
|
||||
let originals = members(&self.document, definition);
|
||||
let copies: Vec<EntityType> = originals
|
||||
.iter()
|
||||
.filter_map(|handle| self.document.get_entity(*handle).cloned())
|
||||
.collect();
|
||||
self.define_block_raw(&name, base, copies);
|
||||
let record = self.document.block_records.get_mut(&name)?;
|
||||
record.flags.anonymous = true;
|
||||
let copy = record.handle;
|
||||
// The copies keep their element ids, now naming themselves.
|
||||
for handle in members(&self.document, copy) {
|
||||
if let Some(id) = self.document.get_entity(handle).and_then(element_id) {
|
||||
set_entity_tag(&mut self.document, handle, element_tag(id, handle));
|
||||
}
|
||||
}
|
||||
let mut tag = ExtendedDataRecord::new(REPRESENTATION_TAG);
|
||||
tag.add_value(XDataValue::Integer16(1));
|
||||
tag.add_value(XDataValue::Handle(definition));
|
||||
self.document.set_object_xdata_record(copy, tag);
|
||||
self.document.ensure_extension_dictionary(copy);
|
||||
|
||||
// The reference: AcDbBlockRepresentation / AcDbRepData names the
|
||||
// definition it was evaluated from.
|
||||
let holder = self.document.ensure_extension_dictionary(insert);
|
||||
let representation = self.document.allocate_handle();
|
||||
let data = self.document.allocate_handle();
|
||||
let mut dictionary = codec::objects::Dictionary::new();
|
||||
dictionary.handle = representation;
|
||||
dictionary.owner = holder;
|
||||
dictionary.reactors.push(holder);
|
||||
dictionary.add_entry("AcDbRepData", data);
|
||||
self.document
|
||||
.objects
|
||||
.insert(representation, ObjectType::Dictionary(dictionary));
|
||||
if let Some(ObjectType::Dictionary(holder)) = self.document.objects.get_mut(&holder) {
|
||||
holder.add_entry("AcDbBlockRepresentation", representation);
|
||||
}
|
||||
let mut link = dynamic(
|
||||
data,
|
||||
representation,
|
||||
"ACDB_BLOCKREPRESENTATION_DATA",
|
||||
"AcDbBlockRepresentationData",
|
||||
DynamicBlockData::Representation(BlockRepresentationData {
|
||||
flags: 1,
|
||||
block: definition,
|
||||
}),
|
||||
);
|
||||
link.reactors.push(representation);
|
||||
self.document
|
||||
.objects
|
||||
.insert(data, ObjectType::DynamicBlock(link));
|
||||
self.document.block_representations.insert(data, definition);
|
||||
if let Some(EntityType::Insert(reference)) = self.document.get_entity_mut(insert) {
|
||||
reference.block_name = name.clone();
|
||||
}
|
||||
for record in self.document.block_records.iter_mut() {
|
||||
if record.handle == definition {
|
||||
record.insert_handles.retain(|handle| *handle != insert);
|
||||
} else if record.handle == copy {
|
||||
record.insert_handles.push(insert);
|
||||
}
|
||||
}
|
||||
self.bump_geometry();
|
||||
Some(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codec::entities::{Circle, Insert, Line};
|
||||
|
||||
/// A block given visibility states round-trips them, and a reference
|
||||
/// given its own copy still finds the definition and its states.
|
||||
#[test]
|
||||
fn states_and_a_reference_copy_survive_dwg_and_dxf() {
|
||||
let mut scene = Scene::new();
|
||||
scene.define_block_raw(
|
||||
"door",
|
||||
Vector3::ZERO,
|
||||
vec![
|
||||
EntityType::Line(Line::from_coords(0.0, 0.0, 0.0, 1.0, 0.0, 0.0)),
|
||||
EntityType::Circle(Circle::from_center_radius(Vector3::new(0.5, 0.5, 0.0), 0.25)),
|
||||
],
|
||||
);
|
||||
let definition = scene.document.block_records.get("door").unwrap().handle;
|
||||
let parameter = create(&mut scene.document, definition, Vector3::ZERO).unwrap();
|
||||
let open = add_state(&mut scene.document, parameter, "Open", 0).unwrap();
|
||||
let circle = members(&scene.document, definition)[1];
|
||||
set_visible(&mut scene.document, parameter, open, &[circle], false);
|
||||
finish_editing(&mut scene.document, definition);
|
||||
|
||||
let insert = scene.add_entity(EntityType::Insert(Insert::new("door", Vector3::ZERO)));
|
||||
let copy = scene.visibility_representation(insert).expect("a copy");
|
||||
assert!(copy.starts_with("*U"));
|
||||
|
||||
for ext in ["dwg", "dxf"] {
|
||||
let bytes = crate::io::save_to_bytes(&scene.document, ext, scene.document.version)
|
||||
.unwrap_or_else(|error| panic!("save {ext}: {error}"));
|
||||
let read = crate::io::load_bytes(&format!("door.{ext}"), bytes)
|
||||
.unwrap_or_else(|error| panic!("load {ext}: {error}"));
|
||||
let insert = read
|
||||
.entities()
|
||||
.find_map(|entity| match entity {
|
||||
EntityType::Insert(insert) if insert.block_name.starts_with("*U") => {
|
||||
Some(insert.common.handle)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| panic!("{ext}: reference to the copy"));
|
||||
let (found, parameter) = read
|
||||
.dynamic_visibility_for_insert(insert)
|
||||
.unwrap_or_else(|| panic!("{ext}: no visibility parameter"));
|
||||
let record = read.block_records.iter().find(|r| r.handle == found).unwrap();
|
||||
assert_eq!(record.name, "door", "{ext}");
|
||||
let names: Vec<&str> = parameter.states.iter().map(|s| s.name.as_str()).collect();
|
||||
assert_eq!(names, ["VisibilityState0", "Open"], "{ext}");
|
||||
assert_eq!(parameter.states[1].visible_blocks.len(), 0, "{ext}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
// cache — block-definition and property caches
|
||||
pub mod annotative;
|
||||
pub mod assoc_array;
|
||||
pub mod block_visibility;
|
||||
pub mod compare;
|
||||
pub mod section_cull;
|
||||
pub mod sub_select;
|
||||
@@ -2123,6 +2124,9 @@ pub struct Scene {
|
||||
/// frozen-layer signature. Invalidated only when a light entity changes;
|
||||
/// ordinary geometry edits never rescan the drawing's lights.
|
||||
lighting_cache: RefCell<HashMap<(Handle, u64), Vec<SceneLight>>>,
|
||||
/// The visibility state each dynamic block shows in the Block Editor,
|
||||
/// by block record.
|
||||
pub visibility_states: HashMap<Handle, usize>,
|
||||
/// Currently selected entity handles.
|
||||
pub selected: HashSet<Handle>,
|
||||
/// Polylines only part of which is selected (Ctrl+click): the picked
|
||||
@@ -2772,6 +2776,7 @@ impl Scene {
|
||||
last_created_dimension: None,
|
||||
object_data_cache: crate::entities::object_data::ObjectDataCache::default(),
|
||||
lighting_cache: RefCell::new(HashMap::default()),
|
||||
visibility_states: HashMap::default(),
|
||||
selected: HashSet::default(),
|
||||
sub_segments: HashMap::default(),
|
||||
selected_order: Vec::new(),
|
||||
|
||||
Reference in new issue
Block a user