Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Insert Dynamic Block with Visibility state pre-selected?

22 REPLIES 22
SOLVED
Reply
Message 1 of 23
mid-awe
8925 Views, 22 Replies

Insert Dynamic Block with Visibility state pre-selected?

Hi all & happy holidays Smiley Happy

 

My question is somewhat of a challenge too. I currently insert certain dynamic block into drawings with a short function that first inserts the specified dynamic block and then immediately changes the visibility state to one specified as an argument to the function.

 

I'm wondering if it is possible / better / faster to somehow insert the dynamic block with the decided visibility state simultaniusly. I've been amazed by many capabilities of VL so I wouldn't at be suprised if this can be done. (the dynamic blocks I'm inserting could have many multiples in the drawing but I need this method to only effect the one being inerted at the time the function is called. I currently use entlast to decide which one is being inserted.)

 

What I'm currently doing is working fine, this question is only for fun for those of us working Christmas Eve 😞 No Worries.

 

Thank you to all who choose to participate.

22 REPLIES 22
Message 2 of 23
Lee_Mac
in reply to: mid-awe

The Visibility State would need to be altered after the block reference is inserted, since the ActiveX methods pertaining to the dynamic block properties would need a pointer to the relevant VLA-Object on which to operate.

 

I would personally suggest using the ActiveX InsertBlock method, and then perhaps using my Set Visibility State function with the VLA Block Reference Object returned by this method.

 

Lee

 

Message 3 of 23
mid-awe
in reply to: Lee_Mac

I like that, it's strait forward.

Perhaps, inserting to 0,0,0 and then entering the vl-move, so that the user experiences the illusion of the method I was describing. (Would that slow the process a lot?) The illusion being as if the block the user is inserting is as intended without first viewing the default visibility state.

What do you think, has much learning made me mad? 😉
Message 4 of 23
Lee_Mac
in reply to: mid-awe


@mid-awe wrote:
Perhaps, inserting to 0,0,0 and then entering the vl-move, so that the user experiences the illusion of the method I was describing. (Would that slow the process a lot?) The illusion being as if the block the user is inserting is as intended without first viewing the default visibility state.

Using the MOVE command is a good idea (the standard AutoCAD command would need to be used instead of the ActiveX move method to achieve the 'ghosting' of the objects whilst the user picks a new insertion point), however, you would still see the original block inserted at the initial insertion point (whether that be 0,0 or elsewhere), and a rubberband between the ghosted block being moved and the original block (as you see with the standard MOVE command).

 

To offer an alternative approach, please try the attached program and let me know what you think Smiley Happy

 

Lee

Message 5 of 23
mid-awe
in reply to: Lee_Mac

Slick Lee. A very nice "universal" approach. That certainly covers all bases.

 

I was thinking more along the lines of being able to use in CUI menu such as an argument (dynblkins "DBLOCKNAME" "DBLOCKVISSTATE"), which requires knowledge of the block and available visibility states. Smiley Very Happy you pulled the rug from under me with this. Now the conundrum, I love universal solutions. Now what? Smiley Indifferent

 

"Think, think, think" -Winnie, the POO

Message 6 of 23
Lee_Mac
in reply to: mid-awe


@mid-awe wrote:

Slick Lee. A very nice "universal" approach. That certainly covers all bases.


Thank you mid-awe, I'm glad you like it! Smiley Happy


@mid-awe wrote:

I was thinking more along the lines of being able to use in CUI menu such as an argument (dynblkins "DBLOCKNAME" "DBLOCKVISSTATE"), which requires knowledge of the block and available visibility states. Smiley Very Happy you pulled the rug from under me with this. Now the conundrum, I love universal solutions. Now what? Smiley Indifferent

 

"Think, think, think" -Winnie, the POO


As you've correctly noted, in order to supply arguments to an appropriate function, you would need prior knowledge of the dynamic block structure - in particular, the names of the defined visibility states.

 

However, the above point aside, the various program prompts could be replaced with function arguments, and for this I would propose the following function:

 

