Author Topic: Reactor with 2 events  (Read 4612 times)

0 Members and 1 Guest are viewing this topic.

Beekee

  • Mosquito
  • Posts: 19
Reactor with 2 events
« on: January 05, 2015, 04:23:52 PM »
Hey guys, especially Lee Mac,
on your site I found lisp "Selection Count" ... thanks for sharing (I mean no just this one). I would like it to be used as a kind of QuickProperties but not as stupid as it is right know in AutoCad. I took your core (= reactor) and added some features according to my needs.
My question is, cause I know nothing about reactores, would be possible to modify the reactor so the program runs with 2 events
(and pickfirstmodified entitymodified) I mean modified by grips, or with PropertiesPalette. THX

Link to original
http://lee-mac.com/selectioncounter.html

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: Reactor with 2 events
« Reply #1 on: January 05, 2015, 04:38:26 PM »
Perhaps I'm missing something, but both of those edit methods should trigger the pickfirst reaction.
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

Beekee

  • Mosquito
  • Posts: 19
Re: Reactor with 2 events
« Reply #2 on: January 07, 2015, 03:30:53 PM »
Thanks for reply... I dont really know anything about reactors, so its possible.. but this one does not.

Code: [Select]
;;----------------------------------------------------------------------;;
;;  Based on SelectionCounterV1-1.lsp by Lee Mac, 2014 ;;
;;  Version 1.1    -    2014-11-15                                      ;;
;;  http://www.lee-mac.com/selectioncounter.html                        ;;
;;----------------------------------------------------------------------;;
;;  Detail Properties functionality added by Beekee, 2015/01 ;;
;;----------------------------------------------------------------------;;

