;;-------------------------=={ Nested Move }==--------------------------;;
;;                                                                      ;;
;;  This program enables the user to move multiple selected objects     ;;
;;  nested within a block or xref (nested to any depth), without        ;;
;;  opening the xref source drawing.                                    ;;
;;                                                                      ;;
;;  Upon calling the program with 'nmove' at the command-line, the      ;;
;;  user is continuously prompted to select objects nested within a     ;;
;;  block or xref to be moved. Similar to the standard move command,    ;;
;;  the user is then prompted to specify a base point & displacement    ;;
;;  for the move operation.                                             ;;
;;                                                                      ;;
;;  The program will then proceed to move the selected object within    ;;
;;  the parent block definition or the xref source drawing, utilising   ;;
;;  an ObjectDBX interface should the xref source drawing be unopened   ;;
;;  in the current drawing session.                                     ;;
;;                                                                      ;;
;;  Upon moving the object: in the case of a block parent, the active   ;;
;;  drawing is regenerated to reflect the modification to the block     ;;
;;  definition across all block references in the drawing; for xrefs,   ;;
;;  the xref source drawing is saved and the xref is reloaded in the    ;;
;;  active drawing.                                                     ;;
;;                                                                      ;;
;;  The program will account for the position, scale, rotation &        ;;
;;  orientation of the parent block or xref relative to the base point  ;;
;;  and displacement vector and will perform successfully under all     ;;
;;  UCS & View settings.                                                ;;
;;                                                                      ;;
;;  Please Note:                                                        ;;
;;  ------------------------------                                      ;;
;;  The act of modifying objects within an xref source drawing involves ;;
;;  saving the external drawing remotely - this action cannot be        ;;
;;  undone within the current drawing and any changes to the external   ;;
;;  drawing must be reset manually.                                     ;;
;;                                                                      ;;
;;  Note that when saving drawings through ObjectDBX, drawing files     ;;
;;  will be saved to the highest version available and drawing file     ;;
;;  thumbnails will be lost until the next manual save.                 ;;
;;                                                                      ;;
;;----------------------------------------------------------------------;;
;;  Author:  Lee Mac, Copyright ?2013  -  www.lee-mac.com              ;;
;;----------------------------------------------------------------------;;
;;  Version 1.0    -    10-08-2013                                      ;;
;;                                                                      ;;
;;  - First release.                                                    ;;
;;----------------------------------------------------------------------;;
;;  Version 1.1    -    26-08-2013                                      ;;
;;                                                                      ;;
;;  - Modified program to move the 'outermost' nested object within     ;;
;;    the parent block or xref.                                         ;;
;;  - Added ability to select multiple nested objects to be moved.      ;;
;;  - Added selection highlighting for visual feedback of selected      ;;
;;    nested objects.                                                   ;;
;;----------------------------------------------------------------------;;
;;  Version 1.2    -    31-08-2013                                      ;;
;;                                                                      ;;
;;  - Fixed bug causing the program to crash when a nested attributed   ;;
;;    block or nested polyline is selected.                             ;;
;;----------------------------------------------------------------------;;

