Beispiel #1
0
    def load_project_button_clicked(self):
        self.editor_startup_configuration['config'] = 'open project'
        import json

        file_name = QFileDialog.getOpenFileName(self, 'select project file', '../saves', 'Ryven Project(*.rpo *.rypo)')[0]
        j_str = ''
        try:
            f = open(file_name)
            j_str = f.read()
            f.close()
        except FileNotFoundError:
            Debugger.debug('couldn\'t open file')
            return


        # strict=False has to be to allow 'control characters' like '\n' for newline when loading the json
        j_obj = json.loads(j_str, strict=False)

        if j_obj['general info']['type'] != 'Ryven project file':
            return

        # scan for all required packages
        packages = []
        package_file_paths = []

        scripts = j_obj['scripts']
        for script in scripts:
            flow = script['flow']
            for n in flow['nodes']:
                package = n['parent node package']
                if package != 'built in' and not packages.__contains__(package):
                    packages.append(package)


        if len(packages) > 0:
            select_packages_dialog = SelectPackages_Dialog(self, packages)
            select_packages_dialog.exec_()
            package_file_paths = select_packages_dialog.file_paths


        self.editor_startup_configuration['required packages'] = package_file_paths
        self.editor_startup_configuration['content'] = j_obj

        self.accept()
Beispiel #2
0
    def create_new_input(self, type_, label, widget_name=None, widget_pos='under', pos=-1, config=None):
        """Creates and adds a new input. Handy for subclasses."""
        Debugger.debug('create_new_input called')
        pi = InputPortInstance(self, type_, label,
                               config_data=config,
                               widget_name=widget_name,
                               widget_pos=widget_pos)
        if pos < -1:
            pos += len(self.inputs)
        if pos == -1:
            self.inputs.append(pi)
            self.add_input_to_layout(pi)
        else:
            self.inputs.insert(pos, pi)
            self.insert_input_into_layout(pos, pi)

        if not self.initializing:
            self.update_shape()
            self.update()
Beispiel #3
0
    def import_nodes_package_from_file(self, file_path):
        j_str = ''
        try:
            f = open(file_path)
            j_str = f.read()
            f.close()
        except FileExistsError or FileNotFoundError:
            Debugger.debug('couldn\'t open file')
            return


        # Important: translate the package first (metacore files -> src code files)
        PackageTranslator = self.get_class_from_file(file_path='../pyScript_PackageTranslator',
                                                     file_name='pyScript_PackageTranslator',
                                                     class_name='PackageTranslator')
        package_translator = PackageTranslator(os.path.dirname(os.path.abspath(file_path)))


        self.parse_nodes(j_str, os.path.dirname(file_path), os.path.splitext(os.path.basename(file_path))[0])
Beispiel #4
0
    def dropEvent(self, event):
        text = event.mimeData().text()
        item: QListWidgetItem = event.mimeData()
        Debugger.debug('drop received in Flow:', text)

        j_obj = None
        type = ''
        try:
            j_obj = json.loads(text)
            type = j_obj['type']
        except Exception:
            return

        if type == 'variable':
            self.show_node_choice_widget(
                event.pos(),  # only show get_var and set_var nodes
                [
                    n for n in self.all_nodes
                    if find_type_in_object(n, GetVariable_Node)
                    or find_type_in_object(n, SetVariable_Node)
                ])
