【MAYA】 인스턴스 모든 머티리얼을 통일한다

12874 단어 파이썬maya
인스턴스마다 머티리얼이 다른 상태인 경우에 머티리얼을 하나로 통일하는 처리 코드를 작성해 보았습니다. (어쩌면 표준의 기능일지도 모르지만, 공부가 되기 때문에.)
예를 들어 스크립트 편집기에 붙여넣기 위한 것입니다. 선반에 등록하면 편하게 사용할 수 있다고 생각합니다. MAYA2018 + MacOS Sierra에서 작동 확인 중입니다.


이 그림에는 세 개의 큐브가 있으며 하나만 다른 재질이 설정되어 있습니다. 전회의 조사에서도 언급했듯이, 셰이프의 인스턴스 그룹으로부터 각 머티리얼(정확하게는 쉐이딩 그룹)의 DAG 세트 멤버에 어트리뷰트가 성장하고 있으므로, 여기를 연결해 바꾸면 좋을 것 같습니다. 구체적인 코드는 마지막으로.

사용법



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 로 커넥션을 만들었다.
  • 좋은 웹페이지 즐겨찾기