Jump to content

Lisp to toggle visibility parameter then run a command on selected blocks?


eyeofnewt555

Recommended Posts

Hey guys!

 

Ideal flow:

 

Select blocks > run lisp > Visibility parameter (called "Buffer Ring") toggled to state called "On" > LineWorkShrinkWrap runs on selected blocks > Visibility parameter toggled back to "Off"

 

Lee Mac's code here looks like a good start.

 

Trying to learn, so walking me through whatever you do would be appreciated.

 

Thanks!

Link to comment
Share on other sites

Lee's code uses defun am2 so you would run this 1st do your thing and run then am22 agian.

 

The only change is that you would do the selection set out side of AM2.

 

Not tested just a guide

(defun c:buff ( / ss)
(setq tag "TAG1" "tag2" tag3")) ;; <<-- Tag to be Searched
(setq ss (ssget "_X" '((0 . "INSERT") (66 . 1))))
(am2 ss)
(shrinkwrap)
(am2 ss)
)

 

What exactly do you mean by shrink wrap just a bounding box or a boundary around shape.

Link to comment
Share on other sites

  • For every block in the SS with a certain name:
  • if its dynamic:
  • Invoke the GetDynamicBlockProperties method
  • using vl-some, check if theres parameter with the PropertyName "Buffer Ring"
  • also check if it that parameter has Allowedvalues, where members are "On" and "Off"
  • then create variant for "On" and use the put-value property,
  • run this LineWorkShrinkWrap,
  • then again using vl-some, create variant for "Off" and use the put-value property.

 

Atleast I think that the coding should look like this.

Link to comment
Share on other sites

My bad, I misunderstood what Lee's code was doing in the post I linked. It was toggling the visibility of an attribute, not turning a visibility parameter on/off (no wonder it wasn't working for me, lol).

 

Gonna try to stitch together some of his code from here with the advice from you guys. I'll report back with my ugly, broken frankenlisp for further guidance shortly.

Link to comment
Share on other sites

Okay so before adding in the LineWorkShrinkWrap bit, I wanted first to be able to just change the visibility state. Road block #1.

 

I modified Lee Mac's wonderful code from here to:

(defun C:chvis ( / blk )
(setq blk (ssget))
(LM:setdynpropvalue blk "Buffer Ring" "On")

(princ)
)


;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
   (setq prp (strcase prp))
   (vl-some
      '(lambda ( x )
           (if (= prp (strcase (vla-get-propertyname x)))
               (progn
                   (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                   (cond (val) (t))
               )
           )
       )
       (vlax-invoke blk 'getdynamicblockproperties)
   )
)

(vl-load-com) (princ)

 

Aaaand, it doesn't work.

 

This, less-modified version does though:

(defun C:changevis ( / blk )
(if (and (setq blk (car (entsel "\nSelect dynamic block: ")))
(setq blk (vlax-ename->vla-object blk))
(= "AcDbBlockReference" (vla-get-objectname blk))
(= :vlax-true (vla-get-isdynamicblock blk))
)
(LM:setdynpropvalue blk "Buffer Ring" "On")
)
(princ)
)

;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
   (setq prp (strcase prp))
   (vl-some
      '(lambda ( x )
           (if (= prp (strcase (vla-get-propertyname x)))
               (progn
                   (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                   (cond (val) (t))
               )
           )
       )
       (vlax-invoke blk 'getdynamicblockproperties)
   )
)

(vl-load-com) (princ)

 

Instead of it changing just the one selected block, I want it to change whatever is in the selection set (might even be different blocks with the same visibility parameter).

 

So, how do I tweak this code to get to that?

 

I've been looking through Lee's dynamic block routines and seeing how they're implemented on different forums, but still too green to really get this working.

 

Thanks!

Edited by eyeofnewt555
Link to comment
Share on other sites

Okay so before adding in the LineWorkShrinkWrap bit, I wanted first to be able to just change the visibility state. Road block #1.

 

Instead of it changing just the one selected block, I want it to change whatever is in the selection set (might even be different blocks with the same visibility parameter).

 

So, how do I tweak this code to get to that?

 

I've been looking through Lee's dynamic block routines and seeing how they're implemented on different forums, but still to green to really get this working.

 

Thanks!

 

You have to iterate over the selection set, check his selection set processing tutorial.

Link to comment
Share on other sites

You have to iterate over the selection set, check his selection set processing tutorial.

 

 

Grrr, thank you! Would you advise using method 5 (I'm super fuzzy on the relationships involved, but I know dynamic blocks have something to do with VLA objects) or method 2a?

Link to comment
Share on other sites

Okay tried method 5 and it's telling me I've got too few arguments. Also, an error related to the latter part of the code where it invokes 'getdynamicblockproperties--which isn't defined anywhere. Think it'll be alright for me to just delete that bit out?

 

(defun C:test5 ( / blk )
(if (ssget)
       (progn
           (vlax-for o (setq blk (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object))))
               (print (vla-get-objectname o))
           )
           (vla-delete blk)
       )
   )
(LM:setdynpropvalue blk "Buffer Ring" "On")

(princ)
)


;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
   (setq prp (strcase prp))
   (vl-some
      '(lambda ( x )
           (if (= prp (strcase (vla-get-propertyname x)))
               (progn
                   (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                   (cond (val) (t))
               )
           )
       )
       (vlax-invoke blk 'getdynamicblockproperties)
   )
)

(vl-load-com) (princ)

Link to comment
Share on other sites

I think that the fastest is the "reverse repeat", method 2a:

(if (setq SS (ssget "_:L" (list (cons 0 "INSERT"))))
 (repeat (setq i (sslength SS))
   (setq e (ssname SS (setq i (1- i)))) ; the "nth" entity in the selection
   (setq enx (entget e))                ; the "nth" entity data in the selection
   (setq o (vlax-ename->vla-object e))  ; the "nth" object in the selection
   (and 
     (= "AcDbBlockReference" (vla-get-ObjectName o))
     (= :vlax-true (vla-get-IsDynamicBlock o))
     (LM:setdynpropvalue blk "Buffer Ring" "On")
   ); and
 ); repeat
); if SS

 

The ActiveX (Method 5) may be a good way too, since it doesn't require to convert every ename into a vla-object,

but you have to delete the selection set object in the end.

 

(if (ssget "_:L-I" (list (cons 0 "INSERT")))
 (progn
   (vlax-for o (setq SS (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object))))
     (and 
       (= "AcDbBlockReference" (vla-get-ObjectName o))
       (= :vlax-true (vla-get-IsDynamicBlock o))
       (LM:setdynpropvalue blk "Buffer Ring" "On")
     ); and
   )
   (vla-delete SS)
 )
)

