Exemplo n.º 1
0
 def toggle(self):
     """
     Toggle the selection state of the current face.
     """
     self.current_face.select = not self.current_face.select
     debug("Set face #%s selection := %s", self.current_face.index,
           self.current_face.select)
Exemplo n.º 2
0
def register():
    global our_menu_classes

    debug("Registering sverchok-open3d")

    settings.register()
    icons.register()
    sockets.register()

    register_nodes()
    extra_nodes = importlib.import_module(".nodes", "sverchok_open3d")
    auto_gather_node_classes(extra_nodes)

    add_nodes_to_sv()
    menu.register()

    cats_menu = make_categories() # This would load every sverchok-open3d category straight in the Sv menu

    menu_category_provider = SvO3CategoryProvider("SVERCHOK_OPEN3D", cats_menu, DOCS_LINK, use_custom_menu=True, custom_menu='NODEVIEW_MT_Open3Dx')
    register_extra_category_provider(menu_category_provider) #if 'SVERCHOK_OPEN3D' in nodeitems_utils._node_categories:
    examples.register()

    # with make_categories() This would load every sverchok-open3d category straight in the Sv menu
    # our_menu_classes = make_extra_category_menus()

    show_welcome()
Exemplo n.º 3
0
def binpack(nodes, max_bin_height, spacing=0):
    ''' Add nodes to the bins of given max bin height and spacing '''
    if nodes:
        debug("There are %d nodes to bin pack" % (len(nodes)))
        for node in nodes:
            if node == None:
                debug("WARNING: a None node in the spawned nodes???")
    else:
        debug("WARNING: there are no nodes to bin pack!!!")
        return []

    scale = 1.0 / get_dpi_factor()  # dpi adjustment scale
    items = [NodeItem(node.dimensions.x * scale, node.dimensions.y * scale, node.bl_idname, node) for node in nodes]
    items = sorted(items, key=lambda item: item.height, reverse=True)

    bins = []
    for item in items:
        # try to fit the next item into the first bin that is not yet full
        for n, bin in enumerate(bins):  # check all the bins created so far
            if bin.height + len(bin.items) * spacing + item.height <= max_bin_height:
                # bin not full ? => add item
                debug("ADDING node <%s> to bin #%d" % (item.name, n))
                bin.append(item)
                break  # proceed to the next item
        else:  # item didn't fit into any bin ? => add it to a new bin
            debug('ADDING node <%s> to new bin' % (item.name))
            bin = Bin()
            bin.append(item)
            bins.append(bin)

    return bins
Exemplo n.º 4
0
    def assert_logs_no_errors(self):
        """
        Assert that the code does not write any ERROR to the log.
        Usage:

            with self.assert_logs_no_errors():
                info("this is just an information, not error")

        """

        has_errors = False

        class Handler(logging.Handler):
            def emit(self, record):
                nonlocal has_errors
                if record.levelno >= logging.ERROR:
                    has_errors = True

        handler = Handler()
        logging.getLogger().addHandler(handler)

        try:
            debug("=== \/ === [%s] Here should be no errors === \/ ===",
                  self.__class__.__name__)
            yield handler
            self.assertFalse(has_errors, "There were some errors logged")
        finally:
            debug("=== /\ === [%s] There should be no errors === /\ ===",
                  self.__class__.__name__)
            logging.getLogger().handlers.remove(handler)
Exemplo n.º 5
0
def add_keymap():

    # handle the keymap
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon

    if not kc:
        debug('no keyconfig path found. that\'s ok')
        return

    km = kc.keymaps.new(name='Text', space_type='TEXT_EDITOR')
    keymaps = km.keymap_items

    if 'noderefresh_from_texteditor' in dir(bpy.ops.text):
        ''' SHORTCUT 1 Node Refresh: Ctrl + Return '''
        ident_str = 'text.noderefresh_from_texteditor'
        if not (ident_str in keymaps):
            new_shortcut = keymaps.new(ident_str, 'RET', 'PRESS', ctrl=1, head=0)
            addon_keymaps.append((km, new_shortcut))

        ''' SHORTCUT 2 Show svplugMenu Ctrl + I (no text selected) '''
        new_shortcut = keymaps.new('wm.call_menu', 'I', 'PRESS', ctrl=1, head=0)
        new_shortcut.properties.name = 'TEXT_MT_svplug_menu'
        addon_keymaps.append((km, new_shortcut))

        debug('added keyboard items to Text Editor.')
