Viewer Stateのマウス・キーボードの入力イベント

環境:Houdini 20.0.751

マウスの入力

マウスのクリックはui_event.device()のisLeftButton()やisMiddleButton()を使う。

# マウスの移動やクリック時に呼び出される
def onMouseEvent(self, kwargs):

    ui_event = kwargs["ui_event"]
    device = ui_event.device()
        
    # 左ボタンクリック
    if device.isLeftButton():
        pass
        
    # 中ボタンクリック
    if device.isMiddleButton():
        pass

マウスカーソルの座標

マウスカーソルのスクリーンスペース座標をカーソルの上に表示するサンプルコード。

import hou
import viewerstate.utils as su

class State(object):
    MSG = "Show Mouse Cursor Position"

    def __init__(self, state_name, scene_viewer):
        self.state_name = state_name
        self.scene_viewer = scene_viewer
        self.mouse_screen = hou.Vector2()

        self.cursor_text = "Text"
        self.text = hou.TextDrawable(self.scene_viewer, "text")
                
    def show(self, visible):
        """ Display or hide drawables.
        """
        self.text.show(visible)

    def onEnter(self, kwargs):
        self.show(True)
        self.scene_viewer.setPromptMessage( State.MSG )

    def onResume(self, kwargs):
        self.show(True)
        self.scene_viewer.setPromptMessage( State.MSG )

    def onInterrupt(self,kwargs):
        self.show(False)

    def onMouseEvent(self, kwargs):
        ui_event = kwargs["ui_event"]
        
        mousex = ui_event.device().mouseX()
        mousey = ui_event.device().mouseY()
        
        (origin, dir) = ui_event.ray()
        
        self.mouse_screen = self.scene_viewer.curViewport().mapToScreen(origin)      
        self.cursor_text = "<font size=4,>%.2f, %.2f</font>" % ( self.mouse_screen[0],
            self.mouse_screen[1] )

    def onDraw( self, kwargs ):
        """ This callback is used for rendering the drawables
        """
        handle = kwargs["draw_handle"]

        # cursor text
        params = {
            "text": self.cursor_text,
            "multi_line": True,
            "translate": (self.mouse_screen[0],self.mouse_screen[1], 0.0),
            "highlight_mode": hou.drawableHighlightMode.MatteOverGlow,
            "glow_width": 1,
            "color1": hou.Color(1.0,1.0,1.0),
            "color2": (0.0,0.0,0.0,1.0) }   
        self.text.draw(handle, params)

def createViewerStateTemplate():
    """ Mandatory entry point to create and return the viewer state 
        template to register. """

    state_typename = kwargs["type"].definition().sections()["DefaultState"].contents()
    state_label = "ViewerStateTest::1.0"
    state_cat = hou.sopNodeTypeCategory()

    template = hou.ViewerStateTemplate(state_typename, state_label, state_cat)
    template.bindFactory(State)
    template.bindIcon(kwargs["type"].icon())

    return template

ワールド座標をビューポート座標に変換する

hou.GeometryViewportクラスのmapToScreen()を使う。

# ワールド空間からスクリーンスペース空間へ座標を変換
viewport = self.scene_viewer.curViewport()
point_pos = hou.Vector3(0,0,0)
view_space_pos = viewport.mapToScreen(point_pos)

キーボードの入力

onKeyEvent()を使う。
https://www.sidefx.com/ja/docs/houdini/hom/state_events.html

このコードで押したキーを表示することができる。

#キーボード入力を検知
def onKeyEvent(self,kwargs):
    
    ui_event = kwargs["ui_event"]
    self.key_pressed = ui_event.device().keyString()
    self.log(ui_event.device().keyString()) # 押しているキーがログに表示される
    return True

キーボードのAを押すことでモードを切り替えるサンプルコード。

import hou
import viewerstate.utils as su
from enum import Enum

# Enumでモード切り替え
class Mode(Enum):
    SELECT = 1
    EDIT = 2

class State(object):
    
    def __init__(self, state_name, scene_viewer):
        self.state_name = state_name
        self.scene_viewer = scene_viewer
        
        self.mode = Mode.SELECT

    def onEnter(self, kwargs):
        pass

    def onResume(self, kwargs):
        pass

    def onInterrupt(self,kwargs):
        pass

    #キーボード入力を検知
    def onKeyEvent(self,kwargs):
      
        ui_event = kwargs["ui_event"]
        self.key_pressed = ui_event.device().keyString()
        #Aキーが押されたらモードを切り替える
        if self.key_pressed in ("a"):
            if self.mode == Mode.SELECT:
                self.mode = Mode.EDIT
            else:
                self.mode = Mode.SELECT
            print(self.mode)
            return True
            
        self.key_pressed = None
        return False

def createViewerStateTemplate():
    """ Mandatory entry point to create and return the viewer state 
        template to register. """

    state_typename = kwargs["type"].definition().sections()["DefaultState"].contents()
    state_label = "ViewerStateTest::1.0"
    state_cat = hou.sopNodeTypeCategory()

    template = hou.ViewerStateTemplate(state_typename, state_label, state_cat)
    template.bindFactory(State)
    template.bindIcon(kwargs["type"].icon())

    return template

修飾キーの判定

Ctrl、Shift、Altなどの修飾キーの判定にはonKeyTransitEvent()を使う。

def onKeyTransitEvent(self, kwargs):
    ui_event = kwargs["ui_event"]
    if ui_event.device().isCtrlKey() == 1:
        self.ctrl = 1
    else:
        self.ctrl = 0

ui_event.device()で取得できるプロパティは以下のように調べることが出来る。

self.log(ui_event.device())

'''
'isAltKey' : 0, 'isAutoRepeat' : 0, 'isKeyPressed' : 1, 'isKeyDown' : 1, 'isKeyUp' : 0,\
'isCapsLock' : 0, 'isCtrlKey' : 1, 'isKeyPad' : 0, 'isShiftKey' : 0, 'isFunctionKey' : 0,\
'isArrowDown' : 0, 'isArrowLeft' : 0, 'isArrowRight' : 0, 'isArrowUp' : 0,\
'isLeftButton' : 0, 'isMiddleButton' : 0, 'isRightButton' : 0,\
'isLeftButtonReleased' : 0, 'isMiddleButtonReleased' : 0, 'isRightButtonReleased' : 0\
    'keyString' : 'Ctrl', 'keyValue' : 0, 'modifierString' : 'Ctrl',\
'mouseWheel' : 163.84, 'mouseX' : 531, 'mouseY' : 388\
'isTablet' : 0, 'tabletAngle' : 0, 'tabletPressure' : 1, 'tabletRoll' : 0, 'tabletTilt' : 90,\
'time' : 27175.5\
'''
タイトルとURLをコピーしました