HDA viewer state について

viewer stateはユニークな名前がついてないとエラーになる。よってHDAがロードされたとき( OnInstallイベントがこれに相当する)にのみ一度だけ定義されるのがよい。
もしくは、該当するイベントが既にScene上に存在しないかどうかをチェックして、存在すれば一度クリアしてから再作成しても良いかもしれない。

以下のコマンドで、当該HDAの名前を利用したviwer stateを削除できる。
state_name = kwargs['type'].name() + ".pystate"
hou.ui.unregisterViewerState(state_name)

以下は登録方法。HDA python moduleにtemplateという変数でviewer stateのインスタンスが存在するなら、これを有効化できる。
module = kwargs['type'].hdaModule()
hou.ui.registerViewerState(module.template)


以下実装方法
Template本体
Python Moduleに書き込む

from __future__ import print_function

class myState(object):
    def __init__(self,state_name,scene_viewer):
        self.state_name = state_name
        self.scene_viewer = scene_viewer

    # Handler methods go here
    def onMouseEvent(self, kwargs):
        dev = kwargs["ui_event"].device()
        print("Mouse:", dev.mouseX(), dev.mouseY(), dev.isLeftButton())        

def createVST():       
    nodetype = kwargs['type']        
    state_name = nodetype.name() + ".pystate"
    label = nodetype.description()                
    category = nodetype.category()    
    
    template = hou.ViewerStateTemplate(state_name,label,category)
    template.bindFactory(myState)
    
    return template        


テンプレートの読み込みとstateの配置
OnInstallに以下を書き込む

module = kwargs['type'].hdaModule()
template = module.createVST()
hou.ui.registerViewerState(template)

categoryName =  template.categoryName()
print categoryName + " is installed"

stateの削除。OnUninstalledイベントに書き込む

state_name = kwargs['type'].name() + ".pystate"
hou.ui.unregisterViewerState(state_name)

print state_name + " is uninstalled"
あとHDA編集中はstateの更新を頻繁にすることになるから、OnUpadatedイベントに以下のコードを入れておくと便利。
さもなければHDA更新時にstateを消去するために毎回Houdniを起動させる羽目になる。

try:
    state_name = kwargs['type'].name() + ".pystate"
    hou.ui.unregisterViewerState(state_name)
except:
    pass
    
module = kwargs['type'].hdaModule()
template = module.createVST()
hou.ui.registerViewerState(template)

print "updated"
ここも忘れるとアウトなんだが、
Default Stateにstate_nameを入れることで、HDAが読み込まれた時点でこのstateが有効になる。
つまり
state_name = nodetype.name() + ".pystate"
で返ってくる値な
//////////////////////////////////////////////////////////////////////////
ビューポート上のオブジェクトとマウスの重なりを取ってくるstateの例

class myState(object):
    def __init__(self,state_name,scene_viewer):
        self.state_name = state_name
        self.scene_viewer = scene_viewer
        self._geometry = None

    def onEnter(self, kwargs):
        node = kwargs["node"]
        self._geometry = node.geometry()
            
    def onMouseEvent(self,kwargs):
        ui_event = kwargs["ui_event"]       
        ray_origin, ray_dir = ui_event.ray()      
        
        if self._geometry:
            hit, pos, norm, uvw = sopGeometryIntersection(
                self._geometry, ray_origin, ray_dir
            )
            
            print(hit,pos,norm)

#Ray Function
def sopGeometryIntersection(geometry, ray_origin, ray_dir):
    # Make objects for the intersect() method to modify
    position = hou.Vector3()
    normal = hou.Vector3()
    uvw = hou.Vector3()
    # Try intersecting the ray with the geometry
    intersected = geometry.intersect(
        ray_origin, ray_dir, position, normal, uvw
    )
    return intersected, position, normal, uvw     

このブログの人気の投稿

Houdini Path 表記法

HDAの作成、更新とバージョン管理について

action buttonを使ってジオメトリをattributeベースで選択するコード