Author Topic: Simple reactor (to change color)  (Read 2644 times)

0 Members and 1 Guest are viewing this topic.

Grrr1337

  • Swamp Rat
  • Posts: 812
Simple reactor (to change color)
« on: March 14, 2017, 01:06:51 PM »
Hi guys,
I'm trying to learn a little about reactors, so decided to create this simple one - that changes the gripped's selection's color to red:

Code - Auto/Visual Lisp: [Select]
  1. (defun C:TempColorReactorOn nil
  2.  
  3.   ; Define the callback function (must be global I guess?):
  4.   (defun ChangeColor:callback ( rtr arg / SS )
  5.     (if (setq SS (cadr (ssgetfirst)))
  6.       (progn
  7.         (setq *LstTmpCol* (mapcar 'entget (apply 'append (mapcar '(lambda (x) (if (= 3 (car x)) (list (cadr x)))) (ssnamex SS))))) ; *LstTmpCol*
  8.         (mapcar '(lambda (x) (entmod (append x '((62 . 1))))) *LstTmpCol*)
  9.       )
  10.       (if *LstTmpCol* (mapcar '(lambda (x) (entmod x)) *LstTmpCol*))
  11.     )
  12.     (princ)
  13.   ); defun ChangeColor:callback
  14.  
  15.   ; check if that reactor exist in the miscellaneous reactors and remove it:
  16.     (if (= "TempColor" (vlr-data rtr)) (vlr-remove rtr))
  17.   ); foreach
  18.  
  19.   ; include the new reactor:
  20.   (vlr-miscellaneous-reactor "TempColor" '((:vlr-PickFirstModified . ChangeColor:callback)))
  21.  
  22.   (alert "\nTemporary color Reactor enabled!")
  23.   (princ)
  24. ); defun C:TempColorReactorOn
  25.  
  26. (defun c:TempColorReactorOff nil
  27.   (foreach rtr (cdar (vlr-reactors :vlr-miscellaneous-reactor)) ; check if that reactor exist in the miscellaneous reactors and remove it
  28.     (if (= "TempColor" (vlr-data rtr)) (vlr-remove rtr))
  29.   ); foreach
  30.   (alert "\nTemporary color Reactor disabled!")
  31.   (princ)
  32. ); defun c:TempColorReactorOff

But the problem is that im getting internal error and autocad crashes, so whats wrong in my code?  :thinking:
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

Lee Mac

  • Seagull
  • Posts: 12906
  • London, England
Re: Simple reactor (to change color)
« Reply #1 on: March 14, 2017, 01:36:56 PM »
I've known AutoCAD to throw an exception when attempting to use entmod within a reactor callback function under certain circumstances, and so this could very well be the cause of your error.

For what it's worth, below is an old example from my library which performs the same operation:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:selection-reactor-on ( )
  2.     (selection-reactor-removereactors "selection-reactor")
  3.     (vlr-miscellaneous-reactor "selection-reactor"
  4.        '(
  5.             (:vlr-pickfirstmodified . selection-reactor-callback)
  6.         )
  7.     )
  8.     (princ "\nSelection reactor enabled.")
  9.     (princ)
  10. )
  11.  
  12. (defun c:selection-reactor-off ( )
  13.     (selection-reactor-removereactors "selection-reactor")
  14.     (selection-reactor-restore selection-reactor-data)
  15.     (setq selection-reactor-data nil)
  16.     (princ "\nSelection reactor disabled.")
  17.     (princ)
  18. )
  19.  
  20. (defun selection-reactor-removereactors ( str )
  21.         (if (= str (vlr-data obj))
  22.             (vlr-remove obj)
  23.         )
  24.     )
  25. )
  26.  
  27. (defun selection-reactor-restore ( lst / obj )
  28.     (foreach itm lst
  29.         (if (vlax-write-enabled-p (setq obj (vlax-ename->vla-object (car itm))))
  30.             (vla-put-color obj (cdr itm))
  31.         )
  32.     )
  33. )
  34.  
  35. (defun selection-reactor-callback ( obj arg / ent idx lst sel )
  36.     (if (setq sel (cadr (ssgetfirst)))
  37.         (progn
  38.             (setq selection-reactor-data
  39.                 (vl-remove-if
  40.                    '(lambda ( itm )
  41.                         (if (not (ssmemb (car itm) sel))
  42.                             (setq lst (cons itm lst))
  43.                         )
  44.                     )
  45.                     selection-reactor-data
  46.                 )
  47.             )
  48.             (selection-reactor-restore lst)
  49.             (repeat (setq idx (sslength sel))
  50.                 (setq ent (ssname sel (setq idx (1- idx)))
  51.                       obj (vlax-ename->vla-object ent)
  52.                 )
  53.                 (if (not (assoc ent selection-reactor-data))
  54.                     (setq selection-reactor-data (cons (cons ent (vla-get-color obj)) selection-reactor-data))
  55.                 )
  56.                 (vla-put-color obj acred) ;; Selected object colour
  57.             )
  58.         )
  59.         (progn
  60.             (selection-reactor-restore selection-reactor-data)
  61.             (setq selection-reactor-data nil)
  62.         )
  63.     )
  64.     (princ)
  65. )