Beispiel #5
0
    def mousePressEvent(self, event):
        Debugger.debug('mouse press event received, point:', event.pos())

        # to catch tablet events (for some reason, it results in a mousePrEv too)
        if self.ignore_mouse_event:
            self.ignore_mouse_event = False
            return

        # there might be a proxy widget meant to receive the event instead of the flow
        QGraphicsView.mousePressEvent(self, event)

        # to catch any Proxy that received the event. Checking for event.isAccepted() or what is returned by
        # QGraphicsView.mousePressEvent(...) both didn't work so far, so I do it manually
        if self.ignore_mouse_event:
            self.ignore_mouse_event = False
            return

        if event.button() == Qt.LeftButton:
            if self.node_choice_proxy.isVisible():
                self.hide_node_choice_widget()
            else:
                if find_type_in_object(self.itemAt(event.pos()),
                                       PortInstanceGate):
                    self.gate_selected = self.itemAt(event.pos())
                    self.dragging_connection = True

            self.left_mouse_pressed_in_flow = True

        elif event.button() == Qt.RightButton:
            if len(self.items(event.pos())) == 0:
                self.node_choice_widget.reset_list()
                self.show_node_choice_widget(event.pos())

        elif event.button() == Qt.MidButton:
            self.panning = True
            self.pan_last_x = event.x()
            self.pan_last_y = event.y()
            event.accept()

        self.mouse_press_pos = self.mapToScene(event.pos())
Beispiel #6
0
    def parse_nodes(self, j_str, package_path, package_name) -> bool:
        """Parses the nodes from a node package in JSON format.
        Here, all the classes get imported and for every node a Node object with specific attribute values gets
        created."""

        import json

        # strict=False is necessary to allow control characters like '\n' for newline when loading the json
        j_obj = json.loads(j_str, strict=False)

        Debugger.debug(j_obj['type'])
        if j_obj['type'] != 'Ryven nodes package' and j_obj[
                'type'] != 'vyScriptFP nodes package':  # old syntax
            return False

        j_nodes_list = j_obj['nodes']

        num_nodes = len(j_nodes_list)
        for ni in range(num_nodes):
            j_node = j_nodes_list[ni]
            suc = self.parse_node(j_node, package_name, package_path)
            if not suc:
                Debugger.debug('error while importing nodes')
                return False

        Debugger.debug(len(self.custom_nodes), 'nodes imported')

        return True
Beispiel #7
0
 def get_class_from_file(self, file_path, file_name, class_name):
     Debugger.debug(file_path)
     Debugger.debug(file_name)
     Debugger.debug(class_name)
     sys.path.append(file_path)
     new_module = __import__(file_name, fromlist=[class_name])
     new_class = getattr(new_module, class_name)
     return new_class
Beispiel #8
0
    def parse_nodes(self, j_str, package_path, package_name):
        """Parses the nodes from a node package in JSON format.
        Here, all the classes get imported and for every node a Node object with specific attribute values gets
        created."""

        import json

        # strict=False is necessary to allow 'control characters' like '\n' for newline when loading the json
        j_obj = json.loads(j_str, strict=False)

        Debugger.debug(j_obj['type'])
        if j_obj['type'] != 'vyScriptFP nodes package':
            return

        # package_title = j_obj['title']
        # package_description = j_obj['description']
        j_nodes_list = j_obj['nodes']

        num_nodes = len(j_nodes_list)
        for ni in range(num_nodes):
            j_node = j_nodes_list[ni]
            self.parse_node(j_node, package_name, package_path)

        Debugger.debug(len(self.custom_nodes), 'nodes imported')
Beispiel #9
0
    def get_val(self):
        """applies on DATA; called NI internally AND externally"""
        Debugger.debug(
            'get value in', self.direction, 'port instance',
            self.parent_node_instance.inputs.index(self) if self.direction
            == 'input' else self.parent_node_instance.outputs.index(self),
            'of', self.parent_node_instance.parent_node.title)
        Debugger.debug('my value is', self.val)

        if self.direction == 'input':
            if len(self.connected_port_instances) == 0:
                if self.widget:
                    return self.widget.get_val()
                else:
                    return None
            else:
                Debugger.debug('calling connected port for val')
                return self.connected_port_instances[0].get_val()
        elif self.direction == 'output':
            Debugger.debug('returning val directly')
            if self.parent_node_instance.gen_data_on_request:
                self.parent_node_instance.update()
            return self.val
Beispiel #10
0
 def on_disable_debugging_triggered(self):
     Debugger.disable()
