diff --git a/multi_user/bl_types/bl_material.py b/multi_user/bl_types/bl_material.py index 3dc82ca..51e4130 100644 --- a/multi_user/bl_types/bl_material.py +++ b/multi_user/bl_types/bl_material.py @@ -27,7 +27,7 @@ from .dump_anything import Loader, Dumper from .bl_datablock import BlDatablock, get_datablock_from_uuid NODE_SOCKET_INDEX = re.compile('\[(\d*)\]') -IGNORED_SOCKETS = ['GEOMETRY', 'SHADER'] +IGNORED_SOCKETS = ['GEOMETRY', 'SHADER', 'CUSTOM'] def load_node(node_data: dict, node_tree: bpy.types.ShaderNodeTree): """ Load a node into a node_tree from a dict @@ -54,8 +54,8 @@ def load_node(node_data: dict, node_tree: bpy.types.ShaderNodeTree): if inputs_data: inputs = [i for i in target_node.inputs if i.type not in IGNORED_SOCKETS] for idx, inpt in enumerate(inputs): - loaded_input = inputs_data[idx] if idx < len(inputs_data) and hasattr(inpt, "default_value"): + loaded_input = inputs_data[idx] try: if inpt.type in ['OBJECT', 'COLLECTION']: inpt.default_value = get_datablock_from_uuid(loaded_input, None) @@ -69,13 +69,17 @@ def load_node(node_data: dict, node_tree: bpy.types.ShaderNodeTree): outputs_data = node_data.get('outputs') if outputs_data: outputs = [o for o in target_node.outputs if o.type not in IGNORED_SOCKETS] - for idx, output in enumerate(outputs_data): - if idx < len(outputs) and hasattr(outputs[idx], "default_value"): + for idx, output in enumerate(outputs): + if idx < len(outputs_data) and hasattr(output, "default_value"): + loaded_output = outputs_data[idx] try: - outputs[idx].default_value = output + if output.type in ['OBJECT', 'COLLECTION']: + output.default_value = get_datablock_from_uuid(loaded_output, None) + else: + output.default_value = loaded_output except Exception as e: logging.warning( - f"Node {target_node.name} output {outputs[idx].name} parameter not supported, skipping ({e})") + f"Node {target_node.name} output {output.name} parameter not supported, skipping ({e})") else: logging.warning( f"Node {target_node.name} output length mismatch.") @@ -328,6 +332,8 @@ def get_node_tree_dependencies(node_tree: bpy.types.NodeTree) -> list: def has_node_group(node): return ( hasattr(node, 'node_tree') and node.node_tree) + def has_texture(node): return ( + node.type in ['ATTRIBUTE_SAMPLE_TEXTURE','TEXTURE'] and node.texture) deps = [] for node in node_tree.nodes: @@ -335,6 +341,8 @@ def get_node_tree_dependencies(node_tree: bpy.types.NodeTree) -> list: deps.append(node.image) elif has_node_group(node): deps.append(node.node_tree) + elif has_texture(node): + deps.append(node.texture) return deps diff --git a/multi_user/bl_types/bl_object.py b/multi_user/bl_types/bl_object.py index 80142c4..2141159 100644 --- a/multi_user/bl_types/bl_object.py +++ b/multi_user/bl_types/bl_object.py @@ -23,6 +23,7 @@ import mathutils from replication.exception import ContextError from .bl_datablock import BlDatablock, get_datablock_from_uuid +from .bl_material import IGNORED_SOCKETS from .dump_anything import ( Dumper, Loader, @@ -43,10 +44,15 @@ else: logging.warning("Geometry node Float parameter not supported in \ blender 2.92.") - -def get_input_index(e): - return int(re.findall('[0-9]+', e)[0]) - +def get_node_group_inputs(node_group): + inputs = [] + for inpt in node_group.inputs: + if inpt.type in IGNORED_SOCKETS: + continue + else: + inputs.append(inpt) + return inputs + # return [inpt.identifer for inpt in node_group.inputs if inpt.type not in IGNORED_SOCKETS] def dump_modifier_geometry_node_inputs(modifier: bpy.types.Modifier) -> list: """ Dump geometry node modifier input properties @@ -54,11 +60,10 @@ def dump_modifier_geometry_node_inputs(modifier: bpy.types.Modifier) -> list: :arg modifier: geometry node modifier to dump :type modifier: bpy.type.Modifier """ - inputs_name = [p for p in dir(modifier) if "Input_" in p] - inputs_name.sort(key=get_input_index) dumped_inputs = [] - for inputs_index, input_name in enumerate(inputs_name): - input_value = modifier[input_name] + for inpt in get_node_group_inputs(modifier.node_group): + input_value = modifier[inpt.identifier] + dumped_input = None if isinstance(input_value, bpy.types.ID): dumped_input = input_value.uuid @@ -80,18 +85,16 @@ def load_modifier_geometry_node_inputs(dumped_modifier: dict, target_modifier: b :type target_modifier: bpy.type.Modifier """ - inputs_name = [p for p in dir(target_modifier) if "Input_" in p] - inputs_name.sort(key=get_input_index) - for input_index, input_name in enumerate(inputs_name): + for input_index, inpt in enumerate(get_node_group_inputs(target_modifier.node_group)): dumped_value = dumped_modifier['inputs'][input_index] - input_value = target_modifier[input_name] + input_value = target_modifier[inpt.identifier] if isinstance(input_value, SUPPORTED_GEOMETRY_NODE_PARAMETERS): - target_modifier[input_name] = dumped_value + target_modifier[inpt.identifier] = dumped_value elif hasattr(input_value, 'to_list'): for index in range(len(input_value)): input_value[index] = dumped_value[index] - elif input_value and isinstance(input_value, bpy.types.ID): - target_modifier[input_name] = get_datablock_from_uuid( + elif inpt.type in ['COLLECTION', 'OBJECT']: + target_modifier[inpt.identifier] = get_datablock_from_uuid( dumped_value, None) @@ -168,19 +171,23 @@ def find_textures_dependencies(modifiers: bpy.types.bpy_prop_collection) -> [bpy return textures -def find_geometry_nodes(modifiers: bpy.types.bpy_prop_collection) -> [bpy.types.NodeTree]: - """ Find geometry nodes group from a modifier stack +def find_geometry_nodes_dependencies(modifiers: bpy.types.bpy_prop_collection) -> [bpy.types.NodeTree]: + """ Find geometry nodes dependencies from a modifier stack :arg modifiers: modifiers collection :type modifiers: bpy.types.bpy_prop_collection :return: list of bpy.types.NodeTree pointers """ - nodes_groups = [] - for item in modifiers: - if item.type == 'NODES' and item.node_group: - nodes_groups.append(item.node_group) - - return nodes_groups + dependencies = [] + for mod in modifiers: + if mod.type == 'NODES' and mod.node_group: + dependencies.append(mod.node_group) + for inpt in get_node_group_inputs(mod.node_group): + parameter = mod.get(inpt.identifier) + if parameter and isinstance(parameter, bpy.types.ID): + dependencies.append(parameter) + logging.info(dependencies) + return dependencies def dump_vertex_groups(src_object: bpy.types.Object) -> dict: @@ -597,6 +604,6 @@ class BlObject(BlDatablock): if self.instance.modifiers: deps.extend(find_textures_dependencies(self.instance.modifiers)) - deps.extend(find_geometry_nodes(self.instance.modifiers)) + deps.extend(find_geometry_nodes_dependencies(self.instance.modifiers)) return deps