Updating the C:GPath Function

Visual LISP

 
Updating the C:GPath Function
 
 
 

Update the C:GPath function by adding reactor creation logic.

To add reactor creation logic to C:GPath

  1. Replace your version of gpmain.lsp with the updated version shown below. Copy this code from the <AutoCAD directory>\Tutorial\VisualLISP\Lesson6 directory:
    (defun C:GPath (/
     gp_PathData
     gp_dialogResults
     PolylineName
     tileList
     )
     (setvar "OSMODE" 0)              ;; Turn off object snaps
    ;|
    ;; Lesson 6 adds a stubbed-out command reactor to AutoCAD
     ;; However, it would be undesirable to react to every
     ;; drawing of a circle should the COMMAND tile creation
     ;; method be chosen by the user.  So, disable the 
     ;; *commandReactor* in case it exists. 
     |;
    (if *commandReactor*
     (progn
     (setq *commandReactor* nil)
     (vlr-remove-all :VLR-Command-Reactor)
     )
     )
     ;; Ask the user for input: first for path location and
     ;; direction, then for path parameters.  Continue only if you
     ;; have valid input.  Store the data in gp_PathData.
     (if (setq gp_PathData (gp:getPointInput))
     (if (setq gp_dialogResults
     (gp:getDialogInput
     (cdr (assoc 40 gp_PathData))
     ) ;_ end of gp:getDialogInput
     ) ;_ end of setq
     (progn
     ;; Now take the results of gp:getPointInput and append this to
     ;; the added information supplied by gp:getDialogInput
     (setq gp_PathData (append gp_PathData gp_DialogResults))
     ;; At this point, you have all the input from the user
     ;; Draw the outline, storing the resulting polyline "pointer"
     ;; in the variable called PolylineName
     (setq PolylineName (gp:drawOutline gp_PathData))
     ;; Next, it is time to draw the tiles within the boundary.
     ;; The gp_tileList contains a list of the object pointers for
     ;; the tiles.  By counting up the number of points (using the
     ;; length function), we can print out the results of how many
     ;; tiles were drawn.
     (princ "\nThe path required ")
     (princ
     (length
     (setq tileList (gp:Calculate-and-Draw-Tiles gp_PathData))
     ) ;_ end of length
     ) ;_ end of princ
     (princ " tiles.")
    ;; Add the list of pointers to the tiles (returned by
     ;; gp:Calculate-and-Draw-Tiles) to gp_PathData. This will
     ;; be stored in the reactor data for the reactor attached 
     ;; to the boundary polyline.  With this data, the polyline
     ;; "knows" what tiles (circles) belong to it.
     (setq gp_PathData
     (append (list (cons 100 tileList))
     ; all the tiles
     gp_PathData
     ) ;_ end of append
     ) ;_ end of setq
    ;; Before we attach reactor data to an object, let's look at
     ;; the function vlr-object-reactor
     ;; vlr-object-reactor has the following arguments:
     ;;  (vlr-object-reactor owner's data callbacks)
     ;;      The callbacks Argument is a list comprised
     ;;      '(event_name . callback_function)
     ;;
     ;; For this exercise we will use all arguments
     ;; associated with vlr-object-reactor
     ;; These reactor functions will execute only if
     ;; the polyline in PolylineName is modified or erased
     (vlr-object-reactor
     ;; The first argument for vlr-object-reactor is
     ;; the "Owner's List" argument.  This is where to
     ;; place the object to be associated with the
     ;; reactor.  In this case, it is the vlaObject
     ;; stored in PolylineName.
     (list PolylineName)
     ;; The second argument contains the data for the path
     gp_PathData
     ;; The third argument is the list of specific reactor
     ;; types that we are interested in using
     '
     (
     ;; reactor that is called upon modification of the object
     (:vlr-modified . gp:outline-changed)
     ;; reactor that is called upon erasure of the object
     (:vlr-erased . gp:outline-erased)
     )
     ) ;_ end of vlr-object-reactor
     ;; Next, register a command reactor to adjust the polyline
     ;; when the changing command is finished
     (if (not *commandReactor*)
     (setq *commandReactor*
    (VLR-Command-Reactor
     nil          ; No data is associated with the command reactor
     '(
     (:vlr-commandWillStart . gp:command-will-start)
     (:vlr-commandEnded . gp:command-ended)
     )
     ) ;_ end of vlr-command-reactor
     )
     )
     ;; The following code removes all reactors when the drawing is
     ;; closed. This is extremely important!!!!!!!!!
     ;; Without this notification, AutoCAD may crash upon exiting!
     (if (not *DrawingReactor*)
     (setq *DrawingReactor*
     (VLR-DWG-Reactor
     nil          ; No data is associated with the drawing reactor
     '((:vlr-beginClose . gp:clean-all-reactors)
     )
     ) ;_ end of vlr-DWG-reactor
     )
     )
     ) ;_ end of progn
     (princ "\nFunction cancelled.")
     ) ;_ end of if
     (princ "\nIncomplete information to draw a boundary.")
     ) ;_ end of if
     (princ)               ; exit quietly
    ) ;_ end of defun
    ;;; Display a message to let the user know the command name.
    (princ "\nType GPATH to draw a garden path.")
    (princ)
  2. Review the code modifications and comments describing what each new statement does. This tutorial shows all modified code in boldface.