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)
Exemple #2
0
    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'}
Exemple #4
0
def do_update_heat_map(node_list, nodes):
    """
    Create a heat map for the node tree,
    Needs development.
    """
    if not nodes.id_data.sv_user_colors:
        color_data = {node.name: (node.color[:], node.use_custom_color) for node in nodes}
        nodes.id_data.sv_user_colors = str(color_data)

    times = do_update_general(node_list, nodes)
    if not times:
        return
    t_max = max(times)
    addon_name = data_structure.SVERCHOK_NAME
    addon = bpy.context.user_preferences.addons.get(addon_name)
    if addon:
        # to use Vector.lerp
        cold = Vector(addon.preferences.heat_map_cold)
        hot = addon.preferences.heat_map_hot
    else:
        error("Cannot find preferences")
        cold = Vector((1, 1, 1))
        hot = (.8, 0, 0)
    for name, t in zip(node_list, times):
        nodes[name].use_custom_color = True
        # linear scale.
        nodes[name].color = cold.lerp(hot, t / t_max)
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)
Exemple #7
0
def make_update_list(node_tree, node_set=None, dependencies=None):
    """
    Makes a update list from a node_group
    if a node set is passed only the subtree defined by the node set is used. Otherwise
    the complete node tree is used.
    If dependencies are not passed they are built.
    """

    ng = node_tree
    if not node_set:  # if no node_set, take all
        node_set = set(ng.nodes.keys())
    if len(node_set) == 1:
        return list(node_set)
    if node_set:  # get one name
        name = node_set.pop()
        node_set.add(name)
    else:
        return []
    if not dependencies:
        deps = make_dep_dict(ng)
    else:
        deps = dependencies

    tree_stack = collections.deque([name])
    tree_stack_append = tree_stack.append
    tree_stack_pop = tree_stack.pop
    out = collections.OrderedDict()
    # travel in node graph create one sorted list of nodes based on dependencies
    node_count = len(node_set)
    while node_count > len(out):
        node_dependencies = True
        for dep_name in deps[name]:
            if dep_name in node_set and dep_name not in out:
                tree_stack_append(name)
                name = dep_name
                node_dependencies = False
                break
        if len(tree_stack) > node_count:
            error("Invalid node tree!")
            return []
        # if all dependencies are in out
        if node_dependencies:
            if name not in out:
                out[name] = 1
            if tree_stack:
                name = tree_stack_pop()
            else:
                if node_count == len(out):
                    break
                for node_name in node_set:
                    if node_name not in out:
                        name = node_name
                        break
    return list(out.keys())
def compile_socket(link):

    try:
        link_data = (link.from_node.name, link.from_socket.index, link.to_node.name, link.to_socket.index)
    except Exception as err:
        if "'NodeSocketColor' object has no attribute 'index'" in repr(err):
            debug('adding node reroute using socketname instead if index')
        else:
            error(repr(err))
        link_data = (link.from_node.name, link.from_socket.name, link.to_node.name, link.to_socket.name)

    return link_data
def display_introspection_info(node, k, v):
    if not isinstance(v, (float, int, str)):
        debug('//')
        debug("%s -> property: %s: %s", node.name, k, type(v))
        if k in node.bl_rna.properties:
            debug(type(node.bl_rna.properties[k]))
        elif k in node:
            # something like node['lp']  , ID Property directly on the node instance.
            debug(type(node[k]))
        else:
            error('%s is not bl_rna or IDproperty.. please report this', k)

        debug('\\\\')
