C#ATIA

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

Command Logger3

こちらの続きです。
Command Logger2 - C#ATIA

以前のものはこちらにUpしているのですが
Fusion360_Small_Tools_for_Developers/CommandLogger at master · kantoku-code/Fusion360_Small_Tools_for_Developers · GitHub
それとは別のお話。


APIフォーラムでのこちらに取り組んでみました。
CommandCreatedEvent not triggering for ApplicationCommands (such as Extrude, Fillet, ...) - Autodesk Community
単に使われたコマンドのログを取りたいのではなく、数値なども
取得したい との事。 ・・・個人的には出来ない事をグズグズ言ってても
しょうがないと思うのですが。

で、自分がアドバイスした方法でちょっと作りました。

# Fusion360API Python add-inns
import adsk.core, adsk.fusion, traceback
import re, threading, json

_app = None
_ui  = None
_handlers = []
_stopFlag = None
_myCustomEvent = 'MyCustomEventId'
_customEvent = None
_dialogInfos = []

class MyCommandTerminatedHandler(adsk.core.ApplicationCommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        blackList = [
            'SelectCommand',
            'CommitCommand'
        ]
        try:
            # command
            global _ui
            cmdId :str = args.commandId
            if cmdId in blackList:
                return

            cmdDef :adsk.core.CommandDefinition = _ui.commandDefinitions.itemById(cmdId)
            cmdName :str = cmdDef.name if cmdDef else '(unknown)'
            infos = [f'---{cmdName}---']

            # dialog
            global _dialogInfos
            infos.extend(_dialogInfos)

            dumpMsg('\n'.join(infos))

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

class ThreadEventHandler(adsk.core.CustomEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        def getDialogInfo() -> list:
            app = adsk.core.Application.get()

            txtCmdRes = app.executeTextCommand(u'Toolkit.cmdDialog')
            infos =[]
            for tmpInfo in txtCmdRes.split('MenuItems:\n')[:-1]:
                stateInfo = tmpInfo.split('\n')[-2]
                lst = [s.split('\n')[0] for s in stateInfo.split(',')]
                label = re.sub(r"\s+|Label=", "", lst[-2])
                value = re.sub(r"\s+", "", lst[-1])
                infos.append(f'{label}:{value}')
            
            app.executeTextCommand(u'Toolkit.hud')
            return infos

        try:
            global _dialogInfos
            _dialogInfos = getDialogInfo() #It's interfering with keyboard input.
        except:
            if _ui:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class MyThread(threading.Thread):
    def __init__(self, event):
        threading.Thread.__init__(self)
        self.stopped = event

    def run(self):
        global _app, _myCustomEvent
        while not self.stopped.wait(0.1):
            args = {'dmy': ''}
            _app.fireCustomEvent(_myCustomEvent, json.dumps(args)) 

def dumpMsg(msg :str):
    adsk.core.Application.get().userInterface.palettes.itemById('TextCommands').writeText(str(msg))

def run(context):
    try:
        dumpMsg('-- start add-ins --')

        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface

        global _myCustomEvent, _customEvent, _handlers
        _customEvent = _app.registerCustomEvent(_myCustomEvent)
        onThreadEvent = ThreadEventHandler()
        _customEvent.add(onThreadEvent)
        _handlers.append(onThreadEvent)

        global _stopFlag        
        _stopFlag = threading.Event()
        myThread = MyThread(_stopFlag)
        myThread.start()

        onCommandTerminated = MyCommandTerminatedHandler()
        _ui.commandTerminated.add(onCommandTerminated)
        _handlers.append(onCommandTerminated)

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

def stop(context):
    try:
        dumpMsg('-- stop add-ins --')

        global _handlers, _customEvent
        for h in _handlers:
            try:
                _ui.commandStarting.remove(h)
            except:
                pass
            try:
                _customEvent.remove.remove(h)
            except:
                pass

        global  _stopFlag, _app
        _stopFlag.set() 
        _app.unregisterCustomEvent(_myCustomEvent)

    except:
        if _ui:
            _ui.messageBox(_('AddIn Stop Failed: {}').format(traceback.format_exc()))

stop関数が非常に怪しい・・・。

コマンドのダイアログの入力値等を取得する為、テキストコマンドを
利用していますが、最初はCommandTerminatedイベントで処理させていたのですが、
CommandTerminatedイベントはダイアログが消えた直後にトリガー
されるようで、何も情報が取得出来ませんでした。

その為、カスタムイベントでスレッドを作成し、常にダイアログ情報を
取得し続けると言う荒業に切り替えた所、上手く情報を取得出来るように
なりました。

押し出しであればこんな感じです。
f:id:kandennti:20210423112135p:plain


おぉこれで十分じゃん! と思ったのですが、アドインを起動したまま
実際に操作してみると、キーボードからの入力が妨げられているようで、
数値等の入力が出来ないじゃないですか!(マウスでの操作は可能)

どうもスレッドでジャンジャンテキストコマンドを実行させている
事が原因なようで、色々試したものの改善しませんでした。

残念ながらボツです。