Jump to content

Block Edit Lisp


KRBeckman

Recommended Posts

95% of the drawings I work on contain only 3 blocks: "(Part Number)-2D", "(Part Number)-3D", & "Reference", and I'm trying to come up with a quick way to use the "Edit Block In-Place" function, avaliable when you right click on a selected block, for each of these blocks. Here's what I have so far:

 

(defun c:be ()
 (setvar 'cmdecho 0)
 (vl-load-com)
 (initget "-2d -3d Reference")
 (setq opt (nentselp "\nSelect block entity or [-2d/-3d/Ref]: "))
 (if (eq (type opt) 'STR)
   (progn
     (setq ss (ssget "_x" (list (cons 0 "INSERT"))))
     (setq i 0)
     (while (or (not ent) (< i (sslength ss)))
(if (vl-string-search (strcase opt) (strcase (cdr (assoc 2 (entget (ssname ss i))))))
  (setq ent (ssname ss i)))
(setq i (+ i 1))))
   (setq ent opt))
 (vl-cmdf "_.-refedit" ent "_o" "" "")
 (setvar 'cmdecho 1)
 (princ))

 

Which almost works, the only problem is I believe the "-refedit" command needs a point associated with the selection along with the entity name (nentselp maybe?), but I'm not sure how to incorporate that.

 

Any help would be greatly appricated.

Link to comment
Share on other sites

Why not use the BEdit command instead?

 

If you have to use RefEdit then you're correct, it expects a ( (point 1) ((X1 Y1 Z1) (X2 Y2 Z2) (X3 Y3 Z3) (point 2)) ) list as you get from nentsel. I suppose you could create such, but how to make a meaningful point from the block, not to mention how to translate a point on an entity inside from the block definition to the WCS as per the block's insertion, and then to calculate the transformation matrix?

Link to comment
Share on other sites

This almost worked too..

 

(defun c:test  (/ opt)
 (setvar 'cmdecho 0)
 (vl-load-com)
 (initget "DD EE FF Select")
 (setq opt (getkword "\nSelect block entity or [DD/EE/FF/Select]: "))
 (cond 
  ((or (= "DD" opt)
     (= "EE" opt)
     (= "EE" opt))
             (sssetfirst nil (ssget "_x" (list '(0  . "INSERT") (cons 2 opt))))
  (vl-cmdf "_.-refedit")
   (while (> (getvar "CMDACTIVE") 0)
    (command "_o" "" "")
  )
 )
 
((= "Select" opt)
 (sssetfirst nil (ssget ":S" '((0 . "INSERT"))))
  (vl-cmdf "_.-refedit")
   (while (> (getvar "CMDACTIVE") 0)
    (command "_o" "" "")
  )
  ) 
)
(setvar 'cmdecho 1)
(princ)
)

 

Only if there's just 1 instance of the block, the select option can be use for any other blocks.

for the love of me i cant remember to put the code on hold while its still active.. i knew i read ir somewhere. (probably on this forum) :)

 

 
((or (= "DD" opt)
     (= "EE" opt)
     (= "EE" opt))
        (setq ss (ssget "_x" (list '(0  . "INSERT") (cons 2 opt))))
 (setq i -1)
       (while 
    (sssetfirst nil (ssget "_x" (list (assoc 10 (entget (ssname ss (setq i (1+ i)))))
    (cons 2 opt))))
  (vl-cmdf "_.-refedit")
   (while (> (getvar "CMDACTIVE") 0)
    (command "_o" "" "")
  )
 )
 )

FAILURE!!!

This fails after first count.. can anyone figure this one? :)

Link to comment
Share on other sites

for the love of me i cant remember to put the code on hold while its still active.. i knew i read ir somewhere. (probably on this forum) :)
Maybe like this?
(command "_.refedit" "_o")
(while (> (getvar "cmdactive") 0) (command ""))

Link to comment
Share on other sites

You know what? That actually gave me an idea ... I'm not sure why it doesn't want to work through lisp. But it seems to work fine if it's simply a CUI macro:

^C^C^P-refedit;Ok;(while (> (getvar "cmdactive") 0) (command ""))

Create an item in the Custom.CUI's Double Click Actions group called Block. Create a command named something like "Block - Double Click - RefEdit" with the above macro, then drag it onto the Block item you've created. The Custom "should" override the ACAD.CUI, if it doesn't then simply delete the Block item from ACAD.CUI (not ideal, but it's not dificult to add it back since you're not deleting the Block - Double Click command in the ACAD.CUI).

Link to comment
Share on other sites

for the love of me i cant remember to put the code on hold while its still active.. i knew i read ir somewhere. (probably on this forum) :)
Or were you meaning the pause action?
(command "_.refedit" pause "_o" "" "")

Link to comment
Share on other sites

You know what? That actually gave me an idea ... I'm not sure why it doesn't want to work through lisp. But it seems to work fine if it's simply a CUI macro:
^C^C^P-refedit;Ok;(while (> (getvar "cmdactive") 0) (command ""))

Create an item in the Custom.CUI's Double Click Actions group called Block. Create a command named something like "Block - Double Click - RefEdit" with the above macro, then drag it onto the Block item you've created. The Custom "should" override the ACAD.CUI, if it doesn't then simply delete the Block item from ACAD.CUI (not ideal, but it's not dificult to add it back since you're not deleting the Block - Double Click command in the ACAD.CUI).

Forgot, you have to add BLOCKREF as the Object Name of the Block item in the Double Click Actions group.
Link to comment
Share on other sites

Maybe like this?

(command "_.refedit" "_o")(while (> (getvar "cmdactive") 0) (command ""))

 

Hmmmn. I did acually used that though :)

What i'm looking for is to put the Lisp code on hold. maybe its a reactor thing.... hmmmmnnnn (ponder ponder)

Link to comment
Share on other sites

Yes ... well ... that's quite a "large" thing to handle :unsure:. Are you wanting to do something once the RefEdit is closed? That could be done in one of 2 ways:

 

  1. Redefine the RefClose command. Make sure you have the same prompts. Perform whatever you wanted to do, and then call the .RefClose from within it.
  2. Have a reactor look at command completed - testing for refclose.

Anyhow, did you try the macro version? It works quite well for me. Also it's a whole lot less code.

Link to comment
Share on other sites

Yes ... well ... that's quite a "large" thing to handle :unsure:. Are you wanting to do something once the RefEdit is closed? That could be done in one of 2 ways:

 

  1. Redefine the RefClose command. Make sure you have the same prompts. Perform whatever you wanted to do, and then call the .RefClose from within it.
  2. Have a reactor look at command completed - testing for refclose.

Anyhow, did you try the macro version? It works quite well for me. Also it's a whole lot less code.

 

Guess you're right.. plus its a memory hog to use Reactors

Besides, its not my post anyway :) but it would be neat to help the OP out.

in the while loop. i can feel I almost got it but can't quite put my finger on it... :sweat:

Link to comment
Share on other sites

Anyhoo ... here goes:

(vl-load-com)

(defun c:be (/ opt ss n)
 (setq *be:selection* nil)
 (if *be:reactor*
   (setq *be:reactor* (vlr-remove *be:reactor*))
 )
 (initget "-2d -3d Reference")
 (if (setq opt (nentselp "\nSelect block entity or [-2d/-3d/Ref]: "))
   (cond
     ((= (type opt) 'STR)
      (if (wcmatch opt "-2d,-3d")
        (setq opt (strcat "(Part Number)" opt))
      )
      (if (setq ss (ssget "_X" (list '(0 . "INSERT") (cons 2 opt))))
        (progn
          (setq n (sslength ss))
          (while (>= (setq n (1- n)) 0)
            (setq *be:selection* (cons (ssname ss n) *be:selection*))
          )
          (VLR-Reaction-Set (setq *be:reactor* (vlr-editor-reactor "BE")) :vlr-commandEnded 'be:CallBack)
          (setq ss (ssadd (car *be:selection*)))
          (command "._ZOOM" "_Object" ss "")
          (c:BE1)
        )
      )
     )

     ((= (type opt) 'LIST)
      (command ".-RefEdit" opt "_Ok")
      (while (> (getvar "CMDACTIVE") 0) (command ""))
     )
   )
 )
 (princ)
)

(defun be:CallBack (ro ci / ss)
 (if (eq (strcase (car ci)) "REFCLOSE")
   (progn
     (setq ss (ssadd (car *be:selection*)))
     (or *ActiveDoc* (setq *ActiveDoc* (vla-get-ActiveDocument (vlax-get-acad-object))))
     (sssetfirst nil ss)
     (vla-SendCommand *ActiveDoc* "._ZOOM\n_Object\n")
     (vla-SendCommand *ActiveDoc* "BE1\n")
   )
 )
 (if (and (not *be:selection*) *be:reactor*)
   (setq *be:reactor* (vlr-remove *be:reactor*))
 )
 (princ)
)

(defun c:BE1 (/ ss)
 (setq ss             (ssadd (car *be:selection*))
       *be:selection* (cdr *be:selection*)
 )
 (sssetfirst nil ss)
 (command ".-RefEdit" "_Ok")
 (while (> (getvar "CMDACTIVE") 0) (command ""))
)

;; Clear reactors
(setq rlst (vlr-reactors))
(foreach item rlst
 (foreach ro (cdr item)
   (if (= "BE" (vlr-data ro))
     (vlr-remove ro)
   ) ;_ end of if
 ) ;_ end of foreach
) ;_ end of foreach
(setq *be:selection* nil)

Link to comment
Share on other sites

Actually ... I can't understand why you'd want to do this. You're editing the block. Then once you've finished editing it, you edit it again. Rinse and repeat for each copy of the block.

 

Sorry, maybe I'm just stupid :shock:

Link to comment
Share on other sites

Why not use the BEdit command instead?

I don't want to use this because Bedit doesn't edit the block in place... It opens the block editor and I'd rather edit the block in the drawing because I use reference points from the other blocks.

 

If you have to use RefEdit then you're correct, it expects a ( (point 1) ((X1 Y1 Z1) (X2 Y2 Z2) (X3 Y3 Z3) (point 2)) ) list as you get from nentsel. I suppose you could create such, but how to make a meaningful point from the block, not to mention how to translate a point on an entity inside from the block definition to the WCS as per the block's insertion, and then to calculate the transformation matrix?

Not sure if it helps, but all of my drawings and blocks have been standardized so that every block has an insertion point at (0,0,0) and within everyblock there is a point entity at (0,0,0). Would this make this possible?

Link to comment
Share on other sites

Actually ... I can't understand why you'd want to do this. You're editing the block. Then once you've finished editing it, you edit it again. Rinse and repeat for each copy of the block.

 

Sorry, maybe I'm just stupid :shock:

 

Is this a question for the original post?

Link to comment
Share on other sites

Is this a question for the original post?
No that's regarding the code I wrote in post #11. Basically it would select all blocks named Reference. If there's more than one, it will perform a RefEdit on each ... waiting for the user to close the RefEdit before going to the next. But seeing as it's a block: if you've edited one, you've edited them all. Thus why would you need to edit the 2nd copy again?

 

BTW, I hate using RefEdit, it causes untold misery with errors cropping up, strange layer / style names, ugly stuff with associative dims & hatches, etc. I prefer using XRefs then overlaying the one onto the other so I can get those references to points between each. But if you're forced into it, then so be it. Anyhow, between pBe and myself I think we've sorted out your request, haven't we?

Link to comment
Share on other sites

No that's regarding the code I wrote in post #11. Basically it would select all blocks named Reference. If there's more than one, it will perform a RefEdit on each ... waiting for the user to close the RefEdit before going to the next. But seeing as it's a block: if you've edited one, you've edited them all. Thus why would you need to edit the 2nd copy again?

 

I wasn't looking for a way to edit multiple blocks... I just wanted a quck and easy way to specify which one of the three blocks I use in a vast majority of my drawings I wanted to edit without having to click.

 

BTW, I hate using RefEdit, it causes untold misery with errors cropping up, strange layer / style names, ugly stuff with associative dims & hatches, etc. But if you're forced into it, then so be it. Anyhow, between pBe and myself I think we've sorted out your request, haven't we?

 

Really, I've never had any problems with it... Also, I think I didn't do a good job of describing what I'm trying to do the first time, because I think this is way more complicated than what I need, but thanks for your help to this point.

Link to comment
Share on other sites

You're welcome in any case :thumbsup:

 

So ... rereading your original post :oops: ... the answer is using the sssetfirst before you issue the -RefEdit command.

Link to comment
Share on other sites

You're welcome in any case :thumbsup:

 

So ... rereading your original post :oops: ... the answer is using the sssetfirst before you issue the -RefEdit command.

 

Ah, good call, never thought to select the object before activating the command... Here's what I got if anybody else is interested:

 

(defun c:be ()
 (_cef)
 (vl-load-com)
 (initget "-2d -3d Reference")
 (setq opt (entsel "\nSelect block entity or [-2d/-3d/Ref]: "))
 (if (eq (type opt) 'STR)
   (progn
     (setq ss (ssget "_x" (list (cons 0 "INSERT"))))
     (setq i 0)
     (while (or (not ent) (< i (sslength ss)))
(if (vl-string-search (strcase opt) (strcase (cdr (assoc 2 (entget (ssname ss i))))))
  (setq ent (ssname ss i)))
(setq i (+ i 1))))
   (setq ent (car opt)))
 (sssetfirst nil (ssadd ent))
 (vl-cmdf "_.-refedit" "_o" "" "")
 (_cen)
 (princ))

 

Thanks again everybody for all your help!!!:)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...