feat: geometry node initial support

refactor: resolve datablocks by uuid by devault
fix: modifier texture dependencies
This commit is contained in:
Swann
2021-02-26 10:38:50 +01:00
parent 505f3ab770
commit 317fc03f87
6 changed files with 39 additions and 30 deletions

View File

@ -127,16 +127,14 @@ class BlDatablock(ReplicatedDatablock):
instance.uuid = self.uuid instance.uuid = self.uuid
def resolve(self, construct = True): def resolve(self, construct = True):
datablock_ref = None
datablock_root = getattr(bpy.data, self.bl_id) datablock_root = getattr(bpy.data, self.bl_id)
datablock_ref = utils.find_from_attr('uuid', self.uuid, datablock_root)
try:
datablock_ref = datablock_root[self.data['name']]
except Exception:
pass
if not datablock_ref: if not datablock_ref:
datablock_ref = utils.find_from_attr('uuid', self.uuid, datablock_root) try:
datablock_ref = datablock_root[self.data['name']]
except Exception:
pass
if construct and not datablock_ref: if construct and not datablock_ref:
name = self.data.get('name') name = self.data.get('name')

View File

@ -27,7 +27,7 @@ from .dump_anything import Loader, Dumper
from .bl_datablock import BlDatablock, get_datablock_from_uuid from .bl_datablock import BlDatablock, get_datablock_from_uuid
NODE_SOCKET_INDEX = re.compile('\[(\d*)\]') NODE_SOCKET_INDEX = re.compile('\[(\d*)\]')
IGNORED_SOCKETS = ['GEOMETRY']
def load_node(node_data: dict, node_tree: bpy.types.ShaderNodeTree): def load_node(node_data: dict, node_tree: bpy.types.ShaderNodeTree):
""" Load a node into a node_tree from a dict """ Load a node into a node_tree from a dict
@ -52,7 +52,8 @@ def load_node(node_data: dict, node_tree: bpy.types.ShaderNodeTree):
inputs_data = node_data.get('inputs') inputs_data = node_data.get('inputs')
if inputs_data: if inputs_data:
inputs = target_node.inputs inputs = [i for i in target_node.inputs if i.type not in IGNORED_SOCKETS]
for idx, inpt in enumerate(inputs_data): for idx, inpt in enumerate(inputs_data):
if idx < len(inputs) and hasattr(inputs[idx], "default_value"): if idx < len(inputs) and hasattr(inputs[idx], "default_value"):
try: try:
@ -64,12 +65,12 @@ def load_node(node_data: dict, node_tree: bpy.types.ShaderNodeTree):
outputs_data = node_data.get('outputs') outputs_data = node_data.get('outputs')
if outputs_data: if outputs_data:
outputs = target_node.outputs outputs = [o for o in target_node.outputs if o.type not in IGNORED_SOCKETS]
for idx, output in enumerate(outputs_data): for idx, output in enumerate(outputs_data):
if idx < len(outputs) and hasattr(outputs[idx], "default_value"): if idx < len(outputs) and hasattr(outputs[idx], "default_value"):
try: try:
outputs[idx].default_value = output outputs[idx].default_value = output
except: except Exception as e:
logging.warning( logging.warning(
f"Node {target_node.name} output {outputs[idx].name} parameter not supported, skipping ({e})") f"Node {target_node.name} output {outputs[idx].name} parameter not supported, skipping ({e})")
else: else:
@ -206,7 +207,7 @@ def dump_node(node: bpy.types.ShaderNode) -> dict:
return dumped_node return dumped_node
def dump_shader_node_tree(node_tree: bpy.types.ShaderNodeTree) -> dict: def dump_node_tree(node_tree: bpy.types.ShaderNodeTree) -> dict:
""" Dump a shader node_tree to a dict including links and nodes """ Dump a shader node_tree to a dict including links and nodes
:arg node_tree: dumped shader node tree :arg node_tree: dumped shader node tree
@ -276,7 +277,7 @@ def load_node_tree_sockets(sockets: bpy.types.Collection,
s['uuid'] = socket_data[2] s['uuid'] = socket_data[2]
def load_shader_node_tree(node_tree_data: dict, target_node_tree: bpy.types.ShaderNodeTree) -> dict: def load_node_tree(node_tree_data: dict, target_node_tree: bpy.types.ShaderNodeTree) -> dict:
"""Load a shader node_tree from dumped data """Load a shader node_tree from dumped data
:arg node_tree_data: dumped node data :arg node_tree_data: dumped node data
@ -387,7 +388,7 @@ class BlMaterial(BlDatablock):
if target.node_tree is None: if target.node_tree is None:
target.use_nodes = True target.use_nodes = True
load_shader_node_tree(data['node_tree'], target.node_tree) load_node_tree(data['node_tree'], target.node_tree)
def _dump_implementation(self, data, instance=None): def _dump_implementation(self, data, instance=None):
assert(instance) assert(instance)
@ -454,7 +455,7 @@ class BlMaterial(BlDatablock):
] ]
data['grease_pencil'] = gp_mat_dumper.dump(instance.grease_pencil) data['grease_pencil'] = gp_mat_dumper.dump(instance.grease_pencil)
elif instance.use_nodes: elif instance.use_nodes:
data['node_tree'] = dump_shader_node_tree(instance.node_tree) data['node_tree'] = dump_node_tree(instance.node_tree)
return data return data