Beispiel #11
0
 def on_enable_debugging_triggered(self):
     Debugger.enable()
Beispiel #12
0
    def tabletEvent(self, event):
        """tabletEvent gets called by stylus operations.
        LeftButton: std, no button pressed
        RightButton: upper button pressed"""

        # if in edit mode and not panning or starting a pan, pass on to std mouseEvent handlers above
        if self.stylus_mode == 'edit' and not self.panning and not \
                (event.type() == QTabletEvent.TabletPress and event.button() == Qt.RightButton):
            return  # let the mousePress/Move/Release-Events handle it

        if event.type() == QTabletEvent.TabletPress:
            self.tablet_press_pos = event.pos()
            self.ignore_mouse_event = True

            if event.button() == Qt.LeftButton:
                if self.stylus_mode == 'comment':
                    new_drawing = self.create_and_place_drawing__cmd(
                        self.mapToScene(self.tablet_press_pos),
                        config=self.stylus_modes_widget.get_pen_settings())
                    self.current_drawing = new_drawing
                    self.drawing = True
            elif event.button() == Qt.RightButton:
                self.panning = True
                self.pan_last_x = event.x()
                self.pan_last_y = event.y()

        elif event.type() == QTabletEvent.TabletMove:
            self.ignore_mouse_event = True
            if self.panning:
                self.pan(event.pos())

            elif event.pointerType() == QTabletEvent.Eraser:
                if self.stylus_mode == 'comment':
                    for i in self.items(event.pos()):
                        if find_type_in_object(i, DrawingObject):
                            self.remove_drawing(i)
                            break
            elif self.stylus_mode == 'comment' and self.drawing:

                mapped = self.mapToScene(
                    QPoint(event.posF().x(),
                           event.posF().y()))
                # rest = QPointF(event.posF().x()%1, event.posF().y()%1)
                # exact = QPointF(mapped.x()+rest.x()%1, mapped.y()+rest.y()%1)
                # TODO: use exact position (event.posF() ). Problem: mapToScene() only uses QPoint, not QPointF. The
                #  calculation above didn't work

                if self.current_drawing.try_to_append_point(mapped):
                    self.current_drawing.stroke_weights.append(
                        event.pressure())
                self.current_drawing.update()
                self.viewport().update()

        elif event.type() == QTabletEvent.TabletRelease:
            if self.panning:
                self.panning = False
            if self.stylus_mode == 'comment' and self.drawing:
                Debugger.debug('drawing obj finished')
                self.current_drawing.finished()
                self.current_drawing = None
                self.drawing = False
Beispiel #13
0
 def update(self, input_called=-1, output_called=-1):
     Debugger.debug('update in', self.parent_node.title, 'on input', input_called)
     try:
         self.update_event(input_called)
     except Exception as e:
         Debugger.debug('EXCEPTION IN', self.parent_node.title, 'NI:', e)
Beispiel #14
0
 def dropEvent(self, event):
     text = event.mimeData().text()
     item: QListWidgetItem = event.mimeData()
     Debugger.debug('drop received in Flow:', text)
