Coding the Command-ended Function

Now that you have seen the pseudo-code and handled some important details, replace the stubbed-out code in the gp:command-ended reactor callback with the following:

(defun gp:command-ended (reactor command-list
                         / objReactor
                         reactorToChange reactorData
                         coordinateValues currentPoints
                         newReactorData newPts
                         tileList
                         )
  (cond
    ;; CONDITION 1 - POLYLINE ERASED (Erase command)
    ;; If one or more polyline borders are being erased (indicated
    ;; by the presence of *reactorsToRemove*), erase the tiles
    ;; within the border, then remove the reactor.
    (*reactorsToRemove*
      (foreach objReactor *reactorsToRemove*
        (gp:erase-tiles objReactor)
      )
      (setq *reactorsToRemove* nil)
    )

    ;; CONDITION 2 - LOST ASSOCIATIVITY (Move, Rotate, etc.)
    ;; If associativity has been lost (undo, move, etc.), then
    ;; erase the tiles within each border
    ;; 
    ((and *lostassociativity* *reactorsToChange*)
      (foreach reactorToChange *reactorsToChange*
        (gp:erase-tiles reactorToChange)
      )
      (setq *reactorsToChange* nil)
    )

    ;; CONDITION 3 - GRIP_STRETCH 
    ;; In this case, the associativity of the tiles to the path is
    ;; kept, but the path and the tiles will need to be
    ;; recalculated and redrawn. A GRIP_STRETCH can only be
    ;; performed on a single POLYLINE at a time.
    ((and (not *lostassociativity*)
      *polytochange*
      *reactorsToChange*
      (member "GRIP_STRETCH" command-list)
      ;; for a GRIP_STRETCH, there will be only one reactor in
      ;; the global *reactorsToChange*.
      (setq reactorData
         (vlr-data (setq reactorToChange
                  (car *reactorsToChange*)
                 )
               )
        )
     )

     ;; First, erase the tiles within the polyline border.
     (gp:erase-tiles reactorToChange)

     ;; Next, get the current coordinate values of the polyline
     ;; vertices.
     (setq coordinateValues
       (vlax-safearray->list
         (vlax-variant-value
           (vla-get-coordinates *polyToChange*)
         )
       )
     )

     ;; If the outline is a lightweight polyline, you have
     ;; 2d points, so use utility function xyList->ListOfPoints
     ;; to convert the coordinate data into lists of
     ;; ((x y) (x y) ...) points. Otherwise, use the
     ;; xyzList->ListOfPoints function that deals
     ;; with 3d points, and converts the coordinate data into
     ;; lists of ((x y z) (x y z) ... ) points.
     (setq CurrentPoints
        (if (= (vla-get-ObjectName *polytochange*) "AcDbPolyline")
          (xyList->ListOfPoints coordinateValues)
          (xyzList->ListOfPoints coordinateValues)
        )
     )

     ;; Send this new information to RedefinePolyBorder -- this
     ;; will return the new Polyline Border
     (setq NewReactorData
       (gp:RedefinePolyBorder CurrentPoints reactorData)
     )

     ;; Get all the border Points and ...
     (setq newpts
            (list
              (cdr (assoc 12 NewReactorData))
              (cdr (assoc 13 NewReactorData))
              (cdr (assoc 14 NewReactorData))
              (cdr (assoc 15 NewReactorData))
            )
     )

     ;; ...update the outline of the polyline with the new points
     ;; calculated above.  If dealing with a lightweight polyline,
     ;; convert these points to 2D (since all the points in
     ;; newpts are 3D), otherwise leave them alone.
     (if (= (cdr (assoc 4 NewReactorData)) "LIGHT")
       (setq newpts (mapcar '(lambda (point)
                        (3dPoint->2dPoint Point)
                      )
                      newpts
                    )
       )
     )

     ;; Now update the polyline with the correct points.
     (vla-put-coordinates
       *polytochange*

       ;; For description of the list->variantArray see utils.lsp.
       (gp:list->variantArray (apply 'append newpts))
     )

     ;; Now use the current definition of the NewReactorData, 
     ;; which is really the same as the garden path data
     ;; structure. The only exception is that the field (100) 
     ;; containing the list of tiles is nil.  This is OK since
     ;; gp:Calculate-and-Draw-Tiles does not require this field 
     ;; to draw the tiles. In fact this function creates the tiles
     ;; and returns a list of drawn tiles.
     (setq tileList (gp:Calculate-and-Draw-Tiles
              ;; path data list without correct tile list
              NewReactorData
              ;; Object creation function
              ;; Within a reactor this *MUST* be ActiveX
              "ActiveX"
              )
     )

     ;; Now that you have received all the tiles drawn, rebuild
     ;; the data structure with the correct tileList value and
     ;; reset the data property in the reactor.
     ;; Update the tiles associated with the polyline border.
     (setq NewReactorData
        (subst (cons 100 tileList)
           (assoc 100 NewReactorData)
           NewReactorData
           )
     )

     ;; By now you have the new data associated with the polyline.
     ;; All there is left to do is associate it with the reactor
     ;; using vlr-data-set.
     (vlr-data-set (car *reactorsToChange*) NewReactorData)

     ;; Remove all references to the temporary
     ;; variables *polytochange* and *reactorsToChange*.
     (setq *polytochange*     nil
       *reactorsToChange* nil
       )
     )
    )
    ;; Delete any items in the *Safe-to-Delete* global if you can!!!
    (Gp:Safe-Delete (car command-list))
   (princ)
 )