ynput / ayon-unreal

Unreal Engine integration addon for AYON
Apache License 2.0
3 stars 2 forks source link

Import Static Mesh (Abc) - loosing Material Slots by parts (acting as single piece of geometry) #21

Closed moonyuet closed 4 weeks ago

moonyuet commented 1 month ago

Is there an existing issue for this?

Current Behavior:

Import Static Mesh (Abc) - loosing Material Slots by parts (acting as single piece of geometry) - not sure what happened but even asset consisting of multiple parts act as single shading entity/slot when trying assign material (works when FBX model repre loaded)

Expected Behavior:

The loaded assets from Import Static Mesh(Abc) should consist of shading entities if they have multiple parts.

Version

1.0.0

What platform you are running on?

Windows

Steps To Reproduce:

1, Publish Model product type in Maya

  1. Load Model in Unreal via Import Static Mesh(Abc)

Are there any labels you wish to add?

Relevant log output:

No response

Additional context:

No response

moonyuet commented 1 month ago

The related PR: https://github.com/ynput/ayon-core/pull/444 for loosing material slots

moonyuet commented 1 month ago

Some research here: https://www.reddit.com/r/Maya/comments/om2v70/script_to_create_face_sets_from_all_materials/

We need to make sure there are face sets created for the materials when we exported the objects from maya

We can make a validator to check on the face sets.

BigRoy commented 1 month ago

@moonyuet as you requested - here's a little script:

from collections import defaultdict
from typing import List

from maya import cmds

def create_face_sets_for_materials(shapes: List[str],
                                   suffix: str = "_FACE_SET"):
    """Create an objectSet for each face assignment of the given shapes.

    If multiple shapes share the same shader they are both added into the same
    object set.

    Arguments:
        shapes (List[str]): The shapes to add into face sets for any component
            assignments of shading engines.
        suffix (str): The suffix to add to the face set object sets to be
            created.

    Returns:
        List[str]: The created face sets (objectSet) with the faces as members.

    """
    shapes = cmds.ls(shapes, shapes=True, long=True)
    all_render_sets = set()
    for shape in shapes:
        render_sets = cmds.listSets(object=shape, t=1, extendToShape=False)
        if render_sets:
            all_render_sets.update(render_sets)

    # Maya has the tendency to return component members by their parent
    # transform like `pCube1.f[0]` instead of the shape `pCube1Shape.f[0]`
    # so we will also need to match against the transform
    def get_parent(shape):
        return cmds.listRelatives(shape, parent=True, fullPath=True)[0]

    shapes_component_prefix = [f"{shape}." for shape in shapes]
    shapes_component_prefix.extend(
        f"{get_parent(shape)}." for shape in shapes
    )
    shapes_component_prefix = tuple(
        shapes_component_prefix)  # to support .startswith

    shader_to_components = defaultdict(list)
    for shading_engine in cmds.ls(list(all_render_sets), type="shadingEngine"):
        members = cmds.sets(shading_engine, query=True)
        if not members:
            continue

        members = cmds.ls(members, long=True)
        for member in members:
            if member.startswith(shapes_component_prefix):
                # Found face assignment to one of the members
                shader_to_components[shading_engine].append(member)

    created_sets: List[str] = []
    for shading_engine, components in shader_to_components.items():
        created_set = cmds.sets(components, name=f"{shading_engine}{suffix}")
        created_sets.append(created_set)

# Example usage
for mesh in cmds.ls(type="mesh"):
    create_face_sets_for_materials(mesh)
LiborBatek commented 4 weeks ago

@moonyuet can be closed now, or?

moonyuet commented 4 weeks ago

@moonyuet can be closed now, or?

We can probably close this ticket.