TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Chuck Gabriel on February 28, 2008, 08:17:38 AM

Title: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 08:17:38 AM
What do you guys do when you want the user to be able to interactively select an entity?

Entsel in its raw form leaves me wanting something more.  If the user misses their pick (easy to do), they don't get any second chances.  I've tried using ssget with the ":S" option, but I wasn't really happy with that either.  I honestly can't remember any longer what it did or didn't do that I didn't like.

I've tried wrapping up entsel in various looping constructs with tests for various conditions, and I've finally come up with something I can live with.  I just wonder if there is a better way.

Code: [Select]
(defun getEntity (msg type / input ent)
  (if
    (vl-catch-all-error-p
      (vl-catch-all-apply
'(lambda ()
   (while
     (and
       (= 3 (car (setq input (grread nil (logior 2 4 8) 2))))
       (or
(null (setq ent (nentselp (cadr input))))
(and
   type
   (/= (strcase type)
       (cdr (assoc 0 (entget (car ent))))
   )
)
       )
     )
   )
)
      )
    )
     nil
     ent
  )
)

My apologies if this has already been done to death.  If it has, I'd love to see the canonical method.
Title: Re: Improving on entsel
Post by: Mark on February 28, 2008, 09:21:39 AM
Chuck will you have any problems using 'type' as an argument?

(msg type  / input ent)
Title: Re: Improving on entsel
Post by: Mark on February 28, 2008, 09:24:34 AM
Chuck will you have any problems using 'type' as an argument?

(msg type  / input ent)

DUH .... never mind!
Title: Re: Improving on entsel
Post by: MP on February 28, 2008, 09:31:23 AM
What do you guys do when you want the user to be able to interactively select an entity?

Anted this post (http://www.theswamp.org/index.php?topic=10028.msg128497#msg128497) up in the remote chance you'll find it interesting.

If the user misses their pick (easy to do), they don't get any second chances.

Is that a bad thing?

:)
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 10:13:16 AM
What do you guys do when you want the user to be able to interactively select an entity?

Anted this post (http://www.theswamp.org/index.php?topic=10028.msg128497#msg128497) up in the remote chance you'll find it interesting.

Thanks.  I did take some inspiration from my memories of that thread.  I actually read that the first time around, studied the code thoroughly, and archived it for future reference.  Maybe now would be a good time to revisit it.

If the user misses their pick (easy to do), they don't get any second chances.

Is that a bad thing?

:)

Speaking as a user, sometimes it frustrates the heck outta me. :-)
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 10:15:42 AM
While I'm at it, I noticed that the code I posted wasn't handling complex entities the way I wanted.  Here is a new attempt:

Code: [Select]
(defun getEntity (msg type / input ent)
  (if
    (vl-catch-all-error-p
      (vl-catch-all-apply
'(lambda ()
   (while
     (and
       (= 3 (car (setq input (grread nil (logior 2 4 8) 2))))
       (or
(null (setq ent (nentselp (cadr input))))
(and
   type
   (/= (strcase type)
       (if (> (length ent) 2)
(cdr (assoc 0 (entget (caar (reverse ent)))))
(cdr (assoc 0 (entget (car ent))))
       )
   )
)
       )
     )
   )
)
      )
    )
     nil
     ent
  )
)
Title: Re: Improving on entsel
Post by: daron on February 28, 2008, 10:30:41 AM
Hmm. I'm still not getting this one. What goes in the msg and type arguments? Why isn't msg being used in the code but required as an argument? Is it because of the vl-catch-all-'s? How is the type argument being used and not returning a problem and what do you put in for its argument?
Title: Re: Improving on entsel
Post by: CAB on February 28, 2008, 10:30:55 AM
Check mine out Chuck.
http://www.theswamp.org/index.php?topic=6992.msg93574#msg93574
Title: Re: Improving on entsel
Post by: T.Willey on February 28, 2008, 11:20:45 AM
If I understand, you want to loop entsel until the user hits enter to exit it... If so I just do it like (for selection a block for example)

