def sv_compile(string): try: root = ast.parse(string, mode='eval') return compile(root, "<expression>", 'eval') except SyntaxError as e: logging.exception(e) raise Exception("Invalid expression syntax: " + str(e))
def read_n_decode(url): try: content_at_url = urlopen(url) found_json = content_at_url.read().decode() return found_json except urllib.error.HTTPError as err: if err.code == 404: message = 'url: ' + str( url ) + ' doesn\'t appear to be a valid url, copy it again from your source' error(message) if operator: operator.report({'ERROR'}, message) else: message = 'url error:' + str(err.code) error(message) if operator: operator.report({'ERROR'}, message) except Exception as err: exception(err) if operator: operator.report( {'ERROR'}, 'unspecified error, check your internet connection') return
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 execute(self, context): if not self.preset_name: msg = "Preset name is not specified" error(msg) self.report({'ERROR'}, msg) return {'CANCELLED'} path = get_preset_path(self.preset_name) gist_filename = self.preset_name + ".json" gist_description = self.preset_name with open(path, 'rb') as jsonfile: gist_body = jsonfile.read().decode('utf8') try: gist_url = sv_gist_tools.main_upload_function(gist_filename, gist_description, gist_body, show_browser=False) context.window_manager.clipboard = gist_url # full destination url info(gist_url) self.report({'WARNING'}, "Copied gist URL to clipboad") sv_gist_tools.write_or_append_datafiles(gist_url, gist_filename) except Exception as err: exception(err) self.report({'ERROR'}, "Error 222: net connection or github login failed!") return {'CANCELLED'} finally: return {'FINISHED'}
def execute(self, context): ng = context.space_data.node_tree gist_filename = ng.name gist_description = 'to do later? 2018' layout_dict = create_dict_of_tree(ng, skip_set={}, selected=self.selected_only) try: gist_body = json.dumps(layout_dict, sort_keys=True, indent=2) except Exception as err: if 'not JSON serializable' in repr(err): error(layout_dict) else: exception(err) self.report({'WARNING'}, "See terminal/Command prompt for printout of error") return {'CANCELLED'} try: gist_url = sv_gist_tools.main_upload_function(gist_filename, gist_description, gist_body, show_browser=False) context.window_manager.clipboard = gist_url # full destination url info(gist_url) self.report({'WARNING'}, "Copied gistURL to clipboad") sv_gist_tools.write_or_append_datafiles(gist_url, gist_filename) return {'FINISHED'} except Exception as err: info(err) self.report({'ERROR'}, "Error 222: net connection or github login failed!") return {'CANCELLED'}
def do_update_general(node_list, nodes, procesed_nodes=set()): """ General update function for node set """ global graphs timings = [] graph = [] gather = graph.append total_time = 0 done_nodes = set(procesed_nodes) # this is a no-op if no bgl being drawn. clear_exception_drawing_with_bgl(nodes) for node_name in node_list: if node_name in done_nodes: continue try: node = nodes[node_name] start = time.perf_counter() if hasattr(node, "process"): node.process() delta = time.perf_counter() - start total_time += delta if data_structure.DEBUG_MODE: debug("Processed %s in: %.4f", node_name, delta) timings.append(delta) gather({ "name": node_name, "bl_idname": node.bl_idname, "start": start, "duration": delta }) except Exception as err: ng = nodes.id_data update_error_nodes(ng, node_name, err) #traceback.print_tb(err.__traceback__) exception("Node %s had exception: %s", node_name, err) if hasattr(ng, "sv_show_error_in_tree"): # not yet supported in monad trees.. if ng.sv_show_error_in_tree: error_text = traceback.format_exc() start_exception_drawing_with_bgl(ng, node_name, error_text, err) return None graphs.append(graph) if data_structure.DEBUG_MODE: debug("Node set updated in: %.4f seconds", total_time) return timings
def execute(self, context): ng = context.space_data.node_tree is_tree_exportable, msg = self.can_be_exported(ng) if not is_tree_exportable: self.report({'ERROR'}, msg) return {'CANCELLED'} gist_filename = ng.name app_version = bpy.app.version_string.replace(" ", "") time_stamp = strftime("%Y.%m.%d | %H:%M", localtime()) license = 'license: CC BY-SA' gist_description = f"Sverchok.{version_and_sha} | Blender.{app_version} | {ng.name} | {time_stamp} | {license}" # layout_dict = create_dict_of_tree(ng, skip_set={}, selected=self.selected_only) if self.selected_only: layout_dict = JSONExporter.get_nodes_structure( [node for node in ng.nodes if node.select]) else: layout_dict = JSONExporter.get_tree_structure(ng) try: gist_body = json.dumps(layout_dict, sort_keys=True, indent=2) except Exception as err: if 'not JSON serializable' in repr(err): error(layout_dict) exception(err) self.report({'WARNING'}, "See terminal/Command prompt for printout of error") return {'CANCELLED'} try: gist_url = sv_gist_tools.main_upload_function(gist_filename, gist_description, gist_body, show_browser=False) if not gist_url: self.report( {'ERROR'}, "You have not specified GitHub API access token, which is " + "required to create gists from Sverchok. Please see " + TOKEN_HELP_URL + " for more information.") return {'CANCELLED'} context.window_manager.clipboard = gist_url # full destination url info(gist_url) self.report({'WARNING'}, "Copied gist URL to clipboad") sv_gist_tools.write_or_append_datafiles(gist_url, gist_filename) return {'FINISHED'} except Exception as err: exception(err) self.report({'ERROR'}, "Error 222: net connection or github login failed!") return {'CANCELLED'}
def apply_socket_props(socket, info): debug("applying socket props") for tracked_prop_name, tracked_prop_value in info.items(): try: setattr(socket, tracked_prop_name, tracked_prop_value) except Exception as err: error("Error while setting node socket: %s | %s", node.name, socket.index) error("the following failed | %s <- %s", tracked_prop_name, tracked_prop_value) exception(err)
def apply_custom_socket_props(node, node_ref): debug("applying node props for node: %s", node.bl_idname) socket_properties = node_ref.get('custom_socket_props') if socket_properties: for idx, info in socket_properties.items(): try: socket = node.inputs[int(idx)] apply_socket_props(socket, info) except Exception as err: error("socket index: %s, trying to pass: %s, num_sockets: %s", idx, info, len(node.inputs)) exception(err)
def handle_reload_event(nodes, imported_modules, old_nodes): node_list = make_node_list(nodes) reload_all(imported_modules, node_list, old_nodes) try: from sverchok.old_nodes import old_bl_idnames debug('Known old_bl_idnames after reload: %s', len(old_bl_idnames)) except Exception as err: exception(err) return node_list
def add_nodes(ng, nodes_to_import, nodes, create_texts): """ return the dictionary that tracks which nodes got renamed due to conflicts. """ name_remap = {} try: for n in sorted(nodes_to_import): add_node_to_tree(nodes, n, nodes_to_import, name_remap, create_texts) except Exception as err: exception(err) return name_remap
def safe_eval_compiled(compiled, variables): """ Evaluate expression, allowing only functions known to be "safe" to be used. """ try: env = dict() env.update(safe_names) env.update(variables) env["__builtins__"] = {} return eval(compiled, env) except SyntaxError as e: logging.exception(e) raise Exception("Invalid expression syntax: " + str(e))
def safe_eval(string, variables): """ Evaluate expression, allowing only functions known to be "safe" to be used. """ try: env = dict() env.update(safe_names) env.update(variables) env["__builtins__"] = {} root = ast.parse(string, mode='eval') return eval(compile(root, "<expression>", 'eval'), env) except SyntaxError as e: logging.exception(e) raise Exception("Invalid expression syntax: " + str(e))
def add_nodes(ng, nodes_to_import, nodes, create_texts): ''' return the dictionary that tracks which nodes got renamed due to conflicts. setting 'ng.limited_init' supresses any custom defaults associated with nodes in the json. ''' name_remap = {} ng.limited_init = True try: for n in sorted(nodes_to_import): add_node_to_tree(nodes, n, nodes_to_import, name_remap, create_texts) except Exception as err: exception(err) ng.limited_init = False return name_remap
def make_links(update_lists, name_remap): print_update_lists(update_lists) failed_connections = [] for link in update_lists: try: ng.links.new(*resolve_socket(*link, name_dict=name_remap)) except Exception as err: exception(err) failed_connections.append(link) continue if failed_connections: error("failed total: %s", len(failed_connections)) error(failed_connections) else: debug('no failed connections! awesome.')
def do_update_general(node_list, nodes, procesed_nodes=set()): """ General update function for node set """ global graphs timings = [] graph = [] gather = graph.append total_time = 0 done_nodes = set(procesed_nodes) for node_name in node_list: if node_name in done_nodes: continue try: node = nodes[node_name] start = time.perf_counter() if hasattr(node, "process"): node.process() delta = time.perf_counter() - start total_time += delta if data_structure.DEBUG_MODE: debug("Processed %s in: %.4f", node_name, delta) timings.append(delta) gather({ "name": node_name, "bl_idname": node.bl_idname, "start": start, "duration": delta }) except Exception as err: ng = nodes.id_data update_error_nodes(ng, node_name, err) #traceback.print_tb(err.__traceback__) exception("Node %s had exception: %s", node_name, err) return None graphs.append(graph) if data_structure.DEBUG_MODE: debug("Node set updated in: %.4f seconds", total_time) return timings
def do_update_general(node_list, nodes, procesed_nodes=set()): """ General update function for node set """ ng = nodes.id_data global graphs # graph_dicts[ng.name] = [] timings = [] graph = [] gather = graph.append total_time = 0 done_nodes = set(procesed_nodes) for node_name in node_list: if node_name in done_nodes: continue try: node = nodes[node_name] start = time.perf_counter() if hasattr(node, "process"): node.process() delta = time.perf_counter() - start total_time += delta timings.append(delta) gather(node_info(ng.name, node, start, delta)) # probably it's not great place for doing this, the node can be a ReRoute [ s.update_objects_number() for s in chain(node.inputs, node.outputs) if hasattr(s, 'update_objects_number') ] except Exception as err: update_error_nodes(ng, node_name, err) #traceback.print_tb(err.__traceback__) exception("Node %s had exception: %s", node_name, err) return None graphs.append(graph) # graph_dicts[nodes.id_data.name] = graph return timings
def execute(self, context): ng = context.space_data.node_tree gist_filename = ng.name gist_description = "Sverchok_" + version_and_sha + ng.name + "_Bl_" + bpy.app.version_string.replace( " ", "") + str(tl().tm_year) + str(tl().tm_mon) + str( tl().tm_mday) + str(tl().tm_hour) layout_dict = create_dict_of_tree(ng, skip_set={}, selected=self.selected_only) try: gist_body = json.dumps(layout_dict, sort_keys=True, indent=2) except Exception as err: if 'not JSON serializable' in repr(err): error(layout_dict) exception(err) self.report({'WARNING'}, "See terminal/Command prompt for printout of error") return {'CANCELLED'} try: gist_url = sv_gist_tools.main_upload_function(gist_filename, gist_description, gist_body, show_browser=False) if not gist_url: self.report( {'ERROR'}, "You have not specified GitHub API access token, which is " + "required to create gists from Sverchok. Please see " + TOKEN_HELP_URL + " for more information.") return {'CANCELLED'} context.window_manager.clipboard = gist_url # full destination url info(gist_url) self.report({'WARNING'}, "Copied gist URL to clipboad") sv_gist_tools.write_or_append_datafiles(gist_url, gist_filename) return {'FINISHED'} except Exception as err: exception(err) self.report({'ERROR'}, "Error 222: net connection or github login failed!") return {'CANCELLED'}
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 test_imports(self): """ Test that all files can be imported. Theoretically, there can be cases when some sverchok modules are not imported at registration, but only by some event (for example, when the node is added into tree). This test is intended to check that there are no dangling / broken or cyclic imports in any module. """ for subroot in ['core', 'utils', 'ui', 'nodes', 'old_nodes']: for path in Path(subroot).rglob('*.py'): with self.subTest(path = str(path)): parts = list(path.parts) parts[-1] = parts[-1][:-3] # remove .py suffix module_name = "sverchok." + ".".join(parts) try: module = importlib.import_module(module_name) except Exception as e: exception(e) self.fail(str(e)) self.assertIsNotNone(module)
def read_n_decode(url): try: content_at_url = urlopen(url) found_json = content_at_url.read().decode() return found_json except urllib.error.HTTPError as err: if err.code == 404: message = 'url: ' + str(url) + ' doesn\'t appear to be a valid url, copy it again from your source' error(message) if operator: operator.report({'ERROR'}, message) else: message = 'url error:' + str(err.code) error(message) if operator: operator.report({'ERROR'}, message) except Exception as err: exception(err) if operator: operator.report({'ERROR'}, 'unspecified error, check your internet connection') return
def eval_list(coords): if isinstance(coords, str): coords = [coords] if isinstance(coords, dict): result = dict() for key in coords: result[key] = eval_list(coords[key]) return result v = [] for c in coords: if isinstance(c, str): try: val = safe_eval(c, variables) #self.debug("EVAL: {} with {} => {}".format(c, variables, val)) except NameError as e: exception(e) val = 0.0 else: val = c v.append(val) return v
def register_old(bl_id): if bl_id in old_bl_idnames: mod = importlib.import_module(".{}".format(old_bl_idnames[bl_id]), __name__) res = inspect.getmembers(mod) # print('mod/res:', mod, res) for name, cls in res: if inspect.isclass(cls): if issubclass(cls, bpy.types.Node) and cls.bl_idname == bl_id: if bl_id not in imported_mods: try: mod.register() except Exception as err: print('failed mod register') exception(err) imported_mods[bl_id] = mod return mod else: return imported_mods[bl_id] error("Cannot find {} among old nodes".format(bl_id)) return None
def do_update_general(node_list, nodes, procesed_nodes=set()): """ General update function for node set """ global graphs timings = [] graph = [] total_time = 0 done_nodes = set(procesed_nodes) for node_name in node_list: if node_name in done_nodes: continue try: node = nodes[node_name] start = time.perf_counter() if hasattr(node, "process"): node.process() delta = time.perf_counter() - start total_time += delta if data_structure.DEBUG_MODE: debug("Processed %s in: %.4f", node_name, delta) timings.append(delta) graph.append({"name" : node_name, "bl_idname": node.bl_idname, "start": start, "duration": delta}) except Exception as err: ng = nodes.id_data update_error_nodes(ng, node_name, err) #traceback.print_tb(err.__traceback__) exception("Node %s had exception: %s", node_name, err) return None graphs.append(graph) if data_structure.DEBUG_MODE: debug("Node set updated in: %.4f seconds", total_time) return timings
def create_dict_of_tree(ng, skip_set={}, selected=False, identified_node=None): nodes = ng.nodes layout_dict = {} nodes_dict = {} groups_dict = {} if not skip_set: skip_set = {'Sv3DviewPropsNode'} if selected: nodes = list(filter(lambda n: n.select, nodes)) if identified_node: # this mode will import one node only. nodes = [identified_node] # get nodes and params for node in nodes: if node.bl_idname in skip_set: continue node_dict = {} node_items = {} node_enums = find_enumerators(node) IsMonadInstanceNode = (node.bl_idname.startswith('SvGroupNodeMonad')) for k, v in node.items(): display_introspection_info(node, k, v) if can_skip_property(node, k): continue elif has_state_switch_protection(node, k): continue handle_old_groupnode(node, k, v, groups_dict, create_dict_of_tree) if isinstance(v, (float, int, str)): node_items[k] = v elif node.bl_idname in {'ScalarMathNode', 'SvLogicNode'} and k == 'prop_types': node_items[k] = getattr(node, k)[:] continue else: node_items[k] = v[:] handle_enum_property(node, k, v, node_items, node_enums) if IsMonadInstanceNode and node.monad: pack_monad(node, node_items, groups_dict, create_dict_of_tree) if hasattr(node, "storage_get_data"): node.storage_get_data(node_dict) node_dict['params'] = node_items collect_custom_socket_properties(node, node_dict) # if node.bl_idname == 'NodeFrame': # frame_props = 'shrink', 'use_custom_color', 'label_size' # node_dict['params'].update({fpv: getattr(node, fpv) for fpv in frame_props}) if IsMonadInstanceNode: node_dict['bl_idname'] = 'SvMonadGenericNode' else: node_dict['bl_idname'] = node.bl_idname if node.bl_idname in {'SvGroupInputsNodeExp', 'SvGroupOutputsNodeExp'}: node_dict[node.node_kind] = node.stash() get_superficial_props(node_dict, node) nodes_dict[node.name] = node_dict # ------------------- layout_dict['nodes'] = nodes_dict layout_dict['groups'] = groups_dict # ''' get connections ''' # links = (compile_socket(l) for l in ng.links) # connections_dict = {idx: link for idx, link in enumerate(links)} # layout_dict['connections'] = connections_dict ''' get framed nodes ''' framed_nodes = {} for node in nodes: if node.bl_idname in skip_set: continue if node.parent: if selected and node.parent.select: framed_nodes[node.name] = node.parent.name elif not selected: framed_nodes[node.name] = node.parent.name layout_dict['framed_nodes'] = framed_nodes ''' get update list (cache, order to link) ''' # try/except for now, node tree links might be invalid # among other things. auto rebuild on F8 try: ng.build_update_list() links_out = [] for name in chain(*ng.get_update_lists()[0]): for socket in ng.nodes[name].inputs: if selected and not ng.nodes[name].select: continue if socket.links: link = socket.links[0] if selected and not link.from_node.select: continue links_out.append(compile_socket(link)) layout_dict['update_lists'] = links_out except Exception as err: exception(err) error('no update lists found or other error!') error(' - trigger an update and retry') return layout_dict['export_version'] = _EXPORTER_REVISION_ return layout_dict
def register(): for clazz in classes: try: bpy.utils.register_class(clazz) except Exception as e: exception("Cant register class %s: %s", clazz, e)
def unregister(): for clazz in reversed(classes): try: bpy.utils.unregister_class(clazz) except Exception as e: exception("Cant unregister class %s: %s", clazz, e)
def create_dict_of_tree(ng, skip_set={}, selected=False): nodes = ng.nodes layout_dict = {} nodes_dict = {} groups_dict = {} if not skip_set: skip_set = {'Sv3DviewPropsNode'} if selected: nodes = list(filter(lambda n: n.select, nodes)) # get nodes and params for node in nodes: if node.bl_idname in skip_set: continue node_dict = {} node_items = {} node_enums = find_enumerators(node) IsMonadInstanceNode = (node.bl_idname.startswith('SvGroupNodeMonad')) for k, v in node.items(): display_introspection_info(node, k, v) if can_skip_property(node, k): continue elif has_state_switch_protection(node, k): continue handle_old_groupnode(node, k, v, groups_dict, create_dict_of_tree) if isinstance(v, (float, int, str)): node_items[k] = v elif node.bl_idname in {'ScalarMathNode', 'SvLogicNode' } and k == 'prop_types': node_items[k] = getattr(node, k)[:] continue else: node_items[k] = v[:] handle_enum_property(node, k, v, node_items, node_enums) if IsMonadInstanceNode and node.monad: pack_monad(node, node_items, groups_dict, create_dict_of_tree) if hasattr(node, "storage_get_data"): node.storage_get_data(node_dict) node_dict['params'] = node_items collect_custom_socket_properties(node, node_dict) # if node.bl_idname == 'NodeFrame': # frame_props = 'shrink', 'use_custom_color', 'label_size' # node_dict['params'].update({fpv: getattr(node, fpv) for fpv in frame_props}) if IsMonadInstanceNode: node_dict['bl_idname'] = 'SvMonadGenericNode' else: node_dict['bl_idname'] = node.bl_idname if node.bl_idname in {'SvGroupInputsNodeExp', 'SvGroupOutputsNodeExp'}: node_dict[node.node_kind] = node.stash() get_superficial_props(node_dict, node) nodes_dict[node.name] = node_dict # ------------------- layout_dict['nodes'] = nodes_dict layout_dict['groups'] = groups_dict # ''' get connections ''' # links = (compile_socket(l) for l in ng.links) # connections_dict = {idx: link for idx, link in enumerate(links)} # layout_dict['connections'] = connections_dict ''' get framed nodes ''' framed_nodes = {} for node in nodes: if node.bl_idname in skip_set: continue if node.parent: if selected and node.parent.select: framed_nodes[node.name] = node.parent.name elif not selected: framed_nodes[node.name] = node.parent.name layout_dict['framed_nodes'] = framed_nodes ''' get update list (cache, order to link) ''' # try/except for now, node tree links might be invalid # among other things. auto rebuild on F8 try: ng.build_update_list() links_out = [] for name in chain(*ng.get_update_lists()[0]): for socket in ng.nodes[name].inputs: if selected and not ng.nodes[name].select: continue if socket.links: link = socket.links[0] if selected and not link.from_node.select: continue links_out.append(compile_socket(link)) layout_dict['update_lists'] = links_out except Exception as err: exception(err) error('no update lists found or other error!') error(' - trigger an update and retry') return layout_dict['export_version'] = _EXPORTER_REVISION_ return layout_dict
def create_dict_of_tree(ng, skip_set={}, selected=False, identified_node=None, save_defaults = False): nodes = ng.nodes layout_dict = {} nodes_dict = {} groups_dict = {} if not skip_set: skip_set = {'Sv3DviewPropsNode'} if selected: nodes = list(filter(lambda n: n.select, nodes)) if identified_node: # this mode will import one node only. nodes = [identified_node] # get nodes and params for node in nodes: if node.bl_idname in skip_set: continue node_dict = {} node_items = {} node_enums = find_enumerators(node) IsMonadInstanceNode = (node.bl_idname.startswith('SvGroupNodeMonad')) if save_defaults: node_props = get_node_annotations(node) else: node_props = node.items() for k, v in node_props: display_introspection_info(node, k, v) if can_skip_property(node, k): continue elif has_state_switch_protection(node, k): continue handle_old_groupnode(node, k, v, groups_dict, create_dict_of_tree) if isinstance(v, (float, int, str)): node_items[k] = v elif node.bl_idname in {'ScalarMathNode', 'SvLogicNode'} and k == 'prop_types': node_items[k] = getattr(node, k)[:] continue else: ann = node.bl_rna.__annotations__ # this will only ever encounter pointerproperties that are interactive with # by the user, or they happen to be visible in the UI by defailt. arguably # we should be iterating over `node_props from get_node_annotations(node)` if k in ann: prop_type, prop_details = ann[k] if prop_type == bpy.props.PointerProperty: info(f"skipping {node.name}.{k} (a PointerProperty)") continue node_items[k] = v[:] handle_enum_property(node, k, v, node_items, node_enums) if IsMonadInstanceNode and node.monad: pack_monad(node, node_items, groups_dict, create_dict_of_tree) if hasattr(node, "storage_get_data"): node.storage_get_data(node_dict) node_dict['params'] = node_items collect_custom_socket_properties(node, node_dict) # if node.bl_idname == 'NodeFrame': # frame_props = 'shrink', 'use_custom_color', 'label_size' # node_dict['params'].update({fpv: getattr(node, fpv) for fpv in frame_props}) if IsMonadInstanceNode: node_dict['bl_idname'] = 'SvMonadGenericNode' # these are indeed stored. as ints. which is fine. # must also store (.vectorize, bool) (.loop_me, bool) (.loops, int) else: node_dict['bl_idname'] = node.bl_idname if node.bl_idname in {'SvGroupInputsNodeExp', 'SvGroupOutputsNodeExp'}: node_dict[node.node_kind] = node.stash() get_superficial_props(node_dict, node) nodes_dict[node.name] = node_dict # ------------------- layout_dict['nodes'] = nodes_dict layout_dict['groups'] = groups_dict # ''' get connections ''' # links = (compile_socket(l) for l in ng.links) # connections_dict = {idx: link for idx, link in enumerate(links)} # layout_dict['connections'] = connections_dict ''' get framed nodes ''' framed_nodes = {} for node in nodes: if node.bl_idname in skip_set: continue if node.parent: if selected and node.parent.select: framed_nodes[node.name] = node.parent.name elif not selected: framed_nodes[node.name] = node.parent.name layout_dict['framed_nodes'] = framed_nodes ''' get update list (cache, order to link) ''' # try/except for now, node tree links might be invalid # among other things. auto rebuild on F8 try: build_update_list(ng) links_out = [] for name in chain(*get_update_lists(ng)[0]): for socket in ng.nodes[name].inputs: if selected and not ng.nodes[name].select: continue if socket.links: link = socket.links[0] if selected and not link.from_node.select: continue links_out.append(compile_socket(link)) layout_dict['update_lists'] = links_out except Exception as err: exception(err) error('no update lists found or other error!') error(' - trigger an update and retry') return layout_dict['export_version'] = _EXPORTER_REVISION_ return layout_dict
def register(): for clazz in classes: try: bpy.utils.register_class(clazz) except Exception as e: exception("Can't register class %s: %s", clazz, e)
def unregister(): for clazz in reversed(classes): try: bpy.utils.unregister_class(clazz) except Exception as e: exception("Can't unregister class %s: %s", clazz, e)