(defun c:selcounton nil
    (selcount:remove)
    (vlr-miscellaneous-reactor "selcount" '((:vlr-pickfirstmodified . selcount:callback)))
    (vlr-command-reactor       "selcount" '((:vlr-commandwillstart  . selcount:undostart) (:vlr-commandended . selcount:undoended)))
    (princ "\nModeMacroProperties enabled.")
    (princ)
)
(defun c:selcountoff nil
    (selcount:remove)
    (princ "\nModeMacroProperties disabled.")
    (princ)
)
(defun selcount:remove nil
    (foreach obj (apply 'append (mapcar 'cdr (vlr-reactors :vlr-miscellaneous-reactor :vlr-command-reactor)))
        (if (= "selcount" (vlr-data obj)) (vlr-remove obj))
    )
)
(defun selcount:callback ( obj arg / int sel)

    (if (and (setq sel (cadr (ssgetfirst)))
     (< 0 (setq int (sslength sel))))
        (progn
            (if (null selcount:modemacro)
                (setq selcount:modemacro (getvar 'modemacro))
            )
    (if (< 201 int)
      (setvar 'modemacro (strcat "(" (itoa int)")"))
      (setvar 'modemacro (_STRmodemacroProperties sel)))
        )
        (progn
    (setvar 'modemacro "")
            ;(if (= 'str (type selcount:modemacro))
            ;    (setvar 'modemacro selcount:modemacro)
            ;)
            (setq selcount:modemacro nil)
        )
    )
    (princ)
)
(defun selcount:undostart ( obj arg )
    (if (wcmatch (strcase (car arg)) "U,UNDO")
        (setq selcount:undomodemacro (getvar 'modemacro))
    )
    (princ)
)
(defun selcount:undoended ( obj arg )
    (if (= 'str (type selcount:undomodemacro))
        (progn
            (setvar 'modemacro selcount:undomodemacro)
            (setq selcount:undomodemacro nil)
        )
    )
    (princ)
)



;;; procedures for MODEMACRO detail properies

(defun _STRmodemacroProperties (ss / lss i etype aso etypelist)
 
 (setq lss (sslength ss)
i (1- lss))
  (repeat lss
    (setq etype (cdr (assoc 0 (setq ed (entget (ssname ss i))))))
    (if (not (setq aso (assoc etype etypelist)))
      (setq etypelist (cons (cons etype 1) etypelist)) ; new type
      (setq etypelist (subst (cons etype (1+ (cdr aso))) aso etypelist))) ;exists
    (setq i (1- i)))

    (cond
    ((and (= 1 lss)
  (assoc "LINE" etypelist))
     (strcat (rtos (vlax-curve-getDistAtParam (ssname ss 0) (vlax-curve-getEndParam (ssname ss 0))) 2 1))))

;...
)
 
(vl-load-com) (c:selcounton)

BlackBox

  • King Gator
  • Posts: 3770
Re: Reactor with 2 events
« Reply #3 on: January 08, 2015, 02:39:10 AM »
I understand that you're not too familiar with Reactors, so please forgive anything that follows, that your are already adept at.

One of the rules of reactors / event handlers, is that you cannot open an Object that is already open in the Database (in any API).

One common way of doing 'something' to an Object after being modified, is to monitor CommandWillStart Event for specific Command(s), then register an ObjectModified Reactor to filter for specific Object Types, and store their ObjectId to global variable, unregister said ObjectModified Reactor upon CommandCancelled, CommandEnded, or CommandFailed Events, and then process the ObjectIds previously stored (as they're now closed).

This works great for many things, but is utterly ineffective at both capturing ObjectIds, and acting on them when modified via Properties Pane... Even when you remove the CommandWillStart Event dependency, continuously monitoring ObjectModified is not only inefficient, but no Event is subsequently raised in which to process the ObjectIds stored... There are Events, they just require the cursor back within the Editor window, which obviously intoroduces lag, which is less than desirable.

The only way I know of, to truly act on an Object at the time it is modified via Properties Pane, is to implement a .NET Close() Method Override via ObjectOverrule (something I learned from TheMaster); here's a quick video demonstration, from an 'AnnoAuto' plugin I use to dynamically manage MLeaders, etc.

Perhaps if you could clarify exactly what you're after (I haven't read through your code), we might be able to better offer some help.

Cheers
"How we think determines what we do, and what we do determines what we get."

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Reactor with 2 events
« Reply #4 on: January 08, 2015, 05:38:59 AM »
I think the OP wants something like the code below.
Note: Only tested on BricsCAD V14. May well fail on AutoCAD.

Code - Auto/Visual Lisp: [Select]
  1. (defun LengthStatus_OnLoad ()
  2.   (if *LengthStatus_acdbReactor*          (vlr-remove *LengthStatus_acdbReactor*))
  3.   (if *LengthStatus_miscellaneousReactor* (vlr-remove *LengthStatus_miscellaneousReactor*))
  4.   (if *LengthStatus_commandReactor*       (vlr-remove *LengthStatus_commandReactor*))
  5.   (setq *LengthStatus_acdbReactor*
  6.       nil ; No data.
  7.       '((:vlr-objectmodified . LengthStatus_CallBack))
  8.     )
  9.   )
  10.   (setq *LengthStatus_miscellaneousReactor*
  11.       nil ; No data.
  12.       '((:vlr-pickfirstmodified . LengthStatus_CallBack))
  13.     )
  14.   )
  15.   (setq *LengthStatus_commandReactor*
  16.       nil ; No data.
  17.       '((:vlr-commandended . LengthStatus_CallBack))
  18.     )
  19.   )
  20.   (princ "\nLengthStatus is running ")
  21.   (princ)
  22. )
  23.  
  24. ;;; ======================================================================
  25. ;;; Function:     LengthStatus_CallBack
  26. ;;; Arguments:    rea - Vlr-object.
  27. ;;;               lst - Data list:
  28. ;;;                       For vlr-acdb-reactor:
  29. ;;;                         Length 2: database object and entity as ename.
  30. ;;;                       For vlr-miscellaneous-reactor:
  31. ;;;                         Always(?) nil.
  32. ;;;                       For vlr-command-reactor:
  33. ;;;                         Nil or length 1: command as string.
  34. ;;; ======================================================================
  35. (defun LengthStatus_CallBack (rea lst / ss obj)
  36.   ; (print "LengthStatus_CallBack")
  37.   (cond
  38.     (
  39.       (and
  40.         (= (vlr-type rea) :vlr-command-reactor)
  41.         (vl-position (car lst) '("U" "UNDO"))
  42.       )
  43.       ; (print "LengthStatus_CallBack 0")
  44.       (setvar 'modemacro (cond (*LengthStatus_modemacro*) ("")))
  45.     )
  46.     (
  47.       (and
  48.         (setq ss (cadr (ssgetfirst)))
  49.         (= (sslength ss) 1)
  50.         (setq obj (vlax-ename->vla-object (ssname ss 0)))
  51.         (vlax-read-enabled-p obj)
  52.         (vl-position
  53.           (vla-get-objectname obj)
  54.           '("AcDb2dPolyline"  "AcDbArc" "AcDbCircle" "AcDbEllipse" "AcDbLine" "AcDbPolyline" "AcDbSpline")
  55.         )
  56.       )
  57.       ; (print "LengthStatus_CallBack 1")
  58.       (if (not *LengthStatus_modemacro*) (setq *LengthStatus_modemacro* (getvar 'modemacro)))
  59.       (setvar 'modemacro (strcat "L=" (rtos (vlax-curve-getdistatparam obj (vlax-curve-getendparam obj)) 2 1)))
  60.     )
  61.     (T
  62.       ; (print "LengthStatus_CallBack 3")
  63.       (setvar 'modemacro (cond (*LengthStatus_modemacro*) ("")))
  64.       (setq *LengthStatus_modemacro* nil)
  65.     )
  66.   )
  67. )
  68.  
  69. (LengthStatus_OnLoad) ; Starts the reactors.

Beekee

  • Mosquito
  • Posts: 19
Re: Reactor with 2 events
« Reply #5 on: January 09, 2015, 04:28:28 AM »
Thanks guys you both for your answers.
Roy, your code is exactly what I wanted. Thank you very much, it's perfect. In AutoCAD it works without problems.
It will take me a while to understand what the reactors are about, but I put my procedure for processing and other properties of other entities in your code, and it works perfect as well.
By the way, thanks for showing (cond (string) (""))... nice and inspiring.


Beekee

  • Mosquito
  • Posts: 19
Re: Reactor with 2 events
« Reply #7 on: January 12, 2015, 08:44:31 AM »
Thanks CAB for recap, its inspirational.

Using the reactor, I found that it makes a mess in the undo function. Makes it so many records that undo function is almost useless (often dozens of "Group of commands" than follow "Intellipan" or something else). I can think of nothing to do with it ...Any way to do that to be ignored by UNDO.. or made less records?
UNDOCTL = 53 (read only)
THX in advance.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Reactor with 2 events
« Reply #8 on: January 12, 2015, 09:17:34 AM »
You're welcome.

I do believe you can set the undo start & End to avoid some problems.

I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Reactor with 2 events
« Reply #9 on: January 12, 2015, 04:38:41 PM »
@ Beekee:
You are right: The code in my previous post causes problems with the undo-redo stack (these problems also occur on BricsCAD :oops:). Changing the status line by modifying the modemacro variable messes things up. The code below used the grtext function instead. Calling this function has no impact on the undo-redo stack thereby avoiding any related issues.

Code - Auto/Visual Lisp: [Select]
  1. (defun LengthStatus_OnLoad ()
  2.   (if *LengthStatus_acdbReactor*          (vlr-remove *LengthStatus_acdbReactor*))
  3.   (if *LengthStatus_miscellaneousReactor* (vlr-remove *LengthStatus_miscellaneousReactor*))
  4.   (if *LengthStatus_commandReactor*       (vlr-remove *LengthStatus_commandReactor*))
  5.   (setq *LengthStatus_acdbReactor*
  6.       nil ; No data.
  7.       '((:vlr-objectmodified . LengthStatus_CallBack))
  8.     )
  9.   )
  10.   (setq *LengthStatus_miscellaneousReactor*
  11.       nil ; No data.
  12.       '((:vlr-pickfirstmodified . LengthStatus_CallBack))
  13.     )
  14.   )
  15.   (setq *LengthStatus_commandReactor*
  16.       nil ; No data.
  17.       '((:vlr-commandwillstart . LengthStatus_CallBack))
  18.     )
  19.   )
  20.   (grtext -1 "")
  21.   (princ "\nLengthStatus is running ")
  22.   (princ)
  23. )
  24.  
  25. ;;; ======================================================================
  26. ;;; Function:     LengthStatus_CallBack
  27. ;;; Arguments:    rea - Vlr-object.
  28. ;;;               lst - Data list:
  29. ;;;                       For vlr-acdb-reactor:
  30. ;;;                         Length 2: database object and entity as ename.
  31. ;;;                       For vlr-miscellaneous-reactor:
  32. ;;;                         Always(?) nil.
  33. ;;;                       For vlr-command-reactor:
  34. ;;;                         Nil or length 1: command as string.
  35. ;;; ======================================================================
  36. (defun LengthStatus_CallBack (rea lst / ss obj)
  37.   ; (print "LengthStatus_CallBack")
  38.   (cond
  39.     ((= (vlr-type rea) :vlr-command-reactor)
  40.       ; (print "LengthStatus_CallBack 0")
  41.       (grtext -1 "")
  42.     )
  43.     (
  44.       (and
  45.         (setq ss (cadr (ssgetfirst)))
  46.         (= (sslength ss) 1)
  47.         (setq obj (vlax-ename->vla-object (ssname ss 0)))
  48.         (vlax-read-enabled-p obj)
  49.         (vl-position
  50.           (vla-get-objectname obj)
  51.           '("AcDb2dPolyline"  "AcDbArc" "AcDbCircle" "AcDbEllipse" "AcDbLine" "AcDbPolyline" "AcDbSpline")
  52.         )
  53.       )
  54.       ; (print "LengthStatus_CallBack 1")
  55.       (grtext -1 (strcat "L=" (rtos (vlax-curve-getdistatparam obj (vlax-curve-getendparam obj)) 2 1)))
  56.     )
  57.     (T
  58.       (grtext -1 "")
  59.     )
  60.   )
  61. )
  62.  
  63. (LengthStatus_OnLoad) ; Starts the reactors.
« Last Edit: January 12, 2015, 04:45:20 PM by roy_043 »

Beekee

  • Mosquito
  • Posts: 19
Re: Reactor with 2 events
« Reply #10 on: January 13, 2015, 10:10:35 AM »
Thanks Roy again. Works great.