Exemple #10
0
    def update_cls(self):
        """
        create or update the corresponding class reference
        """

        if not all((self.input_node, self.output_node)):
            error("Monad %s not set up correctly", self.name)
            return None

        cls_dict = {}

        if not self.cls_bl_idname:
            
            # the monad cls_bl_idname needs to be unique and cannot change
            monad_base_name = make_valid_identifier(self.name)
            monad_itentifier = id(self) ^ random.randint(0, 4294967296)

            cls_name = "SvGroupNode{}_{}".format(monad_base_name, monad_itentifier)
            # set the unique name for the class, depending on context this might fail
            # then we cannot do the setup of the class properly so abandon
            try:
                self.cls_bl_idname = cls_name
            except Exception:
                return None
        else:
            cls_name = self.cls_bl_idname

        self.verify_props()

        cls_dict["bl_idname"] = cls_name
        cls_dict["bl_label"] = self.name

        cls_dict["input_template"] = self.generate_inputs()
        cls_dict["output_template"] = self.generate_outputs()

        self.make_props(cls_dict)

        # done with setup

        old_cls_ref = get_node_class_reference(cls_name)

        bases = (SvGroupNodeExp, Node, SverchCustomTreeNode)

        cls_ref = type(cls_name, bases, cls_dict)

        if old_cls_ref:
            sverchok.utils.unregister_node_class(old_cls_ref)
        sverchok.utils.register_node_class(cls_ref)

        return cls_ref
Exemple #11
0
 def frame_array(self, ts):
     tangents, normals, binormals = self.tangent_normal_binormal_array(ts)
     tangents = tangents / np.linalg.norm(tangents, axis=1)[np.newaxis].T
     matrices_np = np.dstack((normals, binormals, tangents))
     matrices_np = np.transpose(matrices_np, axes=(0,2,1))
     try:
         matrices_np = np.linalg.inv(matrices_np)
         return matrices_np, normals, binormals
     except np.linalg.LinAlgError as e:
         error("Some of matrices are singular:")
         for i, m in enumerate(matrices_np):
             if abs(np.linalg.det(m) < 1e-5):
                 error("M[%s] (t = %s):\n%s", i, ts[i], m)
         raise e
Exemple #12
0
    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())
        gist_description = f"Sverchok.{version_and_sha} | Blender.{app_version} | {ng.name} | {time_stamp}"

        # 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'}
Exemple #13
0
    def update_cls(self):
        """
        create or update the corresponding class reference
        """

        if not all((self.input_node, self.output_node)):
            error("Monad %s not set up correctly", self.name)
            return None

        cls_dict = {}

        if not self.cls_bl_idname:
            
            # the monad cls_bl_idname needs to be unique and cannot change
            monad_base_name = make_valid_identifier(self.name)
            monad_itentifier = id(self) ^ random.randint(0, 4294967296)

            cls_name = "SvGroupNode{}_{}".format(monad_base_name, monad_itentifier)
            # set the unique name for the class, depending on context this might fail
            # then we cannot do the setup of the class properly so abandon
            try:
                self.cls_bl_idname = cls_name
            except Exception:
                return None
        else:
            cls_name = self.cls_bl_idname

        self.verify_props()

        cls_dict["bl_idname"] = cls_name
        cls_dict["bl_label"] = self.name

        cls_dict["input_template"] = self.generate_inputs()
        cls_dict["output_template"] = self.generate_outputs()

        self.make_props(cls_dict)

        # done with setup

        old_cls_ref = get_node_class_reference(cls_name)

        bases = (SvGroupNodeExp, Node, SverchCustomTreeNode)

        cls_ref = type(cls_name, bases, cls_dict)

        if old_cls_ref:
            sverchok.utils.unregister_node_class(old_cls_ref)
        sverchok.utils.register_node_class(cls_ref)

        return cls_ref
Exemple #14
0
    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)

        os.remove(path)
        info("Removed `%s'", path)
        self.report({'INFO'}, "Removed `{}'".format(self.preset_name))

        return {'FINISHED'}
def compile_socket(link):

    try:
        link_data = (link.from_node.name, link.from_socket.index,
                     link.to_node.name, link.to_socket.index)
    except Exception as err:
        if "'NodeSocketColor' object has no attribute 'index'" in repr(err):
            debug('adding node reroute using socketname instead if index')
        else:
            error(repr(err))
        link_data = (link.from_node.name, link.from_socket.name,
                     link.to_node.name, link.to_socket.name)

    return link_data