Exemplo n.º 6
0
def _create_node_tree(
    name="TestingTree",
    must_not_exist=True,
) -> bpy.types.BlendDataNodeTrees:
    """
    Create new Sverchok node tree in the scene.

    Description: hello

    Args:
        name (str, optional): Defaults to "TestingTree"
        must_not_exist (bool, optional): Defaults to True.

            If must_not_exist == True (default), then it is checked that
            the tree with such name did not exist before. If it exists,
            an exception is raised.
            If must_not_exist == False, then new tree will be created anyway,
            but it can be created with another name
            (standard Blender's renaming)

    Raises:
        _ExistingTreeError: Tree name already existed

    Returns:
        bpy.BlendDataNodeTrees: Created nodeTree
    """
    if must_not_exist:
        if name in bpy.data.node_groups:
            raise _ExistingTreeError(
                f"Will not create tree `{name}': it already exists", )
    debug(f"Creating tree: {name}")
    return bpy.data.node_groups.new(name=name, type="SverchCustomTreeType")
Exemplo n.º 7
0
    def process_node(self, context):
        '''
        Doesn't work as intended, inherited functions can't be used for bpy.props
        update= ...
        Still this is called from updateNode
        '''
        if self.id_data.bl_idname == "SverchCustomTreeType":
            if self.id_data.is_frozen():
                return

            # self.id_data.has_changed = True

            if data_structure.DEBUG_MODE:
                a = time.perf_counter()
                process_from_node(self)
                b = time.perf_counter()
                debug("Partial update from node %s in %s", self.name,
                      round(b - a, 4))
            else:
                process_from_node(self)
        elif self.id_data.bl_idname == "SverchGroupTreeType":
            monad = self.id_data
            for instance in monad.instances:
                instance.process_node(context)
        else:
            pass
Exemplo n.º 8
0
 def update_point(self, context):
     if hasattr(context, 'node') and hasattr(context.node, 'on_update'):
         context.node.on_update(context)
     else:
         debug(
             "Node is not defined in this context, so will not update the node."
         )
Exemplo n.º 9
0
    def generate_layout(fullpath, nodes_json):

        # it may be necessary to store monads as dicts instead of string/json
        # this will handle both scenarios
        if isinstance(nodes_json, str):
            nodes_json = json.loads(nodes_json)
            debug('==== loading monad ====')
        info(('#' * 12) + nodes_json['export_version'])

        # create all nodes and groups '''
        update_lists = nodes_json['update_lists']
        nodes_to_import = nodes_json['nodes']
        if center is not None:
            center_nodes(nodes_to_import, center)
        groups_to_import = nodes_json.get('groups', {})

        add_groups(groups_to_import)  # this return is not used yet
        name_remap = add_nodes(ng, nodes_to_import, nodes, create_texts)

        # now connect them / prevent unnecessary updates
        ng.freeze(hard=True)
        make_links(update_lists, name_remap)

        # set frame parents '''
        place_frames(ng, nodes_json, name_remap)

        # clean up
        old_nodes.scan_for_old(ng)
        ng.unfreeze(hard=True)

        ng.update()
        ng.update_tag()
Exemplo n.º 10
0
    def generate_layout(fullpath, nodes_json):

        # it may be necessary to store monads as dicts instead of string/json
        # this will handle both scenarios
        if isinstance(nodes_json, str):
            nodes_json = json.loads(nodes_json)
            debug('==== loading monad ====')
        info(('#' * 12) + nodes_json['export_version'])

        # create all nodes and groups '''
        update_lists = nodes_json['update_lists']
        nodes_to_import = nodes_json['nodes']
        if center is not None:
            center_nodes(nodes_to_import, center)
        groups_to_import = nodes_json.get('groups', {})

        add_groups(groups_to_import)  # this return is not used yet
        name_remap = add_nodes(ng, nodes_to_import, nodes, create_texts)

        # now connect them / prevent unnecessary updates
        ng.freeze(hard=True)
        make_links(update_lists, name_remap)

        # set frame parents '''
        place_frames(ng, nodes_json, name_remap)

        # clean up
        old_nodes.scan_for_old(ng)
        ng.unfreeze(hard=True)
        
        ng.update()
        ng.update_tag()
