from .sockets import Input, Output class Node: """Blender Node abstraction.""" def __init__(self, bl_node, parent): self.bl_node = bl_node self.tree = parent self.id = hex(id(self.bl_node)) self.data = {} self.parameters = [] for prop in self.bl_node.bl_rna.properties: if prop.is_readonly: continue prop_id = prop.identifier setattr(self, prop_id, getattr(self.bl_node, prop_id)) self.parameters.append(prop_id) self.inputs = [Input(ipt, self.tree) for ipt in self.bl_node.inputs] self.outputs = [Output(opt, self.tree) for opt in self.bl_node.outputs] @classmethod def from_dict(cls, data, tree): """Create all nodes from their dict representation. Args: data (dict): dict nodes representation. tree (Tree): blender node tree abstraction. Returns: Node: Create abstract node. """ new_bl_node = tree.nodes.new(type=data['bl_idname']) node = cls(new_bl_node, parent=tree) for p in node.parameters: setattr(node, p, data[p]) setattr(node.bl_node, p, data[p]) node.inputs = [Input.from_dict(ipt_data, node) for ipt_data in data['inputs'].values()] node.outputs = [Output.from_dict(opt_data, node) for opt_data in data['outputs'].values()] return node def to_dict(self): """Export currrent Node to its dict representation. Returns: dict: Node dict representation. """ for prop_id in self.parameters: if not hasattr(self, prop_id): continue attr_value = getattr(self, prop_id) if attr_value is None: attr_value = None elif not isinstance(attr_value, (str, int, float, list, tuple)): attr_value = list(attr_value) self.data[prop_id] = attr_value self.data['id'] = self.id self.data['inputs'] = {ipt.id: ipt.to_dict() for ipt in self.inputs} self.data['outputs'] = {opt.id: opt.to_dict() for opt in self.outputs} return self.data class Link: """Blender Link abstraction.""" def __init__(self, bl_link, parent): self.bl_link = bl_link self.tree = parent self.id = hex(id(self.bl_link)) self.input = self.bl_link.to_socket self.output = self.bl_link.from_socket self.data = {} def to_dict(self): self.data['id'] = self.id return self.data