Exemple #16
0
    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)

        os.remove(path)
        info("Removed `%s'", path)
        self.report({'INFO'}, "Removed `{}'".format(self.preset_name))

        return {'FINISHED'}
Exemple #17
0
def unpack_monad(nodes, node_ref):
    params = node_ref.get('params')
    if params:

        socket_prop_data = params.get('all_props')

        monad_name = params.get('monad')
        monad = bpy.data.node_groups[monad_name]
        if socket_prop_data:
            # including this to keep bw comp for trees that don't include this info.
            monad.set_all_props(socket_prop_data)

        cls_ref = monad.update_cls()
        node = nodes.new(cls_ref.bl_idname)

        # -- addition 1 --------- setting correct properties on sockets.
        cls_dict = params.get('cls_dict')
        input_template = cls_dict['input_template']
        for idx, (sock_name, sock_type, sock_props) in enumerate(input_template):
            socket_reference = node.inputs[idx]
            if sock_props:
                for prop, val in sock_props.items():
                    setattr(socket_reference, prop, val)

        # -- addition 2 --------- force push param values 
        # -- (this step is skipped by apply_core_props because this node has a cls_dict)
        for prop_data in ('float_props', 'int_props'):
            data_list = socket_prop_data.get(prop_data)
            if not data_list:
                continue

            for k, v in data_list.items():
                if hasattr(node, k):
                    if k in params:
                        setattr(node, k, params[k])
                    # else:
                    #    print(k, 'not in', params)
                #else:
                #    print('node name:', node, node.name, 'has no property called', k, 'yet..')

        # node.output_template = cls_dict['output_template']
        for attr in 'vectorize', 'loop_me', 'loops_max', 'loops':
            if attr in params:
                setattr(node, attr, params[attr])

        return node
    else:
        error('no parameters found! .json might be broken')                
Exemple #18
0
 def check_dir(directory, fnames):
     dir_name = basename(directory)
     index_name = dir_name + "_index.rst"
     index_file_path = join(directory, index_name)
     bad_files = []
     for fname in fnames:
         if fname.endswith("_index.rst"):
             continue
         if not check(index_file_path, fname):
             bad_files.append(fname)
     if bad_files:
         error("The following files are not mentioned in %s:\n%s",
               index_name, "\n".join(bad_files))
         self.fail(
             "Not all node documentation files are mentioned in their corresponding indexes."
         )
Exemple #19
0
    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.')
Exemple #20
0
def write_json(layout_dict, destination_path):

    try:
        m = json.dumps(layout_dict, sort_keys=True, indent=2)
    except Exception as err:
        error(repr(err))
        info(layout_dict)

    # optional post processing step
    post_processing = False
    if post_processing:
        flatten = lambda match: r' {}'.format(match.group(1), m)
        m = re.sub(r'\s\s+(\d+)', flatten, m)

    with open(destination_path, 'w') as node_tree:
        node_tree.writelines(m)
Exemple #21
0
        def check_dir(directory):
            dir_name = basename(directory)
            bad_files = []
            for doc_path in glob(join(directory, "*.rst")):
                if doc_path.endswith("_index.rst"):
                    continue
                doc_file = basename(doc_path)
                doc_name, ext = splitext(doc_file)
                py_name = doc_name + ".py"
                py_path = join(nodes_dir, dir_name, py_name)
                if not exists(py_path):
                    bad_files.append(doc_file)

            if bad_files:
                error("Category %s: The following documentation files do not have respective python modules:\n%s", dir_name, "\n".join(bad_files))
                self.fail("There are excessive documentation files.")
def write_json(layout_dict, destination_path):

    try:
        m = json.dumps(layout_dict, sort_keys=True, indent=2)
    except Exception as err:
        error(repr(err))
        info(layout_dict)

    # optional post processing step
    post_processing = False
    if post_processing:
        flatten = lambda match: r' {}'.format(match.group(1), m)
        m = re.sub(r'\s\s+(\d+)', flatten, m)

    with open(destination_path, 'w') as node_tree:
        node_tree.writelines(m)