Exemplo n.º 11
0
def SvGetSocket(socket, deepcopy=True):
    """gets socket data from socket,
    if deep copy is True a deep copy is make_dep_dict,
    to increase performance if the node doesn't mutate input
    set to False and increase performance substanstilly
    """
    global socket_data_cache
    if socket.is_linked:
        other = socket.other
        s_id = other.socket_id
        s_ng = other.id_data.tree_id
        if s_ng not in socket_data_cache:
            raise LookupError
        if s_id in socket_data_cache[s_ng]:
            out = socket_data_cache[s_ng][s_id]
            if deepcopy:
                return sv_deep_copy(out)
            else:
                return out
        else:
            if data_structure.DEBUG_MODE:
                debug(
                    f"cache miss: {socket.node.name} -> {socket.name} from: {other.node.name} -> {other.name}"
                )
            raise SvNoDataError(socket, msg="not found in socket_data_cache")
    # not linked
    raise SvNoDataError(socket)
Exemplo n.º 12
0
    def make_add_operator(self):
        """
        Create operator class which adds specific preset nodes to current node tree.
        Tooltip (docstring) for that operator is copied from metainfo/description field.
        """

        global preset_add_operators
        if self.category is None:
            self.category = GENERAL

        if (self.category, self.name) not in preset_add_operators:

            preset_name = self.name if not self.description else self.description

            class SverchPresetAddOperator(bpy.types.Operator):
                bl_idname = "node.sv_preset_" + get_preset_idname_for_operator(self.name, self.category)
                bl_label = "Add {} preset ({} category)".format(preset_name, self.category)
                bl_options = {'REGISTER', 'UNDO'}

                cursor_x: bpy.props.IntProperty()
                cursor_y: bpy.props.IntProperty()

                @classmethod
                def poll(cls, context):
                    try:
                        return context.space_data.node_tree.bl_idname in {'SverchCustomTreeType', 'SverchGroupTreeType'}
                    except:
                        return False

                def execute(operator, context):
                    # please not be confused: "operator" here references to
                    # SverchPresetAddOperator instance, and "self" references to
                    # SvPreset instance.  
                    ntree = context.space_data.node_tree
                    id_tree = ntree.name
                    ng = bpy.data.node_groups[id_tree]

                    center = tuple(context.space_data.cursor_location)
                    # Deselect everything, so as a result only imported nodes
                    # will be selected
                    bpy.ops.node.select_all(action='DESELECT')
                    import_tree(ng, self.path, center = center)
                    bpy.ops.transform.translate('INVOKE_DEFAULT')
                    return {'FINISHED'}

                def invoke(self, context, event):
                    self.cursor_x = event.mouse_region_x
                    self.cursor_y = event.mouse_region_y
                    return self.execute(context)

            SverchPresetAddOperator.__name__ = self.name
            SverchPresetAddOperator.__doc__ = self.meta.get("description", self.name)
            if self.standard:
                SverchPresetAddOperator.__doc__ += " [standard]"

            preset_add_operators[(self.category, self.name)] = SverchPresetAddOperator
            bpy.utils.register_class(SverchPresetAddOperator)
            debug("Registered: %s",
                "node.sv_preset_" + get_preset_idname_for_operator(self.name, self.category))
Exemplo n.º 13
0
    def execute(self, context):
        if not self.old_node_name:
            self.report({'ERROR'}, "Old node name is not provided")
            return {'CANCELLED'}

        if not self.new_bl_idname:
            self.report({'ERROR'}, "New node bl_idname is not provided")
            return {'CANCELLED'}

        tree = context.space_data.edit_tree

        old_node = tree.nodes[self.old_node_name]
        new_node = tree.nodes.new(self.new_bl_idname)
        # Copy UI properties
        ui_props = ['location', 'height', 'width', 'label', 'hide']
        for prop_name in ui_props:
            setattr(new_node, prop_name, getattr(old_node, prop_name))
        # Copy ID properties
        for prop_name, prop_value in old_node.items():
            new_node[prop_name] = old_node[prop_name]

        # Copy incoming / outgoing links
        old_in_links = [link for link in tree.links if link.to_node == old_node]
        old_out_links = [link for link in tree.links if link.from_node == old_node]

        for old_link in old_in_links:
            new_target_socket_name = self.get_new_input_name(old_link.to_socket.name)
            if new_target_socket_name in new_node.inputs:
                new_target_socket = new_node.inputs[new_target_socket_name]
                new_link = tree.links.new(old_link.from_socket, new_target_socket)
            else:
                debug("New node %s has no input named %s, skipping", new_node.name, new_target_socket_name)
            tree.links.remove(old_link)

        for old_link in old_out_links:
            new_source_socket_name = self.get_new_output_name(old_link.from_socket.name)
            # We have to remove old link before creating new one
            # Blender would not allow two links pointing to the same target socket
            old_target_socket = old_link.to_socket
            tree.links.remove(old_link)
            if new_source_socket_name in new_node.outputs:
                new_source_socket = new_node.outputs[new_source_socket_name]
                new_link = tree.links.new(new_source_socket, old_target_socket)
            else:
                debug("New node %s has no output named %s, skipping", new_node.name, new_source_socket_name)

        if hasattr(new_node, "migrate_from"):
            # Allow new node to copy what generic code could not.
            new_node.migrate_from(old_node)

        msg = "Node `{}' ({}) has been replaced with new node `{}' ({})".format(
                old_node.name, old_node.bl_idname,
                new_node.name, new_node.bl_idname)
        info(msg)
        self.report({'INFO'}, msg)

        tree.nodes.remove(old_node)

        return {'FINISHED'}