View File

@ -21,13 +21,13 @@ import mathutils
from .dump_anything import Dumper, Loader, np_dump_collection, np_load_collection from .dump_anything import Dumper, Loader, np_dump_collection, np_load_collection
from .bl_datablock import BlDatablock from .bl_datablock import BlDatablock
from .bl_material import (dump_shader_node_tree, from .bl_material import (dump_node_tree,
load_shader_node_tree, load_node_tree,
get_node_tree_dependencies) get_node_tree_dependencies)
class BlNodeGroup(BlDatablock): class BlNodeGroup(BlDatablock):
bl_id = "node_groups" bl_id = "node_groups"
bl_class = bpy.types.ShaderNodeTree bl_class = bpy.types.NodeTree
bl_check_common = False bl_check_common = False
bl_icon = 'NODETREE' bl_icon = 'NODETREE'
bl_reload_parent = False bl_reload_parent = False
@ -36,10 +36,10 @@ class BlNodeGroup(BlDatablock):
return bpy.data.node_groups.new(data["name"], data["type"]) return bpy.data.node_groups.new(data["name"], data["type"])
def _load_implementation(self, data, target): def _load_implementation(self, data, target):
load_shader_node_tree(data, target) load_node_tree(data, target)
def _dump_implementation(self, data, instance=None): def _dump_implementation(self, data, instance=None):
return dump_shader_node_tree(instance) return dump_node_tree(instance)
def _resolve_deps_implementation(self): def _resolve_deps_implementation(self):
return get_node_tree_dependencies(self.instance) return get_node_tree_dependencies(self.instance)

View File

@ -91,18 +91,25 @@ def _is_editmode(object: bpy.types.Object) -> bool:
child_data.is_editmode) child_data.is_editmode)
def find_textures_dependencies(collection): def find_textures_dependencies(modifiers):
""" Check collection """ Check collection
""" """
textures = [] textures = []
for item in collection: for mod in modifiers:
for attr in dir(item): modifier_attributes = [getattr(mod, attr_name) for attr_name in mod.bl_rna.properties.keys()]
inst = getattr(item, attr) for attr in modifier_attributes:
if issubclass(type(inst), bpy.types.Texture) and inst is not None: if issubclass(type(attr), bpy.types.Texture) and attr is not None:
textures.append(inst) textures.append(attr)
return textures return textures
def find_geometry_nodes_groups(collection):
nodes_groups = []
for item in collection:
if item.type == 'NODES' and item.node_group:
nodes_groups.append(item.node_group)
return nodes_groups
def dump_vertex_groups(src_object: bpy.types.Object) -> dict: def dump_vertex_groups(src_object: bpy.types.Object) -> dict:
""" Dump object's vertex groups """ Dump object's vertex groups
@ -481,5 +488,6 @@ class BlObject(BlDatablock):
if self.instance.modifiers: if self.instance.modifiers:
deps.extend(find_textures_dependencies(self.instance.modifiers)) deps.extend(find_textures_dependencies(self.instance.modifiers))
deps.extend(find_geometry_nodes_groups(self.instance.modifiers))
return deps return deps

View File

@ -21,8 +21,8 @@ import mathutils
from .dump_anything import Loader, Dumper from .dump_anything import Loader, Dumper
from .bl_datablock import BlDatablock from .bl_datablock import BlDatablock
from .bl_material import (load_shader_node_tree, from .bl_material import (load_node_tree,
dump_shader_node_tree, dump_node_tree,
get_node_tree_dependencies) get_node_tree_dependencies)
@ -44,7 +44,7 @@ class BlWorld(BlDatablock):
if target.node_tree is None: if target.node_tree is None:
target.use_nodes = True target.use_nodes = True
load_shader_node_tree(data['node_tree'], target.node_tree) load_node_tree(data['node_tree'], target.node_tree)
def _dump_implementation(self, data, instance=None): def _dump_implementation(self, data, instance=None):
assert(instance) assert(instance)
@ -58,7 +58,7 @@ class BlWorld(BlDatablock):
] ]
data = world_dumper.dump(instance) data = world_dumper.dump(instance)
if instance.use_nodes: if instance.use_nodes:
data['node_tree'] = dump_shader_node_tree(instance.node_tree) data['node_tree'] = dump_node_tree(instance.node_tree)
return data return data

View File

@ -596,6 +596,8 @@ class Loader:
instance.write(bpy.data.textures.get(dump)) instance.write(bpy.data.textures.get(dump))
elif isinstance(rna_property_type, T.ColorRamp): elif isinstance(rna_property_type, T.ColorRamp):
self._load_default(instance, dump) self._load_default(instance, dump)
elif isinstance(rna_property_type, T.NodeTree):
instance.write(bpy.data.node_groups.get(dump))
elif isinstance(rna_property_type, T.Object): elif isinstance(rna_property_type, T.Object):
instance.write(bpy.data.objects.get(dump)) instance.write(bpy.data.objects.get(dump))
elif isinstance(rna_property_type, T.Mesh): elif isinstance(rna_property_type, T.Mesh):