C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

マウスカーソルの座標値を取得する2

こちらの続きです。
マウスカーソルの座標値を取得する - C#ATIA

前回よくわからず、スコープを大きくした変数ですが、こんな感じにすると、
commandInputs が EventHandler の args から取得出来る事が判りました。
(commandInputs はVBAのフォームのようなもの)

class MyMouseMoveHandler(adsk.core.MouseEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        eventArgs = adsk.core.MouseEventArgs.cast(args)
        cmd = eventArgs.firingEvent.sender
        inputs = cmd.commandInputs

他もチョロチョロ修正し、こんな感じです。

#FusionAPI_python
#Author-kantoku
#Description-MouseMoveTest ver0.0.2

import adsk.core, traceback

_ui  = None
_handlers = []

#このコマンドのイベント・ダイアログ作成
class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            global _handlers
            cmd = adsk.core.Command.cast(args.command)

            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            onMouseMove = MyMouseMoveHandler()
            cmd.mouseMove.add(onMouseMove)
            _handlers.append(onMouseMove)

            inputs = cmd.commandInputs
            
            inputs.addTextBoxCommandInput('Vp_Pos', 'Fusion360画面上の座標値', '-', 1, True)
            inputs.addTextBoxCommandInput('Sc_Pos', 'ディスプレイ上の座標値', '-', 1, True)
            inputs.addTextBoxCommandInput('3D_Pos', 'マウス3D仮座標値', '-', 1, True)
            inputs.addTextBoxCommandInput('Cam_Vec', 'カメラ向き(単位ベクトル)', '-', 1, True)
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
            
#このコマンドの破棄
class MyCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            adsk.terminate()
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

#MouseMoveイベント
class MyMouseMoveHandler(adsk.core.MouseEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        eventArgs = adsk.core.MouseEventArgs.cast(args)
        cmd = eventArgs.firingEvent.sender
        inputs = cmd.commandInputs
        
        #ビューポイント
        vp = eventArgs.viewport
        
        #Fusion360画面上の座標値
        vppos = eventArgs.viewportPosition
        ui_vp = inputs.itemById('Vp_Pos')
        ui_vp.text = 'x:[%d] y:[%d]'%(vppos.x, vppos.y)
        
        #ディスプレイ上の座標値
        scrpos = vp.viewToScreen(vppos)
        ui_sc = inputs.itemById('Sc_Pos')
        ui_sc.text = 'x:[%d] y:[%d]'%(scrpos.x, scrpos.y)
        
        #マウス3D仮座標値-奥行きがNGな為正しくない(通過点)
        d3pos = vp.viewToModelSpace(vppos)
        d3_sc = inputs.itemById('3D_Pos')
        d3_sc.text = 'x:{:.3f} y:{:.3f} z:{:.3f}'.format(d3pos.x, d3pos.y, d3pos.z)
        
        #カメラ向き(単位ベクトル)
        cam = vp.camera
        vec = cam.eye.vectorTo(cam.target)
        vec.normalize()
        vec_sc = inputs.itemById('Cam_Vec')
        vec_sc.text = 'x:{:.3f} y:{:.3f} z:{:.3f}'.format(vec.x, vec.y, vec.z)        
        
def run(context):
    try:
        #global _app, _ui
        app = adsk.core.Application.get()
        _ui = app.userInterface
        
        cmdDef = _ui.commandDefinitions.itemById('Mouse_Move_Test')
        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition('Mouse_Move_Test', 'Mouse_Move_Test', 'Mouse_Move_Test')

        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)
        
        cmdDef.execute()

        adsk.autoTerminate(False)
    except:
        if _ui:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

動作はこんな感じです。

マウス3D仮座標値はキューブの向きが上とかの向きになった場合のみ、
奥行き以外の座標値は正しく得られます。
ディスプレイが2Dな為に奥行きが確定せず、傾いた場合は全ての座標値が
正しく得られません。
マウスカーソルは3D空間上では、カメラ向き方向のベクトルでマウス3D仮座標値を
通過する状態になっているはず・・・確認していませんが。

カメラ向き方向のベクトルは、直接取得できるメソッドが無かった為、
カメラ位置からターゲットを単位ベクトル化しました。

        #カメラ向き(単位ベクトル)
        cam = vp.camera
        vec = cam.eye.vectorTo(cam.target)
        vec.normalize()

ターゲットが常に画面中央になっている事を前提で考えたのですが、
多分正しいよね?