Exemplo n.º 14
0
def get_color(bl_id):
    """
    Get color for bl_id
    """
    if not colors_cache:
        debug("building color cache")
        rebuild_color_cache()
    return colors_cache.get(bl_id)
Exemplo n.º 15
0
def create_node(node_type, tree_name=None):
    """
    Create Sverchok node by it's bl_idname.
    """
    if tree_name is None:
        tree_name = "TestingTree"
    debug("Creating node of type %s", node_type)
    return bpy.data.node_groups[tree_name].nodes.new(type=node_type)
Exemplo n.º 16
0
def create_node(node_type, tree_name=None):
    """
    Create Sverchok node by it's bl_idname.
    """
    if tree_name is None:
        tree_name = "TestingTree"
    debug("Creating node of type %s", node_type)
    return bpy.data.node_groups[tree_name].nodes.new(type=node_type)
Exemplo n.º 17
0
def get_color(bl_id):
    """
    Get color for bl_id
    """
    if not colors_cache:
        debug("building color cache")
        rebuild_color_cache()
    return colors_cache.get(bl_id)
Exemplo n.º 18
0
    def click(self):
        """
        Jump to the face which is beyond the edge
        at which the turtle is looking currently.
        This turtle is a bit strange, because when it jumps it
        turns around, to look at the same edge it was looking, but
        from another side:

        +----+----+      +----+----+
        | @> |    |  --> |    | <@ |
        +----+----+      +----+----+

        This changes the selection state of the face where the turtle
        stepped, if it is in "start_selecting()" mode, according to selection
        mask.

        This updates custom data layers of the face where the turtle stepped,
        if it is in "start_painting()" mode, according to painting masks.
        """
        self.current_index += 1
        self.current_face[self.index_layer] = self.current_index
        next_loop = self.current_loop.link_loop_radial_next
        self.current_loop = next_loop
        self.current_face = next_loop.face

        debug("Current face # := %s", self.current_face.index)

        if self.selection_mode == self.MASK:
            if not self.selection_mask:
                raise Exception("Selection mode is set to MASK, but mask is not specified")
            n = len(self.selection_mask)
            self.selection_cycle_index = (self.selection_cycle_index + 1) % n
            mode = self.selection_mask[self.selection_cycle_index]
            if mode not in [self.SELECT, self.UNSELECT, self.TOGGLE, 0, 1, False, True]:
                raise Exception("Unsupported flag in the selection mask")
            if mode == True or mode == 1:
                mode = self.SELECT
            elif mode == False or mode == 0:
                mode = self.UNSELECT
        else:
            mode = self.selection_mode
        if mode == self.SELECT:
            self.select()
        elif mode == self.UNSELECT:
            self.unselect()
        elif mode == self.TOGGLE:
            self.toggle()

        if self.is_painting:
            for painting_layer in self.painting_layer.values():
                painting_mask = self.painting_mask.get(painting_layer.name)
                if not painting_mask:
                    raise Exception("Painting layer is set, but painting mask is not")
                n = len(painting_mask)
                self.painting_index[painting_layer.name] = (self.painting_index[painting_layer.name] + 1) % n
                value = painting_mask[self.painting_index[painting_layer.name]]
                self.current_face[painting_layer] = value
                debug("Paint face #%s, layer `%s' with value `%s'", self.current_face.index, painting_layer.name, value)
Exemplo n.º 19
0
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
Exemplo n.º 20
0
 def start(self):
     debug("* Timer {0}: START".format(self.timer_id))
     if self.timer_status in [TIMER_STATUS_STOPPED, TIMER_STATUS_EXPIRED]:
         debug("starting from zero")
         self.timer_time = 0
         self.timer_start_frame = bpy.context.scene.frame_current
         self.timer_loop_count = 0
     self.timer_status = TIMER_STATUS_STARTED
     self.last_timer_status = TIMER_STATUS_STARTED
Exemplo n.º 21
0
 def finish_task(cls):
     try:
         gc.enable()
         debug(
             f'Global update - {int((time() - cls._start_time) * 1000)}ms')
         cls._report_progress()
     finally:
         cls._event, cls._handler, cls._node_tree_area, cls._last_node, cls._start_time = [
             None
         ] * 5
Exemplo n.º 22
0
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)
Exemplo n.º 23
0
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)
Exemplo n.º 24
0
    def save(self):
        if self._data is None:
            debug("Preset `%s': no data was loaded, nothing to save.", self.name)
            return

        data = json.dumps(self.data, sort_keys=True, indent=2).encode('utf8')
        with open(self.path, 'wb') as jsonfile:
            jsonfile.write(data)

        info("Saved preset `%s'", self.name)
Exemplo n.º 25
0
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)
Exemplo n.º 26
0
def get_node_tree(name=None):
    """
    Return existing node tree, or raise an exception if there is no such.
    """
    if name is None:
        name = "TestingTree"
    if name in bpy.data.node_groups:
        debug("Using existing tree: %s", name)
        return bpy.data.node_groups[name]
    else:
        raise Exception("There is no node tree named `{}'".format(name))
Exemplo n.º 27
0
def get_node_tree(name=None):
    """
    Return existing node tree, or raise an exception if there is no such.
    """
    if name is None:
        name = "TestingTree"
    if name in bpy.data.node_groups:
        debug("Using existing tree: %s", name)
        return bpy.data.node_groups[name]
    else:
        raise Exception("There is no node tree named `{}'".format(name))
Exemplo n.º 28
0
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)
Exemplo n.º 29
0
def get_or_create_node_tree(name=None):
    """
    Create new Sverchok node tree or reuse existing one.
    """
    if name is None:
        name = "TestingTree"
    if name in bpy.data.node_groups:
        debug("Using existing tree: %s", name)
        return bpy.data.node_groups[name]
    else:
        return create_node_tree(name)
Exemplo n.º 30
0
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
Exemplo n.º 31
0
def get_or_create_node_tree(name=None):
    """
    Create new Sverchok node tree or reuse existing one.
    """
    if name is None:
        name = "TestingTree"
    if name in bpy.data.node_groups:
        debug("Using existing tree: %s", name)
        return bpy.data.node_groups[name]
    else:
        return create_node_tree(name)
Exemplo n.º 32
0
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
Exemplo n.º 33
0
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
Exemplo n.º 34
0
def perform_scripted_node_inject(node, node_ref):
    '''
    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.

    '''
    texts = bpy.data.texts
    params = node_ref.get('params')
    if params:

        script_name = params.get('script_name')
        script_content = params.get('script_str')

        with node.sv_throttle_tree_update():

            if script_name and not (script_name in texts):
                new_text = texts.new(script_name)
                new_text.from_string(script_content)
            elif script_name and (script_name in texts):
                # This was added to fix existing texts with the same name but no / different content.
                if texts[script_name].as_string() == script_content:
                    debug(
                        "SN skipping text named `%s' - their content are the same",
                        script_name)
                else:
                    info(
                        "SN text named `%s' already found in current, but content differs",
                        script_name)
                    new_text = texts.new(script_name)
                    new_text.from_string(script_content)
                    script_name = new_text.name
                    info('SN text named replaced with %s', script_name)

        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()
    elif node.bl_idname == 'SvScriptNodeLite':
        node.load()
        # node.storage_set_data(node_ref)
    else:
        node.files_popup = node.avail_templates(None)[0][0]
        node.load()
