Houdini 20.0 Pythonスクリプト

Pythonステート Undoへの対応

独自ステートでのアクションをUndo可能にする方法。

On this page

概要

Houdiniは、スクリプトによる多くの変更(例えば、パラメータ値の編集など)のUndoスタックに対して自動的にアイテムを生成します。しかし、これらの自動的に生成されるUndoアイテムは非常に細かいです。

hou.undosモジュールとSceneViewerメソッドを使用することで、ステートのUndoスタックから戻したいアイテムを指定することができます。

スクリプトによるアクションがUndoスタックに追加されないようにする方法

場合によっては、スクリプトによるアクションがUndoスタックに追加されないようにしたいことがあります。 例えば、カスタムステートを動作させるためだけに用意した非表示パラメータがアセットにあったとします。 この場合、Undoスタックが重くならないようにそれらの非表示パラメータの変更情報は追加したくありません。

hou.undos.disabler()マネージャを使用することで、Undoスタックに追加したくないアクションを設定することができます:

with hou.undos.disabler():
    node.parm("guide_tx").set(position.x())
    node.parm("")

一連のユーザ操作を1個のUndoブロックにまとめる方法

カスタムステートでは、スクリプトによるアクションによってたくさんの関数がコールされることがほとんどなので、それらのアクションを1個のUndo可能なアクションにまとめたいです。

例えば、アセットのカスタムPythonステートだと、ユーザがビューア内でマウスをドラッグすると、ノードのパラメータを連続的に変更させることができます。 1回のドラッグで1回のUndo可能なアクションにしたいのですが、デフォルトでは、そのドラッグしている間のパラメータ値の変更すべてがUndo可能アイテムになってしまうので、そのドラッグ操作すべてをUndoするのが面倒でうんざりしてしまいます。

Undo可能にしたいアクションをユーザが実行開始した時に、hou.SceneViewer.beginStateUndoをコールしてください。 beginStateUndo()メソッドの文字列引数には、Undo可能アクションとしてユーザに表示させたいラベルを指定します。

そのアクションが終了した時に、hou.SceneViewer.endStateUndoをコールしてください。 これら2つのコール間のすべてのスクリプト処理をUndoスタックに対してUndo可能アクションとして一括りにします。

class DrawPoints(object):    
    # ...

    def _start(self):
        if not self._pressed:
            self.scene_viewer.beginStateUndo("Add point")
            self._index = self._insert_point()
        self._pressed = True

    def _finish(self):
        if self._pressed:
            self.scene_viewer.endStateUndo()
        self._pressed = False

    def onMouseEvent(self, kwargs):
        node = self._node = kwargs["node"]
        ui_event = kwargs["ui_event"]
        device = ui_event.device()
        origin, direction = ui_event.ray()

        # ジオメトリまたは地面との交点を求めます。
        intersected = -1
        inputs = node.inputs()
        # ノードに入力があれば、ジオメトリとの交差のみを試します。
        if inputs and inputs[0]:
            geometry = inputs[0].geometry()
            intersected, position, _, _ = stateutils.sopGeometryIntersection(geometry, origin, direction)
        if intersected < 0:
            position = stateutils.cplaneIntersection(self.scene_viewer, origin, direction)

        # LMBクリックされたら、ポイントを作成/移動します。
        if device.isLeftButton():
            self._start()
            self._set(self._index, position)
        else:
            self._finish()

    def onInterrupt(self, kwargs):
        self._finish()

    # ...

一連のステートメントを1個のUndoブロックにまとめる方法

1個の関数の中で、スクリプトによる一連のアクションを1個のUndo可能アクションとしてユーザが実行できるようにしたいことがよくあります。 ツールスクリプトを例にすると、新しくSOPノードを生成するには、コンテナオブジェクトの作成、ノードと既存ネットワークの接続、ネットワークエディタ内でのノードの移動といった複数の過程が必要になります。

hou.undos.group()マネージャを使用することで、グループ化したいアクションを1個のUndo可能アクションにまとめることができます。 group()関数の文字列引数には、Undo可能アクションとしてユーザに表示させたいラベルを指定します:

with hou.undos.group("Creation of My Asset"):
    # アセット用の新しいコンテナオブジェクトを作成します。
    container = hou.node("/obj").createNode("geo")
    container.createNode("myasset")
    container.moveToGoodPosition()

Pythonスクリプト

はじめよう

次のステップ

リファレンス

  • hou

    Houdiniにアクセスできるサブモジュール、クラス、ファンクションを含んだモジュール。

導師レベル

Python Viewerステート

Pythonビューアハンドル

プラグインタイプ