You may also be interested in this utility as another example of performing operations triggered on object selection.

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Simple reactor (to change color)
« Reply #2 on: March 14, 2017, 02:14:10 PM »
Hi, Lee!

Gathering your comments about reactors so far:
I've known AutoCAD to throw an exception when attempting to use entmod within a reactor callback function under certain circumstances, and so this could very well be the cause of your error.
Quote from: Lee Mac;657974
Note that you cannot invoke a command call from within a reactor callback function, therefore a post-process evaluation using the sendcommand method is required.
I did the conclusion that they work OK only with ActiveX (as you mentioned above: use vla-sendcommand instead of command, and avoid any entity-manipulation functions)

For what it's worth, below is an old example from my library which performs the same operation:
Thank you! As a reactor newbie I appreciate it, since its not easy to determine where and how the error occured while using some reactor.

You may also be interested in this utility as another example of performing operations triggered on object selection.
Yes, I clearly remember this thread
Always when I think about practicing with reactors - I visit it, either to re-analyse how you did construct the whole thing, or to use it as a template for something else.
It looks for me as the perfect example for constructing a reactor.
I knew that I could use vla-sendcommand with CHPROP from there, but rather decided to write one from scratch, guided by your code. :)

Thanks, again!
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

Lee Mac

  • Seagull
  • Posts: 12906
  • London, England
Re: Simple reactor (to change color)
« Reply #3 on: March 14, 2017, 02:30:44 PM »
You're welcome Grr1337  :-)

Quote from: Lee Mac
Note that you cannot invoke a command call from within a reactor callback function, therefore a post-process evaluation using the sendcommand method is required.

I did the conclusion that they work OK only with ActiveX (as you mentioned above: use vla-sendcommand instead of command, and avoid any entity-manipulation functions)
I knew that I could use vla-sendcommand with CHPROP from there...

The use of vla-sendcommand does enable you to perform post-process operations, but if presented with multiple ways to achieve the same result, I would generally avoid this method unless there is no alternative.

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Simple reactor (to change color)
« Reply #4 on: March 14, 2017, 05:54:25 PM »

The use of vla-sendcommand does enable you to perform post-process operations, but if presented with multiple ways to achieve the same result, I would generally avoid this method unless there is no alternative.

Exactly, I've spotted that professional lispers try to avoid command calls (needless to say that you are one of them...).

For this one even the callback function was hard for me, so I had to copy from yours to recreate this flawless performance!

Also reminded me what you've said in that other thread:
Quote from: Lee Mac;657974
the supporting code needs to be watertight, accounting for every possibly eventuality to ensure uninterrupted operation.

Aside: Your codes are always perfect - I think you have LISP OCD.  :angel:
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Simple reactor (to change color)
« Reply #5 on: March 14, 2017, 06:10:02 PM »
This has nothing to do with your code, but if you are looking for other reactor examples, here are two:
Xref reactor (this is the simpler example)
https://www.theswamp.org/index.php?topic=15557.0