Exemplo n.º 35
0
def _draw_text_handler(tree_id,
                       node_id,
                       text: str,
                       color=(1, 1, 1, 1),
                       scale=1.0,
                       align='RIGHT',
                       text_coordinates=None):
    """Draw the text in a node tree editor nearby the given node"""
    editor = bpy.context.space_data

    if editor.type != 'NODE_EDITOR':
        return

    if editor.tree_type not in {"SverchCustomTreeType", 'SvGroupTree'}:
        return

    if not editor.edit_tree or editor.edit_tree.tree_id != tree_id:
        return

    # this is less efficient because it requires search of the node each redraw call
    if not text_coordinates:
        if not any(n for n in editor.edit_tree.nodes if n.node_id == node_id):
            debug(
                f'Some node looks like was removed without removing bgl drawing, text: {text}'
            )
            return

        # find node location
        node = next(n for n in editor.edit_tree.nodes if n.node_id == node_id)
        (x, y), z = _get_text_location(node, align), 0

    # put static coordinates if there are a lot of nodes with text to draw (does not react on the node movements)
    else:
        (x, y), z = text_coordinates, 0

    # https://github.com/nortikin/sverchok/issues/4247
    ui_scale = bpy.context.preferences.system.ui_scale
    x, y = x * ui_scale, y * ui_scale

    # todo add scale from the preferences
    text_height = int(15 * scale * ui_scale)
    line_height = int(18 * scale * ui_scale)
    font_id = 0
    dpi = 72

    blf.size(font_id, text_height, dpi)
    blf.color(font_id, *color)

    for line in text.split('\n'):
        blf.position(font_id, x, y, z)
        blf.draw(font_id, line)
        y -= line_height
Exemplo n.º 36
0
def SvForgetSocket(socket):
    """deletes socket data from cache"""
    global socket_data_cache
    if data_structure.DEBUG_MODE:
        if not socket.is_output:
            warning(
                f"{socket.node.name} forgetting input socket: {socket.name}")
    s_id = socket.socket_id
    s_ng = socket.id_data.tree_id
    try:
        socket_data_cache[s_ng].pop(s_id, None)
    except KeyError:
        debug("it was never there")
Exemplo n.º 37
0
    def navigate_category(self, direction):
        ''' Navigate to PREV or NEXT category '''
        debug("Navigate to PREV or NEXT category")

        categories = get_category_names()

        for i, category in enumerate(categories):
            if self.category == category:
                # prev or next category (cycle around)
                new_index = (i + 2 * direction - 1) % len(categories)
                new_category = categories[new_index]
                self.category = new_category
                break
Exemplo n.º 38
0
def parse_profile(src):
    # Strip comments
    # (hope no one uses # in expressions)
    cleaned = ""
    for line in src.split("\n"):
        comment_idx = line.find('#')
        if comment_idx != -1:
            line = line[:comment_idx]
        cleaned = cleaned + " " + line

    profile = parse(parse_definition, cleaned)
    debug(profile)
    return profile
Exemplo n.º 39
0
def add_spawned_node(context, name):
    if not _spawned_nodes:
        _spawned_nodes["main"] = []

    debug("ADDING spawned node: %s" % name)

    tree = context.space_data.edit_tree

    try:
        node = tree.nodes.new(name)
        _spawned_nodes["main"].append(node)
    except:
        print("EXCEPTION: failed to spawn node with name: ", name)
Exemplo n.º 40
0
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('\\\\')
Exemplo n.º 41
0
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('\\\\')
Exemplo n.º 42
0
def remove_node_tree(name=None):
    """
    Remove existing Sverchok node tree.
    """
    if name is None:
        name = "TestingTree"
    if name in bpy.data.node_groups:
        win      = bpy.context.window
        scr      = win.screen
        areas  = [area for area in scr.areas if area.type == 'NODE_EDITOR']
        if len(areas):
            space = areas[0].spaces[0]
            space.node_tree = None
        debug("Removing tree: %s", name)
        tree = bpy.data.node_groups[name]
        bpy.data.node_groups.remove(tree)
Exemplo n.º 43
0
def create_node_tree(name=None, must_not_exist=True):
    """
    Create new Sverchok node tree in the scene.
    If must_not_exist == True (default), then it is checked that
    the tree with such name did not exist before. If it exists,
    an exception is raised.
    If must_not_exist == False, then new tree will be created anyway,
    but it can be created with another name (standard Blender's renaming).
    """
    if name is None:
        name = "TestingTree"
    if must_not_exist:
        if name in bpy.data.node_groups:
            raise Exception("Will not create tree `{}': it already exists".format(name))
    debug("Creating tree: %s", name)
    return bpy.data.node_groups.new(name=name, type="SverchCustomTreeType")