Code: [Select]
(setvar 'ErrNo 0)
(while (not (equal (getvar 'ErrNo) 52))
    (if
        (and
            (setq Sel (entsel "\n Select block: "))
            (setq EntData (entget (car Sel)))
            (= (cdr (assoc 0 EntData)) "INSERT")
        )
        (progn
            (prompt "\n Got block, select again.")
        )
    )
)
Title: Re: Improving on entsel
Post by: CAB on February 28, 2008, 12:11:17 PM
Chuck,
Do you realize that type is a function and you are using it as a variable?
Title: Re: Improving on entsel
Post by: daron on February 28, 2008, 12:22:41 PM
Chuck,
Do you realize that type is a function and you are using it as a variable?

I think that's what Mark was alluding to, but seems to have gained understanding of its usefulnes.
Chuck will you have any problems using 'type' as an argument?

(msg type  / input ent)

DUH .... never mind!
And what I am still waiting on an answer for.
Hmm. I'm still not getting this one. What goes in the msg and type arguments? Why isn't msg being used in the code but required as an argument? Is it because of the vl-catch-all-'s? How is the type argument being used and not returning a problem and what do you put in for its argument?

CAB, in case you did catch all that, I was just putting it all together for safe keeping.
Title: Re: Improving on entsel
Post by: CAB on February 28, 2008, 12:36:29 PM
Wow, jumped in the end here and missed all that.   :oops:
Guess I'll read the entire thread now. 8-)
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 12:41:48 PM
Hmm. I'm still not getting this one. What goes in the msg and type arguments?

Msg is supposed to be a prompt.  See below.  The type parameter allows you to filter for specific entity types.

Why isn't msg being used in the code but required as an argument? Is it because of the vl-catch-all-'s?

That would be an error.  It's supposed to be a prompt, but I changed some things around and forgot to put the prompt back in.  Thanks for pointing that out.  I need to fix it.
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 12:46:42 PM
If I understand, you want to loop entsel until the user hits enter to exit it... If so I just do it like (for selection a block for example)

Code: [Select]
(setvar 'ErrNo 0)
(while (not (equal (getvar 'ErrNo) 52))
    (if
        (and
            (setq Sel (entsel "\n Select block: "))
            (setq EntData (entget (car Sel)))
            (= (cdr (assoc 0 EntData)) "INSERT")
        )
        (progn
            (prompt "\n Got block, select again.")
        )
    )
)

Interesting.  ERRNO is not documented in the AutoCAD 2000i docs.
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 12:48:15 PM
Chuck will you have any problems using 'type' as an argument?

(msg type  / input ent)

DUH .... never mind!

No.  It was a good point.  I forgot that type is a reserved word.  I'll change it to etype.
Title: Re: Improving on entsel
Post by: Mark on February 28, 2008, 12:50:47 PM
Chuck will you have any problems using 'type' as an argument?

(msg type  / input ent)

DUH .... never mind!

No.  It was a good point.  I forgot that type is a reserved word.  I'll change it to etype.

Now I'm really confused. Second time today, I'm on a roll!! :-)
Title: Re: Improving on entsel
Post by: daron on February 28, 2008, 12:52:45 PM
Hmm. I'm still not getting this one. What goes in the msg and type arguments?

Msg is supposed to be a prompt.  See below.  The type parameter allows you to filter for specific entity types.

Why isn't msg being used in the code but required as an argument? Is it because of the vl-catch-all-'s?

That would be an error.  It's supposed to be a prompt, but I changed some things around and forgot to put the prompt back in.  Thanks for pointing that out.  I need to fix it.

Chuck will you have any problems using 'type' as an argument?

(msg type  / input ent)

DUH .... never mind!

No.  It was a good point.  I forgot that type is a reserved word.  I'll change it to etype.
That's what we were getting at. I was just confused by Marks revelation that seems to have been cleared up. See post above.
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 12:58:59 PM
That's what we were getting at. I was just confused by Marks revelation that seems to have been cleared up. See post above.

He was so convincing, he had me believing it wasn't a problem too. :D

The reason it wasn't causing me any problems is probably because I have the warning for "setq to protected symbols" turned off.

CAB - I haven't quite gotten to your version yet.  I plan to study right after I post this.

Thanks for all the input everybody.  This has been really enlightening for me.
Title: Re: Improving on entsel
Post by: daron on February 28, 2008, 01:03:44 PM
He was so convincing, he had me believing it wasn't a problem too. :D
Likewise, but the more I looked at it, the more confused I became trying to figure out how it could be used like that.  :pissed: Mark, I needed that braincell. :ugly:
Title: Re: Improving on entsel
Post by: CAB on February 28, 2008, 01:20:36 PM
After reading the entire thread, here is my version.
Code: [Select]
(defun getEntity (msg enttype / picked ent1 ent2 return)
  (setvar "ErrNo" 0) ; reset variable
  (while
    (not
      (cond
        ((and (null (setq picked (nentsel msg)))
              (/= 52 (getvar "ErrNo")) ; <Enter> was not hit
         )
         (prompt "\nMissed, Try Again.")
        )
        ((null picked) t) ; exit loop
        ((progn
           (setq ent1 (car picked))
           (if (> (length picked) 2)
             (setq ent2 (caar (reverse picked)))
             (setq ent2 nil)
           )
           (cond
             ((null enttype)
              (setq return (if ent2 ent2 ent1))
             )
             ((and ent2 (= (strcase enttype)(cdr (assoc 0 (entget ent2)))))
              (setq return ent2)
             )
             ((= (strcase enttype) (cdr (assoc 0 (entget ent1))))
              (setq return ent1)
             )
             (t (prompt "\nWrong entity type, Try Again."))
           )
         )
        )
      )
    )
  )
  return
)


Code: [Select]
(defun c:test ()
  (getEntity "\nSelect a circle object." "CIRCLE")
)
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 01:23:30 PM
Wow!  Information overload!

I came up with this after T.Willey educated me about the ERRNO system variable (how did that one slip under the radar?):

Code: [Select]
(defun getEntity (msg etype / ent)
  (setvar "ERRNO" 0)
  (if
    (vl-catch-all-error-p
      (vl-catch-all-apply
'(lambda ()
   (while
     (and
       (/= 52 (getvar "ERRNO"))
       (or
(null (setq ent (entsel msg)))
(/= (strcase etype) (cdr (assoc 0 (entget (car ent)))))
       )
     )
   )
)
      )
    )
     nil
     ent
  )
)
Title: Re: Improving on entsel
Post by: T.Willey on February 28, 2008, 01:25:45 PM
Glad I could help illuminate.
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 01:39:34 PM
CAB - The only reason I was using nentselp before was so I could convert the picked point from grread into an entity.  I was never actually interested in the complex entity data.  That introduced the requirement to get the "parent" object when a complex entity was selected.

In fact, I started out with this:

Code: [Select]
(defun cci:getEntity (msg type / ent)
  (if (vl-catch-all-error-p
(vl-catch-all-apply
  '(lambda ()
     (while
       (or
(null (setq ent (entsel msg)))
(/= type (cdr (assoc 0 (entget (car ent)))))
       )
     )
   )
)
      )
    nil
    ent
  )
)

However, the only way the user could get out of the loop was by selecting an appropriate entity or pressing the escape key.  I switched to using grread instead of entsel so that I could differentiate between a missed pick and the user pressing return.

I'm probably on about the twentieth iteration of this thing now.  It keeps evolving bit by bit.
Title: Re: Improving on entsel
Post by: CAB on February 28, 2008, 01:48:11 PM
One more then.  :-)
Code: [Select]
(defun getEntity (msg enttype / picked ent return)
  (setvar "ErrNo" 0) ; reset variable
  (while
    (not
      (cond
        ((and (null (setq picked (entsel msg)))
              (/= 52 (getvar "ErrNo")) ; <Enter> was not hit
         )
         (prompt "\nMissed, Try Again.")
        )
        ((null picked) t) ; exit loop
        ((progn
           (setq ent (car picked))
           (cond
             ((null enttype) (setq return ent))
             ((= (strcase enttype) (cdr (assoc 0 (entget ent))))
              (setq return ent)
             )
             (t (prompt "\nWrong entity type, Try Again."))
           )
         )
        )
      )
    )
  )
  return
)
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 01:57:45 PM
Thanks again everybody.

CAB - I noticed you allowed for non-filtered selection.  I had forgotten to do that in the last version I posted.  Good catch!

Here is what I think I have settled on:

Code: [Select]
(defun getEntity (msg etype / ent)
  (setvar "ERRNO" 0)
  (if
    (vl-catch-all-error-p
      (vl-catch-all-apply
'(lambda ()
   (while
     (and
       (/= 52 (getvar "ERRNO"))
       (or
(null (setq ent (entsel msg)))
(and
   etype
   (/= (strcase etype)
       (cdr (assoc 0 (entget (car ent))))
   )
)
       )
     )
   )
)
      )
    )
     nil
     ent
  )
)

Title: Re: Improving on entsel
Post by: daron on February 28, 2008, 02:39:29 PM
Any thoughts on *polylines, so you don't have to differentiate between different types?
Title: Re: Improving on entsel
Post by: ronjonp on February 28, 2008, 03:01:32 PM
Any thoughts on *polylines, so you don't have to differentiate between different types?

Possibly:

Code: [Select]
(defun getEntity (msg etype / ent)
  (setvar "ERRNO" 0)
  (if
    (vl-catch-all-error-p
      (vl-catch-all-apply
'(lambda ()
   (while
     (and
       (/= 52 (getvar "ERRNO"))
       (or
(null (setq ent (entsel msg)))
(and
   (not (wcmatch (cdr (assoc 0 (entget (car ent))))
(strcase etype)
)
   )
)
       )
     )
   )
)
      )
    )
     nil
     ent
  )
)
Title: Re: Improving on entsel
Post by: daron on February 28, 2008, 03:11:34 PM
Hmm. You know, I tried that, but couldn't get it to work.
Title: Re: Improving on entsel
Post by: daron on February 28, 2008, 03:13:57 PM
Don't know what I was doing wrong, but that works nice, Ron. Thanks.
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 03:21:45 PM
Good suggestion Daron and nice solution ronjonp.
Title: Re: Improving on entsel
Post by: ronjonp on February 28, 2008, 03:21:55 PM
Don't know what I was doing wrong, but that works nice, Ron. Thanks.

You're welcome  :-) (although Chuck Gabriel did all the work)
Title: Re: Improving on entsel
Post by: whdjr on February 28, 2008, 04:06:20 PM
I'm late to the party as always (or uninvited).
Here's my version.

Code: [Select]
;;;---------------------------------------------------------------------;;;
;;;A rewrite of the entsel function.                                    ;;;
;;;---------------------------------------------------------------------;;;
  (defun ent_sel (msg / ent)
    (while (not ent)
      (cond ((setq ent (entsel msg)))
    ((= (getvar "ErrNo") 7)
     (princ "\nSelection missed.  Please try again.")
    )
    ((= (getvar "ErrNo") 52) (exit))
      )
    )
    ent
  )
Title: Re: Improving on entsel
Post by: daron on February 28, 2008, 04:22:13 PM
Don't know what I was doing wrong, but that works nice, Ron. Thanks.

You're welcome  :-) (although Chuck Gabriel did all the work)
I'm aware, but I was thanking you for answering my part of the question. It was seemingly overlooked.
Title: Re: Improving on entsel
Post by: JohnK on February 28, 2008, 05:00:28 PM
Im a bit late and unprepaird (i didnt read this thread so far -- you guys talk a lot!).

Whats wrong with a simple recursive test?!

Code: [Select]
(defun entse7 ( msg )
  ;; EntSe7
  ;; dont allow null pick
  ;; EX:
  ;;    (entse7 "Select something or you DIE! ")
  ;;  >: ent picked
  (cond
    ( (entsel (strcat "\n" msg)))
    ( T (entse7 msg))) )
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 06:12:23 PM
Im a bit late and unprepaird (i didnt read this thread so far -- you guys talk a lot!).

Whats wrong with a simple recursive test?!

Code: [Select]
(defun entse7 ( msg )
  ;; EntSe7
  ;; dont allow null pick
  ;; EX:
  ;;    (entse7 "Select something or you DIE! ")
  ;;  >: ent picked
  (cond
    ( (entsel (strcat "\n" msg)))
    ( T (entse7 msg))) )

I don't recall.  Does AutoLISP do tail call optimization.  If it does, then I guess recursion is just as good as iteration.  However, some of us, like myself, just reach for the looping constructs out of habit.  Probably baggage from other programming languages.

Incidentally, no one has asked me why I used the vl-catch-all-apply, but I noticed many of the other solutions posted don't.  I did it because I want to be able to recover and return something meaningful to the calling function if the user presses the escape key.
Title: Re: Improving on entsel
Post by: Kerry on February 28, 2008, 06:50:22 PM

Nice clean solution Chuck.

My method is posted (or similar) to the thread that CAB referenced, and a couple of other places here . .. allows for nested selection (optional) and allows for an eType list ("LINE" "ARC")
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 06:54:36 PM
Thanks Kerry.

Those are good ideas (nested selection and eType list).  I hadn't looked beyond my immediate needs, but I can definitely imagine putting those features to work.
Title: Re: Improving on entsel
Post by: CAB on February 28, 2008, 07:34:08 PM
This one needs a list of etypes & honors wcmatch characters.
AND has feed back messages. 8-)
Code: [Select]
(defun getEntity (msg ; string - select message
                  etypes ; list pf types '("LINE" "CIRCLE")
                  /
                  ent
                 )
  (setvar "ERRNO" 0)
  (if
    (vl-catch-all-error-p
      (vl-catch-all-apply
        '(lambda ()
           (while
             (and
               (/= 52 (getvar "ERRNO"))
               (or
                 (and (null (setq ent (entsel msg)))
                      (princ "\nMissed, Try Again.")
                 )
                 (and
                   etypes
                   (and
                     (not (vl-some
                            '(lambda(x)
                               (wcmatch (cdr (assoc 0 (entget (car ent)))) x))
                                      (mapcar 'strcase etypes)))
                     (princ "\nWrong entity type, Try Again.")
                   )
                 )
               )
             )
           )
         )
      )
    )
     nil
     ent
  )
)
Title: Re: Improving on entsel
Post by: JohnK on February 28, 2008, 07:44:17 PM
I don't recall.  Does AutoLISP do tail call optimization.  If it does, then I guess recursion is just as good as iteration.  However, some of us, like myself, just reach for the looping constructs out of habit.  Probably baggage from other programming languages.

Incidentally, no one has asked me why I used the vl-catch-all-apply, but I noticed many of the other solutions posted don't.  I did it because I want to be able to recover and return something meaningful to the calling function if the user presses the escape key.
*blink-blink*
If the user chews up his or her stack with the task of selecting an object, then that is their problem, not mine.

IMO, recursion is the simplest form of a loop.

But seriously though, i was just offering a suggestion of simplicity. You know more about what your doing then i do. You guys are already way over my head.
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 08:38:58 PM
*blink-blink*
If the user chews up his or her stack with the task of selecting an object, then that is their problem, not mine.

IMO, recursion is the simplest form of a loop.

But seriously though, i was just offering a suggestion of simplicity. You know more about what your doing then i do. You guys are already way over my head.

It was a perfectly good suggestion.  It's funny though how recursion feels simpler to some people, while others feel more comfortable with looping constructs.  I'm pretty much equally at home with either, but I seem to have a natural tendency to go with a looping construct for some reason.
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 28, 2008, 08:45:25 PM
This one needs a list of etypes & honors wcmatch characters.
AND has feed back messages. 8-)

That's a good one.  I like the fact that you included feedback.  I tend to be lazy about that sort of thing because I forget that people other than me might use my programs at some point.  In other words my programs are only user-friendly if the user is me. :D
Title: Re: Improving on entsel
Post by: Kerry on February 28, 2008, 09:24:17 PM

Chuck, this is probably surplus to your needs .. :-)
Code: [Select]
;;;------------------------------------------------------------------
;;;------------------------------------------------------------------
;;;
;;; kwb 20021103
;;; KDUB:entsel (msg kwd def typelist selectflag lockflag

;;; Arguments:
;;; msg : The prompt string.
;;; kwd : Initget keywords string.
;;; def : Value to return if response is <enter>.
;;; typelist  : Stringlist of entity types allowed for selection. If nil select anything.
;;; selectflag : If true nentsel permitted , otherwise use entsel.
;;; lockflag  : If true dont allow selection from locked layers.
;;;
;;; Note : Arguments may be set to nil
;;;
;;; Return output from (n)entsel, a key word, the default argument, or nil.
;;;
;; example1 : (KDUB:EntSel "Select Arc Object" nil nil (list "ARC" "CIRCLE") nil T)
;;  ==>  (<Entity name: 40bcd540> (-28175.1 154575.0 1250.0))
;; example2 : (KDUB:EntSel "Select Datum Line" nil nil (list "LINE") T T) ; line in block
;;  ==>  (<Entity name: 4022c680> (-21613.1 142392.0 0.0)
;;  ((70.0 0.0 0.0) (0.0 70.0 0.0) (0.0 0.0 70.0) (-21611.9 142635.0 0.0))
;;          (<Entity name: 4022c6b8>)  )

(defun kdub:entsel (msg        kwd        def        typelist
                    selectflag lockflag   /          pickok
                    returnvalue           tmp
                   )
  (setq msg (strcat "\n"
                    (cond (msg)
                          ("Select object")
                    )
                    " : "
            )
  )
  (while (not pickok)
    (setvar "ERRNO" 0)
    (if kwd
      (initget kwd)
    )
    (setq returnvalue (if selectflag
                        (nentsel msg)
                        (entsel msg)
                      )
    )
    (cond
      ((= (getvar "ERRNO") 52)               ; enter
       (if def
         (setq returnvalue def)
       )
       ;; skip out
       (setq pickok t)
      )
      ((= (getvar "ERRNO") 7)
       (princ "Nothing found at selectedpoint. ")
      )
      ((= (type returnvalue) 'str) (setq pickok t)) ; keyword
      ((and
         (setq tmp (entget (car returnvalue))) ; object type
         typelist
         (not (member (cdr (assoc 0 tmp)) (mapcar 'strcase typelist)))
       )                                     ; wrong type
       (alert
         (strcat "Selected object is not"
                 "\na "
                 (apply 'strcat
                        (cons (car typelist)
                              (mapcar '(lambda (x) (strcat "\nor " x))
                                      (cdr typelist)
                              )
                        )
                 )
                 ". "
         )
       )
      )
      ((and lockflag                         ;Locked Layer Not Permitted
            (setq                            ;layer name
              tmp (entget (tblobjname "LAYER" (cdr (assoc 8 tmp))))
            )
            (= (logand 4 (cdr (assoc 70 tmp))) 4) ;is layer locked
       )
       (princ "Selected object is on a locked layer. ")
      )
      ;; skip out
      ((setq pickok t))
    )
  )
  returnvalue
)
Title: Re: Improving on entsel
Post by: hermanm on February 28, 2008, 11:53:39 PM
Here is something  I wrote recently.

Code: [Select]
;;function to mark checked annotation objects
;;supports ATTRIB,TEXT,MTEXT,& MTEXT in DIMENSIONs
;;
(defun C:OK ( /
                code
                count
                etype
                obj
                retval
                stypes)
  (setq stypes '("ATTRIB" "MTEXT" "TEXT");define supported types
        count 0)
  (prompt "\nMark as Checked <U to Undo, any other key to exit>:")
  ;;grread to acquire points
  (while (or(> (setq code (car (setq retval (grread nil 14 2))))2);not keyboard
            (and (= 2 code) (member (cadr retval) '(85 117))));key u or U
     (cond ((= 2 code);undo one step
            (if (> count 0)
              (progn
                (remove_image (entlast))
                (setq count (1- count))
              );progn
                (princ "\nNothing to Undo.")
            );if
           );pred
        ((= 3 code);point selected
          (and
          (setq obj (car (nentselp (cadr retval))));object found
          (member (setq etype (cdr (assoc 0 (setq obj(entget obj))))) stypes);supported type
          ;;process it
          (mark_as_checked obj)
          (setq count (1+ count))
          );and
        );pred
     );cond
  );while
  (princ)
);end OK
Title: Re: Improving on entsel
Post by: taner on February 29, 2008, 03:09:55 AM
(defun uentsel (msg / en)
  (while (null (setq en (entsel (strcat "\nPichk up " msg ":"))))
    (princ "\nNothing selected,Try again.")
  )
  en
)
Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 29, 2008, 08:49:17 AM
I know we've just about beaten this one to death, but I thought I'd throw out on more thing:

Code: [Select]
(defun cci:getEntity (msg eTypes / ent)
  (or
    (null eTypes)
    (listp eTypes)
    (setq eTypes (list eTypes))
  )
  (setvar "ERRNO" 0)
  (if
    (vl-catch-all-error-p
      (vl-catch-all-apply
'(lambda ()
   (while
     (and
       (/= 52 (getvar "ERRNO"))
       (or
(and (null (setq ent (entsel msg)))
      (or
(= 52 (getvar "ERRNO"))
(princ "\nMissed. Try again.")
      )
)
(and
   eTypes
   (and
     (not
       (vl-some
'(lambda (pattern)
    (wcmatch
      (cdr (assoc 0 (entget (car ent))))
      pattern
    )
  )
(mapcar 'strcase etypes)
       )
     )
     (princ "\nWrong entity type. Try Again.")
   )
)
       )
     )
   )
)
      )
    )
     nil
     ent
  )
)

I just took the last version CAB posted, added some code to allow the caller to pass eTypes as a single string when a list isn't called for, and added a couple of lines to prevent the missed pick feedback from printing when the user terminates by pressing enter.

For now, I'll leave it up to the caller to deal with locked layers and dig into complex entity data.


Thanks again everybody for all your input.
Title: Re: Improving on entsel
Post by: CAB on February 29, 2008, 09:21:41 AM
My last version too. :)
Took yours & gussied up the feed back, also added one.
Rearranged the exit.
Code: [Select]
;;  CAB 02.29.08, rev 02.13.2010
;|
1) allows the user to select a single entity
2) allows the calling function to specify the prompt that will be displayed to the user
3) provides a mechanism for optional filtering of entity types, uses wcmatch filter
4) loops when missed picks
5) differentiates between a missed pick vs. the user pressing the enter key
6) will exit cleanly and return a value to the caller if the user presses the escape key
7) returns a value compatible with what would be returned by the entsel function
|;
;;  Catch escape, allow enter, entity filter or not, wcmatch on type filter
(defun getEntity (msg ; string - select message
                  etypes ; list pf types '("LINE" "CIRCLE") or pattern "Line,*Polyline"
                  /
                  ent
                 )
  (or ; except nil or single string or list of strings, force strings to upper case
    (null eTypes)
    (and (listp eTypes) (setq eTypes (mapcar 'strcase etypes)))
    (setq eTypes (list (strcase eTypes))) ; make into a list
  )
  (setvar "ERRNO" 0) ; reset error flag
  (if  ; this will catch ESCape & return nil
    (vl-catch-all-error-p
      (vl-catch-all-apply
        '(lambda ()
           (while ; return nil to exit
             (cond
               ((and (null (setq ent (entsel msg)))  (/= 52 (getvar "ERRNO")))
                 (princ "\n*-> Missed, Try Again."))
               ((= 52 (getvar "ERRNO")) (prompt "\n*-> User Quit."))
               (etypes
                   (if (vl-some '(lambda(x)
                               (wcmatch (cdr (assoc 0 (entget (car ent)))) x)) etypes)
                       (prompt "\n*-> Selection made successfully.")
                       (princ "\n*-> Wrong entity type, Try Again.")
                   )
               )
                (ent (prompt "\nselection made."))
             )
           ) ; end while
         )
      )
    )
     nil ; error return
     ent
  )
)
Title: Re: Improving on entsel
Post by: JohnK on February 29, 2008, 10:48:21 AM
Just for kicks; can i get a brief description of what you want/are thinking of? The reason i ask is because, you guys keep talking about feedback and using `catch-all' -- I was wondering the reason for that...instead of say, just exit on a null user return (esc and enter) -? 

Title: Re: Improving on entsel
Post by: Chuck Gabriel on February 29, 2008, 11:48:31 AM
Just for kicks; can i get a brief description of what you want/are thinking of? The reason i ask is because, you guys keep talking about feedback and using `catch-all' -- I was wondering the reason for that...instead of say, just exit on a null user return (esc and enter) -? 

By feedback, I mean notifying the user that he either missed the pick or selected the wrong type of entity.

The reason for using vl-catch-all-apply is because this function will generally be called by other functions, and it is sometimes useful to let the caller know that the function failed, and decide what to do about it, rather than just aborting everything including the calling function.

So the specification would go something like this:

Provide a function that
1) allows the user to select a single entity
2) allows the calling function to specify the prompt that will be displayed to the user
3) provides a mechanism for optional filtering of entity types
4) is tolerant of missed picks
5) differentiates between a missed pick vs. the user pressing the enter key
6) will exit cleanly and return a value to the caller if the user presses the escape key
7) returns a value compatible with what would be returned by the entsel function
Title: Re: Improving on entsel
Post by: JohnK on February 29, 2008, 11:57:44 AM
Just for kicks; can i get a brief description of what you want/are thinking of? The reason i ask is because, you guys keep talking about feedback and using `catch-all' -- I was wondering the reason for that...instead of say, just exit on a null user return (esc and enter) -? 

By feedback, I mean notifying the user that he either missed the pick or selected the wrong type of entity.

The reason for using vl-catch-all-apply is because this function will generally be called by other functions, and it is sometimes useful to let the caller know that the function failed, and decide what to do about it, rather than just aborting everything including the calling function.

So the specification would go something like this:

Provide a function that
1) allows the user to select a single entity
2) allows the calling function to specify the prompt that will be displayed to the user
3) provides a mechanism for optional filtering of entity types
4) is tolerant of missed picks
5) differentiates between a missed pick vs. the user pressing the enter key
6) will exit cleanly and return a value to the caller if the user presses the escape key
7) returns a value compatible with what would be returned by the entsel function


Cool thanx, i might try and get my hands dirty with this after my project goes out. Sounds like fun.
Title: Re: Improving on entsel
Post by: daron on February 29, 2008, 01:37:57 PM
You know what would be cool? At least I think it would. Add to the return value the converted object. So you would have (<Entity name: blahblahblah> (0.0 0.0 0.0) <VLA-OBJECT IAcadLine blahblahblah>)
I know, easy, but why not?