Skip to content

load_pointcache

Simple alembic loader for 3dsmax.

Because of limited api, alembics can be only loaded, but not easily updated.

AbcLoader

Bases: LoaderPlugin

Alembic loader.

Source code in client/ayon_max/plugins/load/load_pointcache.py
 18
 19
 20
 21
 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
class AbcLoader(load.LoaderPlugin):
    """Alembic loader."""

    product_types = {"camera", "animation", "pointcache"}
    label = "Load Alembic"
    representations = {"abc"}
    order = -10
    icon = "code-fork"
    color = "orange"

    def load(self, context, name=None, namespace=None, data=None):
        from pymxs import runtime as rt

        file_path = self.filepath_from_context(context)
        file_path = os.path.normpath(file_path)

        abc_before = {
            c
            for c in rt.rootNode.Children
            if rt.classOf(c) == rt.AlembicContainer
        }

        rt.AlembicImport.ImportToRoot = False
        # TODO: it will be removed after the improvement
        # on the post-system setup
        reset_frame_range()
        rt.importFile(file_path, rt.name("noPrompt"), using=rt.AlembicImport)

        abc_after = {
            c
            for c in rt.rootNode.Children
            if rt.classOf(c) == rt.AlembicContainer
        }

        # This should yield new AlembicContainer node
        abc_containers = abc_after.difference(abc_before)

        if len(abc_containers) != 1:
            self.log.error("Something failed when loading.")

        abc_container = abc_containers.pop()
        selections = rt.GetCurrentSelection()
        for abc in selections:
            for cam_shape in abc.Children:
                cam_shape.playbackType = 0

        namespace = unique_namespace(
            name + "_",
            suffix="_",
        )
        abc_objects = []
        for abc_object in abc_container.Children:
            abc_object.name = f"{namespace}:{abc_object.name}"
            abc_objects.append(abc_object)
        # rename the abc container with namespace
        abc_container_name = f"{namespace}:{name}"
        abc_container.name = abc_container_name
        abc_objects.append(abc_container)

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

    def update(self, container, context):
        from pymxs import runtime as rt

        repre_entity = context["representation"]
        path = os.path.normpath(self.filepath_from_context(context))
        node = rt.GetNodeByName(container["instance_node"])
        abc_container = [n for n in get_previous_loaded_object(node)
                         if rt.ClassOf(n) == rt.AlembicContainer]
        with maintained_selection():
            rt.Select(abc_container)

            for alembic in rt.Selection:
                abc = rt.GetNodeByName(alembic.name)
                rt.Select(abc.Children)
                for abc_con in abc.Children:
                    abc_con.source = path
                    rt.Select(abc_con.Children)
                    for abc_obj in abc_con.Children:
                        abc_obj.source = path

        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)


    @staticmethod
    def get_container_children(parent, type_name):
        from pymxs import runtime as rt

        def list_children(node):
            children = []
            for c in node.Children:
                children.append(c)
                children += list_children(c)
            return children

        filtered = []
        for child in list_children(parent):
            class_type = str(rt.classOf(child.baseObject))
            if class_type == type_name:
                filtered.append(child)

        return filtered