Exemplo n.º 44
0
 def get_target_location(node_tree):
     """
     Calculate average location of selected nodes in the tree,
     or all nodes if there are no nodes selected.
     """
     selection = [node for node in node_tree.nodes if node.select]
     if not len(selection):
         debug("No selection, using all nodes")
         selection = node_tree.nodes[:]
     n = len(selection)
     if not n:
         return [0,0]
     locations = [node.location for node in selection]
     location_sum = [sum(x) for x in zip(*locations)]
     average_location = [x / float(n) for x in location_sum]
     return average_location
Exemplo n.º 45
0
def perform_scripted_node_inject(node, node_ref):
    '''
    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.

    '''
    texts = bpy.data.texts
    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)
        elif script_name and (script_name in texts):
            # This was added to fix existing texts with the same name but no / different content.
            if texts[script_name].as_string() == script_content:
                debug("SN skipping text named `%s' - their content are the same", script_name)
            else:
                info("SN text named `%s' already found in current, but content differs", script_name)
                new_text = texts.new(script_name)
                new_text.from_string(script_content)
                script_name = new_text.name
                info('SN text named replaced with %s', script_name)

        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()
    elif node.bl_idname == 'SvScriptNodeLite':
        node.load()
        # node.storage_set_data(node_ref)
    else:
        node.files_popup = node.avail_templates(None)[0][0]
        node.load()
Exemplo n.º 46
0
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])
Exemplo n.º 47
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.')
Exemplo n.º 48
0
    def intersect_with_plane(self, plane2):
        """
        Return an intersection of this plane with another one.
        
        input: PlaneEquation
        output: LineEquation or None, in case two planes are parallel.
        """
        if self.is_parallel(plane2):
            debug("{} is parallel to {}".format(self, plane2))
            return None

        # We need an arbitrary point on this plane and two vectors.
        # Draw two lines in this plane and see for theirs intersection
        # with another plane.
        p0 = self.nearest_point_to_origin()
        v1, v2 = self.two_vectors()
        # it might be that p0 belongs to plane2; in that case we choose
        # another point in the same plane
        if plane2.check(p0):
            # Since v1 and v2 are orthogonal, it may not be that they are
            # both parallel to plane2.
            if not plane2.is_parallel(v1):
                p0 = p0 + v1
            else:
                p0 = p0 + v2
        line1 = LineEquation.from_direction_and_point(v1, p0)
        line2 = LineEquation.from_direction_and_point(v2, p0)

        # it might be that one of vectors we chose is parallel to plane2
        # (since we are choosing them arbitrarily); but from the way
        # we are choosing v1 and v2, we know they are orthogonal.
        # So if wee just rotate them by pi/4, they will no longer be
        # parallel to plane2.
        if plane2.is_parallel(line1) or plane2.is_parallel(line2):
            v1_new = v1 + v2
            v2_new = v1 - v2
            info("{}, {} => {}, {}".format(v1, v2, v1_new, v2_new))
            line1 = LineEquation.from_direction_and_point(v1_new, p0)
            line2 = LineEquation.from_direction_and_point(v2_new, p0)

        p1 = plane2.intersect_with_line(line1)
        p2 = plane2.intersect_with_line(line2)
        return LineEquation.from_two_points(p1, p2)
Exemplo n.º 49
0
def perform_svtextin_node_object(node, node_ref):
    '''
    as it's a beta service, old IO json may not be compatible - in this interest
    of neat code we assume it finds everything.
    '''
    texts = bpy.data.texts
    params = node_ref.get('params')

    # original textin used 'current_text', textin+ uses 'text'
    current_text = params.get('current_text', params.get('text'))

    # it's not clear from the exporter code why textmode parameter isn't stored
    # in params.. for now this lets us look in both places. ugly but whatever.
    textmode = params.get('textmode')
    if not textmode:
        textmode = node_ref.get('textmode')
    node.textmode = textmode

    if not current_text:
        info("`%s' doesn't store a current_text in params", node.name)

    elif not current_text in texts:
        new_text = texts.new(current_text)
        text_line_entry = node_ref['text_lines']

        if node.textmode == 'JSON':
            if isinstance(text_line_entry, str):
                debug('loading old text json content / backward compatibility mode')

            elif isinstance(text_line_entry, dict):
                text_line_entry = json.dumps(text_line_entry['stored_as_json'])

        new_text.from_string(text_line_entry)

    else:
        # reaches here if  (current_text) and (current_text in texts)
        # can probably skip this..
        # texts[current_text].from_string(node_ref['text_lines'])
        debug('%s seems to reuse a text block loaded by another node - skipping', node.name)
