C#ATIA

↑タイトル詐欺 主にCATIA V5 の VBA(最近はPMillマクロとFusion360APIが多い)

俺コマンドを作る1

Fusion360のアドインを何個か作りましたが、実はツールバーに登録・発火させる
仕組みが分かっていないです。
今までこちらを使って、楽をしていたものでして・・・。
github.com

あちら、非常に便利なのですが対応しているイベントが少なく、作りたいものが未対応
状態なもので、重い腰を上げ勉強してみました。

f:id:kandennti:20200206183141p:plain
こんな感じにツールバーに登録するのが目的です。
・・・英語で "MyCommand" だったら、"俺コマンド" と言う表現で間違いありません。

時間が無いので、とりあえずコードだけ記載。中身は後日です。
念のためお伝えしておくと、この "俺コマンド” は何もしません。
何もしないのに、このボリュームは相当ハードルが高いです。
スクリプトの方が開発が桁違いに楽なんです。

#FusionAPI_python addin
#Author-kantoku
#Description-俺コマンド(アドイン)を作成するサンプル

import adsk.core, adsk.fusion, traceback

_app = adsk.core.Application.cast(None)
_ui  = adsk.core.UserInterface.cast(None)
_handlers = []

# 俺コマンド用情報
_cmdInfo = ['cmdTest','俺コマンド','偉そうにしているが何も出来ない']

# SelectionCommandInput用情報
_selInfo = ['dlgSel','さぁ選べ!!','何もしないから']

# 俺コマンドを追加するタブのID
_tabId = 'SolidTab'

# 俺コマンドを追加するパネルのID
_panelId = 'InspectPanel'


def run(context):
    ui = None
    try:
        # 色々と使う、ApplicationとuserInterfaceを取得
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface

        # -- 俺コマンドを作成するためにcommandDefinitionを作るよ --

        # 今利用出来る全てのコマンドを取得
        cmdDefs :adsk.core.CommandDefinitions = _ui.commandDefinitions

        # 既に同一のIDの俺コマンドが無いか? 確認してみる
        global _cmdInfo
        cmdDef :adsk.core.CommandDefinition = cmdDefs.itemById(_cmdInfo[0])
        if cmdDef:
            # 見つけたら非情にも消し去る(行儀悪いから良い子はしない)
            cmdDef.deleteMe()

        # commandDefinitionを作る
        # http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-04eb6198-72cd-4430-a6a4-8d68a1105b8e
        cmdDef = cmdDefs.addButtonDefinition(_cmdInfo[0],_cmdInfo[1],_cmdInfo[2])

        # 俺コマンドはイベントを使って産み出す
        # もうおまじないレベル
        # http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-895ee146-8697-4ba0-98e7-4f72b74edb4f
        global _handlers
        onCommandCreated = CommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)


        # -- 俺コマンドを呼び出しやすくする為にパネルに登録するから --

        # タブを使用しているか確認
        # 旧UIの関係かも 恐らくもういらないと思う
        if not _ui.isTabbedToolbarUI: return

        # 'デザイン' の全タブを取得
        desTabs = adsk.core.ToolbarTabs.cast(None)
        desTabs = _ui.toolbarTabsByProductType('DesignProductType')
        if desTabs.count < 1: return

        # 目的のタブ取得
        global _tabId
        targetTab :adsk.core.ToolbarTab = desTabs.itemById(_tabId)

        # タブ見つかった?
        if not targetTab:
            # 見つからないので作っちゃう
            # https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-81247FED-3EC7-4EEA-80DD-0017F0E2450E
            # targetTab = desTabs.add(_tabId, '俺タブ')
            # と思ったけど未対応っぽい(ver2.0.7421)
            _ui.messageBox('未対応タブID!')

        # 目的のタブ内の全パネル取得
        panels :adsk.core.ToolbarPanels = targetTab.toolbarPanels
        if panels.count < 1: return

        # 目的のパネル取得
        global _panelId
        targetpanel :adsk.core.ToolbarPanel = panels.itemById(_panelId)

        # パネル見つかった?
        if not targetpanel:
            # 見つからないので作っちゃう
            # https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-6b387530-93c1-4238-aefb-eca54b03852d
            targetpanel = panels.add(_panelId, '俺パネル')

        # パネルを使えるように
        targetpanel.isVisible = True

        # パネル内のコントロール取得
        # あれはコントロールって呼ぶんだな
        controls :adsk.core.ToolbarControls = targetpanel.controls

        # 既に 俺コマンドが登録されてる?
        cmdControl :adsk.core.ToolbarControl = controls.itemById(cmdDef.id)
        if cmdControl:
            # 見つけたら非情にも、また消し去る
            cmdControl.deleteMe()

        # 俺コマンドをパネルに登録
        # https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-1ed0cfb5-2ad4-4285-9eec-484ef19f2729
        cmdControl = controls.addCommand(cmdDef)

        # 俺コマンドを使える状態にするぞ
        # あくまで登録しているだけで、コントロールが押されるまで待機
        cmdControl.isVisible = True
        cmdControl.isPromoted = True
        cmdControl.isPromotedByDefault = True                

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

# 俺コマンド作成
class CommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            global _ui, _handlers
            cmd = adsk.core.Command.cast(args.command)
            
            # 本当はここにコマンドのイベント類を記述する

            # SelectionCommandInputを追加
            global _selInfo
            inputs = cmd.commandInputs
            inputs.addSelectionInput(_selInfo[0], _selInfo[1], _selInfo[2])
        except:
            if _ui:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

# 俺コマンド削除
def stop(context):
    try:
        # 全てのパネルを取得
        panels :adsk.core.ToolbarPanels = _ui.allToolbarPanels

        # 俺コマンドの入ったパネル取得
        global _panelId
        panel :adsk.core.ToolbarPanel = panels.itemById(_panelId)

        # 行儀良く、俺コマンドを削除
        global _cmdInfo
        if panel:
            panel.controls.itemById(_cmdInfo[0]).deleteMe()

        # タブ作っていたら削除
        # と思ったけど現状はタブ自体が作れない(ver2.0.7421)
        global _tabId
        tabs :adsk.core.ToolbarTabs = _ui.allToolbarTabs
        tab :adsk.core.ToolbarTab = tabs.itemById(_tabId)
        if not tab:
            if tab.toolbarPanels.count < 1 and not tab.isNative:
                tab.deleteMe()

    except:
        print('Failed:\n{}'.format(traceback.format_exc()))

なるべくコメントやType Hints、使わなくても良い部分でもglobalを付けました。
個人的にはもっとリファクタリングしたいのですが、逆に "わかりにくい" と
言われることがあったため、あえてエントリポイント(run)にゴリゴリと書いてます。

元ネタはこちらです。
Fusion 360 Help
ネストが深いの嫌なんだよね。