def test_import_examples(self): for examples_path, category_name in example_categories_names(): info("Opening Dir named: %s", category_name) examples_set = examples_path / category_name for listed_path in examples_set.iterdir(): # cast from Path class to dumb string. path = str(listed_path) # assuming these are all jsons for now. name = basename(path) if name in UNITTEST_SKIPLIST: info(f"Skipping test import of: {name} - to permit unit-tests to continue") continue with self.subTest(file=name): # info("Importing: %s", name) with self.temporary_node_tree("ImportedTree") as new_tree: # Do not try to process imported tree, # that will just take time anyway new_tree.sv_process = False importer = JSONImporter.init_from_path(path) importer.import_into_tree(new_tree, print_log=False) for node in new_tree.nodes: if is_old(node): error_format = "This example contains deprecated node `{}' ({}). Please upgrade the example file." self.fail(error_format.format(node.name, node.bl_idname)) if is_dependent(node.bl_idname): self.skipTest("Some dependencies was not installed") if importer.has_fails: raise ImportError(importer.fail_massage)
def add_node_to_tree(nodes, n, nodes_to_import, name_remap, create_texts): node_ref = nodes_to_import[n] bl_idname = node_ref['bl_idname'] try: if old_nodes.is_old(bl_idname): old_nodes.register_old(bl_idname) if bl_idname == 'SvMonadGenericNode': node = unpack_monad(nodes, node_ref) if not node: raise Exception("It seems no valid node was created for this Monad {0}".format(node_ref)) else: node = nodes.new(bl_idname) except Exception as err: print(traceback.format_exc()) print(bl_idname, 'not currently registered, skipping') return if create_texts: add_texts(node, node_ref) if bl_idname in {'SvObjInLite', 'SvExecNodeMod', 'SvMeshEvalNode'}: node.storage_set_data(node_ref) if bl_idname == 'SvObjectsNodeMK3': for named_object in node_ref.get('object_names', []): node.object_names.add().name = named_object gather_remapped_names(node, n, name_remap) apply_core_props(node, node_ref) apply_superficial_props(node, node_ref) apply_post_processing(node, node_ref)
def _build_nodes(self, tree, factories, imported_structs): """Build nodes of the main tree, other dependencies should be already initialized""" with tree.init_tree(): # first all nodes should be created without applying their inner data # because some nodes can have `parent` property which points into another node node_structs = [] for node_name, raw_structure in self._struct["main_tree"]["nodes"].items(): with self.logger.add_fail("Init node (main tree)", f"Name: {node_name}"): node_struct = factories.node(node_name, self.logger, raw_structure) # register optional node classes if old_nodes.is_old(node_struct.read_bl_type()): old_nodes.register_old(node_struct.read_bl_type()) if dummy_nodes.is_dependent(node_struct.read_bl_type()): dummy_nodes.register_dummy(node_struct.read_bl_type()) # add node an save its new name node = tree.nodes.new(node_struct.read_bl_type()) node.name = node_name imported_structs[(StrTypes.NODE, tree.name, node_name)] = node.name node_structs.append(node_struct) for node_struct in node_structs: with self.logger.add_fail("Build node (main tree)", f"Name {node_struct.name}"): new_name = imported_structs[(StrTypes.NODE, tree.name, node_struct.name)] node = tree.nodes[new_name] node_struct.build(node, factories, imported_structs) for raw_struct in self._struct["main_tree"]["links"]: with self.logger.add_fail("Build link (main tree)", f"Struct: {raw_struct}"): factories.link(None, self.logger, raw_struct).build(tree, factories, imported_structs)
def test_import_examples(self): for cat in examples_paths: if not examples_paths.get(cat): info("Dir named: %s is empty", cat) continue info("Opening Dir named: %s", cat) examples_set = Path(examples_paths.get(cat)) for listed_path in examples_set.iterdir(): # cast from Path class to dumb string. path = str(listed_path) # assuming these are all jsons for now. name = basename(path) if name in UNITTEST_BLACKLIST: info("Skipping (blacklisted) : %s to permit unit tests to continue", name) continue with self.subTest(file=name): # info("Importing: %s", name) with self.temporary_node_tree("ImportedTree") as new_tree: with self.assert_logs_no_errors(): # Do not try to process imported tree, # that will just take time anyway new_tree.sv_process = False import_tree(new_tree, path) for node in new_tree.nodes: if is_old(node): error_format = "This example contains deprecated node `{}' ({}). Please upgrade the example file." self.fail(error_format.format(node.name, node.bl_idname))
def build(self, tree, factories: StructFactory, imported_structs: OldNewNames): """Reads and generates nodes, links, dependent data blocks""" with tree.init_tree(): # first all nodes should be created without applying their inner data # because some nodes can have `parent` property which points into another node node_structs = [] for node_name, raw_structure in self._struct["nodes"].items(): with self.logger.add_fail("Init node", f"Tree: {tree.name}, Node: {node_name}"): node_struct = factories.node(node_name, self.logger, raw_structure) # register optional node classes if old_nodes.is_old(node_struct.read_bl_type()): old_nodes.register_old(node_struct.read_bl_type()) if dummy_nodes.is_dependent(node_struct.read_bl_type()): dummy_nodes.register_dummy(node_struct.read_bl_type()) # add node an save its new name node = tree.nodes.new(node_struct.read_bl_type()) node.name = node_name imported_structs[(StrTypes.NODE, tree.name, node_name)] = node.name node_structs.append(node_struct) for node_struct in node_structs: with self.logger.add_fail("Build node", f"Tree: {tree.name}, Node: {node_struct.name}"): new_name = imported_structs[(StrTypes.NODE, tree.name, node_struct.name)] node = tree.nodes[new_name] node_struct.build(node, factories, imported_structs) for raw_struct in self._struct["links"]: with self.logger.add_fail("Build link", f"Tree: {tree.name}, Struct: {raw_struct}"): factories.link(None, self.logger, raw_struct).build(tree, factories, imported_structs) for prop_name, prop_value in self._struct.get("properties", dict()).items(): with self.logger.add_fail("Setting tree property", f'Tree: {node.id_data.name}, prop: {prop_name}'): factories.prop(prop_name, self.logger, prop_value).build(tree, factories, imported_structs)
def add_node_to_tree(nodes, n, nodes_to_import, name_remap, create_texts): node_ref = nodes_to_import[n] bl_idname = node_ref['bl_idname'] try: if old_nodes.is_old(bl_idname): old_nodes.register_old(bl_idname) if bl_idname == 'SvMonadGenericNode': node = nodes.new(bl_idname) params = node_ref.get('params') cls_dict = params.get('cls_dict') monad_name = params.get('monad') monad = bpy.data.node_groups[monad_name] node.input_template = cls_dict['input_template'] node.output_template = cls_dict['output_template'] setattr(node, 'cls_bl_idname', cls_dict['cls_bl_idname']) setattr(monad, 'cls_bl_idname', cls_dict['cls_bl_idname']) # node.bl_idname = node.cls_bl_idname else: node = nodes.new(bl_idname) except Exception as err: print(traceback.format_exc()) print(bl_idname, 'not currently registered, skipping') return if create_texts: add_texts(node, node_ref) gather_remapped_names(node, n, name_remap) apply_core_props(node, node_ref) apply_superficial_props(node, node_ref) apply_post_processing(node, node_ref)
def add_node_to_tree(nodes, n, nodes_to_import, name_remap, create_texts): node_ref = nodes_to_import[n] bl_idname = node_ref['bl_idname'] try: if old_nodes.is_old(bl_idname): old_nodes.register_old(bl_idname) if bl_idname == 'SvMonadGenericNode': node = unpack_monad(nodes, node_ref) if not node: raise Exception("It seems no valid node was created for this Monad {0}".format(node_ref)) else: node = nodes.new(bl_idname) except Exception as err: exception(err) error('%s not currently registered, skipping', bl_idname) return if create_texts: add_texts(node, node_ref) if hasattr(node, 'storage_set_data'): node.storage_set_data(node_ref) if bl_idname == 'SvObjectsNodeMK3': for named_object in node_ref.get('object_names', []): node.object_names.add().name = named_object gather_remapped_names(node, n, name_remap) apply_core_props(node, node_ref) apply_superficial_props(node, node_ref) apply_post_processing(node, node_ref) apply_custom_socket_props(node, node_ref)
def test_import_examples(self): for cat in examples_paths: if not examples_paths.get(cat): info("Dir named: %s is empty", cat) continue info("Opening Dir named: %s", cat) examples_set = Path(examples_paths.get(cat)) for listed_path in examples_set.iterdir(): # cast from Path class to dumb string. path = str(listed_path) # assuming these are all jsons for now. name = basename(path) if name in UNITTEST_BLACKLIST: info("Skipping (blacklisted) : %s to permit unit tests to continue", name) continue with self.subTest(file=name): info("Importing: %s", name) with self.temporary_node_tree("ImportedTree") as new_tree: with self.assert_logs_no_errors(): # Do not try to process imported tree, # that will just take time anyway new_tree.sv_process = False import_tree(new_tree, path) for node in new_tree.nodes: if is_old(node): error_format = "This example contains deprecated node `{}' ({}). Please upgrade the example file." self.fail(error_format.format(node.name, node.bl_idname))
def execute(self, context): ntree = context.space_data.node_tree for node in ntree.nodes: if old_nodes.is_old(node): info("Deprecated node: `%s' (%s)", node.name, node.bl_idname) self.report({'INFO'}, "See logs") return {'FINISHED'}
def execute(self, context): ntree = context.space_data.node_tree for node in ntree.nodes: if is_old(node): info("Deprecated node: `%s' (%s)", node.name, node.bl_idname) self.report({'INFO'}, "See logs") return {'FINISHED'}
def add_node(self, bl_type: str, node_name: str) -> Union[SverchCustomTreeNode, None]: """ Trying to add node with given bl_idname into given tree Also it can register dummy and old nodes and register fails """ with self._fails_log.add_fail("Creating node", f'Tree: {self._tree_name}, Node: {node_name}'): if old_nodes.is_old(bl_type): # old node classes are registered only by request old_nodes.register_old(bl_type) if dummy_nodes.is_dependent(bl_type): # some node types are not registered if dependencies are not installed # in this case such nodes are registered as dummies dummy_nodes.register_dummy(bl_type) node = self._tree.nodes.new(bl_type) node.name = node_name return node
def add_node_to_tree(nodes, n, nodes_to_import, name_remap, create_texts): node_ref = nodes_to_import[n] bl_idname = node_ref['bl_idname'] try: if old_nodes.is_old(bl_idname): old_nodes.register_old(bl_idname) if bl_idname == 'SvMonadGenericNode': node = unpack_monad(nodes, node_ref) if not node: raise Exception( "It seems no valid node was created for this Monad {0}". format(node_ref)) else: if dummy_nodes.is_dependent(bl_idname): try: node = nodes.new(bl_idname) except RuntimeError: dummy_nodes.register_dummy(bl_idname) node = nodes.new(bl_idname) else: node = nodes.new(bl_idname) except Exception as err: exception(err) error('%s not currently registered, skipping', bl_idname) return # fix_enum_identifier_spaces_if_needed(node, node_ref) if create_texts: add_texts(node, node_ref) if hasattr(node, 'storage_set_data'): node.storage_set_data(node_ref) if bl_idname == 'SvObjectsNodeMK3': for named_object in node_ref.get('object_names', []): node.object_names.add().name = named_object gather_remapped_names(node, n, name_remap) import_node_settings(node, node_ref)
def add_node_to_tree(nodes, n, nodes_to_import, name_remap, create_texts): node_ref = nodes_to_import[n] bl_idname = node_ref["bl_idname"] try: if old_nodes.is_old(bl_idname): old_nodes.register_old(bl_idname) if bl_idname == "SvMonadGenericNode": node = nodes.new(bl_idname) params = node_ref.get("params") cls_dict = params.get("cls_dict") monad_name = params.get("monad") monad = bpy.data.node_groups[monad_name] node.input_template = cls_dict["input_template"] node.output_template = cls_dict["output_template"] setattr(node, "cls_bl_idname", cls_dict["cls_bl_idname"]) setattr(monad, "cls_bl_idname", cls_dict["cls_bl_idname"]) # node.bl_idname = node.cls_bl_idname else: node = nodes.new(bl_idname) except Exception as err: print(traceback.format_exc()) print(bl_idname, "not currently registered, skipping") return if create_texts: add_texts(node, node_ref) if bl_idname in {"SvObjInLite", "SvExecNodeMod"}: node.storage_set_data(node_ref) if bl_idname == "SvObjectsNodeMK3": print(node_ref) obj_names = node_ref.get("object_names", []) for n in obj_names: node.object_names.add().name = n gather_remapped_names(node, n, name_remap) apply_core_props(node, node_ref) apply_superficial_props(node, node_ref) apply_post_processing(node, node_ref)
def generate_layout(fullpath, nodes_json): print('#' * 12, nodes_json['export_version']) ''' first create all nodes. ''' nodes_to_import = nodes_json['nodes'] groups_to_import = nodes_json.get('groups', {}) group_name_remap = {} for name in groups_to_import: group_ng = bpy.data.node_groups.new(name, 'SverchGroupTreeType') if group_ng.name != name: group_name_remap[name] = ng.name import_tree(group_ng, '', groups_to_import[name]) name_remap = {} texts = bpy.data.texts for n in sorted(nodes_to_import): node_ref = nodes_to_import[n] bl_idname = node_ref['bl_idname'] try: if old_nodes.is_old(bl_idname): old_nodes.register_old(bl_idname) node = nodes.new(bl_idname) except Exception as err: print(traceback.format_exc()) print(bl_idname, 'not currently registered, skipping') continue if create_texts: if node.bl_idname in SCRIPTED_NODES: ''' Scripted Node will no longer create alternative versions of a file. If a scripted node wants to make a file called 'inverse.py' and the current .blend already contains such a file, then for simplicity the importer will not try to create 'inverse.001.py' and reference that. It will instead do nothing and assume the existing python file is functionally the same. If you have files that work differently but have the same name, stop. ''' params = node_ref.get('params') if params: script_name = params.get('script_name') script_content = params.get('script_str') if script_name and not (script_name in texts): new_text = texts.new(script_name) new_text.from_string(script_content) node.script_name = script_name node.script_str = script_content if node.bl_idname == 'SvScriptNode': node.user_name = "templates" # best would be in the node. node.files_popup = "sv_lang_template.sn" # import to reset easy fix node.load() else: node.files_popup = node.avail_templates(None)[0][0] node.load() elif node.bl_idname == 'SvProfileNode': new_text = texts.new(node_ref['params']['filename']) new_text.from_string(node_ref['path_file']) node.update() # as it's a beta service, old IO json may not be compatible - in this interest # of neat code we assume it finds everything. elif node.bl_idname == 'SvTextInNode': params = node_ref.get('params') current_text = params['current_text'] node.textmode = params['textmode'] if not current_text: print(node.name, "doesn't store a current_text in params") elif not (current_text in texts): new_text = texts.new(current_text) if node.textmode == 'JSON': json_str = json.dumps( node_ref['text_lines']['stored_as_json']) new_text.from_string(json_str) else: new_text.from_string(node_ref['text_lines']) else: texts[current_text].from_string(node_ref['text_lines']) ''' When n is assigned to node.name, blender will decide whether or not it can do that, if there exists already a node with that name, then the assignment to node.name is not n, but n.00x. Hence on the following line we check if the assignment was accepted, and store a remapped name if it wasn't. ''' node.name = n if not (node.name == n): name_remap[n] = node.name params = node_ref['params'] # print(node.name, params) for p in params: val = params[p] setattr(node, p, val) node.location = node_ref['location'] node.height = node_ref['height'] node.width = node_ref['width'] node.label = node_ref['label'] node.hide = node_ref['hide'] node.color = node_ref['color'] ''' Nodes that require post processing to work properly ''' if node.bl_idname in {'SvGroupInputsNode', 'SvGroupOutputsNode'}: node.load() elif node.bl_idname in {'SvGroupNode'}: node.load() group_name = node.group_name node.group_name = group_name_remap.get(group_name, group_name) elif node.bl_idname == 'SvTextInNode': # node.reload() # node.reset() # node.reload() node.load() update_lists = nodes_json['update_lists'] print('update lists:') for ulist in update_lists: print(ulist) ''' now connect them ''' # naive # freeze updates while connecting the tree, otherwise # each connection will cause an update event ng.freeze(hard=True) failed_connections = [] for link in update_lists: try: ng.links.new(*resolve_socket(*link, name_dict=name_remap)) except Exception as err: print(traceback.format_exc()) failed_connections.append(link) continue if failed_connections: print('failed total {0}'.format(len(failed_connections))) print(failed_connections) else: print('no failed connections! awesome.') ''' set frame parents ''' finalize = lambda name: name_remap.get(name, name) framed_nodes = nodes_json['framed_nodes'] for node_name, parent in framed_nodes.items(): ng.nodes[finalize(node_name)].parent = ng.nodes[finalize(parent)] old_nodes.scan_for_old(ng) ng.unfreeze(hard=True) ng.update()
def generate_layout(fullpath, nodes_json): print('#' * 12, nodes_json['export_version']) ''' first create all nodes. ''' nodes_to_import = nodes_json['nodes'] groups_to_import = nodes_json.get('groups', {}) group_name_remap = {} for name in groups_to_import: group_ng = bpy.data.node_groups.new(name, 'SverchGroupTreeType') if group_ng.name != name: group_name_remap[name] = ng.name import_tree(group_ng, '', groups_to_import[name]) name_remap = {} texts = bpy.data.texts for n in sorted(nodes_to_import): node_ref = nodes_to_import[n] bl_idname = node_ref['bl_idname'] try: if old_nodes.is_old(bl_idname): old_nodes.register_old(bl_idname) node = nodes.new(bl_idname) except Exception as err: print(traceback.format_exc()) print(bl_idname, 'not currently registered, skipping') continue ''' When n is assigned to node.name, blender will decide whether or not it can do that, if there exists already a node with that name, then the assignment to node.name is not n, but n.00x. Hence on the following line we check if the assignment was accepted, and store a remapped name if it wasn't. ''' node.name = n if not (node.name == n): name_remap[n] = node.name params = node_ref['params'] print(node.name, params) for p in params: val = params[p] setattr(node, p, val) node.location = node_ref['location'] node.height = node_ref['height'] node.width = node_ref['width'] node.label = node_ref['label'] node.hide = node_ref['hide'] node.color = node_ref['color'] ''' maintenance warning: for the creation of new text files. If this script is run in a file which contains these Text names already, then the script/file names stored in the node must be updated to reflect this. Also is a script/profile is used for more than one node it will lead to duplication. All names have to collected and then fixed at end ''' if create_texts: if node.bl_idname in ('SvScriptNode', 'SvScriptNodeMK2'): new_text = texts.new(node.script_name) # there is no gurantee that we get the name we request if new_text.name != node.script_name: node.script_name = new_text.name new_text.from_string(node.script_str) node.user_name = "templates" # best would be in the node. node.files_popup = "sv_lang_template.sn" # import to reset easy fix node.load() elif node.bl_idname == 'SvProfileNode': new_text = texts.new(node.filename) new_text.from_string(node_ref['path_file']) # needed! node.update() ''' Nodes that require post processing to work properly ''' if node.bl_idname in {'SvGroupInputsNode', 'SvGroupOutputsNode'}: node.load() elif node.bl_idname in {'SvGroupNode'}: node.load() group_name = node.group_name node.group_name = group_name_remap.get(group_name, group_name) update_lists = nodes_json['update_lists'] print('update lists:') for ulist in update_lists: print(ulist) ''' now connect them ''' # naive # freeze updates while connecting the tree, otherwise # each connection will cause an update event ng.freeze(hard=True) failed_connections = [] for link in update_lists: try: ng.links.new(*resolve_socket(*link, name_dict=name_remap)) except Exception as err: print(traceback.format_exc()) failed_connections.append(link) continue if failed_connections: print('failed total {0}'.format(len(failed_connections))) print(failed_connections) else: print('no failed connections! awesome.') ''' set frame parents ''' finalize = lambda name: name_remap.get(name, name) framed_nodes = nodes_json['framed_nodes'] for node_name, parent in framed_nodes.items(): ng.nodes[finalize(node_name)].parent = ng.nodes[finalize(parent)] old_nodes.scan_for_old(ng) ng.unfreeze(hard=True) ng.update()
def generate_layout(fullpath, nodes_json): print('#' * 12, nodes_json['export_version']) ''' first create all nodes. ''' nodes_to_import = nodes_json['nodes'] groups_to_import = nodes_json.get('groups', {}) group_name_remap = {} for name in groups_to_import: group_ng = bpy.data.node_groups.new(name, 'SverchGroupTreeType') if group_ng.name != name: group_name_remap[name] = ng.name import_tree(group_ng, '', groups_to_import[name]) name_remap = {} texts = bpy.data.texts for n in sorted(nodes_to_import): node_ref = nodes_to_import[n] bl_idname = node_ref['bl_idname'] try: if old_nodes.is_old(bl_idname): old_nodes.register_old(bl_idname) node = nodes.new(bl_idname) except Exception as err: print(traceback.format_exc()) print(bl_idname, 'not currently registered, skipping') continue ''' maintenance warning: for the creation of new text files. If this script is run in a file which contains these Text names already, then the script/file names stored in the node must be updated to reflect this. Also is a script/profile is used for more than one node it will lead to duplication. All names have to collected and then fixed at end ''' if create_texts: if node.bl_idname in ('SvScriptNode', 'SvScriptNodeMK2'): new_text = texts.new(node.script_name) # there is no gurantee that we get the name we request if new_text.name != node.script_name: node.script_name = new_text.name new_text.from_string(node.script_str) node.user_name = "templates" # best would be in the node. node.files_popup = "sv_lang_template.sn" # import to reset easy fix node.load() elif node.bl_idname == 'SvProfileNode': new_text = texts.new(node.filename) new_text.from_string(node_ref['path_file']) # needed! node.update() elif node.bl_idname == 'SvTextInNode': if node_ref['current_text'] not in [a.name for a in texts]: new_text = texts.new(node.current_text) new_text.name = node_ref['current_text'] new_text.from_string(node_ref['text_lines']) else: texts[node_ref['current_text']].from_string(node_ref['text_lines']) ''' When n is assigned to node.name, blender will decide whether or not it can do that, if there exists already a node with that name, then the assignment to node.name is not n, but n.00x. Hence on the following line we check if the assignment was accepted, and store a remapped name if it wasn't. ''' node.name = n if not (node.name == n): name_remap[n] = node.name params = node_ref['params'] print(node.name, params) for p in params: val = params[p] setattr(node, p, val) node.location = node_ref['location'] node.height = node_ref['height'] node.width = node_ref['width'] node.label = node_ref['label'] node.hide = node_ref['hide'] node.color = node_ref['color'] ''' Nodes that require post processing to work properly ''' if node.bl_idname in {'SvGroupInputsNode', 'SvGroupOutputsNode'}: node.load() elif node.bl_idname in {'SvGroupNode'}: node.load() group_name = node.group_name node.group_name = group_name_remap.get(group_name, group_name) elif node.bl_idname == 'SvTextInNode': node.reload() #node.reset() #node.load() update_lists = nodes_json['update_lists'] print('update lists:') for ulist in update_lists: print(ulist) ''' now connect them ''' # naive # freeze updates while connecting the tree, otherwise # each connection will cause an update event ng.freeze(hard=True) failed_connections = [] for link in update_lists: try: ng.links.new(*resolve_socket(*link, name_dict=name_remap)) except Exception as err: print(traceback.format_exc()) failed_connections.append(link) continue if failed_connections: print('failed total {0}'.format(len(failed_connections))) print(failed_connections) else: print('no failed connections! awesome.') ''' set frame parents ''' finalize = lambda name: name_remap.get(name, name) framed_nodes = nodes_json['framed_nodes'] for node_name, parent in framed_nodes.items(): ng.nodes[finalize(node_name)].parent = ng.nodes[finalize(parent)] old_nodes.scan_for_old(ng) ng.unfreeze(hard=True) ng.update()
def generate_layout(fullpath, nodes_json): print('#' * 12, nodes_json['export_version']) ''' first create all nodes. ''' nodes_to_import = nodes_json['nodes'] groups_to_import = nodes_json.get('groups', {}) group_name_remap = {} for name in groups_to_import: group_ng = bpy.data.node_groups.new(name, 'SverchGroupTreeType') if group_ng.name != name: group_name_remap[name] = ng.name import_tree(group_ng, '', groups_to_import[name]) name_remap = {} texts = bpy.data.texts for n in sorted(nodes_to_import): node_ref = nodes_to_import[n] bl_idname = node_ref['bl_idname'] try: if old_nodes.is_old(bl_idname): old_nodes.register_old(bl_idname) node = nodes.new(bl_idname) except Exception as err: print(traceback.format_exc()) print(bl_idname, 'not currently registered, skipping') continue if create_texts: if node.bl_idname in SCRIPTED_NODES: ''' Scripted Node will no longer create alternative versions of a file. If a scripted node wants to make a file called 'inverse.py' and the current .blend already contains such a file, then for simplicity the importer will not try to create 'inverse.001.py' and reference that. It will instead do nothing and assume the existing python file is functionally the same. If you have files that work differently but have the same name, stop. ''' params = node_ref.get('params') if params: script_name = params.get('script_name') script_content = params.get('script_str') if script_name and not (script_name in texts): new_text = texts.new(script_name) new_text.from_string(script_content) node.script_name = script_name node.script_str = script_content if node.bl_idname == 'SvScriptNode': node.user_name = "templates" # best would be in the node. node.files_popup = "sv_lang_template.sn" # import to reset easy fix node.load() else: node.files_popup = node.avail_templates(None)[0][0] node.load() elif node.bl_idname == 'SvProfileNode': new_text = texts.new(node_ref['params']['filename']) new_text.from_string(node_ref['path_file']) node.update() # as it's a beta service, old IO json may not be compatible - in this interest # of neat code we assume it finds everything. elif node.bl_idname == 'SvTextInNode': params = node_ref.get('params') current_text = params['current_text'] node.textmode = params['textmode'] if not current_text: print(node.name, "doesn't store a current_text in params") elif not (current_text in texts): new_text = texts.new(current_text) if node.textmode == 'JSON': json_str = json.dumps(node_ref['text_lines']['stored_as_json']) new_text.from_string(json_str) else: new_text.from_string(node_ref['text_lines']) else: texts[current_text].from_string(node_ref['text_lines']) ''' When n is assigned to node.name, blender will decide whether or not it can do that, if there exists already a node with that name, then the assignment to node.name is not n, but n.00x. Hence on the following line we check if the assignment was accepted, and store a remapped name if it wasn't. ''' node.name = n if not (node.name == n): name_remap[n] = node.name params = node_ref['params'] # print(node.name, params) for p in params: val = params[p] setattr(node, p, val) node.location = node_ref['location'] node.height = node_ref['height'] node.width = node_ref['width'] node.label = node_ref['label'] node.hide = node_ref['hide'] node.color = node_ref['color'] ''' Nodes that require post processing to work properly ''' if node.bl_idname in {'SvGroupInputsNode', 'SvGroupOutputsNode'}: node.load() elif node.bl_idname in {'SvGroupNode'}: node.load() group_name = node.group_name node.group_name = group_name_remap.get(group_name, group_name) elif node.bl_idname == 'SvTextInNode': # node.reload() # node.reset() # node.reload() node.load() update_lists = nodes_json['update_lists'] print('update lists:') for ulist in update_lists: print(ulist) ''' now connect them ''' # naive # freeze updates while connecting the tree, otherwise # each connection will cause an update event ng.freeze(hard=True) failed_connections = [] for link in update_lists: try: ng.links.new(*resolve_socket(*link, name_dict=name_remap)) except Exception as err: print(traceback.format_exc()) failed_connections.append(link) continue if failed_connections: print('failed total {0}'.format(len(failed_connections))) print(failed_connections) else: print('no failed connections! awesome.') ''' set frame parents ''' finalize = lambda name: name_remap.get(name, name) framed_nodes = nodes_json['framed_nodes'] for node_name, parent in framed_nodes.items(): ng.nodes[finalize(node_name)].parent = ng.nodes[finalize(parent)] old_nodes.scan_for_old(ng) ng.unfreeze(hard=True) ng.update()