Fusion360-Addons/python/Samples/ApplyMaterialToSelection/ApplyMaterialToSelection.py
2021-10-31 19:12:13 +01:00

221 lines
8.4 KiB
Python

#Author-Autodesk Inc.
#Description-Apply a material to selected bodies or occurrences.
import adsk.core, adsk.fusion, traceback
commandId = 'ApplyMaterialToSelectionCommand'
commandName = 'ApplyMaterialToSelection'
commandDescription = 'Apply a material to selected bodies or occurrences'
app = None
ui = None
# global set of event handlers to keep them referenced for the duration of the command
handlers = []
materialsMap = {}
app = adsk.core.Application.get()
if app:
ui = app.userInterface
class ApplyMaterialInputChangedHandler(adsk.core.InputChangedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
cmd = args.firingEvent.sender
inputs = cmd.commandInputs
materialListInput = None
filterInput = None
materialLibInput = None
global commandId
for inputI in inputs:
if inputI.id == commandId + '_materialList':
materialListInput = inputI
elif inputI.id == commandId + '_filter':
filterInput = inputI
elif inputI.id == commandId + '_materialLib':
materialLibInput = inputI
cmdInput = args.input
if cmdInput.id == commandId + '_materialLib' or cmdInput.id == commandId + '_filter':
materials = getMaterialsFromLib(materialLibInput.selectedItem.name, filterInput.value)
replaceItems(materialListInput, materials)
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
class ApplyMaterialToSelectionCommandExecuteHandler(adsk.core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
command = args.firingEvent.sender
inputs = command.commandInputs
for input in inputs:
if input.id == commandId + '_selection':
selectionInput = input
elif input.id == commandId + '_materialList':
materialListInput = input
entities = getSelectedEntities(selectionInput)
if len(entities) == 0:
return
if not materialListInput.selectedItem:
if ui:
ui.messageBox('Material is not selected.')
return
material = getMaterial(materialListInput.selectedItem.name)
if not material:
return
applyMaterialToEntities(material, entities)
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
class ApplyMaterialToSelectionCommandDestroyHandler(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 ApplyMaterialToSelectionCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
cmd = args.command
cmd.isRepeatable = False
onExecute = ApplyMaterialToSelectionCommandExecuteHandler()
cmd.execute.add(onExecute)
onDestroy = ApplyMaterialToSelectionCommandDestroyHandler()
cmd.destroy.add(onDestroy)
onInputChanged = ApplyMaterialInputChangedHandler()
cmd.inputChanged.add(onInputChanged)
# keep the handler referenced beyond this function
handlers.append(onExecute)
handlers.append(onDestroy)
handlers.append(onInputChanged)
# Define the inputs.
inputs = cmd.commandInputs
global commandId
selectionInput = inputs.addSelectionInput(commandId + '_selection', 'Select', 'Select bodies or occurrences')
selectionInput.setSelectionLimits(1)
selectionInput.selectionFilters = ['SolidBodies', 'Occurrences']
materialLibInput = inputs.addDropDownCommandInput(commandId + '_materialLib', 'Material Library', adsk.core.DropDownStyles.LabeledIconDropDownStyle)
listItems = materialLibInput.listItems
materialLibNames = getMaterialLibNames()
for materialName in materialLibNames :
listItems.add(materialName, False, '')
listItems[0].isSelected = True
materialListInput = inputs.addDropDownCommandInput(commandId + '_materialList', 'Material', adsk.core.DropDownStyles.TextListDropDownStyle)
materials = getMaterialsFromLib(materialLibNames[0], '')
listItems = materialListInput.listItems
for materialName in materials :
listItems.add(materialName, False, '')
listItems[0].isSelected = True
inputs.addStringValueInput(commandId + '_filter', 'Filter', '')
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def getMaterial(materialName):
materialLibs = app.materialLibraries
material = None
for materialLib in materialLibs:
materials = materialLib.materials
try:
material = materials.itemByName(materialName)
except:
pass
if material:
break
return material
def getSelectedEntities(selectionInput):
entities = []
for x in range(0, selectionInput.selectionCount):
mySelection = selectionInput.selection(x)
selectedObj = mySelection.entity
if type(selectedObj) is adsk.fusion.BRepBody or type(selectedObj) is adsk.fusion.Component:
entities.append(selectedObj)
elif type(selectedObj) is adsk.fusion.Occurrence:
entities.append(selectedObj.component)
return entities
def applyMaterialToEntities(material, entities):
for entity in entities:
entity.material = material
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 getMaterialLibNames():
materialLibs = app.materialLibraries
libNames = []
for materialLib in materialLibs:
if materialLib.materials.count > 0:
libNames.append(materialLib.name)
return libNames
def getMaterialsFromLib(libName, filterExp):
global materialsMap
materialList = None
if libName in materialsMap:
materialList = materialsMap[libName]
else:
materialLib = app.materialLibraries.itemByName(libName)
materials = materialLib.materials
materialNames = []
for material in materials:
materialNames.append(material.name)
materialsMap[libName] = materialNames
materialList = materialNames
if filterExp and len(filterExp) > 0:
filteredList = []
for materialName in materialList:
if materialName.lower().find(filterExp.lower()) >= 0:
filteredList.append(materialName)
return filteredList
else:
return materialList
def run(context):
try:
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 = ApplyMaterialToSelectionCommandCreatedHandler()
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()))