Area reactor (before I new about fields)
https://www.theswamp.org/index.php?topic=8710.0

Just FYI.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Simple reactor (to change color)
« Reply #6 on: March 14, 2017, 06:52:55 PM »
Thanks, Tim
Hopefully I'll get some more ideas (currently I practice only with the vlr-PickFirstModified event).
Heres another one that turned out simplier (than the one from my initial thought) :
Code - Auto/Visual Lisp: [Select]
  1. ; Define the callback function - MUST BE GLOBAL
  2. (defun MarkCentroids:callback ( rtr arg / SS acSpc i o e reg )
  3.   (cond
  4.     ( (setq SS (cadr (ssgetfirst)))
  5.       (repeat (setq i (sslength SS))
  6.         (setq o (vlax-ename->vla-object (setq e (ssname SS (setq i (1- i))))))
  7.         (cond
  8.           ( (member (cdr (assoc 5 (entget e))) *MarkedCentroids*) )
  9.           ( (and (= "LWPOLYLINE" (cdr (assoc 0 (entget e)))) (vlax-curve-isClosed o) )
  10.             (vlax-invoke acSpc 'addpoint (trans (vlax-get (setq reg (car (vlax-invoke acSpc 'addregion (list o)))) 'Centroid) 1 0) )
  11.             (vla-Delete reg)
  12.             (setq *MarkedCentroids* (cons (vla-get-Handle o) *MarkedCentroids*))
  13.           )
  14.         ); cond
  15.       ); repeat
  16.     )
  17.   ); cond
  18. ); defun MarkCentroids:callback
  19.  
  20.  
  21. ; Define the function that turns on the reactor:
  22. (defun C:MarkCentroidsOn nil
  23.   (setq *MarkedCentroids* nil)
  24.   ; check if that reactor exist in the miscellaneous reactors and remove it:
  25.   (foreach rtr (cdar (vlr-reactors :vlr-miscellaneous-reactor)) (if (= "MarkCentroids" (vlr-data rtr)) (vlr-remove rtr)) )
  26.  
  27.   ; include the new reactor:
  28.   (cond
  29.     ( (not MarkCentroids:callback) (alert "\nMarkCentroids:callback function not defined!") )
  30.     (T
  31.       (vlr-miscellaneous-reactor "MarkCentroids" '((:vlr-PickFirstModified . MarkCentroids:callback)))
  32.       (alert "\nMark Centroids Reactor enabled!")
  33.     )
  34.   ); cond
  35.  
  36.   (princ)
  37. ); defun C:MarkCentroidsOn
  38.  
  39.  
  40. ; Define the function that turns off the reactor:
  41. (defun c:MarkCentroidsOff nil
  42.   (setq *MarkedCentroids* nil)
  43.   (foreach rtr (cdar (vlr-reactors :vlr-miscellaneous-reactor)) ; check if that reactor exist in the miscellaneous reactors and remove it
  44.     (if (= "MarkCentroids" (vlr-data rtr)) (vlr-remove rtr))
  45.   ); foreach
  46.   (alert "\nMark Centroids Reactor disabled!")
  47.   (princ)
  48. ); defun c:MarkCentroidsOff
« Last Edit: March 14, 2017, 06:58:29 PM by Grrr1337 »
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

navsun@qq.com

  • Guest
Re: Simple reactor (to change color)
« Reply #7 on: March 15, 2017, 05:52:46 AM »
Very good code

hanhphuc

  • Newt
  • Posts: 64
Re: Simple reactor (to change color)
« Reply #8 on: March 16, 2017, 04:28:14 AM »
region does not accept self intersect polyline (not sure latest version?), IMO it can be solved by average algorithm if non-bulge polyline my $0.02
( apply 'equal "hp" "happy" "hạnh phúc" "ハッピー" "幸福" "행복" ) ; error: too many arguments