Jump to content
KRBeckman

Block Edit Lisp

Recommended Posts

KRBeckman

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.

Share this post


Link to post
Share on other sites
irneb

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?

Share this post


Link to post
Share on other sites
pBe

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? :)

Share this post


Link to post
Share on other sites
irneb
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 ""))

Share this post


Link to post
Share on other sites
irneb

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).

Share this post


Link to post
Share on other sites
irneb
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" "" "")

Share this post


Link to post
Share on other sites
irneb
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.

Share this post


Link to post
Share on other sites
pBe
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)

Share this post


Link to post
Share on other sites
irneb

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.

Share this post


Link to post
Share on other sites
pBe
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:

Share this post


Link to post
Share on other sites
irneb

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)

Share this post


Link to post
Share on other sites
pBe

Wow.. 8)

 

You did actually wrote one for reactors.

I'll check it out later... tied up with work :sweat:

Share this post


Link to post
Share on other sites
irneb

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:

Share this post


Link to post
Share on other sites
KRBeckman
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?

Share this post


Link to post
Share on other sites
KRBeckman
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?

Share this post


Link to post
Share on other sites
irneb
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?

Share this post


Link to post
Share on other sites
KRBeckman
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.

Share this post


Link to post
Share on other sites
irneb

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.

Share this post


Link to post
Share on other sites
KRBeckman
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!!!:)

Share this post


Link to post
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
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  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...