I'm hoping someone can help. I've attached the MILA script which is
responsibly for most of the UI for the MR layering library; what is
missing from the MILA Material Library is the ability to rename the
Layering Layers or even add notes to layers or groups of layers, I was
hoping someone could help so I can also understand more about Python ?
Christopher
--
You received this message because you are subscribed to the Google Groups "Python
Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/python_inside_maya/55F903EE.30207%40gmail.com.
For more options, visit https://groups.google.com/d/optout.
import re
from functools import partial
import maya.cmds as cmds
import maya.mel as mel
def get_connection_or_value(node_layer, attribute):
connection = cmds.connectionInfo('%s.%s' % (node_layer, attribute),
sourceFromDestination=True)
if connection:
return connection
else:
attr_value = cmds.getAttr('%s.%s' % (node_layer, attribute))
if type(attr_value) == list: # color (eg, tint) is returned in list of
tuple, [(r,g,b)]
attr_value = attr_value[0]
return attr_value
def get_connection(node_layer, attribute):
connections = cmds.listConnections('%s.%s' % (node_layer, attribute),
s=True, d=False)
if connections:
return connections[0]
else:
return ''
def disconnect_layer_attr(node_layer, attribute):
attr = '%s.%s' % (node_layer, attribute)
if cmds.objExists(attr):
connections = cmds.listConnections(attr, s=True, d=False)
if connections[0]:
cmds.disconnectAttr(connections[0], attr)
def set_connection_or_value(attr_value, node_layer, attribute):
attr = str('%s.%s' % (node_layer, attribute))
connection = cmds.connectionInfo(attr, sourceFromDestination=True)
if type(attr_value) in (str, unicode) and cmds.objExists(attr):
if connection:
cmds.connectAttr(attr_value, attr, f=True)
else:
cmds.connectAttr(attr_value, attr)
else:
if connection:
cmds.disconnectAttr(connection, attr)
attr_type = cmds.attributeQuery(attribute, node=node_layer,
attributeType=True)
if attr_type in ('double3', 'float3'): # value returned is a list of
one tuple, ie [(r,g,b)]
cmds.setAttr(attr, attr_value[0], attr_value[1], attr_value[2],
type='double3')
else:
cmds.setAttr(attr, attr_value)
def component_attr_index (component_attr):
match = re.search('.*\[([0-9]*)\]', component_attr)
if match:
return int(match.groups()[0])
class mix():
def __init__(self, node, component_attr):
self.node = node
self.attr = component_attr # indexed mix attr, eg component[0]
node_mix_component = '%s.%s' % (node, component_attr)
self.on = get_connection_or_value(node_mix_component, 'on')
self.background_color = [0.3,0.3,0.3]
self.shader = get_connection(node_mix_component, 'shader')
self.weight = get_connection_or_value(node_mix_component, 'weight')
self.weight_tint = get_connection_or_value(node_mix_component,
'weight_tint')
self.bump = get_connection_or_value(node_mix_component, 'bump')
def index(self):
return component_attr_index(self.attr)
def move_up(self, material_node, *args):
self.move(True)
if material_node:
refresh_material_layout(material_node)
def move_down(self, material_node, *args):
self.move(False)
if material_node:
refresh_material_layout(material_node)
def move(self, up):
node = self.node
attr = self.attr
mixes = collect_mixes(node)
current_mix = None
swap_mix = None
for i in range(len(mixes)):
if mixes[i].attr == self.attr:
current_mix = mixes[i]
if up:
swap_mix = mixes[i-1]
else:
swap_mix = mixes[i+1]
node_current_mix_attr = '%s.%s' % (node, current_mix.attr)
node_swap_mix_attr = '%s.%s' % (node, swap_mix.attr)
cmds.connectAttr ('%s.message' % swap_mix.shader, '%s.shader' %
node_current_mix_attr, f=True)
cmds.connectAttr ('%s.message' % current_mix.shader, '%s.shader' %
node_swap_mix_attr, f=True)
set_connection_or_value(swap_mix.on, node_current_mix_attr, 'on')
set_connection_or_value(current_mix.on, node_swap_mix_attr, 'on')
set_connection_or_value(swap_mix.weight, node_current_mix_attr,
'weight')
set_connection_or_value(current_mix.weight, node_swap_mix_attr,
'weight')
set_connection_or_value(swap_mix.weight_tint, node_current_mix_attr,
'weight_tint')
set_connection_or_value(current_mix.weight_tint, node_swap_mix_attr,
'weight_tint')
set_connection_or_value(swap_mix.bump, node_current_mix_attr, 'bump')
set_connection_or_value(current_mix.bump, node_swap_mix_attr, 'bump')
def __str__(self):
return ('Attr: %s\nEnabled: %s, Shader: %s, Weight: %s, WeightTint: %s'
% (self.attr, str(self.on), str(self.shader), str(self.weight),
str(self.weight_tint), str(self.bump)))
def collect_mixes(node):
mixes = []
component_attrs = cmds.listAttr(node, m=True, v=True, c=True,
st='components')
if component_attrs:
for component_attr in component_attrs:
component = mix(node, component_attr)
mixes.append(component)
return mixes
class layer():
def __init__(self, node, layer_attr):
self.node = node
self.attr = layer_attr # indexed layer id, eg layer[0]
node_layer = '%s.%s' % (node, layer_attr)
self.on = get_connection_or_value(node_layer, 'on')
self.background_color = [0.3,0.3,0.3]
self.shader = get_connection(node_layer, 'shader')
self.weight = get_connection_or_value(node_layer, 'weight')
self.weight_tint = get_connection_or_value(node_layer, 'weight_tint')
self.bump = get_connection_or_value(node_layer, 'bump')
self.use_directional_weight = get_connection_or_value(node_layer,
'use_directional_weight')
self.directional_weight_mode = get_connection_or_value(node_layer,
'directional_weight_mode')
self.ior = get_connection_or_value(node_layer, 'ior')
self.normal_reflectivity = get_connection_or_value(node_layer,
'normal_reflectivity')
self.grazing_reflectivity = get_connection_or_value(node_layer,
'grazing_reflectivity')
self.exponent = get_connection_or_value(node_layer, 'exponent')
def index(self):
return component_attr_index(self.attr)
def move_up(self, material_node, *args):
self.move(True)
if material_node:
refresh_material_layout(material_node)
def move_down(self, material_node, *args):
self.move(False)
if material_node:
refresh_material_layout(material_node)
def move(self, up):
node = self.node
attr = self.attr
layers = collect_layers(node)
current_layer = None
swap_layer = None
for i in range(len(layers)):
if layers[i].attr == self.attr:
current_layer = layers[i]
if up:
swap_layer = layers[i-1]
else:
swap_layer = layers[i+1]
node_current_layer_attr = '%s.%s' % (node, current_layer.attr)
node_swap_layer_attr = '%s.%s' % (node, swap_layer.attr)
cmds.connectAttr ('%s.message' % swap_layer.shader, '%s.shader' %
node_current_layer_attr, f=True)
cmds.connectAttr ('%s.message' % current_layer.shader, '%s.shader' %
node_swap_layer_attr, f=True)
set_connection_or_value(swap_layer.on, node_current_layer_attr, 'on')
set_connection_or_value(current_layer.on, node_swap_layer_attr, 'on')
set_connection_or_value(swap_layer.weight, node_current_layer_attr,
'weight')
set_connection_or_value(current_layer.weight, node_swap_layer_attr,
'weight')
set_connection_or_value(swap_layer.weight_tint,
node_current_layer_attr, 'weight_tint')
set_connection_or_value(current_layer.weight_tint,
node_swap_layer_attr, 'weight_tint')
set_connection_or_value(swap_layer.use_directional_weight,
node_current_layer_attr, 'use_directional_weight')
set_connection_or_value(current_layer.use_directional_weight,
node_swap_layer_attr, 'use_directional_weight')
set_connection_or_value(swap_layer.directional_weight_mode,
node_current_layer_attr, 'directional_weight_mode')
set_connection_or_value(current_layer.directional_weight_mode,
node_swap_layer_attr, 'directional_weight_mode')
set_connection_or_value(swap_layer.ior, node_current_layer_attr, 'ior')
set_connection_or_value(current_layer.ior, node_swap_layer_attr, 'ior')
set_connection_or_value(swap_layer.normal_reflectivity,
node_current_layer_attr, 'normal_reflectivity')
set_connection_or_value(current_layer.normal_reflectivity,
node_swap_layer_attr, 'normal_reflectivity')
set_connection_or_value(swap_layer.grazing_reflectivity,
node_current_layer_attr, 'grazing_reflectivity')
set_connection_or_value(current_layer.grazing_reflectivity,
node_swap_layer_attr, 'grazing_reflectivity')
set_connection_or_value(swap_layer.exponent, node_current_layer_attr,
'exponent')
set_connection_or_value(current_layer.exponent, node_swap_layer_attr,
'exponent')
set_connection_or_value(swap_layer.bump, node_current_layer_attr,
'bump')
set_connection_or_value(current_layer.bump, node_swap_layer_attr,
'bump')
def __str__(self):
return ('Attr: %s\nEnabled: %s, Shader: %s, Weight: %s, WeightTint: %s,
UseDirectionalWeight: %s, DirectionalWeightMode: %s, IOR: %s,
NormalReflectivity: %s, GrazingReflectivity: %s, Exponent: %s' % (self.attr,
str(self.on), str(self.shader), str(self.weight), str(self.weight_tint),
str(self.use_directional_weight), str(self.directional_weight_mode),
str(self.ior), str(self.normal_reflectivity), str(self.grazing_reflectivity),
str(self.exponent), str(self.bump)))
def collect_layers(node):
layers = []
component_attrs = cmds.listAttr(node, m=True, v=True, c=True, st='layers')
if component_attrs:
for layer_name in component_attrs:
component = layer(node, layer_name)
layers.append(component)
return layers
def create_base_layout(material_node):
cmds.columnLayout('AEmila_material_base', adj=True)
refresh_base_layout(material_node)
cmds.setParent('..')
base_component_labels = {'mila_diffuse_reflection':"Diffuse",
'mila_mix_subsurface_scatter':"Diffuse (Scatter)",
'mila_mix_reflective':"Reflective",
'mila_mix_reflective_aniso':"Reflective (Anisotropic)",
'mila_layer_reflective':"Reflective (Fresnel)",
'mila_layer_reflective_aniso':"Reflective (Anisotropic,
Fresnel)",
'mila_layer_reflective_plastic':"Reflective (Plastic)",
'mila_layer_reflective_paint':"Reflective (Paint)",
'mila_layer_transmissive':"Transmissive",
'mila_layer_transmissive_clear':"Transmissive (Clear)",
'mila_layer_transmissive_distance':"Transmissive
(Distance)",
'mila_mix_translucent':"Diffuse (Translucent)",
'mila_hair':"Hair",
'mila_skin':"Skin"}
def refresh_base_layout(material_node):
to_del = cmds.layout('AEmila_material_base', q=True, childArray=True)
if to_del:
for ui in to_del:
cmds.deleteUI(ui)
cmds.setParent('AEmila_material_base')
base_select_control=cmds.optionMenuGrp(l='Base Component',
changeCommand=partial(change_base_component, material_node))
cmds.menuItem(label="Diffuse")
cmds.menuItem(label="Diffuse (Scatter)")
cmds.menuItem(label="Diffuse (Translucent)")
cmds.menuItem(label="Reflective")
cmds.menuItem(label="Reflective (Anisotropic)")
cmds.menuItem(label="Reflective (Plastic)")
cmds.menuItem(label="Reflective (Paint)")
cmds.menuItem(label="Transmissive")
cmds.menuItem(label="Transmissive (Clear)")
cmds.menuItem(label="Transmissive (Distance)")
#ensure the current base component is indicated in the UI
components = collect_components(get_components_node(material_node,
create_when_empty=True))
base_component_node, parent_components =
get_base_component_node(components) #recurses through connection hierarchy
selected_type_label =
base_component_labels[cmds.nodeType(base_component_node)]
cmds.optionMenuGrp(base_select_control, edit=True,
value=selected_type_label)
refresh_component_layout(material_node, base_component_node,
collapsable=False)
def refresh_base_layout_after_change(material_node):
to_del = cmds.layout('AEmila_material_base', q=True, childArray=True)
base_select_control=to_del[0]
if to_del:
for ui in to_del:
if not (ui == base_select_control): # first ui
cmds.deleteUI(ui)
cmds.setParent('AEmila_material_base')
#ensure the current base component is indicated in the UI
components = collect_components(get_components_node(material_node,
create_when_empty=True))
base_component_node, parent_components =
get_base_component_node(components) #recurses through connection hierarchy
refresh_component_layout(material_node, base_component_node,
collapsable=False)
def get_base_component_node (components):
if len(components) >0:
last_component_node = get_connection('%s.%s' % (components[-1].node,
components[-1].attr), 'shader')
if last_component_node:
if cmds.nodeType(last_component_node) in ('mila_layer', 'mila_mix'):
components = collect_components(last_component_node)
last_component_node, components =
get_base_component_node(components)
return (last_component_node, components)
base_component_nodes = {"Diffuse":'mila_diffuse_reflection',
"Diffuse (Scatter)":'mila_mix_subsurface_scatter',
"Diffuse (Translucent)":'mila_mix_translucent',
"Reflective":'mila_mix_reflective',
"Reflective (Anisotropic)":'mila_mix_reflective_aniso',
"Reflective (Fresnel)":'mila_layer_reflective',
"Reflective (Anisotropic,
Fresnel)":'mila_layer_reflective_aniso',
"Reflective (Plastic)":'mila_layer_reflective_plastic',
"Reflective (Paint)":'mila_layer_reflective_paint',
"Transmissive":'mila_layer_transmissive',
"Transmissive (Clear)":'mila_layer_transmissive_clear',
"Transmissive
(Distance)":'mila_layer_transmissive_distance'
}
def change_base_component(material_node, value):
components_node = get_components_node(material_node,
create_when_empty=False)
if components_node:
components = collect_components(components_node)
current_base_component_node, parent_components =
get_base_component_node(components) #recurses through connection hierarchy
if current_base_component_node:
current_base_component_node_type =
cmds.nodeType(current_base_component_node)
new_node_type = base_component_nodes[value]
if (new_node_type and (new_node_type !=
current_base_component_node_type)):
cmds.disconnectAttr("%s.message" % current_base_component_node,
'%s.%s.shader' % (parent_components[-1].node, parent_components[-1].attr))
new_shader_node = cmds.createNode(new_node_type,
skipSelect=True) # skipSelect allows us to stay on this node
cmds.connectAttr ('%s.message' % new_shader_node,
'%s.%s.shader' % (parent_components[-1].node, parent_components[-1].attr))
current_color =
get_connection_or_value(current_base_component_node, 'tint')
set_connection_or_value(current_color, new_shader_node, 'tint')
update_material_swatch(material_node)
refresh_base_layout_after_change(material_node)
else:
print('MILA warning: no components')
def create_material_layout(material_node):
components_node = get_components_node(material_node, create_when_empty=True)
cmds.setUITemplate('attributeEditorTemplate', pushTemplate=True)
cmds.columnLayout(adj=True)
cmds.rowLayout(nc=3, cw3=[100, 100, 100], cat=[1, 'left', 20])
cmds.button('mila_create_new_mix', w=120, rs=False, label='+ Mix',
command=lambda *args: create_new_mix(components_node, material_node))
cmds.button('mila_create_new_layer', w=120, rs=False, label='+ Layer',
command=lambda *args: create_new_layer(components_node, material_node))
cmds.setParent('..')
cmds.setParent('..')
cmds.setUITemplate(popTemplate=True)
cmds.columnLayout('AEmila_material_components', adj=True)
refresh_material_layout(material_node)
cmds.setParent('..') # matching column layout for initial creation
def get_components_node(material_node, create_when_empty=True):
connection = cmds.connectionInfo('%s.shader' % material_node,
sourceFromDestination=True)
if ((not connection) and create_when_empty):
layer_node = cmds.createNode('mila_layer', skipSelect=True) #
skipSelect allows us to stay on this node
cmds.connectAttr ('%s.message' % (layer_node), '%s.shader' %
material_node)
shader_node = cmds.createNode('mila_diffuse_reflection',
skipSelect=True) # skipSelect allows us to stay on this node
cmds.connectAttr ('%s.message' % (shader_node), '%s.layers[0].shader' %
(layer_node))
connection = cmds.connectionInfo('%s.shader' % material_node,
sourceFromDestination=True)
cmds.setAttr('%s.tint' % shader_node, 0.7, 0.7, 0.7, type='double3')
return connection.split(".")[-2] # not the last which should be "message",
but the second to last layer or mix
def get_components_node_type(components_node):
return cmds.nodeType(components_node)
def components_node_is_layer(components_node):
return cmds.nodeType(components_node) == 'mila_layer'
def components_node_is_mix(components_node):
return cmds.nodeType(components_node) == 'mila_mix'
def collect_components(components_node):
components_node_type = cmds.nodeType(components_node)
components_info = []
if components_node_type == 'mila_layer':
components_info = collect_layers(components_node)
elif components_node_type == 'mila_mix':
components_info = collect_mixes(components_node)
else:
print('MILA warning: Unknown components type %s' % components_node_type)
return components_info
def refresh_material_layout(material_node):
components_node = get_components_node(material_node)
cmds.button('mila_create_new_mix', e=True,
en=len(collect_components(components_node)) > 1, command=lambda *args:
create_new_mix(components_node, material_node))
cmds.button('mila_create_new_layer', e=True, command=lambda *args:
create_new_layer(components_node, material_node))
to_del = cmds.layout('AEmila_material_components', q=True, childArray=True)
if to_del:
for ui in to_del:
cmds.deleteUI(ui)
refresh_components_layout(components_node, material_node,
hierarchy_level=0) #level 0 is top level
component_titles = {'mila_diffuse_reflection':"Diffuse Reflection",
'mila_glossy_reflection':"Glossy Reflection",
'mila_specular_reflection':"Specular Reflection",
'mila_diffuse_transmission':"Diffuse Transmission",
'mila_glossy_transmission':"Glossy Transmission",
'mila_specular_transmission':"Specular Transmission",
'mila_transparency':"Transparency",
'mila_scatter':"Scatter",
'mila_emission':"Emission",
'mila_mix_reflective':"Reflective",
'mila_mix_reflective_aniso':"Reflective (Anisotropic)",
'mila_layer_reflective':"Reflective (Fresnel)",
'mila_layer_reflective_aniso':"Reflective (Anisotropic,
Fresnel)",
'mila_layer_reflective_plastic':"Reflective (Plastic)",
'mila_layer_reflective_paint':"Reflective (Paint)",
'mila_layer_transmissive':"Transmissive",
'mila_layer_transmissive_clear':"Transmissive (Clear)",
'mila_layer_transmissive_distance':"Transmissive
(Distance)",
'mila_mix_translucent':"Translucent",
'mila_mix_glossy_reflection':"Glossy Reflection Mix",
'weighted_layer':"Weighted Layer",
'fresnel_layer':"Fresnel Layer",
'custom_layer':"Custom Layer",
'mila_mix':"Mix",
'mila_layer':"Layer"}
def get_component_title(component_node):
component_node_type = cmds.nodeType(component_node)
title = component_titles[component_node_type]
if title:
return title
else:
return component_node_type
level_colors = [[0.38, 0.38, 0.38],[0.32, 0.32, 0.32],[0.26, 0.26, 0.26],[0.20,
0.20, 0.20],[0.14, 0.14, 0.14]]
def change_bump(material_node, components_node_layer):
bump = cmds.getAttr('%s.bump' % components_node_layer)
if get_connection_or_value(components_node_layer, 'bump')[2]==1: # just
disconnected, defaulting to 0,0,1
cmds.setAttr('%s.bump' % components_node_layer, 0, 0, 0)
else:
update_material_swatch(material_node)
def refresh_components_layout(components_node, material_node,
hierarchy_level=0):
components_node_type = get_components_node_type(components_node)
components = collect_components(components_node)
base_component_node, parent_components =
get_base_component_node(collect_components(get_components_node(material_node)))
if components:
length_components_even = len(components) % 2 == 0
if hierarchy_level == 0:
cmds.setParent('AEmila_material_components')
label_title_prefix = "%s" % get_component_title(components_node)
label_title = ""
for component in components:
component.background_color = level_colors[hierarchy_level]
last_component = (component == components[-1]) # last (base)
component
base_component = base_component_node == component.shader
has_sub_components = (cmds.nodeType(component.shader) in
('mila_mix','mila_layer'))
if not base_component:
if has_sub_components:
label_title = "%s: %s Sub-Components" %
(label_title_prefix, get_component_title(component.shader))
else:
label_title = "%s: %s" % (label_title_prefix,
get_component_title(component.shader))
indent_margin = hierarchy_level * 40
layout = cmds.frameLayout(label='%s' % (label_title),
labelIndent=indent_margin, collapsable=True, collapse=0,
backgroundColor=component.background_color)
cmds.setUITemplate('attributeEditorTemplate', pushTemplate=True)
cmds.columnLayout(rowSpacing=1, adjustableColumn=True,
backgroundColor=component.background_color, columnOffset=['left',
indent_margin])
node_component_attr = '%s.%s' % (component.node, component.attr)
if not (last_component and has_sub_components):
cmds.rowLayout(nc=5, cw5=[30, 25, 25, 270,30], cat=[1,
'left', 5])
enabled = cmds.checkBox(l='',
cc=partial(update_material_swatch, material_node))
cmds.connectControl(enabled, '%s.on' % node_component_attr)
# move up not enabled for first component, nor last
up_enabled = not (component == components[0])
if last_component:
up_enabled = False
# move down not enabled for last component, nor for second
to last
down_enabled = not last_component
if (len(components) > 1) and (component == components[-2]):
down_enabled = False
cmds.symbolButton(image='arrowDown.png', vis=down_enabled,
c=partial(component.move_down, material_node))
cmds.symbolButton(image='arrowUp.png', vis=up_enabled,
c=partial(component.move_up, material_node))
cmds.attrFieldSliderGrp( l='Weight', min=0, max=1,
at='%s.weight' % node_component_attr, cw=[1,60], vis=(not last_component))
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.weight' % node_component_attr,
partial(update_material_swatch, material_node)] )
cmds.iconTextButton(style='iconOnly', h=25, mw=0, mh=0,
image='smallTrash.png', c=partial(delete_component, node_component_attr,
material_node), vis=(not last_component))
cmds.setParent('..') # row layout for top row of component
containing icons and weight slider
is_layer = components_node_is_layer(components_node)
directional_enable = is_layer and
cmds.getAttr('%s.use_directional_weight' % node_component_attr)
directional_mode = is_layer and
cmds.getAttr('%s.directional_weight_mode' % node_component_attr)
fresnel_enable = (directional_mode == 0) and directional_enable
if is_layer:
cmds.attrFieldSliderGrp( l='Fresnel IOR', min=1.0, smx=2.0,
at='%s.ior' % node_component_attr, vis=fresnel_enable)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.ior' % node_component_attr,
partial(update_material_swatch, material_node)] )
custom_enable = directional_mode == 1
cmds.attrFieldSliderGrp( l='Normal Reflectivity', min=0,
max=1, at='%s.normal_reflectivity' % node_component_attr,
en=cmds.getAttr('%s.directional_weight_mode' % node_component_attr)==1,
vis=custom_enable)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.normal_reflectivity' % node_component_attr,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Grazing Reflectivity', min=0,
max=1, at='%s.grazing_reflectivity' % node_component_attr,
en=cmds.getAttr('%s.directional_weight_mode' % node_component_attr)==1,
vis=custom_enable )
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.grazing_reflectivity' % node_component_attr,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Exponent', min=0.1, smx=20,
at='%s.exponent' % node_component_attr,
en=cmds.getAttr('%s.directional_weight_mode' % node_component_attr)==1,
vis=custom_enable)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.exponent' % node_component_attr,
partial(update_material_swatch, material_node)] )
cmds.attrNavigationControlGrp(label='Bump', attribute='%s.bump'
% node_component_attr,
disconnect='cmds.setAttr(%s.bump,
0, 0, 0)' % node_component_attr)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.bump'
% node_component_attr, partial(change_bump, material_node,
node_component_attr)] )
cmds.separator()
refresh_component_layout(material_node, component.shader,
hierarchy_level=hierarchy_level, background_color=component.background_color,
collapsable=(not last_component))
cmds.setParent('..') # matched with column layout for icons
and weight controls, ie layer/mix controls
cmds.setUITemplate(popTemplate=True)
cmds.setParent('..') # matched with frame layout for this
component
def refresh_component_layout(material_node, component_node, hierarchy_level=0,
background_color=[.267,.267,.267], collapsable=True):
component_node_type = cmds.nodeType(component_node)
has_sub_components = component_node_type in ('mila_mix', 'mila_layer')
margin = hierarchy_level * 40
if has_sub_components:
components_node = component_node
refresh_components_layout(components_node, material_node,
hierarchy_level=hierarchy_level+1)
elif component_node_type == 'mila_transparency':
cmds.attrColorSliderGrp(l='Transparency Color', at='%s.transparency' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.transparency'
% component_node, partial(update_material_swatch, material_node)] )
elif component_node_type == 'mila_scatter':
scatter_layout(component_node, material_node, background_color)
else:
cmds.attrColorSliderGrp( l='Color', at='%s.tint' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.tint' %
component_node, partial(update_material_swatch, material_node)] )
if component_node_type in ('mila_diffuse_reflection',
'mila_glossy_reflection', 'mila_glossy_transmission',
'mila_mix_subsurface_scatter', 'mila_mix_translucent'):
cmds.attrFieldSliderGrp( l='Roughness', min=0, max=1,
at='%s.roughness' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.roughness'
% component_node, partial(update_material_swatch, material_node)] )
if component_node_type == 'mila_mix_glossy_reflection':
cmds.attrFieldSliderGrp( l='Roughness 1', min=0, max=1,
at='%s.roughness1' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.roughness1' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Weight 1', min=0, max=1,
at='%s.weight1' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.weight1' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Roughness 2', min=0, max=1,
at='%s.roughness2' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.roughness2' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Weight 2', min=0, max=1,
at='%s.weight2' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.weight2' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Roughness 3', min=0, max=1,
at='%s.roughness3' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.roughness3' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Weight 3', min=0, max=1,
at='%s.weight3' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.weight3' %
component_node, partial(update_material_swatch, material_node)] )
if component_node_type in ('mila_mix_subsurface_scatter',
'mila_mix_translucent'):
cmds.attrFieldSliderGrp( l='Diffuse Weight', min=0, max=1,
at='%s.diffuse_weight' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.diffuse_weight' % component_node,
partial(update_material_swatch, material_node)] )
if component_node_type == 'mila_mix_subsurface_scatter':
diffuse_scatter_layout(component_node, material_node,
background_color)
if component_node_type in ('mila_glossy_transmission',
'mila_specular_transmission'):
cmds.attrFieldSliderGrp( l='IOR', min=1, smx=2, fmx=10, at='%s.ior'
% component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.ior' %
component_node, partial(update_material_swatch, material_node)] )
if component_node_type in ('mila_mix_reflective',
'mila_mix_reflective_aniso', 'mila_layer_reflective',
'mila_layer_reflective_plastic'):
cmds.attrFieldSliderGrp( l='Glossy Blend', min=0, max=1,
at='%s.glossy_weight' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.glossy_weight' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Glossy Roughness', min=0, max=1,
at='%s.glossy_roughness' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.glossy_roughness' % component_node,
partial(update_material_swatch, material_node)] )
if component_node_type in ('mila_mix_reflective_aniso',
'mila_layer_reflective_aniso'):
anisotropy_layout(component_node, material_node,
background_color)
cmds.attrFieldSliderGrp( l='Diffuse Roughness', min=0, max=1,
at='%s.diffuse_roughness' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.diffuse_roughness' % component_node,
partial(update_material_swatch, material_node)] )
if component_node_type in ('mila_layer_reflective',
'mila_layer_reflective_plastic'):
cmds.attrFieldSliderGrp( l='Fresnel IOR', min=1, smx=2, fmx=10,
at='%s.ior' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.ior' %
component_node, partial(update_material_swatch, material_node)] )
if component_node_type == 'mila_layer_reflective_paint':
cmds.attrFieldSliderGrp( l='Edge Weight', min=0, max=1,
at='%s.edge_weight' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.edge_weight' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrColorSliderGrp( l='Edge Color', at='%s.edge_color' %
component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.edge_color' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Edge Color Bias', min=1, smx=2, fmx=10,
at='%s.edge_color_bias' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.edge_color_bias' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Glossy Blend', min=0, max=1,
at='%s.glossy_weight' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.glossy_weight' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrColorSliderGrp( l='Glossy Color', at='%s.glossy_color' %
component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.glossy_color' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Glossy Roughness', min=0, max=1,
at='%s.glossy_roughness' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.glossy_roughness' % component_node,
partial(update_material_swatch, material_node)] )
flakes_layout(component_node, material_node, background_color)
if component_node_type in
('mila_layer_transmissive','mila_layer_transmissive_clear','mila_layer_transmissive_distance'):
if (component_node_type == 'mila_layer_transmissive_distance'):
cmds.attrFieldSliderGrp( l='At Distance', min=0, smx=10,
at='%s.max_dist' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.max_dist' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Reflective Weight', min=0, max=1,
at='%s.reflective_weight' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.reflective_weight' % component_node,
partial(update_material_swatch, material_node)] )
if component_node_type in
('mila_layer_transmissive','mila_layer_transmissive_distance'):
cmds.attrFieldSliderGrp( l='Roughness', min=0, max=1,
at='%s.roughness' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.roughness' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='IOR', min=1, smx=2, fmx=10, at='%s.ior'
% component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.ior' %
component_node, partial(update_material_swatch, material_node)] )
if (component_node_type == 'mila_layer_transmissive'):
anisotropy_layout(component_node, material_node,
background_color)
if (component_node_type == 'mila_emission'):
cmds.attrFieldSliderGrp( l='Intensity', min=0, smx=20,
at='%s.intensity' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.intensity'
% component_node, partial(update_material_swatch, material_node)] )
else:
contribution_layout(component_node, material_node, background_color)
def scatter_layout(component_node, material_node, background_color):
cmds.attrColorSliderGrp( l='Front Tint', at='%s.front_tint' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.front_tint' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Front Weight', min=0, max=1,
at='%s.front_weight' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.front_weight' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldGrp(label='Front Radius', at='%s.front_radius' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.front_radius' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrColorSliderGrp( l='Front Radius Mod', at='%s.front_radius_mod' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.front_radius_mod'
% component_node, partial(update_material_swatch, material_node)] )
cmds.separator()
cmds.attrColorSliderGrp( l='Back Tint', at='%s.back_tint' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.back_tint' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Back Weight', min=0, max=1, at='%s.back_weight'
% component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.back_weight' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldGrp(label='Back Radius', at='%s.back_radius' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.back_radius' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrColorSliderGrp( l='Back Radius Mod', at='%s.back_radius_mod' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.back_radius_mod' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Back Depth', min=0, smx=10, ann='Back depth
distance scale, if 0, uses radius',
at='%s.back_depth' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.back_depth' %
component_node, partial(update_material_swatch, material_node)] )
cmds.separator()
cmds.attrFieldSliderGrp( l='Scale Conversion', min=0, smx=10,
at='%s.scale_conversion' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.scale_conversion'
% component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Sampling Radius Factor', min=0, smx=10,
at='%s.sampling_radius_mult' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.sampling_radius_mult' % component_node,
partial(update_material_swatch, material_node)] )
cmds.attrEnumOptionMenuGrp(l='Resolution',
at='%s.resolution' % component_node,
ei = [(0, "2 x Image"),
(1, "1 x Image"),
(2, "1/2 x Image"),
(3, "1/3 x Image"),
(4, "1/4 x Image"),
(5, "1/5 x Image")])
cmds.attrFieldSliderGrp( l='Light Storage Gamma', min=0, smx=2,
at='%s.light_storage_gamma' % component_node)
cmds.scriptJob( killWithScene=True,
attributeChange=['%s.light_storage_gamma' % component_node,
partial(update_material_swatch, material_node)] )
def diffuse_scatter_layout(component_node, material_node, background_color):
cmds.separator()
cmds.attrColorSliderGrp( l='Front Scatter Color', at='%s.front_color' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.front_color' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Front Weight', min=0, max=1,
at='%s.front_weight' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.front_weight' %
component_node, partial(update_material_swatch, material_node)] )
cmds.separator()
cmds.attrColorSliderGrp( l='Back Scatter Color', at='%s.back_color' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.back_color' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Back Weight', min=0, max=1, at='%s.back_weight'
% component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.back_weight' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Back Scatter Depth', min=0, smx=10, ann='Back
depth distance scale, if 0, uses radius',
at='%s.back_depth' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.back_depth' %
component_node, partial(update_material_swatch, material_node)] )
cmds.separator()
cmds.attrFieldSliderGrp( l='Scale Conversion', min=0, smx=10,
at='%s.scale_conversion' % component_node,
ann='Divide scatter distance of 20 units by this
conversion factor; higher values scatter less')
cmds.scriptJob( killWithScene=True, attributeChange=['%s.scale_conversion'
% component_node, partial(update_material_swatch, material_node)] )
flake_types = {"Distortion 1":0,
"Distortion 2":1,
"Distortion 3":2,
"Cellular 1":3,
"Cellular 2":4,
"Cellular 3":5}
def change_flake_type(material_node, paint_node, value):
set_connection_or_value(flake_types[value], paint_node, 'flake_type')
cell_enable = flake_types[value] > 2
cmds.optionMenuGrp("AEmila_flake_cell_style", e=True, en=cell_enable)
circle_size_enable = cell_enable and (cmds.getAttr('%s.flake_cell_style' %
paint_node) == 1)
cmds.attrFieldSliderGrp("AEmila_flake_circle_size", e=True,
en=circle_size_enable)
update_material_swatch(material_node)
cell_styles = {"Edgy":0,
"Circular":1}
def change_cell_style(material_node, paint_node, value):
set_connection_or_value(cell_styles[value], paint_node, 'flake_cell_style')
circle_size_enable = cell_styles[value] == 1
cmds.attrFieldSliderGrp("AEmila_flake_circle_size", e=True,
en=circle_size_enable)
update_material_swatch(material_node)
def flakes_layout(component_node, material_node, background_color):
cmds.frameLayout(collapsable=True, collapse=True, label="Flakes",
labelIndent=80, font="tinyBoldLabelFont", backgroundColor=background_color)
cmds.columnLayout(rowSpacing=1, adjustableColumn=True,
backgroundColor=background_color)
cmds.attrFieldSliderGrp( l='Flake Weight', min=0, max=1,
at='%s.flake_weight' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.flake_weight' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrColorSliderGrp( l='Flake Color', at='%s.flake_color' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.flake_color' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Flake Roughness', min=0, max=1,
at='%s.flake_roughness' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.flake_roughness' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Flake Scale', min=0, smx=2, fmx=10,
at='%s.flake_scale' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.flake_scale' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Flake Strength', min=0, smx=1,
at='%s.flake_strength' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.flake_strength' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Flake Density', min=0, smx=2,
at='%s.flake_density' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.flake_density' %
component_node, partial(update_material_swatch, material_node)] )
cmds.optionMenuGrp("AEmila_flake_type", l='Flake Type')
cmds.menuItem("Distortion 1")
cmds.menuItem("Distortion 2")
cmds.menuItem("Distortion 3")
cmds.menuItem("Cellular 1")
cmds.menuItem("Cellular 2")
cmds.menuItem("Cellular 3")
cmds.optionMenuGrp("AEmila_flake_type", e=True,
select=cmds.getAttr("%s.flake_type"%component_node)+1,
cc=partial(change_flake_type, material_node,
component_node))
cell_enable = cmds.getAttr('%s.flake_type' % component_node) > 2
cmds.optionMenuGrp("AEmila_flake_cell_style", l='Cell Style',
en=cell_enable)
cmds.menuItem("Edgy")
cmds.menuItem("Circular")
flake_cell_style = cmds.getAttr('%s.flake_cell_style' % component_node)
cmds.optionMenuGrp("AEmila_flake_cell_style", e=True, select =
flake_cell_style + 1,
cc=partial(change_cell_style, material_node,
component_node))
circle_size_enable = cell_enable and (flake_cell_style == 1)
cmds.attrFieldSliderGrp("AEmila_flake_circle_size",
l='Circle Size', min=0, smx=2, fmx=10,
at='%s.flake_circle_size' % component_node,
en=circle_size_enable )
cmds.scriptJob( killWithScene=True, attributeChange=['%s.flake_circle_size'
% component_node, partial(update_material_swatch, material_node)] )
cmds.setParent('..') # matched with column layout
cmds.setParent('..') # matched with Flakes frame layout
def anisotropy_layout(component_node, material_node, background_color):
cmds.frameLayout(collapsable=True, collapse=True, label="Anisotropy",
labelIndent=80, font="tinyBoldLabelFont", backgroundColor=background_color)
cmds.columnLayout(rowSpacing=1, adjustableColumn=True,
backgroundColor=background_color)
cmds.attrFieldSliderGrp( l='Anisotropy', min=0.1, smx=10,
at='%s.anisotropy' % component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.anisotropy' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Angle', smn=0, smx=1, at='%s.aniso_angle' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.aniso_angle' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrEnumOptionMenuGrp(l='Channel',
at='%s.aniso_channel' % component_node,
ei = [(-1, "World Point"),
(0, "Texture space 0"),
(1, "Texture space 1"),
(2, "Texture space 2"),
(3, "Texture space 3"),
(4, "Texture space 4"),
(5, "Texture space 5")])
cmds.scriptJob( killWithScene=True, attributeChange=['%s.aniso_channel' %
component_node, partial(update_material_swatch, material_node)] )
cmds.setParent('..') # matched with column layout
cmds.setParent('..') # matched with Anisotropy frame layout
def contribution_layout(component_node, material_node, background_color):
cmds.frameLayout(collapsable=True, collapse=True, label="Contribution",
labelIndent=80, font="tinyBoldLabelFont", backgroundColor=background_color)
cmds.columnLayout(rowSpacing=1, adjustableColumn=True,
backgroundColor=background_color)
cmds.attrFieldSliderGrp( l='Direct', min=0, smx=1, at='%s.direct' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.direct' %
component_node, partial(update_material_swatch, material_node)] )
cmds.attrFieldSliderGrp( l='Indirect', min=0, smx=1, at='%s.indirect' %
component_node)
cmds.scriptJob( killWithScene=True, attributeChange=['%s.indirect' %
component_node, partial(update_material_swatch, material_node)] )
cmds.setParent('..') # matched with column layout
cmds.setParent('..') # matched with Contribution frame layout
def choose_form_layout(components, title_label="Choose"):
form = cmds.setParent(q=True)
cmds.formLayout(form, e=True, width=210) #hardcode width, cause not
resizable
title = cmds.text(l=title_label)
buttons = []
for component in components:
if component in component_titles.keys():
component_title = component_titles[component]
button = cmds.button(component, label=component_title, width=200,
command='import maya.cmds\nmaya.cmds.layoutDialog(dismiss="' + component + '")'
)
buttons.append(button)
elif component == 'separator':
buttons.append(cmds.separator(st='in'))
else:
buttons.append(cmds.text(label=component))
cancel = cmds.button(l='Cancel', c='import
maya.cmds\ncmds.layoutDialog(dismiss="Cancel")')
spacer = 4
top = 8
edge = 5
attach_form_arg = [(title, 'top', top), (title, 'left', edge), (title,
'right', edge), (cancel, 'bottom', edge)]
attach_none_arg = [(title, 'bottom')]
attach_control_arg = []
i = 0
for button in buttons:
if i == 0:
above_button = title
spacer = 10
else:
above_button = buttons[i-1]
spacer = 4
attach_form_arg.append((button, 'left', edge))
attach_form_arg.append((button, 'right', edge))
attach_none_arg.append((button, 'bottom'))
attach_control_arg.append((button, 'top', spacer, above_button))
i += 1
attach_form_arg.append((cancel, 'left', 65))
attach_form_arg.append((cancel, 'right', 65))
attach_control_arg.append((cancel, 'top', 12, buttons[-1]))
cmds.formLayout(form, edit=True,
attachForm=attach_form_arg,
attachNone=attach_none_arg,
attachControl=attach_control_arg)
def elemental_component_form():
choose_form_layout(['separator',
'Reflection',
'mila_specular_reflection',
'mila_glossy_reflection',
'mila_mix_glossy_reflection',
'mila_diffuse_reflection',
'separator',
'Transmission',
'mila_specular_transmission',
'mila_glossy_transmission',
'mila_diffuse_transmission',
'separator',
'mila_transparency',
'separator',
'Subsurface Scattering',
'mila_scatter',
'separator',
'Emission',
'mila_emission'],
title_label="Choose elemental component")
def choose_elemental_component():
component = cmds.layoutDialog(ui=elemental_component_form)
if component in ('Cancel','dismiss'):
return 'None'
else:
return component
def layer_type_form():
choose_form_layout(['weighted_layer','fresnel_layer','custom_layer'],title_label="Choose
layer type")
def choose_layer_type():
layer_type = cmds.layoutDialog(ui=layer_type_form)
if layer_type in ('Cancel','dismiss'):
return 'None'
else:
return layer_type
def create_new_layer(node, material_node):
index = 0
component_attrs = []
if components_node_is_mix(node):
component_attrs = cmds.listAttr(node, m=True, v=True, c=True,
st='components')
if len(component_attrs) > 1:
bottom_component = node
elif len(component_attrs) == 0:
print ("MILA Error: expected mila_mix with 1 layer, got %i instead"
% len(component_attrs))
else:
print ("MILA: Adding layer, single mix component, so replace mix
with layer")
bottom_component = collect_mixes(node)[0].shader
layer_node = cmds.createNode('mila_layer', skipSelect=True)
cmds.connectAttr ('%s.message' % bottom_component,
'%s.layers[0].shader' % layer_node, f=True)
cmds.connectAttr ('%s.message' % layer_node, '%s.shader' %
material_node, f=True)
node = layer_node # was mix node
component_attrs = cmds.listAttr(node, m=True, v=True, c=True, st='layers')
if component_attrs:
index = component_attr_index(component_attrs[-1])
index += 1
layer_type = choose_layer_type()
if (layer_type != 'None'):
shader_name = choose_elemental_component()
if (shader_name != 'None'):
shader_node = cmds.createNode(shader_name, skipSelect=True) #
skipSelect allows us to stay on this node
cmds.connectAttr ('%s.message' % (shader_node),
'%s.layers[%i].shader' % (node, index))
if layer_type in ('fresnel_layer', 'custom_layer'):
cmds.setAttr('%s.layers[%i].use_directional_weight' % (node,
index), 1)
if (layer_type == 'custom_layer'):
cmds.setAttr('%s.layers[%i].directional_weight_mode' %
(node, index), 1)
layers = collect_layers(node)
if (len(layers) == index+1):
while (index > 0):
layers = collect_layers(node)
layers[index].move_up(material_node)
index -= 1
refresh_material_layout(material_node)
update_material_swatch(material_node)
def mix_over_layers_form():
choose_form_layout(['Mix into top layer','Mix with all layers'],
title_label="Choose mix placement")
def mix_with_components_form():
choose_form_layout(['Mix with all components','Mix'], title_label="Choose
mix type")
def choose_mix_component_type():
mix_type = cmds.layoutDialog(ui=mix_over_layers_form)
if mix_type in ('Cancel','dismiss'):
return 'None'
else:
return mix_type
def create_new_mix(node, material_node):
index = 0
component_attrs = []
shader_name = choose_elemental_component()
if (shader_name == 'None'):
return
node_is_layer = components_node_is_layer(node)
if node_is_layer:
mix_into_top_layer = False
create_new_mix_node = True
component_attrs = cmds.listAttr(node, m=True, v=True, c=True,
st='layers')
if len(component_attrs) > 1:
mix_into_top_layer = True
if mix_into_top_layer:
bottom_component = collect_layers(node)[0].shader
if components_node_is_mix(bottom_component):
create_new_mix_node = False
print ("MILA: Adding mix to top layer %s" % bottom_component)
else:
bottom_component = node # mix with current mila_layer as
bottom(base)component
else:
print ("MILA: Adding mix, single layer component, so replace layer
with mix")
bottom_component = collect_layers(node)[0].shader
if components_node_is_mix(bottom_component):
create_new_mix_node = False
if create_new_mix_node:
mix_node = cmds.createNode('mila_mix', skipSelect=True)
cmds.connectAttr ('%s.message' % bottom_component,
'%s.components[0].shader' % mix_node, f=True)
cmds.setAttr('%s.clamp' % (mix_node), 1)
if mix_into_top_layer:
cmds.connectAttr ('%s.message' % mix_node,
'%s.layers[0].shader' % node, f=True)
else: # mix into material
cmds.connectAttr ('%s.message' % mix_node, '%s.shader' %
material_node, f=True)
node = mix_node # node was layer node
else:
node = bottom_component # an existing mix node
# node ensured to be a mix node, ready for adding a top mix component over
one or more others
component_attrs = cmds.listAttr(node, m=True, v=True, c=True,
st='components')
if component_attrs:
index = component_attr_index(component_attrs[-1])
index += 1
shader_node = cmds.createNode(shader_name, skipSelect=True) #
skipSelect allows us to stay on this node
cmds.connectAttr ('%s.message' % (shader_node),
'%s.components[%i].shader' % (node, index))
mixes = collect_mixes(node)
# move new last component to component 0 slot by moving it up, index
from high to low
if (len(mixes) == index+1):
while (index > 0):
mixes = collect_mixes(node)
mixes[index].move_up(material_node)
index -= 1
cmds.setAttr('%s.components[0].weight' % (node), 0.5)
refresh_material_layout(material_node)
update_material_swatch(material_node)
def check_component_indices(components):
i = 0
for component in components:
if (i != component.index()):
return False
i += 1
return True
def delete_component(attr, material_node, *args):
print('MILA: Deleting %s' % attr)
index = component_attr_index(attr)
node = attr.partition('.')[0]
if node:
components = collect_components(node)
if check_component_indices(components):
i = 0
while (i < len(components)-1): # moving layer-to-delete to bottom,
last move is second-to-last layer
if (i == index):
components[index].move_down(None) # None is no
material_node, so refresh doesn't happen til end
index += 1
i += 1
components = collect_components(node)
if (components[-1].index() == (len(components) - 1)): # check that
last layer is correctly numbered
node_layers_attr='%s.%s' % (components[-1].node,
components[-1].attr)
cmds.removeMultiInstance('%s' % node_layers_attr, b=True)
for job in cmds.scriptJob(listJobs=True):
if node_layers_attr in job:
cmds.scriptJob(kill=int(job.partition(':')[0]))
remaining_node = components[-2].shader
if ((len(components) == 2) and (node ==
get_components_node(material_node))):
if cmds.nodeType(remaining_node) in ('mila_mix', 'mila_layer'):
cmds.connectAttr ('%s.message' % (remaining_node),
'%s.shader' % (material_node), f=True)
refresh_material_layout(material_node)
update_material_swatch(material_node)
def update_material_swatch(material_node, *args):
fb = cmds.getAttr('%s.show_framebuffer' % material_node)
cmds.setAttr('%s.show_framebuffer' % material_node, fb)
# Copyright (C) 1997-2014 Autodesk, Inc., and/or its licensors.
# All rights reserved.
#
# The coded instructions, statements, computer programs, and/or related
# material (collectively the "Data") in these files contain unpublished
# information proprietary to Autodesk, Inc. ("Autodesk") and/or its licensors,
# which is protected by U.S. and Canadian federal copyright law and by
# international treaties.
#
# The Data is provided for use exclusively by You. You have the right to use,
# modify, and incorporate this Data into other products for purposes authorized
# by the Autodesk software license agreement, without fee.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. AUTODESK
# DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTIES
# INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF NON-INFRINGEMENT,
# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ARISING FROM A COURSE
# OF DEALING, USAGE, OR TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS
# LICENSORS BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL,
# DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK AND/OR ITS
# LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY OR PROBABILITY OF SUCH DAMAGES.