Аннотативный размерный стиль и dimscale
Столкнулся недавно с файлом, в котором не удавалось заменить значение dimscale. Ни в какую! В чем же проблема?
Как выяснилось, проблема крылась в том, что текущий размерный стиль был аннотативным. Можно, конечно, руками проверять и менять - но "это не наш метод!". Значительно интереснее разобраться, как обойти эту фичу (встретился в ACAD2018 и 2019).
Вариантов на самом деле не так уж и много - вешаем реактор на изменение системной переменной, и либо находим первый неаннотативный размерный стиль и его устанавливаем, либо снимаем аннотативность с текущего. Ну и под конец, естественно, все вернуть обратно надо не забыть.
Но существует ненулевая вероятность, что неаннотативного размерного стиля в текущем документе попросту не будет. Так что снимаем аннотативность, а потом ее возвращаем. Ну и в результате получается нечто типа:
1 2 3 4 5 6 7 8 9 10 11 12 13 | ;; Активируем где-нибудь в загрузчике или отдельной команде реакторы на системные переменные (if *vlr-sysvar* (progn (setq *vlr-sysvar* nil) (vlr-remove-all :vlr-sysvar-reactor)) ) ;_ end of if (if (not *vlr-sysvar*) (setq *vlr-sysvar* (vlr-sysvar-reactor "pik-ind-sysvar-reactor" '((:vlr-sysvarchanged . _kpblc-vlr-sysvar-changed) (:VLR-sysVarWillChange . _kpblc-vlr-sysvar-will-change) ))) ) ;_ end of if ;; Также для работы понадобятся глобальные переменные (setq *kpblc-acad* (vlax-get-acad-object) *kpblc-adoc* (vla-get-activedocument *kpblc-acad*) ) |
И собственно обработки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | (defun _kpblc-vlr-sysvar-will-change (reactor value / sysvar dimst) ;| * Реактор на начало смены значения системной переменной |; (setq sysvar (strcase (car value))) (cond ((= sysvar "DIMSCALE") (if (_kpblc-is-ent-annotative (setq dimst (vla-get-activedimstyle *kpblc-adoc*))) (progn ;; В *KPBLC-SETTINGS-DOC* Запоминаем, что текущий стиль аннотативный и снимаем анно (setq *kpblc-settings-doc* (_kpblc-list-add-or-subst *kpblc-settings-doc* "annodimstyle" t)) (_kpblc-ent-modify-annotative dimst nil) ) ;_ end of progn ) ;_ end of If ) ) ;_ end of cond ) ;_ end of defun (defun _kpblc-vlr-sysvar-changed (reactor value / sysvar descr) (setq sysvar (strcase (car value))) (cond ((= sysvar "DIMSCALE") ;; Можно прописать дополнительные действия. DIMSCALE уже изменен (if (cdr (assoc "annodimstyle" *kpblc-settings-doc*)) (progn (_kpblc-ent-modify-annotative (vla-get-activedimstyle *kpblc-adoc*) t) (setq *kpblc-settings-doc* (_kpblc-list-add-or-subst *kpblc-settings-doc* "annodimstyle" nil)) ) ;_ end of progn ) ;_ end of if ) ) ;_ end of cond ) ;_ end of defun |
Ну и сервисные функции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | (defun _kpblc-conv-ent-to-ename (ent_value / _lst) ;| * Функция преобразования полученного значения в ename * Параметры вызова: * ent_value значение, которое надо преобразовать в примитив. Может * быть именем примитива, vla-указателем или просто * списком. * Если не принадлежит ни одному из указанных типов, * возвращается nil * Примеры вызова: (_kpblc-conv-ent-to-ename (entlast)) (_kpblc-conv-ent-to-ename (vlax-ename->vla-object (entlast))) |; (cond ((= (type ent_value) 'vla-object) (vlax-vla-object->ename ent_value)) ((= (type ent_value) 'ename) ent_value) ((and (= (type ent_value) 'str) (handent ent_value) (entget (handent ent_value))) (handent ent_value) ) ((and (= (type ent_value) 'str) (handent ent_value) (tblobjname "style" ent_value)) (tblobjname "style" ent_value) ) ((and (= (type ent_value) 'str) (handent ent_value) (tblobjname "dimstyle" ent_value)) (tblobjname "dimstyle" ent_value) ) ((and (= (type ent_value) 'str) (handent ent_value) (tblobjname "block" ent_value)) (tblobjname "block" ent_value) ) ((and (= (type ent_value) 'list) (cdr (assoc -1 ent_value))) (cdr (assoc -1 ent_value))) (t nil) ) ;_ end of cond ) ;_ end of defun (defun _kpblc-is-ent-annotative (ent) ;| * Проверяет, является ли объект аннотативным * Параметры вызова: ent ; указатель на обрабатываемый объект |; (and ent (setq ent (_kpblc-conv-ent-to-ename ent)) (cdr (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*")))))) ) ;_ end of and ) ;_ end of defun (defun _kpblc-list-add-or-subst (lst key value) ;| * Производит замену или дополнение элемента списка новым * Параметры вызова: lst обрабатываемый список key ключ value устанавливаемое значение |; (if (not value) (vl-remove-if (function (lambda (x) (= (car x) key))) lst) (if (cdr (assoc key lst)) (subst (cons key value) (assoc key lst) lst) (cons (cons key value) (vl-remove-if (function (lambda (x) (= (car x) key))) lst)) ) ;_ end of if ) ;_ end of if ) ;_ end of defun (defun _kpblc-ent-modify-annotative (ent make / res) ;| * Обработка аннотативности объекта ent ; Указатель на объект make ; назначать аннотативноть (t) или снимать ее (nil) |; (if (and ent (setq ent (_kpblc-conv-ent-to-ename ent)) (> (atoi (getvar "acadver")) 17.0) ;; (not (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*")))))) ) ;_ end of and (cond ((and make (not (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*"))))))) (regapp "AcadAnnotative") (setq res (entmod (list (cons -1 ent) '(-3 ("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}"))) ) ;_ end of list ) ;_ end of entmod ) ;_ end of setq ) ((and (not make) (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*")))))) (setq res (entmod (append (entget ent) (list (cons -3 (append '(("AcadAnnotative")) (vl-remove-if (function (lambda (x) (= (car x "AcadAnnotative")))) (cdr (assoc -2 (entget ent '("*")))) ) ;_ end of vl-remove-if ) ;_ end of append ) ;_ end of cons ) ;_ end of list ) ;_ end of append ) ;_ end of entmod ) ;_ end of setq ) ) ;_ end of cond ) ;_ end of if ) ;_ end of defun |
Если понадобится весь код загнать в один lsp, сообщите в комментариях. Сделаю при первой возможности.