(defun c:lm_block_move ( / old_cmd itm app dbx def doc dwg dwl han hil lst obj own par pt1 pt2 sel tmp vec vrs nmove:entmakex nmove:copynested)
;; Identity Matrix  -  Lee Mac
;; Args: n - matrix dimension
(mai_last_com "lm_block_move")

(defun nmove:entmakex ( enx )
	(entmakex
		(append
			(vl-remove-if
				'(lambda ( x )
					(or (member (car x) '(5 6 8 39 48 62 102 370))
						(= 'ename (type (cdr x)))
					)
				)
				enx
			)
			'(
				(6 . "CONTINUOUS")
				(8 . "0")
				(39 . 0.)
				(48 . 1.)
				(62 . 7)
				(370 . 0)
			)
		)
	)
)

(defun nmove:copynested ( ent / enx)
	(setq enx (entget ent))
	(if (= 1 (mai_dxf 66 enx))
		(progn
			(nmove:entmakex enx)
			(setq
				ent (entnext ent)
				enx (entget  ent)
			)
			(while (/= "SEQEND" (mai_dxf 0 enx))
				(nmove:entmakex enx)
				(setq ent (entnext ent) enx (entget ent))
			)
			(mai_dxf 330 (nmove:entmakex enx))
		)
		(nmove:entmakex enx)
	)
)



	(mini_start nil)
	(setq doc (vlax-get (vlax-get-acad-object) 'activedocument))
	(while
		(progn
			(setvar 'errno 0)
			(setq sel (nentselp "\n选择嵌套实体移动: <回车退出>"))
			(cond
				(	(= 7 (getvar 'errno))
					(princ "\n空选，再试一次.")
				)
				(	(null sel)
					nil
				)
				(	(or (= 2 (length sel))
						(/= "INSERT" (mai_dxf 0 (setq own (last (last sel)))))
					)
					(princ "\n不是【块或外部参照】的内部实体.")
				)
				(	(mai_IsDynamicBlock own)
					(princ "\n这个命令不支持【动态块】内部实体.")
				)
				(	(and (= 'ename (type par)) (not (eq par own)))
					(princ "\nObject is nested within a different parent.")
				)
				(	t
					(or par (setq par own))
					(if (wcmatch (mai_dxf 0 (car sel)) "ATTRIB,VERTEX")
						(setq sel (cons (mai_dxf 330 (car sel)) (cdr sel)))
					)
					(if (cdr (last sel))
						(setq lst (cons (cons (cadr (reverse (last sel))) (car (mai_blk_RevMatrix par))) lst))
						(setq lst (cons (cons (car sel) (mapcar 'mai_rcdr (mai_rcdr (mai_m_inv (caddr sel))))) lst))
					)
					(if (setq tmp (nmove:copynested (caar lst)))
						(progn
							(vla-transformby (vlax-ename->vla-object tmp)
								(vlax-tmatrix
									(if (cdr (last sel))
										(append
											(apply 'mapcar
												(cons
													'(lambda ( r v ) (append r (list v)))
													(mai_blk_matrix par)
												)
											)
											'((0. 0. 0. 1.))
										)
										(caddr sel)
									)
								)
							)
							(redraw tmp 3)
							(setq hil (cons tmp hil))
						)
					)
					t
				)
			)
		)
	)
	(cond
		(	(not
				(and
					(= 'list (type lst))
					(setq pt1 (getpoint "\n移动基点:<回车退出>"))
					(setq pt2 (getpoint "\n移动到点:<回车退出>" pt1))
					(setq vec (mapcar '- (trans pt2 1 0) (trans pt1 1 0)))
				)
			)
		)
		(	(zerop (logand 4 (mai_dxf 70 (setq def (tblsearch "block" (mai_block_name (vlax-ename->vla-object par)))))))
			(foreach itm lst
				(if (vlax-write-enabled-p (setq obj (vlax-ename->vla-object (car itm))))
					(vla-move obj
						(vlax-3D-point 0 0)
						(vlax-3D-point (mai_mxv (cdr itm) vec))
					)
					(princ (strcat "\n句柄名为【 \"" (vlax-get obj 'handle) "\" 】的实体在被锁定的层上."))
				)
			)
			(vla-regen doc acallviewports)
		)
		(	(progn
				(setq app (vlax-get-acad-object)
					  vrs (atoi (getvar 'acadver))
					  dbx "objectdbx.axdbdocument"
					  dbx (vl-catch-all-apply 'vla-getinterfaceobject
								(list app (if (< vrs 16) dbx (strcat dbx "." (itoa vrs))))
						  )
				)
				(and dbx (vl-catch-all-error-p dbx))
			)
			(prompt "\n无法访问 ObjectDBX.")
		)
		(	(or (not (setq dwg (findfile (mai_dxf 1 def))))
				(progn
					(vlax-for doc (vlax-get app 'documents)
						(setq dwl (cons (cons (strcase (vlax-get doc 'fullname)) doc) dwl))
					)
					(not (setq doc (mai_dxf (strcase dwg) dwl)))
				)
				(not (vl-catch-all-error-p (vl-catch-all-apply 'vla-open (list dbx dwg))))
				(not (setq doc dbx))
			)
			(princ "\n无法访问外部参照源文件.")
		)
		(	t
			(foreach itm lst
				(setq
					han (mai_dxf 5 (car itm))
					obj (vl-catch-all-apply 'vla-handletoobject (list doc han))
				)
				(cond
					(	(vl-catch-all-error-p obj)
						(princ (strcat "\n无法定位在外部参照源文件句柄名为【 \"" han "\"】的实体."))
					)
					(	(vlax-write-enabled-p obj)
						(vla-move obj
							(vlax-3D-point 0 0)
							(vlax-3D-point (mai_mxv (cdr itm) vec))
						)
					)
					(	(princ (strcat "\n外部参照源文件内句柄名为 【\"" han "\"】 实体在一个被锁定的层上.")))
				)
			)
			(vla-saveas doc dwg)
			(vla-reload (vla-item (vlax-get doc 'blocks) (mai_dxf 2 def)))
		)
	)
	(mai_end)
)
