以前、フォーラムのこちらにアクティブなドキュメントの
全てのスケッチテキストのフォントを変更するスクリプトを
作った事があります。
Solved: Re: Script to edit font across multiple sketches - Autodesk Community
実は心残りな部分がありまして、変更するフォントを
ドロップダウンリスト(コンボボックス)で表示させているのですが
この使用出来るフォントのリストの取得が難しいんです。
この時は事前にフォントリストを調べてcsvファイルにしておき、
それを読み込んで対処していました。
これだと、PCによって使用出来るフォントが異なるはずなのですが
それに対応することが出来ませんでした。
今回は、実際に使用出来るフォント名を動的に取得して
ドロップダウンリストに表示させています。
# Change Sketch Text Font ver0.0.2 # Author-kantoku # Description-Changes the font for all sketch text in the document. # Fusion360API Python script import adsk.core import adsk.fusion import traceback # Command ID _cmdId = 'ChangeSketchTextFont' # TextBoxCommandInput _txtIptId = 'txtIpt' # DropDownCommandInput _ddIptId = 'ddIpt' # handlers _handlers = [] def run(context): ui = None try: app :adsk.core.Application = adsk.core.Application.get() ui :adsk.core.UserInterface = app.userInterface # Command Definition global _cmdId, _cmdName, _cmdTooltip cmdDefs :adsk.core.CommandDefinitions = ui.commandDefinitions cmdDef :adsk.core.CommandDefinition = cmdDefs.itemById(_cmdId) if cmdDef: cmdDef.deleteMe() cmdDef = cmdDefs.addButtonDefinition( _cmdId, 'Change Sketch Text Font', 'Changes the font for all sketch text in the document.') # Command Created Handler global _handlers onCommandCreated = CommandCreatedHandler() cmdDef.commandCreated.add(onCommandCreated) _handlers.append(onCommandCreated) cmdDef.execute() adsk.autoTerminate(False) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def getAllFontList() -> list: app: adsk.core.Application = adsk.core.Application.get() ui = app.userInterface des: adsk.fusion.Design = app.activeProduct root: adsk.fusion.Component = des.rootComponent app.executeTextCommand(u'PTransaction.Start getFontName') skt: adsk.fusion.Sketch = root.sketches.add(root.xYConstructionPlane) sktTxtIpt: adsk.fusion.SketchTextInput = skt.sketchTexts.createInput2( 'Arial', 2.0 ) sktTxtIpt.setAsMultiLine( adsk.core.Point3D.create(0, 0, 0), adsk.core.Point3D.create(10, 5, 0), adsk.core.HorizontalAlignments.LeftHorizontalAlignment, adsk.core.VerticalAlignments.TopVerticalAlignment, 0 ) sktTxt: adsk.fusion.SketchText = skt.sketchTexts.add(sktTxtIpt) sels: adsk.core.Selections = ui.activeSelections sels.clear() sels.add(sktTxt) app.executeTextCommand(u'Commands.Start EditMTextCmd') dialogInfo = app.executeTextCommand(u'Toolkit.cmdDialog') app.executeTextCommand(u'NuCommands.CancelCmd') skt.deleteMe() app.executeTextCommand(u'PTransaction.Abort') # app.log(dialogInfo) fontInfos = dialogInfo.split('TextFont,')[-1].split('TextExStyle,')[0].split('MenuItems:')[-1].split('\n') fonts = [str.strip(t.split(',')[0]) for t in fontInfos] # [print(k) for k in fonts] return fonts # I think it would be more correct to create a list based on the sketches displayed, # sketches with specific names, etc. def getAllSketchTextList( des :adsk.fusion.Design ) -> list: sktsLst = [c.sketches for c in des.allComponents] txts = [] for skts in sktsLst: for skt in skts: for txt in skt.sketchTexts: txts.append(txt) return txts class CommandCreatedHandler(adsk.core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: global _ui, _handlers cmd = adsk.core.Command.cast(args.command) # -- event -- onExecute = ExecuteHandler() cmd.execute.add(onExecute) _handlers.append(onExecute) onDestroy = DestroyHandler() cmd.destroy.add(onDestroy) _handlers.append(onDestroy) # -- dialog -- # message app :adsk.core.Application = adsk.core.Application.get() des :adsk.fusion.Design = app.activeProduct txts = getAllSketchTextList(des) if len(txts) < 1: cmd.isOKButtonVisible = False global _txtIptId inputs = cmd.commandInputs inputs.addTextBoxCommandInput( _txtIptId, 'info', f'There are {len(txts)} sketch texts', 1, True) if len(txts) < 1: return # font global _ddIptId fonts = getAllFontList() ddIpt :adsk.core.DropDownCommandInput = inputs.addDropDownCommandInput( _ddIptId, 'select font', adsk.core.DropDownStyles.TextListDropDownStyle) items :adsk.core.ListItems = ddIpt.listItems for font in fonts: if txts[0].fontName == font.split('.')[0]: items.add(font, True) else: items.add(font, False) except: app :adsk.core.Application = adsk.core.Application.get() ui :adsk.core.UserInterface = app.userInterface ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class DestroyHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): try: adsk.terminate() except: app :adsk.core.Application = adsk.core.Application.get() ui :adsk.core.UserInterface = app.userInterface ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class ExecuteHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): eventArgs = adsk.core.CommandEventArgs.cast(args) ipts :adsk.core.CommandInputs = eventArgs.command.commandInputs global _ddIptId ddIpt :adsk.core.DropDownCommandInput = ipts.itemById(_ddIptId) fontName = ddIpt.selectedItem.name app :adsk.core.Application = adsk.core.Application.get() des :adsk.fusion.Design = app.activeProduct txts = getAllSketchTextList(des) for txt in txts: try: txt.fontName = fontName except: pass des.computeAll()
今回は "getAllFontList" 関数を書き換えただけなんですけどね。
PCに登録されているフォントのリストの取得方法があるのは
知っているのですが、その場合だとFusion360で使用出来るとは
限らない為、実際にスケッチテキストのダイアログから取得しています。
本当は正規表現でリストを取得したかったのですが、上手く行かず
断念。残念。