C#ATIA

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

マウスカーソル位置を表現したい1

もう2年前だ・・・こちらの不満部分を解消したいのですが。
OnTheFly1 - C#ATIA

そもそもあのアドインですが、"それ程、使わないな" と放置して
いるのですが、フォームらのリプライ書く際に結構角度(や曲率)
を確認したい時が多いのですが、未だに標準の機能に無いため
こちらのアドインを使って確認しています。
つまり、個人的には需要があります。


但し実際使っていると、どうしても "測定している感" が全く無く
イマイチなんです。

例えば、メッシュの作業スペースの時にはマウスカーソルを
メッシュに乗せた際、ある程度の範囲の面の色が変わります。

これだと、"マウスカーソル乗っている感" をしっかり感じます。


テストとして、これに近いものを自作してみました。

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core

_app: adsk.core.Application = None
_ui: adsk.core.UserInterface = None
_handlers = []

_selIpt: adsk.core.SelectionCommandInput = None
_cgFact: 'CustomGraphicsFactry' = None

class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandCreatedEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)
        try:
            global _handlers
            cmd: adsk.core.Command = adsk.core.Command.cast(args.command)
            inputs: adsk.core.CommandInputs = cmd.commandInputs

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

            onExecute = MyExecuteHandler()
            cmd.execute.add(onExecute)
            _handlers.append(onExecute)

            onPreSelect = MyPreSelectHandler()
            # cmd.preSelect.add(onPreSelect)
            cmd.preSelectMouseMove.add(onPreSelect)
            _handlers.append(onPreSelect)


            global _selIpt
            _selIpt = inputs.addSelectionInput(
                'selIptId',
                'select',
                'select'
            )

            global _cgFact
            _cgFact = CustomGraphicsFactry('test')

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


class MyExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)


class MyCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)
        adsk.terminate()


def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface

        cmdDef: adsk.core.CommandDefinition = _ui.commandDefinitions.itemById(
            'test_cmd'
        )

        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(
                'test_cmd',
                'Test',
                'Test'
            )

        global _handlers
        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()))


class MyPreSelectHandler(adsk.core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.SelectionEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)

        tmpMgr: adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get()

        entity = args.selection.entity
        if not entity.objectType == adsk.fusion.BRepBody.objectType:
            if hasattr(entity, 'body'):
                entity = entity.body
            else:
                return

        clone = tmpMgr.copy(entity)

        tmpMgr.booleanOperation(
            clone,
            tmpMgr.createSphere(
                args.selection.point,
                0.5
            ),
            adsk.fusion.BooleanTypes.IntersectionBooleanType
        )

        global _cgFact
        _cgFact.updateBody(clone)


class CustomGraphicsFactry():

    def __init__(
        self,
        id :str,):

        self.app: adsk.core.Application = adsk.core.Application.get()
        self.cgGroup: adsk.fusion.CustomGraphicsGroup = None
        self.color = adsk.fusion.CustomGraphicsSolidColorEffect.create(
            adsk.core.Color.create(255,0,0,255)
        )
        self.id = id
        self.refreshCG()

    def __del__(
        self):

        self.removeCG()

    def removeCG(
        self):

        des :adsk.fusion.Design = self.app.activeProduct
        cgs = [cmp.customGraphicsGroups for cmp in des.allComponents]
        cgs = [cg for cg in cgs if cg.count > 0]
        
        if len(cgs) < 1: return

        for cg in cgs:
            gps = [c for c in cg]
            gps.reverse()
            for gp in gps:
                if not hasattr(gp, 'id'):
                    continue

                if not gp.id == self.id:
                    continue

                gp.deleteMe()

    def refreshCG(
        self
        ):

        self.removeCG()
        des :adsk.fusion.Design = self.app.activeProduct
        comp :adsk.fusion.Component = des.activeComponent
        self._cgGroup: adsk.fusion.CustomGraphicsGroup = comp.customGraphicsGroups.add()
        self._cgGroup.id = self.id

    def updateBody(
        self,
        body: adsk.fusion.BRepBody,
        isRefresh :bool = True
        ):

        if isRefresh:
            self.refreshCG()

        cgBody: adsk.fusion.CustomGraphicsBRepBody = self._cgGroup.addBRepBody(body)
        cgBody.color = self.color

こんな感じです。

色がイマイチだとか、センス無いとか色々ありますが、
何とかなりそうな雰囲気はあるのですが、あまり頻繁に
動かすと処理が追い付かず、Fusion360がクラッシュします・・・。

最初はpreSelectイベントを利用していたのですが、クラッシュ。
preSelectMouseMoveイベントに切り替えると少しは
耐えてくれるのですが、やはりクラッシュ・・・。

薄々、"処理が重いだろうなぁ" とは思っていたのですが、
やはり無理っぽいです。 他に何か方法あるかな・・・。