AfraLISP - Learn AutoLISP for AutoCAD productivity

Reactors - Part 3

by Kenny Ramage

Object Reactors

Object Reactors, or VLR-Object-Reactor, fall under general reactor types. They are almost identical in functionality to Drawing and Command reactors except for a couple of things! They need to include a reference to the Object that will be reacted upon, (Crikey, that sounds terrible!) and the reference to the Object needs to be created before the reactor is called. Let's have a look at the syntax of an Object reactor :

   (vlr-object-reactor owners data callback)

The data and callback arguments, we are familiar with. But what is the owners argument? This is an AutoLISP list of Visual Lisp Objects identifying the drawing Objects to be watched. In other words, a reference to the Object that contains the reactor.

The reactor event we are going to use is the :vlr-modified event, and our Callback function will be named print-length. Have a look at the coding for our reactor :

   (vlr-object-reactor (list myLine) "Line Reactor"
      '((:vlr-modified . print-length)))

As I mentioned earlier though, we need to have a reference to the Object before we can call this statement. Consider the following :

(vl-load-com)
 
;*************
 
(defun line-draw ()
 
(setq acadDocument (vla-get-activedocument (vlax-get-acad-object)))
 
(setq mspace (vla-get-modelspace acadDocument))
 
(setq apt (getpoint "Specify First Point: "))
 
(setq pt (getpoint "Specify next point: " apt))
 
(setq myLine (vla-addline mspace (vlax-3d-point apt)(vlax-3d-point pt)))
 
(setq lineReactor (vlr-object-reactor (list myLine)
"Line Reactor" '((:vlr-modified . print-length))))
 
(princ)
 
);defun

We started off by drawing a line. As the line was created from scratch, and created using Visual LISP functions, we already have a reference to the line Object (myLine). We can now safely run our reactor function and attach it to our Line. "But where is the Callback function?"

Hah, I was waiting for that. We've made the Callback function a separate function for one main reason. If we didn't, every time we ran the application it would prompt us to draw a new line. So, what we have to do now, is link the reactor function to our Callback function so that when our line is modified, only the Callback function is put into motion. The reactor sends three arguments to the Callback function, the notifier-object (our line), the reactor-object (:vlr-modified), and the event parameter-list which in this case is nil.

Here's the coding for the Callback function :

(defun print-length (notifier-object reactor-object parameter-list)
 
(cond
	((vlax-property-available-p notifier-object "Length")
	 (alert (strcat "The length is now "
                        (rtos (vla-get-length notifier-object)))))
);cond
 
(princ)
 
);defun
 
(princ)

Copy all of this coding into one file and save it as Line-Draw.lsp. Now load Line-Draw.lsp and then run the line-draw function. Draw a single line when prompted. Now stretch the line so that it's length changes. A dialog will appear displaying the new length of the line :

AutoCAD Message

In essence, this is what happened :

  1. We loaded Line-Draw.lsp and all functions contained within were placed into memory.
  2. We ran the line-draw function which prompted us to draw a line. The reactor was then loaded and linked to both the line Object and the Callback function.
  3. As the Callback function print-length was also loaded into memory, every time we modify the line Object, the Callback function is processed and the length of the line is displayed.

Did you notice how we checked that our Object had a Length Property before continuing? Good idea, as this validation can save lot's of problems.

"But what happens when I close my drawing? Will I lose all my reactors?" Good questions. Reactors can be transient or persistent. Transient reactors are lost when the drawing closes and this is the default reactor mode. Persistent reactors are saved with the drawing and exist when the drawing is next open.

You can use the vlr-pers function to make a reaction persistent. To remove a persistence from a reactor and make it transient, use the vlr-pers-release function. To determine whether a reactor is persistent or transient, use the vlr-pers-p function. Each function takes the reactor Object as it's only argument :

_$(vlr-pers lineReactor)
#<VLR-Object-Reactor>

If successful vlr-pers returns the specified reactor Object.

Note : A reactor is only a link between an event and a Callback function. The Callback function is not part of the reactor, and is normally not part of the drawing. The reactors saved in the drawing are only usable if their associated Callback functions are loaded in AutoCAD. In other words, if we made our reactor lineReactor persistent, we would have to ensure that the Callback function print-length was loaded every time the drawing containing our lines with reactors was opened.

If you would like the source coding for all the examples in this tutorial, then you can download them from here.