インスタンスごとにマテリアルが異なっている状態の場合に、マテリアルを一つに統一する処理コードを書いてみました。(ひょっとすると標準の機能であるのかもしれませんが、勉強にはなるので。)
例によってスクリプトエディタにペーストする用です。シェルフに登録すると楽に使えると思います。MAYA2018 + MacOS Sierraで動作確認しています。

使い方
1.ノードを選択状態にします。対象としてはインスタンスメッシュそのもの、またはその親トランスフォームとなります。
2.Scriptを実行します。
3.親兄弟インスタンスノードがあれば全て同じマテリアル設定になります。選択すべきものがなければエラーメッセージが表示されます。




何らかのエラーでマテリアルが外れてしまっているパターンにも対応しています。
対応していないパターン
- マテリアルのフェイスアサインには対応していません。(次課題)
- 一部にマテリアルを反映しないような操作はできません。(すぐ作れそうだが)
クイック実行用コード
import pymel.core as pm
def get_instance_siblings(node):
"""
関連インスタンス全てを得る
:param node: 探索元インスタンスノード参照
:type node: pymel.nodetypes.DagNode
:param exclude_first_instance: 親インスタンスを除くか
:type exclude_first_instance: bool
:return: 見つかったノードとその関連ノードとエラー情報ストリング
:rtype: tuple of DagNode and (list of DagNode) and str
"""
is_instanced = node.isInstanced()
if not is_instanced:
# 選択がインスタンスでない場合は子供を探す
children = pm.listRelatives(node)
node = None
for child_node in children:
if child_node.isInstanced():
node = child_node
break
if node is None:
return None, '対象インスタンスが見つかりません。'
instances = node.getOtherInstances()
if len(instances) == 0:
return node, [], '兄弟インスタンスが存在しません。'
return node, instances, None
def sync_instance_material():
"""
選択したインスタンスのマテリアルに他のインスタンス全てを合わせる
"""
selected = pm.selected()
if len(selected) == 0:
pm.confirmDialog(title='Info', message='ノードを選択して下さい。', button=['Ok'])
return
node = selected[0]
base_node, sibling_nodes, error_info = get_instance_siblings(node)
if error_info is not None:
pm.confirmDialog(title='Info', message=error_info, button=['Ok'])
return
# 選択したノードのインスタンス番号を得る
base_ins_index = base_node.instanceNumber()
# そのノードに設定されているマテリアルを得る( 例)phong1SG
cons = pm.listConnections(base_node.instObjGroups[base_ins_index], plugs=False)
if len(cons) == 0:
# マテリアルが外れてる場合を考慮
base_ins_mat = None
target_dist_attr = None
else:
base_ins_mat = cons[0]
target_dist_attr = base_ins_mat.dagSetMembers
for sibling_node in sibling_nodes:
# 兄弟インスタンスのインスタンス番号を得る
sibling_ins_index = sibling_node.instanceNumber()
# マテリアルへの接続元アトリビュートを得る
src_attr = sibling_node.instObjGroups[sibling_ins_index]
# 兄弟インスタンスのマテリアルを得る( 例)phong2SG
cons = pm.listConnections(src_attr, plugs=False)
if len(cons) == 0:
# マテリアルが外れてる場合を考慮
sibling_ins_mat = None
else:
sibling_ins_mat = cons[0]
# 現在のマテリアルが選択ノードのマテリアルと異なる場合に処理実行
if base_ins_mat != sibling_ins_mat:
# 現在の接続先アトリビュートを切断 ( 一度切断しないとエラーになった(connectAttrがforce=Trueであっても))
cons = pm.listConnections(src_attr, plugs=True)
if len(cons) > 0:
# マテリアルが外れてる場合を考慮
current_dist_attr = cons[0]
pm.disconnectAttr(src_attr, current_dist_attr)
# 新しい接続先に変更
if target_dist_attr is not None:
# pm.setsでは失敗したのでconnectAttrで実直につなぐ
pm.connectAttr(src_attr, target_dist_attr, force=True, nextAvailable=True)
sync_instance_material()
del sync_instance_material
del get_instance_siblings
雑メモ・ポイント
- 新しいマテリアルとのコネクション作成の際、
connectAttr
前に一度disconnectAttr
しないとエラーになった。 -
connectAttr
時にnextAvailable
フラグを使うと次のインデックス番号を考慮しなくていいので便利だ。 -
pm.sets
ではそのインデックス番号がらみのエラーになったのでconnectAttr
でコネクションを作った。