Beispiel #15
0
    def parse_nodes(self, j_str, package_path, package_name):
        import json

        # strict=False is necessary to allow 'control characters' like '\n' for newline when loading the json
        j_obj = json.loads(j_str, strict=False)

        Debugger.debug(j_obj['type'])
        if j_obj['type'] != 'vyScriptFP nodes package':
            return

        # package_title = j_obj['title']
        # package_description = j_obj['description']
        j_nodes_list = j_obj['nodes']

        num_nodes = len(j_nodes_list)
        for ni in range(num_nodes):  # new node
            j_node = j_nodes_list[ni]

            new_node = Node()


            node_title = j_node['title']
            node_class_name = j_node['class name']
            node_description = j_node['description']
            node_type = j_node['type']
            node_has_main_widget = j_node['has main widget']
            node_main_widget_pos = j_node['widget position'] if node_has_main_widget else None
            node_design_style = j_node['design style']
            node_color = j_node['color']

            # every node has a custom module name which differs from it's name to prevent import issues when using
            # multiple (different) Nodes with same titles
            # FOR FURTHER EXPLANATION: see node manager
            node_module_name = j_node['module name']
            module_name_separator = '___'



            #   CUSTOM CLASS IMPORTS ----------------------------------------------------------------------------
            # creating all the necessary path variables here for all potentially imported classes


            #       IMPORT NODE INSTANCE SUBCLASS
            node_instance_class_file_path = package_path+'/nodes/'+node_module_name+'/'
            node_instance_widgets_file_path = node_instance_class_file_path+'/widgets'
            node_instance_filename = node_module_name  # the NI file's name is just the 'module name'
            new_node_instance_class = self.get_class_from_file(file_path=node_instance_class_file_path,
                                                               file_name=node_instance_filename,
                                                               class_name=node_class_name+'_NodeInstance')
            self.all_node_instance_classes[new_node] = new_node_instance_class

            #       IMPORT MAIN WIDGET
            if node_has_main_widget:
                main_widget_filename = node_module_name+module_name_separator+'main_widget'
                new_node.main_widget_class = self.get_class_from_file(file_path=node_instance_widgets_file_path,
                                                                      file_name=main_widget_filename,
                                                                      class_name=node_class_name+'_NodeInstance_MainWidget')

            #       I need to create the dict for the node's potential custom input widgets already here
            self.custom_node_input_widget_classes[new_node] = {}
            for w_name in j_node['custom input widgets']:
                input_widget_filename = node_module_name+module_name_separator+w_name
                custom_widget_class = self.get_class_from_file(file_path=node_instance_widgets_file_path,
                                                               file_name=input_widget_filename,
                                                               class_name=w_name+'_PortInstanceWidget')
                self.custom_node_input_widget_classes[new_node][w_name] = custom_widget_class


            #   note: the input widget classes get imported below in the loop
            # ---------------------------------------------------------------------------------------------------


            j_n_inputs = j_node['inputs']
            inputs = []
            num_inputs = len(j_n_inputs)
            for ii in range(num_inputs):
                j_input = j_n_inputs[ii]
                i_type = j_input['type']
                i_label = j_input['label']
                i_has_widget = None
                i_widget_type = ''
                i_widget_name = ''
                i_widget_pos = None
                if i_type == 'data':
                    i_has_widget = j_input['has widget']
                    if i_has_widget:
                        i_widget_type = j_input['widget type']
                        i_widget_pos = j_input['widget position']
                        if i_widget_type == 'custom widget':
                            i_widget_name = j_input['widget name']
                new_input = NodePort()
                new_input.type_ = i_type
                new_input.label = i_label
                if i_has_widget:
                    new_input.widget_type = i_widget_type
                    new_input.widget_name = i_widget_name
                    if i_widget_pos:
                        new_input.widget_pos = i_widget_pos
                else:
                    new_input.widget_type = 'None'
                inputs.append(new_input)

            j_n_outputs = j_node['outputs']
            outputs = []
            num_outputs = len(j_n_outputs)
            for oi in range(num_outputs):
                j_output = j_n_outputs[oi]
                o_type = j_output['type']
                o_label = j_output['label']
                new_output = NodePort()
                new_output.type_ = o_type
                new_output.label = o_label
                outputs.append(new_output)

            new_node.title = node_title
            new_node.description = node_description
            new_node.type_ = node_type
            new_node.package = package_name
            new_node.has_main_widget = node_has_main_widget
            if node_has_main_widget:
                new_node.main_widget_pos = node_main_widget_pos
            new_node.design_style = node_design_style
            new_node.color = QColor(node_color)
            new_node.inputs = inputs
            new_node.outputs = outputs

            
            self.custom_nodes.append(new_node)
            self.all_nodes.append(new_node)


        Debugger.debug(len(self.custom_nodes), 'nodes imported')