Exemple #23
0
    def execute(self, context):
        if not self.category:
            msg = "Category name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}
        if self.category == GENERAL or self.category in get_category_names():
            msg = "Category named `{}' already exists; refusing to overwrite existing category"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        path = get_presets_directory(category=self.category, mkdir=True)
        info("Created new category `%s' at %s", self.category, path)
        self.report({'INFO'}, "Created new category {}".format(self.category))
        return {'FINISHED'}
def apply_core_props(node, node_ref):
    params = node_ref['params']
    if 'cls_dict' in params:
        return
    for p in params:
        val = params[p]
        try:
            setattr(node, p, val)
        except Exception as e:
            # FIXME: this is ugly, need to find better approach
            error_message = repr(e)  # for reasons
            error(error_message)
            msg = 'failed to assign value to the node'
            debug("`%s': %s = %s: %s", node.name, p, val, msg)
            if "val: expected sequence items of type boolean, not int" in error_message:
                debug("going to convert a list of ints to a list of bools and assign that instead")
                setattr(node, p, [bool(i) for i in val])
    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 apply_core_props(node, node_ref):
    params = node_ref['params']
    if 'cls_dict' in params:
        return
    for p in params:
        val = params[p]
        try:
            setattr(node, p, val)
        except Exception as e:
            # FIXME: this is ugly, need to find better approach
            error_message = repr(e)  # for reasons
            error(error_message)
            msg = 'failed to assign value to the node'
            debug("`%s': %s = %s: %s", node.name, p, val, msg)
            if "val: expected sequence items of type boolean, not int" in error_message:
                debug("going to convert a list of ints to a list of bools and assign that instead")
                setattr(node, p, [bool(i) for i in val])
Exemple #27
0
    def execute(self, context):
        bpy.ops.text.select_line()
        bpy.ops.text.copy()
        copied_text = bpy.data.window_managers[0].clipboard
        if "def sv_main(" not in copied_text:
            self.report({'INFO'}, "ERROR - LOOK CONSOLE")
            error(sv_error_message)
            return {'CANCELLED'}
        answer = converted(copied_text)

        if answer:
            info(answer)
            bpy.data.window_managers[0].clipboard = answer
            bpy.ops.text.move(type='LINE_BEGIN')
            bpy.ops.text.move(type='NEXT_LINE')
            bpy.ops.text.paste()
        return {'FINISHED'}
def unpack_monad(nodes, node_ref):
    params = node_ref.get('params')
    if params:
        socket_prop_data = params.get('all_props')

        monad_name = params.get('monad')
        monad = bpy.data.node_groups[monad_name]
        if socket_prop_data:
            # including this to keep bw comp for trees that don't include this info.
            monad.set_all_props(socket_prop_data)

        cls_ref = monad.update_cls()
        node = nodes.new(cls_ref.bl_idname)

        # -- addition 1 --------- setting correct properties on sockets.
        cls_dict = params.get('cls_dict')
        input_template = cls_dict['input_template']
        for idx, (sock_name, sock_type, sock_props) in enumerate(input_template):
            socket_reference = node.inputs[idx]
            if sock_props:
                for prop, val in sock_props.items():
                    setattr(socket_reference, prop, val)

        # -- addition 2 --------- force push param values 
        # -- (this step is skipped by apply_core_props because this node has a cls_dict)
        for prop_data in ('float_props', 'int_props'):
            data_list = socket_prop_data.get(prop_data)
            if not data_list:
                continue

            for k, v in data_list.items():
                if hasattr(node, k):
                    if k in params:
                        setattr(node, k, params[k])
                    # else:
                    #    print(k, 'not in', params)
                #else:
                #    print('node name:', node, node.name, 'has no property called', k, 'yet..')


        # node.output_template = cls_dict['output_template']

        return node
    else:
        error('no parameters found! .json might be broken')                
    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'}
