C#ATIA

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

ドキュメントを開ききったタイミングを得る

Fusion360APIでドキュメントを開ききったタイミングで
発生するイベント "Application.documentOpened" があります。
Fusion 360 Help

”開ききったタイミング” と言うのは、開いたドキュメントに
アクセス可能なタイミングです。
前からそうなのですが、このイベントのハンドラーでドキュメントに
アクセスしても、早すぎてアクセス出来ないんです。

恐らくクラウドを使っている事が原因のような気がします。
クラウド
・ローカルキャッシュフォルダにコピー
・コピーしたものを開く
恐らくこの手順で開かれているので、イベントの発生が早すぎるんです。

過去にテキストコマンドでFusion360のタスクを監視してタイミングを
合わせたものを作った事はあるのですが、あまりにイマイチで
もう一度やろうと言う気がしませんでした。


が、こちらに取り組みました。
Accessing attributes inside the Application.documentOpened event - Autodesk Community

4個目のリプライのやつは、私的には出来てます。
開ききったタイミングでドキュメントにアクセスし、中からデータの取得に
成功してます。

結局、pythonのthreadingで開かれているドキュメントを監視して、
増えた時だけcustom eventを発生させる事にしました。
・・・知識が無いので、custom event結構大変でした。
イベントの利用を簡素化する為、ヘルパークラスを作りました。
あちらでは長くなりすぎたので、こちらに記載。

# Description-Document Opened Event Helper

import adsk.core
import adsk.fusion
import adsk.cam
import traceback
import threading

_DEBUG = False

class DocOpenedEventHelper():
    def __init__(self, customEventHandler: adsk.core.CustomEventHandler):
        self.handlers = []
        self.stopFlag: threading.Event = None
        self.customEventId = 'docOpenedEventHelperId'
        self.customEvent: adsk.core.CustomEvent = None
        self.threadEventHandler = customEventHandler

    def __del__(self):
        app: adsk.core.Application = adsk.core.Application.get()
        try:
            if self.handlers.count:
                self.customEvent.remove(self.handlers[0])
            self.stopFlag.set()
            app.unregisterCustomEvent(self.customEventId)
            if _DEBUG:
                app.log('stop')
        except:
            app.userInterface.messageBox(
                'Failed:\n{}'.format(traceback.format_exc()))

    def start(self):
        app: adsk.core.Application = adsk.core.Application.get()
        try:
            try:
                app.unregisterCustomEvent(self.customEventId)
            except:
                pass

            self.customEvent = app.registerCustomEvent(self.customEventId)
            onThreadEvent = self.threadEventHandler
            self.customEvent.add(onThreadEvent)
            self.handlers.append(onThreadEvent)

            self.stopFlag = threading.Event()
            myThread = MyThread(self.stopFlag, self.customEventId)
            myThread.start()
        except:
            app.userInterface.messageBox(
                'Failed:\n{}'.format(traceback.format_exc()))


class MyThread(threading.Thread):
    def __init__(self, event: threading.Event, customEventId: str, wait: float = 0.5):
        threading.Thread.__init__(self)
        self.stopped = event
        self.wait = wait
        self.customEventId = customEventId
        self.docCount = adsk.core.Application.get().documents.count

    def run(self):
        app = adsk.core.Application.get()
        while not self.stopped.wait(self.wait):
            count = app.documents.count
            if count > self.docCount:
                try:
                    app.fireCustomEvent(self.customEventId)
                except:
                    pass
                    if _DEBUG:
                        app.log(f'ID:{self.customEventId}')
                        app.log('Failed:\n{}'.format(traceback.format_exc()))
            self.docCount = count

こうして見ると、結構短い・・・。すごい苦労したのに。

threadingがイマイチわからず、custom eventと併用しないとThreadが
止まってくれなくて。
正直な所、作ったのに未だに意味がわかってない。