直線的でないリアクタ シーケンスを処理する

最後の重要点として、ユーザが特定のグリップ コマンドを使用してポリラインを修正したときの、AutoCAD のコマンド/リアクタ シーケンスの動作を説明します。これら、GRIP_MOVE や GRIP_ROTATE などのコマンドは、オブジェクトのグリップを選択し、次に右クリックした後、ショートカット メニューから使用できます。リアクタ シーケンスは、単純な MOVE[移動]コマンドや ERASE[削除]コマンドのように直線的ではありません。事実、ユーザは、あるコマンドの実行中に、他のコマンドに変更しています。リアクタ イベントのシーケンスを追跡するコードをレッスン 6 からロードして、この状況を確認できます。または、次の Visual LISP の[コンソール]ウィンドウの出力を見て、何が起こるかを理解してください。

;; To start, select the polyline and some of the circles by using a 
;; crossing selection box. The items in the selection set-- 
;; the chosen circles and the polyline--are now shown with grips on.
;; To initiate the sequence, click on one of the polyline grips:
(GP:COMMAND-WILL-START #<VLR-Command-reactor> (GRIP_STRETCH))

;; Now change the command to a move by right-clicking and choosing
;; MOVE from the pop-up menu.  Notice that the command-ended
;; reactor fires in order to close out the GRIP_STRETCH command
;; without having fired an object reactor event:
(GP:COMMAND-ENDED #<VLR-Command-reactor> (GRIP_STRETCH))
(GP:COMMAND-WILL-START #<VLR-Command-reactor> (GRIP_MOVE))

;; Now drag the outline (and the selected circles) to a new location.
(GP:OUTLINE-CHANGED #<VLA-OBJECT IAcadLWPolyline 028f3188> 
                 #<VLR-Object-reactor> nil)
(GP:COMMAND-ENDED #<VLR-Command-reactor> (GRIP_MOVE))

これで明らかなように、どの場合も、オブジェクト リアクタ コールバックは呼び出されません。

このシーケンスに関連する問題があります。最後の command-ended コールバックの中からでさえ、グリップ選択セットの一部である円を削除することはできません。円は、AutoCAD によって開かれた状態のままです。command-ended コールバックの中で円を削除しようとすると、AutoCAD がクラッシュする可能性があります。これは、タイル オブジェクトが削除可能になるまでこのオブジェクトへのポインタのリストを格納する他のグローバル変数を使用することで、回避できます。

直線的でないリアクタ シーケンスを処理するには

  1. ファイル gpreact.lsp に次の関数を追加します。
    (defun gp:erase-tiles (reactor / reactorData tiles tile)
      (if (setq reactorData (vlr-data reactor))
        (progn
          ;; Tiles in the path are stored as data in the reactor.
          (setq tiles (cdr (assoc 100 reactorData)))
          ;; Erase all the existing tiles in the path.
          (foreach tile tiles
              (if (and (null (member tile *Safe-to-Delete*))
                     (not (vlax-erased-p tile))
                     )
                  (progn
                     (vla-put-visible tile 0)
                     (setq *Safe-to-Delete* (cons tile *Safe-to-Delete*))
                  )
              )
          )
          (vlr-data-set reactor nil)
          ) 
        )
     )

    この新しい関数は、タイル削除の最初の段階で使用されます。タイルが実際には削除されない点に注目してください。タイルは非表示にされ、グローバル変数 *Safe-to-Delete* に追加されます。

  2. ファイル gpreact.lsp に次の関数を追加します。
    (defun Gp:Safe-Delete (activeCommand)
      (if (not (equal
          (strcase (substr activeCommand 1 5))
            "GRIP_"
          )
      )
      (progn
         (if *Safe-to-Delete*
            (foreach Item *Safe-to-Delete*
              (if (not (vlax-erased-p Item))
                (vla-erase item)
              )
            )
          )
          (setq *Safe-to-Delete* nil)
          )
        )
     )

    この関数は、GRIP_MOVE または GRIP_STRETCH コマンドが実行されていないときに呼び出すことができます。