Maya에서 Three.js 3D Asset Viewer를 위한 UDIM으로 제작된 Asset의 쉐이더 편하게 복제하기



Maya에서 Three.js 3D Asset viewer를 위한 UDIM으로 제작된 asset의 쉐이더 편하게 복제하는 Python 코드

현재 Three.js에서는 UDIM 방식을 공식적으로 지원하지 않기 때문에, 각각의 쉐이더를 UDIM에서 사용한 개수만큼 복제하여 해당 UV 좌표의 UV에 assign하고, UV들을 모두 1001의 좌표로 이동시켜 사용해야 합니다. 이를 자동화하기 위해 Hypershade의 duplicate shading network 기능을 사용하면 쉐이더의 rename은 자동으로 되지만, 쉐이더에 연결된 파일 노드의 이름이나 연결된 파일의 이름은 자동으로 +1이 되지 않습니다. 따라서, 이를 자동화하는 코드를 작성해보겠습니다.

import maya.cmds as cmds
import re

def duplicate_and_update_shader():
    # 현재 선택된 쉐이더 가져오기
    selected_shaders = cmds.ls(sl=True, materials=True)
    
    # 선택된 각 쉐이더에 대해 처리
    for shader in selected_shaders:
        shader_type = cmds.nodeType(shader)
        # 지원되는 쉐이더 타입인지 확인
        if shader_type not in ["VRayMtl", "aiStandardSurface", "standardSurface"]:
            print(f"Unsupported shader type: {shader_type} for shader: {shader}")
            continue
        
        # 쉐이더 복제 (쉐이딩 네트워크 포함)
        duplicated_shader = cmds.duplicate(shader, un=True, rc=True)[0]
        
        # 복제된 쉐이더와 연결된 파일 노드들 처리
        file_nodes = cmds.listConnections(duplicated_shader, type="file")
        if not file_nodes:
            print(f"No file nodes connected to shader: {duplicated_shader}")
            continue
        
        for file_node in file_nodes:
            current_file_path = cmds.getAttr(f"{file_node}.fileTextureName")
            # 파일 경로 내의 숫자를 찾아 1 증가
            new_file_path = re.sub(r'(\d+)(?=\D*$)', lambda match: str(int(match.group(0)) + 1).zfill(len(match.group(0))), current_file_path)
            
            if new_file_path != current_file_path:
                cmds.setAttr(f"{file_node}.fileTextureName", new_file_path, type="string")
                print(f"File path updated from {current_file_path} to {new_file_path} for {file_node}")
            else:
                print(f"No numeric suffix to update in file path for {file_node}")
        
        # 복제된 쉐이더의 이름 업데이트 (필요시)
        shader_base_name = re.sub(r'(\d+)(?=\D*$)', '', shader)  # 숫자 제거
        new_shader_number = re.search(r'(\d+)(?=\D*$)', duplicated_shader).group(0)
        new_shader_name = f"{shader_base_name}{new_shader_number}"
        cmds.rename(duplicated_shader, new_shader_name)
        print(f"Shader duplicated and renamed to: {new_shader_name}")

# 실행
duplicate_and_update_shader()