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 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 create_nodes(self, context): # remove the previously spawned nodes remove_spawned_nodes(context) node_names = get_nodes_in_category(self.category) if DEBUG: print("* current category : ", self.category) print("* nodes in category : ", node_names) N = len(node_names) # print('There are <%d> nodes in this category' % (N)) if N == 0: return for i, node_name in enumerate(node_names): name = node_name if name == "separator": continue if is_dependent(name): continue if '@' in name: continue if DEBUG: print("Spawning Node %d : %s" % (i, name)) node = add_spawned_node(context, name) # force redraw to update the node dimensions bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
def create_nodes(self, context): # remove the previously spawned nodes remove_spawned_nodes(context) node_names = get_nodes_in_category(self.category) node_names.sort(reverse=False) debug("* current category : %s" % self.category) debug("* nodes in category : %s" % node_names) N = len(node_names) debug('There are <%d> nodes in category <%s>' % (N, self.category)) if N == 0: return for i, name in enumerate(node_names): if name == "separator": debug("SKIPPING separator node") continue if is_dependent(name): debug("SKIPPING dependent node %d of %d : %s" % (i+1, N, name)) continue if '@' in name: debug("SKIPPING subcategory node: %s" % name) continue debug("SPAWNING node %d of %d : %s" % (i+1, N, name)) add_spawned_node(context, name) # force redraw to update the node dimensions bpy.ops.wm.redraw_timer(type='DRAW_WIN', iterations=1) bpy.context.area.tag_redraw()
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 update_category(self, context): """ Spawn all nodes in the selected category note: all previously spawned nodes are removed first """ self.create_nodes(context) self.arrange_nodes(context) # update the total/hidden node count (e.g. nodes with dependency are hidden) node_names = get_nodes_in_category(self.category) self.total_num_nodes = len(node_names) other_node_names = [name for name in node_names if is_dependent(name)] self.hidden_num_nodes = len(other_node_names)
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)