Link to comment
Share on other sites

I think that the fastest is the "reverse repeat", method 2a:

 

Put together, I'm getting the "too few arguments" error. I suspect it has something to do with me conflating the individual object (blk) with the selection set (SS), but I'm not sure which variables to change to fix that.

 

(defun C:chvis ( / blk i e enx o)

(if (setq blk (ssget "_:L" (list (cons 0 "INSERT"))))
 (repeat (setq i (sslength blk))
   (setq e (ssname blk (setq i (1- i)))) ; the "nth" entity in the selection
   (setq enx (entget e))                ; the "nth" entity data in the selection
   (setq o (vlax-ename->vla-object e))  ; the "nth" object in the selection
   (and 
     (= "AcDbBlockReference" (vla-get-ObjectName o))
     (= :vlax-true (vla-get-IsDynamicBlock o))
     (LM:setdynpropvalue blk "Buffer Ring" "On")
   ); and
 ); repeat
); if SS

(princ)
)


;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
   (setq prp (strcase prp))
   (vl-some
      '(lambda ( x )
           (if (= prp (strcase (vla-get-propertyname x)))
               (progn
                   (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                   (cond (val) (t))
               )
           )
       )
      
   )
)

(vl-load-com) (princ)

Link to comment
Share on other sites

This variable is not reffering to a block, but rather a selection set that contain and "index" count of blocks:

(setq blk (ssget "_:L" (list (cons 0 "INSERT"))))

So more proper (understandable for you) symbol to assign to it would be:

(setq SS_of_blocks (ssget "_:L" (list (cons 0 "INSERT"))))

Then get the index count of the selection set:

(setq index (sslength SS_of_blocks))

 

So the iteration in some understandable way would look like:

(repeat (setq index (sslength SS_of_blocks))
 (setq BlockEntity (ssname SS_of_blocks (setq index (1- index))))   ; the "nth" entity in the selection
 (setq BlockDxfData (entget BlockEntity))                           ; the "nth" entity's dxf data in the selection
 (setq BlockVlaObject (vlax-ename->vla-object BlockEntity))         ; the "nth" vla-object in the selection
 (and 
   (= "AcDbBlockReference" (vla-get-ObjectName BlockVlaObject))  ; this check could be removed if (cons 0 "INSERT") is used as a ssget filter
   (= :vlax-true (vla-get-IsDynamicBlock BlockVlaObject))
   (LM:setdynpropvalue BlockVlaObject "Buffer Ring" "On")
 ); and
); repeat

 

And I don't know how did you managed to remove this row from LM's subfunciton:

;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
 (setq prp (strcase prp))
 (vl-some
   '(lambda ( x )
     (if (= prp (strcase (vla-get-propertyname x)))
       (progn
         (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
         (cond (val) (t))
       )
     )
   )
   [color=red](vlax-invoke blk 'getdynamicblockproperties)[/color]
 )
)

Link to comment
Share on other sites

Thank you, Grrr! It finally works. Unfortunately, I think I'm gonna end up going in a different direction to accomplish what I need as I think my original game plan would require waaay too much time to set up and wouldn't be as functional as I'd like (would require editing each block in our library and then the command would only work on our blocks and wouldn't have much versatility). Thank you for your help! Even if I don't end up using this, I learned a lot.

 

 

(defun C:chvis ( / SS i e enx blk)

(if (setq SS (ssget "_:L" (list (cons 0 "INSERT"))))
 (repeat (setq i (sslength SS))
   (setq e (ssname SS (setq i (1- i)))) ; the "nth" entity in the selection
   (setq enx (entget e))                ; the "nth" entity data in the selection
   (setq blk (vlax-ename->vla-object e))  ; the "nth" object in the selection
   (and 
     (= "AcDbBlockReference" (vla-get-ObjectName blk))
     (= :vlax-true (vla-get-IsDynamicBlock blk))
     (LM:setdynpropvalue blk "Buffer Ring" "On")
   ); and
 ); repeat
); if SS


(princ)
)


;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
   (setq prp (strcase prp))
   (vl-some
      '(lambda ( x )
           (if (= prp (strcase (vla-get-propertyname x)))
               (progn
                   (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                   (cond (val) (t))
               )
           )
       )
      (vlax-invoke blk 'getdynamicblockproperties)
   )
)

(vl-load-com) (princ)

Link to comment
Share on other sites

No problem. The most important part for you is this:

Even if I don't end up using this, I learned a lot.

 

Just like you I did struggle over the years how to extract-apply(get/set) certain information with LISP.

But with alot of persistence and interest + the help and advices from the guys on the forum (esp. Lee Mac & Tharwat) now I'm able to suit alot of my personal needs (I've wrote alot of custom codes that deal ONLY with the dynamic/attributed blocks I use).

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