Exemple #30
0
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)
Exemple #31
0
    def execute(self, context):
        if not self.preset_name:
            msg = "Preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        if not self.filepath:
            msg = "Source file path is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        target_path = get_preset_path(self.preset_name)
        shutil.copy(self.filepath, target_path)
        msg = "Imported `{}' as `{}'".format(self.filepath, self.preset_name)
        info(msg)
        self.report({'INFO'}, msg)

        return {'FINISHED'}
Exemple #32
0
    def execute(self, context):
        if not self.preset_name:
            msg = "Preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        if not self.filepath:
            msg = "Target file path is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        existing_path = get_preset_path(self.preset_name, category=self.category)
        shutil.copy(existing_path, self.filepath)
        msg = "Saved `{} / {}' as `{}'".format(self.category, self.preset_name, self.filepath)
        info(msg)
        self.report({'INFO'}, msg)

        return {'FINISHED'}
Exemple #33
0
    def frame_array(self, ts, on_zero_curvature=ASIS, tangent_delta=None):
        """
        input:
            * ts - np.array of shape (n,)
            * on_zero_curvature - what to do if the curve has zero curvature at one of T values.
              The supported options are:
              * SvCurve.FAIL: raise ZeroCurvatureException
              * SvCurve.RETURN_NONE: return None
              * SvCurve.ASIS: do not perform special check for this case, the
                algorithm will raise a general LinAlgError exception if it can't calculate the matrix.

        output: tuple:
            * matrices: np.array of shape (n, 3, 3)
            * normals: np.array of shape (n, 3)
            * binormals: np.array of shape (n, 3)
        """
        h = self.get_tangent_delta(tangent_delta)
        tangents, normals, binormals = self.tangent_normal_binormal_array(
            ts, tangent_delta=h)

        if on_zero_curvature != SvCurve.ASIS:
            zero_normal = np.linalg.norm(normals, axis=1) < 1e-6
            if zero_normal.any():
                if on_zero_curvature == SvCurve.FAIL:
                    raise ZeroCurvatureException(np.unique(ts[zero_normal]),
                                                 zero_normal)
                elif on_zero_curvature == SvCurve.RETURN_NONE:
                    return None

        tangents = tangents / np.linalg.norm(tangents, axis=1)[np.newaxis].T
        matrices_np = np.dstack((normals, binormals, tangents))
        matrices_np = np.transpose(matrices_np, axes=(0, 2, 1))
        try:
            matrices_np = np.linalg.inv(matrices_np)
            return matrices_np, normals, binormals
        except np.linalg.LinAlgError as e:
            error("Some of matrices are singular:")
            for i, m in enumerate(matrices_np):
                if abs(np.linalg.det(m) < 1e-5):
                    error("M[%s] (t = %s):\n%s", i, ts[i], m)
            raise e
Exemple #34
0
    def execute(self, context):
        if not self.category:
            msg = "Preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}
        if self.category == GENERAL:
            msg = "General category can not be deleted"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        path = get_presets_directory(category=self.category)
        files = glob(join(path, "*"))
        if files:
            msg = "Category `{}' is not empty; refusing to delete non-empty category.".format(
                self.category)
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}
        os.rmdir(path)

        ntree = context.space_data.node_tree
        panel_props = ntree.preset_panel_properties
        panel_props.category = GENERAL

        return {'FINISHED'}
Exemple #35
0
    def execute(self, context):
        if not self.preset_name:
            msg = "Preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        if not self.gist_id:
            msg = "Gist ID is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        gist_data = sv_IO_panel_tools.load_json_from_gist(self.gist_id, self)
        target_path = get_preset_path(self.preset_name)
        if os.path.exists(target_path):
            msg = "Preset named `{}' already exists. Refusing to rewrite existing preset.".format(self.preset_name)
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}
        
        with open(target_path, 'wb') as jsonfile:
            gist_data = json.dumps(gist_data, sort_keys=True, indent=2).encode('utf8')
            jsonfile.write(gist_data)

        msg = "Imported `{}' as `{}'".format(self.gist_id, self.preset_name)
        info(msg)
        self.report({'INFO'}, msg)

        return {'FINISHED'}
