C#ATIA

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

フィーチャで色を付ける

個人的にですが、Fusion360は面に色を付けることが結構面倒に
感じてます。理由は複数あるのですが、そのうちの一つが、
"フィーチャ毎に色が付ける為のスマートな方法が無い"
事です。

言葉だけだと分かりにくいのですが、例えばこんな感じです。

タイムライン上のフィレットのフィーチャで出来た面のみ
(要はフィレット面のみ)に色付け と言う事です。
CATIAであれば何も考えることなく出来るのですが・・・。

これ、Fusion360のアイデアに随分前から小原さんが出しています。
外観の色をフィーチャごとに設定できるようにして欲しい - Autodesk Community

今後使うかも知れないと思い、テストしたところ出来たので
スクリプトですが公開しておきます。

# Fusion360API Python script

import traceback
import adsk
import adsk.core as core
# import adsk.fusion as fusion

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

CMD_INFO = {
    'id': 'kantoku_feature_color',
    'name': 'フィーチャ指定の色',
    'tooltip': '指定したフィーチャで色を付けます'
}

_featIpt: core.SelectionCommandInput = None
_colorMap: dict = None
_colorDDown: core.DropDownCommandInput = None
COLOR_RESET = 'リセット'

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

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

            # event
            # https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-0550963a-ff63-4183-b0a7-a1bf0c99f821
            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            onExecutePreview = MyExecutePreviewHandler()
            cmd.executePreview.add(onExecutePreview)
            _handlers.append(onExecutePreview)

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

            # inputs
            inputs: core.CommandInputs = cmd.commandInputs

            global _featIpt
            _featIpt = inputs.addSelectionInput(
                '_featIptId',
                'フィーチャ',
                '色を変更するフィーチャを選択して下さい',
            )
            _featIpt.addSelectionFilter(
                core.SelectionCommandInput.Features
            )
            _featIpt.setSelectionLimits(0)

            global _colorMap
            _colorMap = get_appearance_map()
            if not _colorMap:
                return

            global _colorDDown
            _colorDDown = inputs.addDropDownCommandInput(
                '_colorDDownId',
                'カラー',
                core.DropDownStyles.TextListDropDownStyle,
            )
            items: core.ListItems = _colorDDown.listItems
            for key in _colorMap.keys():
                items.add(
                    key,
                    False,
                    '',
                )
            items.item(4).isSelected = True

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


class MyExecutePreviewHandler(core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: core.CommandEventArgs):

        appe: core.Appearance = None

        global _colorDDown, _colorMap
        selectColor = _colorDDown.selectedItem.name
        if selectColor == COLOR_RESET:
            appe = None
        else:
            appe: core.Appearance = _colorMap[_colorDDown.selectedItem.name]

        global _featIpt
        for idx in range(_featIpt.selectionCount):
            faces = _featIpt.selection(idx).entity.faces
            for face in faces:
                face.appearance = appe

        args.isValidResult = True


class MyValidateInputsHandler(core.ValidateInputsEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: core.ValidateInputsEventArgs):

        global _featIpt
        if _featIpt.selectionCount < 1:
            args.areInputsValid = False


class MyPreSelectHandler(core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: core.SelectionEventArgs):

        entity = args.selection.entity

        if not hasattr(entity, 'faces'):
            args.isSelectable = False


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

    def notify(self, args: core.CommandEventArgs):
        adsk.terminate()


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

        cmdDef: core.CommandDefinition = _ui.commandDefinitions.itemById(
            CMD_INFO['id']
        )

        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(
                CMD_INFO['id'],
                CMD_INFO['name'],
                CMD_INFO['tooltip']
            )

        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 get_appearance_map(
) -> dict:

    app: core.Application = core.Application.get()

    mateLib = app.materialLibraries.itemById(
        'BA5EE55E-9982-449B-9D66-9F036540E140'
    )
    if not mateLib:
        return None

    ids = (
        'Prism-003', # ペイント - メタリック(黒)
        'Prism-004', # ペイント - メタリック(青)
        'Prism-005', # ペイント - メタリック(緑)
        'Prism-006', # ペイント - メタリック(赤)
        'Prism-007', # ペイント - メタリック(シルバー)
        'Prism-008', # ペイント - メタリック(黄)
        'Prism-009', # ペイント - メタリック(濃い灰色)
    )

    colorMap = {COLOR_RESET: None}

    appe: core.Appearance = None
    for id in ids:
        appe = mateLib.appearances.itemById(id)
        if not appe:
            continue
        colorMap.setdefault(f'{appe.name}', appe)

    if len(colorMap.keys()) < 1:
        return None

    return colorMap

実際の動作です。

使用出来る色(外観)は、こちらの7色のみです。

ライブラリに入っているものは幾らでも利用出来るのですが、
テストも兼ねているので、少なくしています。

スクリプトの為、使い勝手が悪いのですが、将来的に必要になったら
アドインにするかもしれないです。