Skip to content

load_model_usd

ModelUSDLoader

Bases: LoaderPlugin

Loading model with the USD loader.

Source code in client/ayon_max/plugins/load/load_model_usd.py
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
class ModelUSDLoader(load.LoaderPlugin):
    """Loading model with the USD loader."""

    product_base_types = {"model"}
    product_types = product_base_types
    label = "Load Model (USD)"
    representations = {"*"}
    extensions = {"usd", "usda", "usdc"}
    order = -10
    icon = "code-fork"
    color = "orange"

    def load(self, context, name=None, namespace=None, data=None):
        # asset_filepath
        plugin_info = get_plugins()
        if "usdimport.dli" not in plugin_info:
            raise LoadError("No USDImporter loaded/installed in Max..")
        filepath = os.path.normpath(self.filepath_from_context(context))
        import_options = rt.USDImporter.CreateOptions()
        base_filename = os.path.basename(filepath)
        _, ext = os.path.splitext(base_filename)
        log_filepath = filepath.replace(ext, "txt")

        rt.LogPath = log_filepath
        rt.LogLevel = rt.Name("info")
        rt.USDImporter.importFile(filepath,
                                  importOptions=import_options)
        folder_name = context["folder"]["name"]
        namespace = unique_namespace(
            name + "_",
            prefix=f"{folder_name}_",
            suffix="_",
        )
        # create "missing" container for obj import
        selections = rt.GetCurrentSelection()
        # get current selection
        for selection in selections:
            selection.name = f"{namespace}:{selection.name}"

        return containerise(
            name, selections, context,
            namespace, loader=self.__class__.__name__)

    def update(self, container, context):
        repre_entity = context["representation"]
        path = os.path.normpath(self.filepath_from_context(context))
        node_name = container["instance_node"]
        node = rt.GetNodeByName(node_name)
        namespace, name = get_namespace(node_name)
        node_list = get_previous_loaded_object(node)
        rt.Select(node_list)
        prev_objects = [sel for sel in rt.GetCurrentSelection()
                        if sel != rt.Container
                        and sel.name != node_name]
        transform_data = object_transform_set(prev_objects)
        for prev_obj in prev_objects:
            if rt.isValidNode(prev_obj):
                rt.Delete(prev_obj)

        import_options = rt.USDImporter.CreateOptions()
        base_filename = os.path.basename(path)
        _, ext = os.path.splitext(base_filename)
        log_filepath = path.replace(ext, "txt")

        rt.LogPath = log_filepath
        rt.LogLevel = rt.Name("info")
        rt.USDImporter.importFile(
            path, importOptions=import_options)

        # get current selection
        selections = rt.GetCurrentSelection()
        for selection in selections:
            selection.name = f"{namespace}:{selection.name}"
            selection_transform = f"{selection.name}.transform"
            if selection_transform in transform_data.keys():
                selection.pos = transform_data[selection_transform] or 0
                selection.rotation = transform_data[
                    f"{selection.name}.rotation"] or 0
                selection.scale = transform_data[
                    f"{selection.name}.scale"] or 0
        update_custom_attribute_data(node, selections)
        with maintained_selection():
            rt.Select(node)

        lib.imprint(container["instance_node"], {
            "representation": repre_entity["id"],
            "project_name": context["project"]["name"]
        })

    def switch(self, container, context):
        self.update(container, context)

    def remove(self, container):
        from pymxs import runtime as rt
        node = rt.GetNodeByName(container["instance_node"])
        remove_container_data(node)