;; Insert With Visibility State  -  Lee Mac
;; Provides an interface through which the user can insert a dynamic block
;; with a preselected visibility state.
;; blk - [str] Block name, filename or full filepath
;; vis - [str] Visibility State to set on insertion
;; Returns: [vla] Inserted VLA block reference object, else nil if unsuccessful

(defun LM:insertwithstate ( blk vis / bse cmd def ent ext new obj pth rtn tmp )
    (setq pth (vl-string-translate "/" "\\" (vl-filename-directory blk)) 
          ext (cond ((vl-filename-extension blk)) (".dwg"))
          bse (vl-filename-base blk)
    )
    (if (/= "" pth)
        (setq pth (strcat pth "\\"))
    )
    (cond
        (   (not
                (or
                    (and
                        (tblsearch "block" bse)
                        (setq blk bse)
                    )
                    (setq blk (findfile (strcat pth bse ext)))
                )
            )
            (prompt (strcat "\nBlock \"" bse "\" not found."))
        )
        (   (progn
                (setq obj
                    (vlax-invoke
                        (vlax-get-property (LM:acdoc)
                            (if (= 1 (getvar 'cvport))
                                'paperspace
                                'modelspace
                            )
                        )
                        'insertblock
                        '(0.0 0.0 0.0)
                        blk
                        1.0 1.0 1.0 0.0
                    )
                )
                (vla-put-visible obj :vlax-false)
                (= :vlax-false (vla-get-isdynamicblock obj))
            )
            (vla-delete obj)
            (prompt (strcat "\nBlock \"" bse "\" is not dynamic."))
        )
        (   (null (LM:setvisibilitystate obj vis))
            (vla-delete obj)
            (prompt
                (strcat
                    "\nUnable to set visibility state of block \""
                    bse
                    "\" to \""
                    vis
                    "\"."
                )
            )
        )
        (   (setq tmp 0)
            (while
                (tblsearch "block"
                    (setq blk
                        (strcat "tmp" (itoa (setq tmp (1+ tmp))))
                    )
                )
            )
            (vla-put-visible
                (car
                    (vlax-invoke (LM:acdoc) 'copyobjects (list obj)
                        (setq def
                            (vlax-invoke
                                (vla-get-blocks (LM:acdoc))
                                'add
                                '(0.0 0.0 0.0)
                                blk
                            )
                        )
                    )
                )
                :vlax-true
            )
            (vla-delete obj)
            (setq ent (entlast)
                  cmd (getvar 'cmdecho)
            )
            (setvar 'cmdecho 0)
            (princ "\nSpecify insertion point: ")
            (if
                (and
                    (vl-cmdf "_.-insert" blk "_S" 1.0 "_R" 0.0 "\\")
                    (not (eq ent (setq ent (entlast))))
                    (setq new (vlax-ename->vla-object ent))
                    (= "AcDbBlockReference" (vla-get-objectname new))
                )
                (progn
                    (setq rtn (car (vlax-invoke new 'explode)))
                    (vla-delete new)
                )
            )
            (setvar 'cmdecho cmd)
            (vl-catch-all-apply 'vla-delete (list def))
        )
    )
    rtn
)

;; Get Visibility Parameter Name  -  Lee Mac
;; Returns the name of the Visibility Parameter of a Dynamic Block (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; Returns: [str] Name of Visibility Parameter, else nil

(defun LM:getvisibilityparametername ( blk / vis )  
    (if
        (and
            (vlax-property-available-p blk 'effectivename)
            (setq blk
                (vla-item
                    (vla-get-blocks (vla-get-document blk))
                    (vla-get-effectivename blk)
                )
            )
            (= :vlax-true (vla-get-isdynamicblock blk))
            (= :vlax-true (vla-get-hasextensiondictionary blk))
            (setq vis
                (vl-some
                   '(lambda ( pair )
                        (if
                            (and
                                (= 360 (car pair))
                                (= "BLOCKVISIBILITYPARAMETER"
                                    (cdr (assoc 0 (entget (cdr pair))))
                                )
                            )
                            (cdr pair)
                        )
                    )
                    (dictsearch
                        (vlax-vla-object->ename (vla-getextensiondictionary blk))
                        "acad_enhancedblock"
                    )
                )
            )
        )
        (cdr (assoc 301 (entget vis)))
    )
)

;; Set Dynamic Block Visibility State  -  Lee Mac
;; Sets the Visibility Parameter of a Dynamic Block to a specific value
;; blk - [vla] VLA Dynamic Block Reference object
;; val - [str] Visibility State Parameter value
;; Returns: [str] New value of Visibility Parameter, else nil

(defun LM:SetVisibilityState ( blk val / vis )
    (if
        (and
            (setq vis (LM:getvisibilityparametername blk))
            (member
                (strcase val)
                (mapcar 'strcase (LM:getdynpropallowedvalues blk vis))
            )
        )
        (LM:setdynpropvalue blk vis val)
    )
)

;; Active Document  -  Lee Mac
;; Returns the VLA Active Document Object

(defun LM:acdoc nil
    (eval
        (list 'defun 'LM:acdoc 'nil
            (vla-get-activedocument (vlax-get-acad-object))
        )
    )
    (LM:acdoc)
)
(vl-load-com) (princ)

 

You can call the above function with the name / filename / filepath of the block to be inserted, and the name of the visibility state to be set prior to block insertion, e.g.:

 

(LM:insertwithstate "myblock" "my state")
(LM:insertwithstate "myblock.dwg" "my state")
(LM:insertwithstate "C:\\myfolder\\myblock.dwg" "my state")

 

The function will then return the VLA-Object representation of the inserted block, if successful.

 

Thank you for this thread mid-awe, I have enjoyed experimenting with this function!

 

Lee

Message 7 of 23
mid-awe
in reply to: Lee_Mac

This has been real fun Lee. Great stuff for kissing away time on this joyous day     Smiley Very Happy

 

You've again proven your mastery of customizing AutoCAD. Salute to you Sir. (I'm afraid that is all the authority I have toward declairing you king of the day Smiley Indifferent )

 

Thank you for these lessons, they have been enlightening. Smiley Happy

 

Oh, and thank you for taking the bait and having a little fun with me.

Message 8 of 23
m.voss.alvine
in reply to: mid-awe

Am I missing something here?  When I try Lee's lisp routine, it comes back stating that "Selected block in not dynamic".  I am selecting our standard company blocks that have 6-8 visibility states.  I really like the sounds of the changes mid-awe suggested, but also get the error "block" is not dynamic.nil.

Revit MEP 2015 Certified Professional
Revit Architecture 2015 Certified Professional
AutoCAD 2015 Certified Professional


remember to 'accept as solution' if this helped
Message 9 of 23
mid-awe
in reply to: mid-awe

I'm not sure what the problem could be. It has worked well for me. Have you made sure to: (VL-LOAD-COM) first?

 

Message 10 of 23
Anonymous
in reply to: Lee_Mac

Seems the LM:getdynpropallowedvalues & LM:setdynpropvalue functions are missing?

 

(defun LM:SetVisibilityState ( blk val / vis )
 (if
  (and
   (setq vis (LM:getvisibilityparametername blk))
   (member
    (strcase val)
    (mapcar 'strcase (LM:getdynpropallowedvalues blk vis))
   )
  )
  (LM:setdynpropvalue blk vis val)
 );if
);defun

Message 11 of 23
mid-awe
in reply to: Anonymous

You can find them here: Dynamic Block Functions

Message 12 of 23
Anonymous
in reply to: Lee_Mac

A part of Lees code is this:

 

 

(   (progn
                (setq obj
                    (vlax-invoke
                        (vlax-get-property (LM:acdoc)
                            (if (= 1 (getvar 'cvport))
                                'paperspace
                                'modelspace
                            )
                        )
                        'insertblock
                        '(0.0 0.0 0.0)
                        blk
                        1.0 1.0 1.0 0.0
                    )
                )
                (vla-put-visible obj :vlax-false)
                (= :vlax-false (vla-get-isdynamicblock obj))
            )
            (vla-delete obj)
            (prompt (strcat "\nBlock \"" bse "\" is not dynamic."))
        )

I understand it in this way:

 

  • insert block
  • set it invisible
  • check if dynamic
  • IF NOT dynamic
    - delete block
    - prompt message

The problem is now: if it is dynamic (like moving, rotating), but without visibility, then the invisible block remains in the drawing.

 

Am I right - or wrong?

 

Regards

Message 13 of 23
Anonymous
in reply to: Lee_Mac

Thanks for posting! I have a block I'm working on turning into a toolbar command and this is almost perfect for it. The only thing missing for me would be to allow the user to rotate the block after placing it. I'm new to lisp routines and I can see the general place in the code where the insertion angle is defined, but I don't know how to allow the user to define it. I can see this post is pretty old, but I hope someone's still paying attention.

Message 14 of 23
mid-awe
in reply to: Anonymous

For handling the rotation, I can recommend one of these two solutions:

 

find this line

 

(vl-cmdf "_.-insert" blk "_S" 1.0 "_R" 0.0 "\\")

and replace it with

 

(vl-cmdf "_.-insert" blk "_S" 1.0 "_R" PAUSE "\\")

(It will result with the user being prompted to enter a rotation.) I don't prefer this option because first it requires altering Lee's code, and second, I prefer to use my mouse to rotate visually.

 

I prefer to call this function:

 

(defun RotateLastEnt (/ BASPNT )
  (PRINC "\n\t =>> Specify Rotation: ")
  (SETQ BASPNT (CDR (ASSOC 10 (ENTGET (ENTLAST)))))
  (vl-cmdf "rotate" (ENTLAST) "" BASPNT PAUSE)
)

just following a call to Lee's,

 

(LM:insertwithstate "C:\\myfolder\\myblock.dwg" "my state")
(RotateLastEnt)

It should work as expected.

 

Hope it helps.

Message 15 of 23
Anonymous
in reply to: mid-awe

Thanks mid-awe!

 

I almost have your second solution working for me, but something's not quite right.

 

Under the toolbar button macro I have the following typed in:

^C^C(lm:insertwithstate "M:/Adam/Library/CAD/Blocks/Piping/pipe fitting.dwg" "Pipe Down") 

(rotatelastent)

But the rotate command doesn't run. I can get them each to run on their own, but not together. Am I missing something?

I'm using AutoCAD 2015 if that makes a difference.

Message 16 of 23
mid-awe
in reply to: Anonymous

Try entering the code on one line with out the

^C^C

Like this:

 

(lm:insertwithstate "M:/Adam/Library/CAD/Blocks/Piping/pipe fitting.dwg" "Pipe Down")(rotatelastent)

If that doesn't work for you then we can add the "RotateLastEnt" call at the end of Lee's code.

 

 

Message 17 of 23
Anonymous
in reply to: mid-awe

Couldn't get it to work with your first suggestion, but your second worked for me. Thanks for the help!

Message 18 of 23
mid-awe
in reply to: Anonymous


@Anonymous wrote:

Couldn't get it to work with your first suggestion, but your second worked for me. Thanks for the help!


You are welcome. I am glad that I could help.

Message 19 of 23
dortega4226
in reply to: mid-awe

Lee,

I got the Lisp to work with a Macro I've added to my Ribbon (see below).  What I'd like to be able to do now is prompt to enter visability/size required.

I've tried adding a pause '\' (backslash) or even double quotes (""), but neither worked.  Is there another way of achieving this?

^C^Cucs;named;world;-layer;m;"ZE-TRIMBLE SLEEVE";;(load "L:/_BIM Standards/Acad MEP Support/Lisp Routines/DynBlockVisState.lsp");(LM:insertwithstate "L:/_MMC TOOL PALETTES/TRIMBLE/TRIMBLE SYMBOL LIBRARY/MM-TRIMBLE SLEEVE.dwg" "");

Thanks in advance

 

David Ortega

Message 20 of 23
mid-awe
in reply to: mid-awe

I don't know is Lee "approves this message", but I would add a (if (= viz nil) (setq viz (get string "\nVisability ? ")))

Your size required question will require an after the fact type solution.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost