229 lines
8.7 KiB
Python
229 lines
8.7 KiB
Python
#Author-Autodesk Inc.
|
|
#Description-Apply an appearance to selected faces, bodies or occurrences.
|
|
|
|
import adsk.core, adsk.fusion, traceback
|
|
|
|
app = None
|
|
ui = None
|
|
commandId = 'ApplyAppearanceToSelectionCommand'
|
|
commandName = 'ApplyAppearanceToSelection'
|
|
commandDescription = 'Apply an appearance to selected bodies or occurrences'
|
|
|
|
# global set of event handlers to keep them referenced for the duration of the command
|
|
handlers = []
|
|
appearancesMap = {}
|
|
|
|
def replaceItems(cmdInput, newItems):
|
|
cmdInput.listItems.clear()
|
|
if len(newItems) > 0:
|
|
for item in newItems:
|
|
cmdInput.listItems.add(item, False, '')
|
|
cmdInput.listItems[0].isSelected = True
|
|
|
|
def getAppearance(appearanceName):
|
|
materialLibs = app.materialLibraries
|
|
appearance = None
|
|
for materialLib in materialLibs:
|
|
appearances = materialLib.appearances
|
|
|
|
try:
|
|
appearance = appearances.itemByName(appearanceName)
|
|
except:
|
|
pass
|
|
|
|
if appearance:
|
|
break
|
|
return appearance
|
|
|
|
def hasAppearances(lib):
|
|
if lib and lib.appearances.count > 0:
|
|
return True
|
|
return False
|
|
|
|
def getMaterialLibNames(libFilter):
|
|
materialLibs = app.materialLibraries
|
|
libNames = []
|
|
for materialLib in materialLibs:
|
|
if (not libFilter) or libFilter(materialLib):
|
|
libNames.append(materialLib.name)
|
|
return libNames
|
|
|
|
def getAppearancesFromLib(libName, filterExp):
|
|
global appearancesMap
|
|
appearanceList = None
|
|
if libName in appearancesMap:
|
|
appearanceList = appearancesMap[libName]
|
|
else:
|
|
materialLib = app.materialLibraries.itemByName(libName)
|
|
appearances = materialLib.appearances
|
|
appearanceNames = []
|
|
for appearance in appearances:
|
|
appearanceNames.append(appearance.name)
|
|
appearancesMap[libName] = appearanceNames
|
|
appearanceList = appearanceNames
|
|
if filterExp and len(filterExp) > 0:
|
|
filteredList = []
|
|
for appearanceName in appearanceList:
|
|
if appearanceName.lower().find(filterExp.lower()) >= 0:
|
|
filteredList.append(appearanceName)
|
|
return filteredList
|
|
else:
|
|
return appearanceList
|
|
|
|
def getSelectedObjects(selectionInput):
|
|
objects = []
|
|
for i in range(0, selectionInput.selectionCount):
|
|
selection = selectionInput.selection(i)
|
|
selectedObj = selection.entity
|
|
if type(selectedObj) is adsk.fusion.BRepBody or \
|
|
type(selectedObj) is adsk.fusion.BRepFace or \
|
|
type(selectedObj) is adsk.fusion.Occurrence:
|
|
objects.append(selectedObj)
|
|
return objects
|
|
|
|
def applyAppearanceToObjects(appearance, objects):
|
|
for obj in objects:
|
|
obj.appearance = appearance
|
|
|
|
class ApplyAppearanceInputChangedHandler(adsk.core.InputChangedEventHandler):
|
|
def __init__(self):
|
|
super().__init__()
|
|
def notify(self, args):
|
|
try:
|
|
cmd = args.firingEvent.sender
|
|
inputs = cmd.commandInputs
|
|
appearanceListInput = None
|
|
materialLibInput = None
|
|
filterInput = None
|
|
global commandId
|
|
for inputI in inputs:
|
|
if inputI.id == commandId + '_appearanceList':
|
|
appearanceListInput = inputI
|
|
elif inputI.id == commandId + '_materialLib':
|
|
materialLibInput = inputI
|
|
elif inputI.id == commandId + '_filter':
|
|
filterInput = inputI
|
|
cmdInput = args.input
|
|
if cmdInput.id == commandId + '_materialLib' or cmdInput.id == commandId + '_filter':
|
|
appearances = getAppearancesFromLib(materialLibInput.selectedItem.name, filterInput.value)
|
|
replaceItems(appearanceListInput, appearances)
|
|
except:
|
|
if ui:
|
|
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
|
|
|
|
class ApplyAppearanceExecuteHandler(adsk.core.CommandEventHandler):
|
|
def __init__(self):
|
|
super().__init__()
|
|
def notify(self, args):
|
|
try:
|
|
cmd = args.firingEvent.sender
|
|
inputs = cmd.commandInputs
|
|
selectionInput = None
|
|
appearanceListInput = None
|
|
for inputI in inputs:
|
|
global commandId
|
|
if inputI.id == commandId + '_selection':
|
|
selectionInput = inputI
|
|
elif inputI.id == commandId + '_appearanceList':
|
|
appearanceListInput = inputI
|
|
|
|
objects = getSelectedObjects(selectionInput)
|
|
|
|
if not objects or len(objects) == 0:
|
|
return
|
|
|
|
if not appearanceListInput.selectedItem:
|
|
if ui:
|
|
ui.messageBox('Appearance is not selected.')
|
|
return
|
|
|
|
appearance = getAppearance(appearanceListInput.selectedItem.name)
|
|
if not appearance:
|
|
return
|
|
|
|
applyAppearanceToObjects(appearance, objects)
|
|
except:
|
|
if ui:
|
|
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
|
|
|
|
class ApplyAppearanceDestroyHandler(adsk.core.CommandEventHandler):
|
|
def __init__(self):
|
|
super().__init__()
|
|
def notify(self, args):
|
|
try:
|
|
# when the command is done, terminate the script
|
|
# this will release all globals which will remove all event handlers
|
|
adsk.terminate()
|
|
except:
|
|
if ui:
|
|
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
|
|
|
|
class ApplyAppearanceCreatedHandler(adsk.core.CommandCreatedEventHandler):
|
|
def __init__(self):
|
|
super().__init__()
|
|
def notify(self, args):
|
|
try:
|
|
cmd = args.command
|
|
cmd.isRepeatable = False
|
|
onExecute = ApplyAppearanceExecuteHandler()
|
|
cmd.execute.add(onExecute)
|
|
|
|
onDestroy = ApplyAppearanceDestroyHandler()
|
|
cmd.destroy.add(onDestroy)
|
|
onInputChanged = ApplyAppearanceInputChangedHandler()
|
|
cmd.inputChanged.add(onInputChanged)
|
|
# keep the handler referenced beyond this function
|
|
handlers.append(onExecute)
|
|
handlers.append(onDestroy)
|
|
handlers.append(onInputChanged)
|
|
inputs = cmd.commandInputs
|
|
global commandId
|
|
selectionInput = inputs.addSelectionInput(commandId + '_selection', 'Select', 'Select bodies or occurrences')
|
|
selectionInput.setSelectionLimits(1)
|
|
materialLibInput = inputs.addDropDownCommandInput(commandId + '_materialLib', 'Material Library', adsk.core.DropDownStyles.LabeledIconDropDownStyle)
|
|
listItems = materialLibInput.listItems
|
|
materialLibNames = getMaterialLibNames(hasAppearances)
|
|
for materialName in materialLibNames:
|
|
listItems.add(materialName, False, '')
|
|
listItems[0].isSelected = True
|
|
appearanceListInput = inputs.addDropDownCommandInput(commandId + '_appearanceList', 'Appearance', adsk.core.DropDownStyles.TextListDropDownStyle)
|
|
appearances = getAppearancesFromLib(materialLibNames[0], '')
|
|
listItems = appearanceListInput.listItems
|
|
for appearanceName in appearances:
|
|
listItems.add(appearanceName, False, '')
|
|
listItems[0].isSelected = True
|
|
inputs.addStringValueInput(commandId + '_filter', 'Filter', '')
|
|
except:
|
|
if ui:
|
|
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
|
|
|
|
def run(context):
|
|
try:
|
|
global app
|
|
app = adsk.core.Application.get()
|
|
global ui
|
|
ui = app.userInterface
|
|
|
|
global commandId
|
|
global commandName
|
|
global commandDescription
|
|
|
|
cmdDef = ui.commandDefinitions.itemById(commandId)
|
|
if not cmdDef:
|
|
cmdDef = ui.commandDefinitions.addButtonDefinition(commandId, commandName, commandDescription) # no resource folder is specified, the default one will be used
|
|
|
|
onCommandCreated = ApplyAppearanceCreatedHandler()
|
|
cmdDef.commandCreated.add(onCommandCreated)
|
|
# keep the handler referenced beyond this function
|
|
handlers.append(onCommandCreated)
|
|
|
|
inputs = adsk.core.NamedValues.create()
|
|
cmdDef.execute(inputs)
|
|
|
|
# prevent this module from being terminate when the script returns, because we are waiting for event handlers to fire
|
|
adsk.autoTerminate(False)
|
|
|
|
except:
|
|
if ui:
|
|
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
|