Exemple #36
0
    def execute(self, context):
        if not self.id_tree:
            msg = "Node tree is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        if not self.preset_name:
            msg = "Preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        ng = bpy.data.node_groups[self.id_tree]

        nodes = list(filter(lambda n: n.select, ng.nodes))
        if not len(nodes):
            msg = "There are no selected nodes to export"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        layout_dict = JSONExporter.get_nodes_structure([n for n in ng.nodes if n.select])
        preset = SvPreset(name=self.preset_name, category = self.category)
        preset.make_add_operator()
        destination_path = preset.path
        json.dump(layout_dict, open(destination_path, 'w'), sort_keys=True, indent=2)
        msg = 'exported to: ' + destination_path
        self.report({"INFO"}, msg)
        info(msg)

        return {'FINISHED'}
Exemple #37
0
    def execute(self, context):
        if not self.id_tree:
            msg = "Node tree is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        if not self.preset_name:
            msg = "Preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        ng = bpy.data.node_groups[self.id_tree]

        nodes = list(filter(lambda n: n.select, ng.nodes))
        if not len(nodes):
            msg = "There are no selected nodes to export"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        layout_dict = create_dict_of_tree(ng, selected=True)
        preset = SvPreset(name=self.preset_name)
        preset.make_add_operator()
        destination_path = preset.path
        write_json(layout_dict, destination_path)
        msg = 'exported to: ' + destination_path
        self.report({"INFO"}, msg)
        info(msg)

        return {'FINISHED'}
Exemple #38
0
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 get_file_obj_from_zip(fullpath):
    '''
    fullpath must point to a zip file.
    usage:
        nodes_json = get_file_obj_from_zip(fullpath)
        print(nodes_json['export_version'])
    '''
    with zipfile.ZipFile(fullpath, "r") as jfile:
        exported_name = ""
        for name in jfile.namelist():
            if name.endswith('.json'):
                exported_name = name
                break

        if not exported_name:
            error('zip contains no files ending with .json')
            return

        debug(exported_name + ' <')
        fp = jfile.open(exported_name, 'r')
        m = fp.read().decode()
        return json.loads(m)
    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
Exemple #41
0
    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
Exemple #42
0
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
Exemple #43
0
def get_file_obj_from_zip(fullpath):
    '''
    fullpath must point to a zip file.
    usage:
        nodes_json = get_file_obj_from_zip(fullpath)
        print(nodes_json['export_version'])
    '''
    with zipfile.ZipFile(fullpath, "r") as jfile:
        exported_name = ""
        for name in jfile.namelist():
            if name.endswith('.json'):
                exported_name = name
                break

        if not exported_name:
            error('zip contains no files ending with .json')
            return

        debug(exported_name + ' <')
        fp = jfile.open(exported_name, 'r')
        m = fp.read().decode()
        return json.loads(m)
Exemple #44
0
    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 uploading the gist, check your internet connection!")

        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:
            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)
Exemple #46
0
        def check_category(directory):
            dir_name = basename(directory)
            bad_files = []
            known = []

            for module_path in glob(join(directory, "*.py")):
                module_file = basename(module_path)
                if module_file == "__init__.py":
                    continue
                module_name, ext = splitext(module_file)
                doc_name = module_name + ".rst"
                doc_path = join(docs_dir, dir_name, doc_name)
                if not exists(doc_path):
                    if module_file in known_problems:
                        known.append(module_file)
                    else:
                        bad_files.append(module_file)

            if known:
                info("Category %s: Tolerating unexistance of the documentation for the following nodes for now:\n%s", dir_name, "\n".join(known))

            if bad_files:
                error("Category %s: The following nodes do not have corresponding documentation files:\n%s", dir_name, "\n".join(bad_files))
                self.fail("Not all nodes have corresponding documentation; missing are:\n{}".format("\n".join(bad_files)))
