6
7
8
9
10
11
12
13
14
15
16
17
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 | class AlembicLoader(plugin.Cinema4DLoader):
"""Load the camera."""
color = "orange"
product_types = {"*"}
icon = "code-fork"
label = "Load Alembic"
order = -10
representations = {"abc"}
def _load_file(self, filepath):
"""Merge a camera from a file.
Arguments:
filepath (str): The full path to the file that contains the camera.
Returns:
c4d.documents.BaseDocument: The loaded document.
"""
return c4d.documents.LoadDocument(
filepath,
c4d.SCENEFILTER_OBJECTS
# | c4d.SCENEFILTER_MERGESCENE
| c4d.SCENEFILTER_NOUNDO
| c4d.SCENEFILTER_IGNOREXREFS
| c4d.SCENEFILTER_DONTCORRECTOUTPUTFORMAT,
)
def load(self, context, name=None, namespace=None, options=None):
"""Merge the Alembic into the scene."""
# Merge the alembic, then containerise the generated nodes so we have
# access to them on update.
filepath = self.filepath_from_context(context)
doc = lib.active_document()
name, namespace = self.get_name_and_namespace(
context, name, namespace, doc=doc)
loaded_doc = self._load_file(filepath)
nodes = []
for obj in loaded_doc.GetObjects():
obj.Remove() # remove from original document
doc.InsertObject(obj, checknames=True)
nodes.append(obj)
# TODO: Also containerize all children objects to ensure we keep them
# linked explicitly
container = pipeline.containerise(
name=str(name),
namespace=str(namespace),
nodes=nodes,
context=context,
loader=str(self.__class__.__name__),
)
c4d.EventAdd()
return container
def update(self, container, context):
container_node = container["node"]
filepath = self.filepath_from_context(context)
# todo: Add new objects
# From the loaded (external) document iterate all its objects, any
# new ones insert them into our current document at the right "place"
# in the hierarchy.
# Any already existing ones, do nothing (unless there are specific
# updates we want to transfer that it doesn't automatically)
# loaded_doc = self._load_file(filepath)
# lib.add_objects_to_container(container_node, [camera])
# todo: Remove or 'tag' removed objects
# Any removed ones, keep them dangling in their "broken" state. It
# looks like Cinema4D is fine with that.
# for obj in remove:
# obj.Remove()
# todo: Update existing objects
members = list(lib.get_objects_from_container(container_node))
objects = set(members)
for obj in members:
children = lib.get_all_children(obj)
objects.update(children)
for obj in objects:
# Update Alembic Generators
if obj.IsInstanceOf(c4d.Oalembicgenerator):
obj[c4d.ALEMBIC_PATH] = filepath
continue
# Or if we find a Alembic Morph tag update that instead
# This will exist on the object if it was made editable.
alembic_morph = obj.GetTag(c4d.Talembicmorphtag)
if alembic_morph:
alembic_morph[c4d.ALEMBIC_MT_PATH] = filepath
# Update representation id
for i, base_container in container_node.GetUserDataContainer():
if base_container[c4d.DESC_NAME] == "representation":
container_node[i] = context["representation"]["id"]
c4d.EventAdd()
def remove(self, container):
"""Remove all sub containers"""
container_node = container["node"]
for obj in lib.get_objects_from_container(container_node):
if obj:
obj.Remove()
container_node.Remove()
c4d.EventAdd()
|