Exemplo n.º 50
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)
Exemplo n.º 51
0
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
Exemplo n.º 52
0
    def process_node(self, context):
        '''
        Doesn't work as intended, inherited functions can't be used for bpy.props
        update= ...
        Still this is called from updateNode
        '''
        if self.id_data.bl_idname == "SverchCustomTreeType":
            if self.id_data.is_frozen():
                return

            if data_structure.DEBUG_MODE:
                a = time.perf_counter()
                process_from_node(self)
                b = time.perf_counter()
                debug("Partial update from node %s in %s", self.name, round(b - a, 4))
            else:
                process_from_node(self)
        elif self.id_data.bl_idname == "SverchGroupTreeType":
            monad = self.id_data
            for instance in monad.instances:
                instance.process_node(context)
        else:
            pass
Exemplo n.º 53
0
def sv_colors_definition():
    addon_name = sverchok.__name__
    addon = bpy.context.user_preferences.addons.get(addon_name)
    debug("got addon")
    if addon:
        prefs = addon.preferences
        sv_node_colors = {
            "Viz": prefs.color_viz,
            "Text": prefs.color_tex,
            "Scene": prefs.color_sce,
            "Layout": prefs.color_lay,
            "Generator": prefs.color_gen,
            }
    else:
        sv_node_colors = default_theme
    sv_node_cats = make_node_cats()
    sv_cats_node = {}
    for ca, no in sv_node_cats.items():
        for n in no:
            try:
                sv_cats_node[n[0]] = sv_node_colors[ca]
            except:
                sv_cats_node[n[0]] = False
    return sv_cats_node
Exemplo n.º 54
0
def print_update_lists(update_lists):
    debug('update lists:')
    for ulist in update_lists:
        debug(ulist)
Exemplo n.º 55
0
    def execute(self, context):
        for tree in bpy.data.node_groups:

            if not tree.bl_idname == 'SverchCustomTreeType':
                continue

            templist = []
            for node in tree.nodes:
                idname = node.bl_idname
   
                if idname in {'ObjectsNodeMK2', 'SvObjectsNodeMK3'}:
                    debug('scans for get option %s %s', node.label, node.name)
                    if any((s.links for s in node.outputs)):
                        templist.append([node.label, node.name, ""])
                
                elif idname in {'SvNumberNode', 'IntegerNode', 'FloatNode', 'SvListInputNode', 'SvColorInputNode', 'SvBmeshViewerNodeMK2'}:
                    if idname != 'SvBmeshViewerNodeMK2':
                        if not node.outputs:
                            debug("Node %s does not have outputs", node.name)
                            continue
                        if len(node.inputs) and node.inputs[0].is_linked:
                            debug("Node %s: first input is linked", node.name)
                            continue
                        if (not node.outputs[0].is_linked) or (node.to3d != True):
                            debug("Node %s: first output is not linked or to3d == False", node.name)
                            continue
                    elif (node.to3d != True):
                        debug("Node %s: first output is not linked or to3d == False", node.name)
                        continue

                    if 'Integer' in idname:
                        templist.append([node.label, node.name, 'int_'])
                    elif 'SvBmeshViewerNodeMK2' in idname:
                        templist.append([node.label, node.name, 'basemesh_name'])
                    elif 'Float' in idname:
                        templist.append([node.label, node.name, 'float_'])                     
                    elif idname == 'SvColorInputNode':
                        templist.append([node.label, node.name, 'color_data'])
                    elif 'SvListInputNode' in idname:
                        if node.mode == 'vector':
                            templist.append([node.label, node.name, 'vector_list'])
                        elif node.mode == 'int_list':
                            templist.append([node.label, node.name, 'int_list'])
                        elif node.mode == 'float_list':
                            templist.append([node.label, node.name, 'float_list'])
                    else:
                        kind = node.selected_mode
                        templist.append([node.label, node.name, kind + '_'])


            templist.sort()
            templ = [[t[1], t[2]] for t in templist]
            tree.Sv3DProps.clear()
            for name, prop in templ:
                debug('sverchok 3d panel appended with %s %s',name, prop)
                item = tree.Sv3DProps.add()
                item.node_name = name
                item.prop_name = prop

        return {'FINISHED'}