Exemple #47
0
    def execute(self, context):
        if not self.old_name:
            msg = "Old preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        if not self.new_name:
            msg = "New preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        preset = SvPreset(name=self.old_name, category=self.old_category)
        preset.meta['description'] = self.description
        preset.meta['keywords'] = self.keywords
        preset.meta['author'] = self.author
        preset.meta['license'] = self.license
        preset.save()

        category_changed = self.allow_change_category and (self.new_category !=
                                                           self.old_category)
        if self.new_name != self.old_name or category_changed:
            old_path = get_preset_path(self.old_name,
                                       category=self.old_category)
            new_path = get_preset_path(self.new_name,
                                       category=self.new_category)

            if os.path.exists(new_path):
                msg = "Preset named `{}' already exists. Refusing to rewrite existing preset.".format(
                    self.new_name)
                error(msg)
                self.report({'ERROR'}, msg)
                return {'CANCELLED'}

            os.rename(old_path, new_path)
            preset.name = self.new_name
            preset.category = self.new_category
            info("Renamed `%s' to `%s'", old_path, new_path)
            self.report({'INFO'},
                        "Renamed `{}' to `{}'".format(self.old_name,
                                                      self.new_name))

        bpy.utils.unregister_class(preset_add_operators[(self.old_category,
                                                         self.old_name)])
        del preset_add_operators[(self.old_category, self.old_name)]
        preset.make_add_operator()

        return {'FINISHED'}
Exemple #48
0
    def execute(self, context):
        if not self.old_name:
            msg = "Old preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        if not self.new_name:
            msg = "New preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        preset = SvPreset(name = self.old_name)
        preset.meta['description'] = self.description
        preset.meta['author'] = self.author
        preset.meta['license'] = self.license
        preset.save()

        if self.new_name != self.old_name:
            old_path = get_preset_path(self.old_name)
            new_path = get_preset_path(self.new_name)

            if os.path.exists(new_path):
                msg = "Preset named `{}' already exists. Refusing to rewrite existing preset.".format(self.new_name)
                error(msg)
                self.report({'ERROR'}, msg)
                return {'CANCELLED'}
            
            os.rename(old_path, new_path)
            preset.name = self.new_name
            info("Renamed `%s' to `%s'", old_path, new_path)
            self.report({'INFO'}, "Renamed `{}' to `{}'".format(self.old_name, self.new_name))

        bpy.utils.unregister_class(preset_add_operators[self.old_name])
        del preset_add_operators[self.old_name]
        preset.make_add_operator()

        return {'FINISHED'}
Exemple #49
0
    def execute(self, context):
        if not self.id_tree:
            msg = "Node tree is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        if not self.preset_name:
            msg = "Preset name is not specified"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        ng = bpy.data.node_groups[self.id_tree]

        nodes = list(filter(lambda n: n.select, ng.nodes))
        if not len(nodes):
            msg = "There are no selected nodes to export"
            error(msg)
            self.report({'ERROR'}, msg)
            return {'CANCELLED'}

        # the operator can be used for both preset importing of a node and preset from a bunch of selected nodes
        if self.is_node_preset:
            layout_dict = JSONExporter.get_node_structure(nodes[0])
        else:
            layout_dict = JSONExporter.get_tree_structure(ng, True)

        preset = SvPreset(name=self.preset_name, category=self.category)
        preset.make_add_operator()
        destination_path = preset.path
        json.dump(layout_dict, open(destination_path, 'w'),
                  indent=2)  # sort keys is not expected by the exporter
        msg = 'exported to: ' + destination_path
        self.report({"INFO"}, msg)
        info(msg)

        return {'FINISHED'}
 def test_get_data_nesting_level_2(self):
     with self.assertRaises(TypeError):
         data = [dict(), 3]
         level = get_data_nesting_level(data)
         error("get_data_nesting_level() returned %s", level)
 def test_ensure_nesting_level_2(self):
     with self.assertRaises(TypeError):
         data = [[[17]]]
         result = ensure_nesting_level(data, 1)
         error("ensure_nesting_level() returned %s", result)
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