Загрузка данных
;;; ============================================================
;;; DIMFIX.LSP
;;; Редактирование префикса/суффикса размеров внутри блоков
;;; Данные хранятся в XDATA объекта DIMENSION (переживают
;;; передачу файла другому пользователю).
;;; При изменении геометрии блока реактор автоматически
;;; восстанавливает преф/суфф в новом анонимном блоке *D...
;;;
;;; Команды:
;;; SETDIMFIX — кликнуть на цифры размера, ввести преф/суфф
;;; CLEARDIMFIX — снять преф/суфф с размера
;;; ============================================================
(vl-load-com)
;;; ------------------------------------------------------------
;;; КОНСТАНТЫ
;;; ------------------------------------------------------------
(setq *DIMFIX_APP* "DIMFIX_APP") ; имя XDATA-приложения
(setq *DIMFIX_REACTORS* '()) ; список активных реакторов
; формат: ((handle . reactor) ...)
;;; ============================================================
;;; БЛОК 1: XDATA — чтение и запись
;;; ============================================================
(defun DIMFIX_XDATA_REGISTER ()
;; Зарегистрировать APPID если ещё не зарегистрирован
(if (null (tblsearch "APPID" *DIMFIX_APP*))
(entmake (list '(0 . "APPID")
(cons 2 *DIMFIX_APP*)))))
(defun DIMFIX_XDATA_SAVE (dim_ent pre suf / dxf xdata new_xdata)
;; Записать префикс и суффикс в XDATA объекта DIMENSION
(DIMFIX_XDATA_REGISTER)
(setq dxf (entget dim_ent (list *DIMFIX_APP*)))
;; Удалить старые XDATA нашего приложения если есть
(setq dxf (vl-remove-if
'(lambda (x) (= (car x) -3))
dxf))
;; Добавить новые XDATA
(setq dxf (append dxf
(list (list -3
(list *DIMFIX_APP*
(cons 1000 pre)
(cons 1000 suf))))))
(entmod dxf))
(defun DIMFIX_XDATA_LOAD (dim_ent / dxf xdata app_data)
;; Прочитать префикс и суффикс из XDATA
;; Возвращает (список "префикс" "суффикс") или nil
(setq dxf (entget dim_ent (list *DIMFIX_APP*)))
(setq xdata (assoc -3 dxf))
(if xdata
(progn
(setq app_data (cdr (assoc *DIMFIX_APP* (cdr xdata))))
(if (and app_data (>= (length app_data) 2))
(list (cdr (car app_data)) ; префикс (1000)
(cdr (cadr app_data))) ; суффикс (1000)
nil))
nil))
(defun DIMFIX_XDATA_CLEAR (dim_ent / dxf)
;; Удалить XDATA с объекта
(setq dxf (entget dim_ent (list *DIMFIX_APP*)))
(setq dxf (vl-remove-if '(lambda (x) (= (car x) -3)) dxf))
(entmod dxf))
;;; ============================================================
;;; БЛОК 2: ОБНОВЛЕНИЕ ТЕКСТА в анонимном блоке *D...
;;; ============================================================
(defun DIMFIX_UPDATE_TEXT (dim_ent pre suf
/ anon_name anon_def src obj_dxf new_text)
;; Записать "преф<>суфф" в TEXT/MTEXT внутри *D... блока
(setq anon_name (cdr (assoc 2 (entget dim_ent))))
(if (and anon_name (= (substr anon_name 1 2) "*D"))
(progn
(setq anon_def (tblobjname "BLOCK" anon_name))
(if anon_def
(progn
(setq new_text (strcat pre "<>" suf))
(setq src (entnext anon_def))
(while (and src
(/= (cdr (assoc 0 (entget src))) "ENDBLK"))
(setq obj_dxf (entget src))
(if (member (cdr (assoc 0 obj_dxf)) '("TEXT" "MTEXT"))
(progn
(entmod (subst (cons 1 new_text)
(assoc 1 obj_dxf)
obj_dxf))
(entupd src)))
(setq src (entnext src))))))))
;;; ============================================================
;;; БЛОК 3: РЕАКТОР на изменение объекта DIMENSION
;;; ============================================================
(defun DIMFIX_CHANGED_CB (reactor params
/ dim_ent data pre suf)
;; Срабатывает при изменении отслеживаемого размера
(setq dim_ent (vlr-owner reactor))
(if (and dim_ent (not (vlax-erased-p dim_ent)))
(progn
(setq data (DIMFIX_XDATA_LOAD dim_ent))
(if data
(progn
(setq pre (car data))
(setq suf (cadr data))
(DIMFIX_UPDATE_TEXT dim_ent pre suf)
(entupd dim_ent))))))
(defun DIMFIX_ATTACH_REACTOR (dim_ent / handle reactor)
;; Повесить персистентный реактор на объект DIMENSION
;; если реактор ещё не висит
(setq handle (cdr (assoc 5 (entget dim_ent))))
(if (null (assoc handle *DIMFIX_REACTORS*))
(progn
(setq reactor
(vlr-object-reactor
(list dim_ent)
*DIMFIX_APP*
'((:vlr-modified . DIMFIX_CHANGED_CB))))
(vlr-pers reactor) ; сохранить реактор в DWG
(setq *DIMFIX_REACTORS*
(append *DIMFIX_REACTORS*
(list (cons handle reactor)))))))
(defun DIMFIX_DETACH_REACTOR (dim_ent / handle entry reactor)
;; Снять реактор с объекта
(setq handle (cdr (assoc 5 (entget dim_ent))))
(setq entry (assoc handle *DIMFIX_REACTORS*))
(if entry
(progn
(setq reactor (cdr entry))
(vlr-pers-release reactor)
(vlr-remove reactor)
(setq *DIMFIX_REACTORS*
(vl-remove entry *DIMFIX_REACTORS*)))))
;;; ============================================================
;;; БЛОК 4: ВОССТАНОВЛЕНИЕ при открытии файла и после REGEN
;;; ============================================================
(defun DIMFIX_RESTORE ( / ss i ent data pre suf)
;; Найти все DIMENSION с нашими XDATA и восстановить:
;; 1) реакторы
;; 2) текст в *D...
(setq *DIMFIX_REACTORS* '())
;; Выбрать все объекты с нашими XDATA
(setq ss (ssget "_X"
(list '(0 . "DIMENSION")
(cons -3 (list *DIMFIX_APP*)))))
(if ss
(progn
(setq i 0)
(while (< i (sslength ss))
(setq ent (ssname ss i))
(setq data (DIMFIX_XDATA_LOAD ent))
(if data
(progn
(setq pre (car data))
(setq suf (cadr data))
;; Восстановить реактор
(DIMFIX_ATTACH_REACTOR ent)
;; Обновить текст немедленно
(DIMFIX_UPDATE_TEXT ent pre suf)
(entupd ent)))
(setq i (1+ i)))))
(princ))
;;; Реактор на открытие файла
(vlr-dwg-reactor
nil
'((:vlr-endDwgOpen . (lambda (r p) (DIMFIX_RESTORE)))))
;;; Реактор на REGEN — перерисовать все отслеживаемые размеры
(vlr-editor-reactor
nil
'((:vlr-commandEnded .
(lambda (r p)
(if (member (strcase (car p))
'("REGEN" "REGENALL" "REGENVISIBLE"))
(DIMFIX_RESTORE))))))
;;; ============================================================
;;; БЛОК 5: РАЗБОР КЛИКА — получить DIMENSION из nentsel
;;; ============================================================
(defun DIMFIX_GET_DIM_FROM_CLICK ( / sel path anon_name blk_name
anon_ins blk_ref edxf
blk_def src obj_dxf dim_ent)
;; Клик на цифры размера внутри блока
;; Возвращает (dim_ent blk_ref) или nil
(setq sel (nentsel "\nКликните на цифры размера внутри блока: "))
(if (null sel) (progn (princ "\nОтмена.") nil)
(progn
(setq path (caddr sel))
(setq anon_ins nil blk_ref nil)
;; Разобрать путь вхождений
(foreach ent path
(setq edxf (entget ent))
(cond
;; Анонимный блок *D... (размерный)
((and (= (cdr (assoc 0 edxf)) "INSERT")
(= (substr (cdr (assoc 2 edxf)) 1 2) "*D")
(null anon_ins))
(setq anon_ins ent
anon_name (cdr (assoc 2 edxf))))
;; Пользовательский блок (не *)
((and (= (cdr (assoc 0 edxf)) "INSERT")
(/= (substr (cdr (assoc 2 edxf)) 1 1) "*")
(null blk_ref))
(setq blk_ref ent
blk_name (cdr (assoc 2 edxf))))))
(if (null anon_ins)
(progn (princ "\nКликните именно на цифры размера!") nil)
(progn
;; Найти объект DIMENSION в блоке по имени *D...
(setq blk_def (tblobjname "BLOCK" blk_name))
(setq src (entnext blk_def) dim_ent nil)
(while (and src
(/= (cdr (assoc 0 (entget src))) "ENDBLK"))
(setq obj_dxf (entget src))
(if (and (= (cdr (assoc 0 obj_dxf)) "DIMENSION")
(= (cdr (assoc 2 obj_dxf)) anon_name))
(setq dim_ent src))
(setq src (entnext src)))
(if (null dim_ent)
(progn (princ "\nDIMENSION не найден в блоке!") nil)
(list dim_ent blk_ref)))))))
;;; ============================================================
;;; БЛОК 6: АВТОУСТАНОВКА в acaddoc.lsp
;;; ============================================================
(defun DIMFIX_INSTALL ( / lsp_path acaddoc_path f line found load_line)
(setq lsp_path (findfile "dimfix.lsp"))
(if (null lsp_path)
(progn (princ "\nОшибка: не найден файл dimfix.lsp!") (exit)))
;; Найти папку поддержки через acad.pat
(setq support_dir (vl-filename-directory (findfile "acad.pat")))
(if (null support_dir)
(progn (princ "\nНе удалось найти папку поддержки AutoCAD!") (exit)))
(setq acaddoc_path (strcat support_dir "acaddoc.lsp"))
;; Строка загрузки (слэши Unix для совместимости)
(setq lsp_path_fwd
(vl-string-subst "/" "\\" lsp_path))
(setq load_line
(strcat "(if (findfile \"" lsp_path_fwd
"\") (load \"" lsp_path_fwd "\"))"))
;; Проверить — не прописан ли уже
(setq found nil)
(if (findfile acaddoc_path)
(progn
(setq f (open acaddoc_path "r"))
(while (setq line (read-line f))
(if (vl-string-search "dimfix" line)
(setq found T)))
(close f)))
(if found
(princ "\nDimFix уже установлен в acaddoc.lsp.")
(progn
(setq f (open acaddoc_path "a"))
(write-line "" f)
(write-line ";; === DimFix autoload ===" f)
(write-line load_line f)
(close f)
(princ (strcat "\nDimFix установлен в: " acaddoc_path))
(princ "\nПри следующем запуске AutoCAD загрузится автоматически.")))
(princ))
;;; Запустить установку при первой загрузке файла
(if (null *DIMFIX_INSTALLED*)
(progn
(DIMFIX_INSTALL)
(setq *DIMFIX_INSTALLED* T)))
;;; ============================================================
;;; КОМАНДА: SETDIMFIX — установить преф/суфф на размер
;;; ============================================================
(defun c:SETDIMFIX ( / result dim_ent blk_ref cur_data
cur_pre cur_suf new_pre new_suf)
(setq result (DIMFIX_GET_DIM_FROM_CLICK))
(if (null result) (exit))
(setq dim_ent (car result))
(setq blk_ref (cadr result))
;; Показать текущие значения
(setq cur_data (DIMFIX_XDATA_LOAD dim_ent))
(setq cur_pre (if cur_data (car cur_data) ""))
(setq cur_suf (if cur_data (cadr cur_data) ""))
(princ (strcat "\nРазмер: "
(rtos (cdr (assoc 42 (entget dim_ent))) 2 2)))
(princ (strcat "\nПреф: \"" cur_pre
"\" Суфф: \"" cur_suf "\""))
;; Запросить новые значения
(setq new_pre
(getstring T (strcat "\nПрефикс [" cur_pre
"] (Enter = без изменений): ")))
(setq new_suf
(getstring T (strcat "\nСуффикс [" cur_suf
"] (Enter = без изменений): ")))
(if (= new_pre "") (setq new_pre cur_pre))
(if (= new_suf "") (setq new_suf cur_suf))
(if (and (= new_pre cur_pre) (= new_suf cur_suf))
(progn (princ "\nИзменений нет.") (exit)))
;; Сохранить в XDATA
(DIMFIX_XDATA_SAVE dim_ent new_pre new_suf)
;; Повесить реактор
(DIMFIX_ATTACH_REACTOR dim_ent)
;; Обновить отображение немедленно
(DIMFIX_UPDATE_TEXT dim_ent new_pre new_suf)
(entupd dim_ent)
(princ (strcat "\nГотово! \"" new_pre "<>" new_suf "\""))
(princ))
;;; ============================================================
;;; КОМАНДА: CLEARDIMFIX — снять преф/суфф с размера
;;; ============================================================
(defun c:CLEARDIMFIX ( / result dim_ent)
(setq result (DIMFIX_GET_DIM_FROM_CLICK))
(if (null result) (exit))
(setq dim_ent (car result))
;; Снять реактор
(DIMFIX_DETACH_REACTOR dim_ent)
;; Удалить XDATA
(DIMFIX_XDATA_CLEAR dim_ent)
;; Вернуть стандартный текст "<>"
(DIMFIX_UPDATE_TEXT dim_ent "" "")
(entupd dim_ent)
(princ "\nПреф/суфф сняты, размер сброшен к стандартному виду.")
(princ))
;;; ============================================================
;;; Восстановить при загрузке (если файл уже открыт)
;;; ============================================================
(if (and (boundp '*DIMFIX_INSTALLED*)
(/= (getvar "DWGNAME") ""))
(DIMFIX_RESTORE))
(princ "\nDimFix загружен. Команды: SETDIMFIX / CLEARDIMFIX")
(princ)
;;; EOF