C#ATIA

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

SelectionCommandInputの不具合っぽさを解消する

こちらで質問しながら思いついた方法で、対処しました。
Solved: Operation using the SelectionCommandInput.addSelection method - Autodesk Community
不具合を再現するコードは、質問部分にあるものです。

ダイアログが表示される際に、addSelectionメソッドを使用して
事前選択した状態にしたいのです。
f:id:kandennti:20220417224108p:plain
これ自体は出来ています。問題はここで既に選択済みの要素を
クリックした際、通常のコマンドと同様に選択が解除される
事を期待していたのですが、CAD画面上は2個の選択された
状態に対して、ダイアログでは3個選択された状態となります。
f:id:kandennti:20220417230618p:plain


回避する為の方法は2個目の方ですが、InputChangedイベント時に
選択要素内に重複するものがあった場合、選択が解除された動作を
行ったものとして扱う事にすると、想定している動作をしました。
(要は不具合を回避出来ました)


ですが、最初の頃からCommandInputのイベント処理に違和感を
ずっと感じていたので、フォーラムのコードをちょっと修正しました。

# 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

class selectionInputBugSupportHandler(adsk.core.InputChangedEventHandler):
    def __init__(self, selInput: adsk.core.SelectionCommandInput):
        super().__init__()
        self.input = selInput

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

        if self.input != args.input:
            return

        ents = [self.input.selection(i).entity for i in range(self.input.selectionCount)]
        singles = [x for x in ents if ents.count(x) == 1]

        if len(ents) == len(singles):
            return

        self.input.clearSelection()
        [self.input.addSelection(x) for x in singles]


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


            # inputs
            global _selIpt
            _selIpt = inputs.addSelectionInput(
                'selIptId',
                'sketch curves',
                'select sketch curves'
            )
            _selIpt.setSelectionLimits(0)
            _selIpt.addSelectionFilter(
                adsk.core.SelectionCommandInput.SketchCurves
            )

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

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

            onActivate = MyActivateHandler()
            cmd.activate.add(onActivate)
            _handlers.append(onActivate)

            onBugSupport = selectionInputBugSupportHandler(_selIpt)
            cmd.inputChanged.add(onBugSupport)
            _handlers.append(onBugSupport)


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

class MyActivateHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.CommandEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)

        # Preselect sketch lines
        global _app, _selIpt
        des: adsk.fusion.Design = _app.activeProduct
        root: adsk.fusion.Component = des.rootComponent
        sktLines: adsk.fusion.SketchLines = root.sketches[0].sketchCurves.sketchLines
        _selIpt.clearSelection()
        _selIpt.addSelection(sktLines[0])
        _selIpt.addSelection(sktLines[1])


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)

        global _app, _selIpt
        selCount = _selIpt.selectionCount
        _app.log(f'selectionCount:{selCount}')
        for idx in range(selCount):
             _app.log(f' {_selIpt.selection(idx).entity.entityToken}')


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

        initSketchLines()

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


def initSketchLines():
    app: adsk.core.Application = adsk.core.Application.get()
    app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
    des: adsk.fusion.Design = app.activeProduct
    root: adsk.fusion.Component = des.rootComponent

    skt: adsk.fusion.Sketch = root.sketches.add(
        root.xYConstructionPlane
    )
    sktLines: adsk.fusion.SketchLines = skt.sketchCurves.sketchLines

    P3D = adsk.core.Point3D
    points =[
        (P3D.create(1,0,0), P3D.create(1,2,0)),
        (P3D.create(2,0,0), P3D.create(2,2,0)),
        (P3D.create(3,0,0), P3D.create(3,2,0)),
        (P3D.create(4,0,0), P3D.create(4,2,0)),
    ]
    for p1, p2 in points:
        sktLines.addByTwoPoints(p1, p2)

    app.activeViewport.fit()

細かな説明を省きます(今日は疲れて眠い・・・)が、満足。