C#ATIA

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

パレットに苦しむ2

こちらの続きです。
パレットに苦しむ1 - C#ATIA

優しいJeromeBriotさんが、もっと簡単なサンプルを作ってくれました。


理解出来ていないのですが、パクッて参考にさせてもらい
この様なサンプルアドインが完成しました。

python側ではこんな感じです。

# Fusion360API Python Addin
import adsk.core
import adsk.fusion
import traceback
import json
import math

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

_cmdInfo = {
    'id': 'TestPaletteCmd',
    'name': 'Test Palette Command',
    'tooltip': 'Test Palette Command',
    'resources': ''
}

_paletteInfo = {
    'id': 'TestPalette',
    'name': 'Test Palette',
    'htmlFileURL': 'palette.html',
    'isVisible': True,
    'showCloseButton': True,
    'isResizable': True,
    'width': 100,
    'height': 20,
    'useNewWebBrowser': False # True
}

_perspectiveAngle = 0.1

def updatePerspectiveAngle():
    try:
        global _perspectiveAngle
        app: adsk.core.Application = adsk.core.Application.get()
        vp: adsk.core.Viewport = app.activeViewport
        cam: adsk.core.Camera = vp.camera
        cam.perspectiveAngle = _perspectiveAngle
        cam.isFitView = False
        cam.isSmoothTransition = False
        vp.camera = cam
        vp.refresh()
    except:
        pass

class MyHTMLEventHandler(adsk.core.HTMLEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args):
        try:
            htmlArgs = adsk.core.HTMLEventArgs.cast(args)

            global _app
            if htmlArgs.action == 'htmlLoaded':
                app: adsk.core.Application = adsk.core.Application.get()
                vp: adsk.core.Viewport = app.activeViewport
                cam: adsk.core.Camera = vp.camera
                args.returnData = json.dumps({
                    'action': 'send',
                    'data': str(math.degrees(cam.perspectiveAngle))
                })
                
            elif htmlArgs.action == 'sliderChange':
                data = json.loads(htmlArgs.data)
                global _perspectiveAngle
                _perspectiveAngle = math.radians(int(data['value']))
                updatePerspectiveAngle()

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


class ShowPaletteCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            global _ui, _paletteInfo

            palette = _ui.palettes.itemById(_paletteInfo['id'])
            if palette:
                palette.deleteMe()

            palette = _ui.palettes.add(
                _paletteInfo['id'],
                _paletteInfo['name'],
                _paletteInfo['htmlFileURL'],
                _paletteInfo['isVisible'],
                _paletteInfo['showCloseButton'],
                _paletteInfo['isResizable'],
                _paletteInfo['width'],
                _paletteInfo['height'],
                _paletteInfo['useNewWebBrowser'],
            )

            palette.dockingState = adsk.core.PaletteDockingStates.PaletteDockStateRight

            onHTMLEvent = MyHTMLEventHandler()
            palette.incomingFromHTML.add(onHTMLEvent)
            handlers.append(onHTMLEvent)

            onClosed = MyCloseEventHandler()
            palette.closed.add(onClosed)
            handlers.append(onClosed)

        except:
            _ui.messageBox('Command executed failed: {}'.format(traceback.format_exc()))


class MyCloseEventHandler(adsk.core.UserInterfaceGeneralEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            pass
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


class ShowPaletteCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            command = args.command
            onExecute = ShowPaletteCommandExecuteHandler()
            command.execute.add(onExecute)
            handlers.append(onExecute)
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def run(context):
    try:
        global _ui, _app
        _app = adsk.core.Application.get()
        _ui  = _app.userInterface
        
        global _cmdInfo
        showPaletteCmdDef = _ui.commandDefinitions.itemById(_cmdInfo['id'])
        if showPaletteCmdDef:
            showPaletteCmdDef.deleteMe()

        showPaletteCmdDef = _ui.commandDefinitions.addButtonDefinition(
            _cmdInfo['id'],
            _cmdInfo['name'],
            _cmdInfo['tooltip'],
            _cmdInfo['resources']
        )

        onCommandCreated = ShowPaletteCommandCreatedHandler()
        showPaletteCmdDef.commandCreated.add(onCommandCreated)
        handlers.append(onCommandCreated)
        
        panel = _ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel')
        cntrl = panel.controls.itemById('showPalette')
        if not cntrl:
            panel.controls.addCommand(showPaletteCmdDef)

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


def stop(context):
    try:
        global _paletteInfo
        palette = _ui.palettes.itemById(_paletteInfo['id'])
        if palette:
            palette.deleteMe()
            
        global _cmdInfo
        panel = _ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel')
        cmd = panel.controls.itemById(_cmdInfo['id'])
        if cmd:
            cmd.deleteMe()
        cmdDef = _ui.commandDefinitions.itemById(_cmdInfo['id'])
        if cmdDef:
            cmdDef.deleteMe()
            
        _app.log('Stop addin')
    except:
        if _ui:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

html側は "palette.html" と言う名前で同一フォルダに入れておきます。

<!DOCTYPE html>
<html>
  <head> </head>

  <body>
    <p>視点角度</p>
    <input type="range" min="1" max="149" step="1" id="angleSlider"
      onchange="sliderChange()">
    <button type="button" onclick="sliderChange()">
        強制適応
    </button>
  </body>

  <script>

    window.onload = function () {
        var adskWaiter = setInterval(function () {
            if (window.adsk) {
                clearInterval(adskWaiter);
                let ret = adsk.fusionSendData('htmlLoaded', '');
                let obj = JSON.parse(ret);
                angleSlider.value = Number(obj.data)
            };
        }, 500);
    }
      
    function sliderChange() {
      var args = {
        value: angleSlider.value
      }
      adsk.fusionSendData("sliderChange", JSON.stringify(args))
    }
  </script>
</html>


事前にカメラをパースに設定。
f:id:kandennti:20210914101542p:plain

アドインを起動しコマンドを実行すると、ダイアログ(パレット)が
表示されます。
f:id:kandennti:20210914101829p:plain

スライダーを変更すると
f:id:kandennti:20210914101923p:plain
視点角度が変更されます。

こちらでskuramochiさんが指摘していますが
解決済み: モデリング中のカメラ設定(パース)につきまして - Autodesk Community
ワークスペース(デザイン→レンダリング等)の変更
・ビューキューブのホームを押した場合
は、視点角度がデフォルト値に戻ってしまいます。

それを今回は克服させたつもりです。
ベタなダイアログの場合、ワークスペースの変更時はダイアログが消えてしまします。
しかし、パレットの場合は出しっぱなしで使用出来ます。
その為、ダイアログが表示されている間は、スライダーの値を保持している為、
”強制適応” と言うセンスのないボタンを押すことで、視点角度を再現出来ます。
f:id:kandennti:20210914103052p:plain


本当は、ワークスペースが切り替わった際、自動的に視点角度を修正する様に
したかったのですが、該当するイベントが見つかりませんでした。
定期的にチェックをしても良いのかもしれないのですが、まぁそこまで
必要ない気もしたので・・・。

もうちょっと機能を付けたい気持ちがあるのですが。