def loadMap(self, mapLocation): with open(mapLocation) as file: mapObjList = json.load(file) for item in mapObjList["objects"]: if (item["type"] == "rect"): shape = QGraphicsRectItem(item["centerX"] - item["length"] / 2, -item["centerY"] - item["width"] / 2, item["length"], item["width"]) shape.setTransformOriginPoint( QPoint(item["centerX"], -item["centerY"])) shape.setPen(QPen(self.black)) shape.setBrush(QBrush(self.black, Qt.SolidPattern)) shape.setRotation(item["rotation"]) self.scene.addItem(shape) elif (item["type"] == "text"): label = QGraphicsTextItem(item["text"]) label.setX(item["centerX"] - item["length"] / 2) label.setY(-item["centerY"] - item["width"] / 2) font = QFont("Bavaria") font.setPointSize(24) font.setWeight(QFont.Bold) label.setFont(font) label.setRotation(item["rotation"]) self.RoomNameList.append(label) self.scene.addItem(label) elif (item["type"] == "obstacle"): shape = QGraphicsRectItem(item["centerX"] - item["length"] / 2, -item["centerY"] - item["width"] / 2, item["length"], item["width"]) shape.setTransformOriginPoint( QPoint(item["centerX"], -item["centerY"])) shape.setPen(QPen(self.gray)) shape.setBrush(QBrush(self.gray, Qt.SolidPattern)) shape.setRotation(item["rotation"]) self.ObstacleList.append(shape) elif (item["type"] == "plant"): shape = QGraphicsEllipseItem( item["centerX"] - item["length"] / 2, -item["centerY"] - item["width"] / 2, item["length"], item["width"]) shape.setTransformOriginPoint( QPoint(item["centerX"], -item["centerY"])) shape.setPen(QPen(self.green)) shape.setBrush(QBrush(self.green, Qt.SolidPattern)) shape.setRotation(item["rotation"]) self.ObstacleList.append(shape) self.SupervisorMap.scale(self.scaleFactor, self.scaleFactor)
def actually_show_text(self, data): text_item = QGraphicsTextItem() text_item.setZValue(5) if len(data) >= 8 and data[7] != None: text_item.setDefaultTextColor(QColor(data[7])) else: text_item.setDefaultTextColor(QColor("#FFFFFF")) text_item.setX(data[2]) text_item.setY(data[3]) text_item.setTextWidth(data[4]) text_item.setPlainText(data[5]) temp_font = text_item.font() temp_font.setPointSize(data[6]) text_item.setFont(temp_font) self.addItem(text_item) self.texts[data[1]] = text_item self.call_next_action()
class Edge(Connection): ''' B-spline/Bezier connection shape ''' def __init__(self, edge, graph): ''' Set generic parameters from Connection class ''' self.text_label = None super(Edge, self).__init__(edge['source'], edge['target']) self.edge = edge self.graph = graph # Set connection points as not visible, by default self.bezier_visible = False # Initialize control point coordinates self.bezier = [self.mapFromScene(*self.edge['spline'][0])] # Bezier control points (groups of three points): assert(len(self.edge['spline']) % 3 == 1) for i in xrange(1, len(self.edge['spline']), 3): self.bezier.append([Controlpoint( self.mapFromScene(*self.edge['spline'][i + j]), self) for j in range(3)]) # Create connection points at start and end of the edge self.source_connection = Connectionpoint( self.start_point or self.bezier[0], self, self.parent) self.parent.movable_points.append(self.source_connection) self.end_connection = Connectionpoint( self.end_point or self.bezier[-1], self, self.child) self.child.movable_points.append(self.end_connection) self.reshape() @property def start_point(self): ''' Compute connection origin - redefine in subclasses ''' # Start point is optional - graphviz decision return self.mapFromScene(*self.edge['start']) \ if self.edge.get('start') else None @property def end_point(self): ''' Compute connection end point - redefine in subclasses ''' return self.mapFromScene(*self.edge['end']) \ if self.edge.get('end') else None def bezier_set_visible(self, visible=True): ''' Display or hide the edge control points ''' self.bezier_visible = visible for group in self.bezier[1:]: for ctrl_point in group: if visible: ctrl_point.show() else: ctrl_point.hide() if visible: self.end_connection.show() self.source_connection.show() else: self.end_connection.hide() self.source_connection.hide() self.update() def mousePressEvent(self, event): ''' On a mouse click, display the control points ''' self.bezier_set_visible(True) # pylint: disable=R0914 def reshape(self): ''' Update the shape of the edge (redefined function) ''' path = QPainterPath() # If there is a starting point, draw a line to the first curve point if self.start_point: path.moveTo(self.source_connection.center) path.lineTo(self.bezier[0]) else: path.moveTo(self.source_connection.center) # Loop over the curve points: for group in self.bezier[1:]: path.cubicTo(*[point.center for point in group]) # If there is an ending point, draw a line to it if self.end_point: path.lineTo(self.end_connection.center) end_point = path.currentPosition() arrowhead = self.angle_arrow(path) path.lineTo(arrowhead[0]) path.moveTo(end_point) path.lineTo(arrowhead[1]) path.moveTo(end_point) try: # Add the transition label, if any (none for the START edge) font = QFont('arial', pointSize=8) metrics = QFontMetrics(font) label = self.edge.get('label', '') lines = label.split('\n') width = metrics.width(max(lines)) # longest line height = metrics.height() * len(lines) # lp is the position of the center of the text pos = self.mapFromScene(*self.edge['lp']) if not self.text_label: self.text_label = QGraphicsTextItem( self.edge.get('label', ''), parent=self) self.text_label.setX(pos.x() - width / 2) self.text_label.setY(pos.y() - height / 2) self.text_label.setFont(font) # Make horizontal center alignment, as dot does self.text_label.setTextWidth(self.text_label.boundingRect().width()) fmt = QTextBlockFormat() fmt.setAlignment(Qt.AlignHCenter) cursor = self.text_label.textCursor() cursor.select(QTextCursor.Document) cursor.mergeBlockFormat(fmt) cursor.clearSelection() self.text_label.setTextCursor(cursor) self.text_label.show() except KeyError: # no label pass self.setPath(path) def __str__(self): ''' user-friendly information about the edge coordinates ''' return('Edge between ' + self.edge['source'].name + ' and ' + self.edge['target'].name + str(self.edge['spline'][0])) def paint(self, painter, option, widget): ''' Apply anti-aliasing to Edge Connections ''' painter.setRenderHint(QPainter.Antialiasing, True) super(Edge, self).paint(painter, option, widget) # Draw lines between connection points, if visible if self.bezier_visible: painter.setPen( QPen(Qt.lightGray, 0, Qt.SolidLine)) painter.setBrush(Qt.NoBrush) points_flat = [point.center for sub1 in self.bezier[1:] for point in sub1] painter.drawPolyline([self.source_connection.center] + points_flat + [self.end_connection.center])
class Scene_Base(QGraphicsScene): def __init__(self, window): super().__init__() self.setSceneRect(0, 0, window.game_width, window.game_height) self.window = window self.init_fields() self.create_fade() self.dialog_box = None self.setup() def init_fields(self): self.actions = [] self.current_action = -1 self.dialog_box = None self.target_text = None self.current_dialog_text = None self.current_dialog_text_offset = 0 self.background = None self.fading_box = None self.fade_dir = 0 self.next_scene = None self.buttons = [] self.current_id = 1 self.texts = {} self.images = {} self.moving_images = [] self.updatable_images = [] self.vaxx = None self.entry = None self.pathogen = None self.tempPic = None def create_fade(self, opc=1): self.fading_box = QGraphicsRectItem(0, 0, self.width(), self.height()) self.fading_box.setBrush(QColor(0, 0, 0)) self.fading_box.setOpacity(opc) self.fading_box.setZValue(100) self.addItem(self.fading_box) # ============================================== # * Setup # # Overwrite with child classes to add actions. # ============================================== def setup(self): pass # ============================================== # * Update # # Updates the scene. Handles input, waiting, etc. # ============================================== def update(self): self.update_fade() self.update_dialog() self.update_dialog_text() self.update_moving_images() self.update_animated_images() def update_fade(self): if self.fading_box is not None: if self.fade_dir == 0 and self.fading_box.opacity() > 0: self.fading_box.setOpacity(self.fading_box.opacity() - 0.02) if self.fading_box.opacity() <= 0: self.removeItem(self.fading_box) self.fading_box = None elif self.fade_dir == 1 and self.fading_box.opacity() < 1: self.fading_box.setOpacity(self.fading_box.opacity() + 0.02) if self.fading_box.opacity() >= 1: if self.next_scene is not None: self.window.goto_scene(self.next_scene) else: self.actually_close_game() def update_dialog(self): if self.dialog_box is not None: if self.dialog_box.opacity() < 0.5: self.dialog_box.setOpacity(self.dialog_box.opacity() + 0.04) if self.dialog_box.opacity() >= 0.5: self.dialog_box.setOpacity(0.5) if self.actions[0][0] == 0: self.actually_show_dialog(self.actions[0]) def update_dialog_text(self): if self.current_dialog_text is not None: curr_text = self.current_dialog_text.toPlainText() if curr_text != self.target_text: if self.current_dialog_text_offset < 3: self.current_dialog_text_offset += 1 else: self.current_dialog_text_offset = 0 self.current_dialog_text.setPlainText(self.target_text[:len(curr_text) + 1]) def update_moving_images(self): if len(self.moving_images) > 0: index = 0 new_data = [] for image in self.moving_images: pic_id = image[0] item = self.images[pic_id] item.setX(item.x() + image[1]) item.setY(item.y() + image[2]) image[3] -= 1 if image[3] > 0: new_data.append(image) elif image[4] is not None: image[4]() index += 1 self.moving_images = new_data def update_animated_images(self): if len(self.updatable_images) > 0: index = 0 for image in self.updatable_images: image[2] += 1 if image[2] > image[4]: image[2] = 0 image[3] += 1 if image[3] >= len(image[1]): image[3] = 0 image[0].setPixmap(QPixmap(image[1][image[3]])) # ============================================== # * Mouse Events # # Handle mouse input. # ============================================== def mouseMoveEvent(self, mouseEvent): pass def mousePressEvent(self, mouseEvent): self.when_mouse_pressed(mouseEvent) def mouseDoubleClickEvent(self, mouseEvent): self.when_mouse_pressed(mouseEvent) def when_mouse_pressed(self, mouseEvent): if self.current_action == 0 and mouseEvent.button() == 1: if self.current_dialog_text is not None: if self.current_dialog_text.toPlainText() != self.target_text: self.current_dialog_text.setPlainText(self.target_text) else: self.removeItem(self.current_dialog_text) self.call_next_action() else: super(Scene_Base, self).mousePressEvent(mouseEvent) # ============================================== # * Action Management # ============================================== def finish_action(self): if len(self.actions) > 0: self.actions.pop(0) else: self.wait_for_button_press() def check_if_first(self): if len(self.actions) == 1: self.perform_next_action() def perform_next_action(self): if len(self.actions) > 0: action = self.actions[0] self.current_action = action_type = action[0] if action_type is -1: self.actually_hide_dialog_box() elif action_type is 0: self.actually_show_dialog(action) elif action_type is 1: self.actually_show_button(action) elif action_type is 2: self.actually_set_background(action) elif action_type is 3: self.actually_goto_scene(action) elif action_type is 4: self.actually_close_game() elif action_type is 5: self.actually_play_song(action) elif action_type is 6: self.actually_wait_for_button_press() elif action_type is 7: self.actually_remove_all_buttons() elif action_type is 8: self.actually_show_text(action) elif action_type is 9: self.actually_hide_text(action) elif action_type is 10: self.actually_show_image(action) elif action_type is 11: self.actually_hide_image(action) elif action_type is 12: self.actually_move_image(action) elif action_type is 50: self.actually_play_sound(action) def call_next_action(self): self.finish_action() self.perform_next_action() # ============================================== # * Actual Implementations # ============================================== def actually_show_dialog(self, data): if self.dialog_box is None: self.create_dialog_box() else: self.current_dialog_text = QGraphicsTextItem() self.current_dialog_text.setZValue(20) self.current_dialog_text.setDefaultTextColor(QColor(255, 255, 255)) temp_font = self.current_dialog_text.font() temp_font.setPointSize(data[2]) self.current_dialog_text.setFont(temp_font) self.addItem(self.current_dialog_text) self.current_dialog_text.setX(self.dialog_box.x() + 10) self.current_dialog_text.setY(self.dialog_box.y() + 10) self.current_dialog_text.setTextWidth(self.dialog_box.boundingRect().width() - 20) self.target_text = data[1] self.current_dialog_text_offset = 0 def create_dialog_box(self): self.dialog_box = QGraphicsRectItem(0, 0, self.width() - 20, self.height() / 4) self.dialog_box.setBrush(QColor(0, 0, 0)) self.dialog_box.setX(10) self.dialog_box.setY(self.height() - self.dialog_box.boundingRect().height() - 10) self.dialog_box.setZValue(15); self.dialog_box.setOpacity(0) self.addItem(self.dialog_box) def actually_hide_dialog_box(self): if self.dialog_box is not None: self.removeItem(self.dialog_box) self.dialog_box = None def actually_show_button(self, data): button = Button(self, data[3], data[4], data[5], data[6], data[7], data[8], data[9]) button.setX(data[1]) button.setY(data[2]) self.buttons.append(button) self.addItem(button) self.call_next_action() def actually_set_background(self, data): if self.background is not None: self.removeItem(self.background) self.background = None self.background = QGraphicsPixmapItem(QPixmap(data[1]).scaled(self.window.game_width, self.window.game_height)) self.background.setZValue(-10) self.addItem(self.background) self.call_next_action() def actually_goto_scene(self, data): self.next_scene = data[1] self.fade_dir = 1 self.create_fade(0) def actually_close_game(self): self.window.close_game() def actually_play_song(self, data): AudioPlayer.play_song(data[1]) self.call_next_action() def actually_wait_for_button_press(self): self.current_action = -1 def actually_remove_all_buttons(self): for b in self.buttons: self.removeItem(b) self.buttons = [] self.call_next_action() def actually_show_text(self, data): text_item = QGraphicsTextItem() text_item.setZValue(5) if len(data) >= 8 and data[7] != None: text_item.setDefaultTextColor(QColor(data[7])) else: text_item.setDefaultTextColor(QColor("#FFFFFF")) text_item.setX(data[2]) text_item.setY(data[3]) text_item.setTextWidth(data[4]) text_item.setPlainText(data[5]) temp_font = text_item.font() temp_font.setPointSize(data[6]) text_item.setFont(temp_font) self.addItem(text_item) self.texts[data[1]] = text_item self.call_next_action() def actually_hide_text(self, data): self.removeItem(self.texts[data[1]]) self.texts[data[1]] = None self.call_next_action() def actually_show_image(self, data): image = None if isinstance(data[2], list): image = QGraphicsPixmapItem(QPixmap(data[2][0])) self.updatable_images.append([image, data[2], 0, 0, data[5]]) else: image = QGraphicsPixmapItem(QPixmap(data[2])) image.setX(data[3]) image.setY(data[4]) image.setZValue(0) self.addItem(image) self.images[data[1]] = image self.call_next_action() def actually_hide_image(self, data): self.removeItem(self.images[data[1]]) self.images[data[1]] = None self.call_next_action() def actually_move_image(self, data): image_id = data[1] image = self.images[image_id] duration = data[4] x_speed = (data[2] - image.x()) / duration y_speed = (data[3] - image.y()) / duration callback = self.call_next_action if data[5] else None image_data = [image_id, x_speed, y_speed, duration, callback] self.moving_images.append(image_data) if not data[5]: self.call_next_action() def actually_play_sound(self, data): AudioPlayer.play_sound_effect(data[1]) self.call_next_action() # ============================================== # * Setup Calls # ============================================== def add_call(self, data): self.actions.append(data) self.check_if_first() # ============================================== # * Extended Calls # ============================================== # ============================================== # Adds a dialog to the game. # # Ex: # self.add_dialog("Hello World!") # ============================================== def add_dialog(self, msg, fontSize=20): self.add_call([0, msg, fontSize]) # ============================================== # Hides the dialog box # # Ex: # self.hide_dialog_box() # ============================================== def hide_dialog_box(self): self.add_call([-1]) # ============================================== # Adds a button to the game. # After adding all buttons, be sure to call "self.wait_for_button_press". # Check scenes/scene_titlescreen.py for example of "font" and "buttonColors" # # Ex: # self.add_button(30, 30, 200, 200, "My Button!", self.another_function) # ============================================== def add_button(self, x, y, w, h, name, action, font=None, buttonColors=None, textColors=None): self.add_call([1, x, y, w, h, name, font, buttonColors, textColors, action]) # ============================================== # Sets the current background. # # Ex: # self.set_background("images/Background1.png") # ============================================== def set_background(self, path): self.add_call([2, path]) # ============================================== # Changes the game to the provided scene. # # Ex: # self.goto_scene(scenes.my_other_scene.My_Other_Scene) # ============================================== def goto_scene(self, scene): self.add_call([3, scene]) # ============================================== # Closes the game. # # Ex: # self.close_game() # ============================================== def close_game(self): self.add_call([4]) # ============================================== # Plays a song. # # Ex: # self.play_song("audio/testmusic2.mp3") # ============================================== def play_song(self, path): self.add_call([5, path]) # ============================================== # Plays a sound effect once. # # Ex: # self.play_sound("audio/testmusic2.mp3") # ============================================== def play_sound(self, path): self.add_call([50, path]) # ============================================== # Once all buttons are created, this will wait for the player to press one. # # Ex: # self.wait_for_button_press() # ============================================== def wait_for_button_press(self): self.add_call([6]) # ============================================== # Removes all buttons from the screen. # # Ex: # self.remove_all_buttons() # ============================================== def remove_all_buttons(self): self.add_call([7]) # ============================================== # Based on the value provided, there is a chance it will return True. # # Ex: # if self.generate_random_chance(30): # # there is a 30% chance of this happening # else: # # there is a 70% chance of this happening # ============================================== def generate_random_chance(self, val): return random.randint(0, 100) <= val # ============================================== # Shows text on the screen (not in dialog). # This function returns an ID that can be used in self.hide_text. # # Ex: # text_id = self.show_text(10, 10, 200, "Hello Screen!", 40, "#FF44CC") # ============================================== def show_text(self, x, y, w, text, size=30, color=None): new_id = self.current_id self.current_id += 1 self.add_call([8, new_id, x, y, w, text, size, color]) return new_id # ============================================== # Hides the text connected to the ID. # # Ex: # self.hide_text(text_id) # ============================================== def hide_text(self, text_id): self.add_call([9, text_id]) # ============================================== # Shows a picture on the screen. # This function returns an ID that can be used in other functions. # # Ex: # pic_id = self.show_picture("images/TestImage1.png", 30, 30) # # ---------------------------------------------- # # Using an array of strings will create an animation. # In that case, the last argument is the frame-change frequency of the animation. # # Ex: # pic_id = self.show_picture(["images/p1_frame_0.png", "images/p1_frame_1.png"], 100, 100, 30) # ============================================== def show_picture(self, path, x, y, animation_speed=20): new_id = self.current_id self.current_id += 1 self.add_call([10, new_id, path, x, y, animation_speed]) return new_id # ============================================== # Removes the picture connected to the provided ID. # # Ex: # self.hide_picture(pic_id) # ============================================== def hide_picture(self, image_id): self.add_call([11, image_id]) # ============================================== # Moves the picture to new coordinates over a duration of time. # # Ex: # self.move_picture(pic_id, 90, 30, 120) # ============================================== def move_picture(self, image_id, x, y, duration, wait_until_finished=True): self.add_call([12, image_id, x, y, duration, wait_until_finished]) #=============================================== # Sets the vaccination status # True/False, 50% chance #=============================================== def set_vaxx(self): if self.generate_random_chance(50): Scene_Base.vaxx = True else: Scene_Base.vaxx = False #=============================================== # Sets the entry point # 0 is for blood (cut) # 1 is for stomach (mouth) #=============================================== def set_entry(self): if self.generate_random_chance(50): Scene_Base.entry = 0 else: Scene_Base.entry = 1 # ============================================== # Gets and sets global values # # Ex: # self.set_value("Health", 100) # # self.add_value("Health", -1) # # if self.get_value("Health") <= 30: # self.add_dialog("Player is less than 30 health!") # ============================================== def set_value(self, name, value): Scene_Base.GLOBAL_VARS[name] = value def add_value(self, name, value): Scene_Base.GLOBAL_VARS[name] += value def get_value(self, name): return Scene_Base.GLOBAL_VARS[name]
def createGraphics(self): """ Create the graphical representation of the FMU's inputs and outputs """ def variableColor(variable): if variable.type == 'Real': return QColor.fromRgb(0, 0, 127) elif variable.type in ['Integer', 'Enumeration']: return QColor.fromRgb(255, 127, 0) elif variable.type == 'Boolean': return QColor.fromRgb(255, 0, 255) elif variable.type == 'String': return QColor.fromRgb(0, 128, 0) else: return QColor.fromRgb(0, 0, 0) inputVariables = [] outputVariables = [] maxInputLabelWidth = 0 maxOutputLabelWidth = 0 textItem = QGraphicsTextItem() fontMetrics = QFontMetricsF(textItem.font()) for variable in self.modelDescription.modelVariables: if variable.causality == 'input': inputVariables.append(variable) elif variable.causality == 'output': outputVariables.append(variable) for variable in inputVariables: maxInputLabelWidth = max(maxInputLabelWidth, fontMetrics.width(variable.name)) for variable in outputVariables: maxOutputLabelWidth = max(maxOutputLabelWidth, fontMetrics.width(variable.name)) from math import floor scene = QGraphicsScene() self.ui.graphicsView.setScene(scene) group = QGraphicsItemGroup() scene.addItem(group) group.setPos(200.5, -50.5) lh = 15 # line height w = max(150., maxInputLabelWidth + maxOutputLabelWidth + 20) h = max(50., 10 + lh * max(len(inputVariables), len(outputVariables))) block = QGraphicsRectItem(0, 0, w, h, group) block.setPen(QColor.fromRgb(0, 0, 255)) pen = QPen() pen.setWidthF(1) font = QFont() font.setPixelSize(10) # inputs y = floor((h - len(inputVariables) * lh) / 2 - 2) for variable in inputVariables: text = QGraphicsTextItem(variable.name, group) text.setDefaultTextColor(QColor.fromRgb(0, 0, 255)) text.setFont(font) text.setX(3) text.setY(y) polygon = QPolygonF([ QPointF(-13.5, y + 4), QPointF(1, y + 11), QPointF(-13.5, y + 18) ]) path = QPainterPath() path.addPolygon(polygon) path.closeSubpath() contour = QGraphicsPathItem(path, group) contour.setPen(QPen(Qt.NoPen)) contour.setBrush(variableColor(variable)) y += lh # outputs y = floor((h - len(outputVariables) * lh) / 2 - 2) for variable in outputVariables: text = QGraphicsTextItem(variable.name, group) text.setDefaultTextColor(QColor.fromRgb(0, 0, 255)) text.setFont(font) text.setX(w - 3 - text.boundingRect().width()) text.setY(y) polygon = QPolygonF([ QPointF(w, y + 0 + 7.5), QPointF(w + 7, y + 3.5 + 7.5), QPointF(w, y + 7 + 7.5) ]) path = QPainterPath() path.addPolygon(polygon) path.closeSubpath() contour = QGraphicsPathItem(path, group) pen = QPen() pen.setColor(variableColor(variable)) pen.setJoinStyle(Qt.MiterJoin) contour.setPen(pen) y += lh
def drawRobotCallback(self, result): self.RobotListTable.setRowCount(0) #clear table for item in self.RobotShapes: self.scene.removeItem(item) self.RobotShapes.clear() self.AllRobotNames.clear() self.SupervisorSpecificRobotNames.clear() for item in result.robots: obSize = 70 shape = QGraphicsEllipseItem( int(item.pose.pose.pose.position.x * 100 - obSize / 2), -int(item.pose.pose.pose.position.y * 100 + obSize / 2), obSize, obSize) shape.setPen(QPen(self.black)) # separate the robots by "all" and "supervisor specific" if (item.supervisorID == self.id): self.SupervisorSpecificRobotNames.append(item.name) color = QColor(self.RobotTasks[item.currentTaskName][2]) shape.setBrush(QBrush(color, Qt.SolidPattern)) self.RobotListTable.insertRow(self.RobotListTable.rowCount()) self.RobotListTable.setItem(self.RobotListTable.rowCount() - 1, 0, QTableWidgetItem(item.name)) self.RobotListTable.setItem( self.RobotListTable.rowCount() - 1, 1, QTableWidgetItem(item.currentTaskName)) self.RobotListTable.setItem(self.RobotListTable.rowCount() - 1, 2, QTableWidgetItem(item.status)) icon_item = QTableWidgetItem() icon_item.setIcon(QIcon(cameraIcon)) self.RobotListTable.setItem(self.RobotListTable.rowCount() - 1, 3, icon_item) else: color = QColor(self.RobotTasks[item.currentTaskName][2]) shape.setBrush(QBrush(color, Qt.Dense3Pattern)) self.scene.addItem(shape) self.RobotShapes.append(shape) self.AllRobotNames.append(item.name) label = QGraphicsTextItem(item.name) label.setX(int(item.pose.pose.pose.position.x * 100)) label.setY(-int(item.pose.pose.pose.position.y * 100 + obSize * 1.2)) font = QFont("Bavaria") font.setPointSize(18) font.setWeight(QFont.Bold) label.setDefaultTextColor(color) label.setFont(font) self.scene.addItem(label) self.RobotShapes.append(label) quat = item.pose.pose.pose.orientation siny_cosp = 2 * (quat.w * quat.z + quat.x * quat.y) cosy_cosp = 1 - 2 * (quat.y * quat.y + quat.z * quat.z) yaw = math.atan2(siny_cosp, cosy_cosp) #making the arrow arrowLines = self.makeArrow(item.pose.pose.pose.position.x * 100, item.pose.pose.pose.position.y * 100, yaw, obSize) for line in arrowLines: self.scene.addItem(line) self.RobotShapes.append(line) type = item.currentTask.taskName if self.RobotTasks[type][1] == "True": X = item.currentTask.X * 100 Y = item.currentTask.Y * -100 shapes = self.makeTarget(X, Y, 50, self.red) for shape in shapes: self.RobotShapes.append(shape) self.scene.addItem(shape) label = QGraphicsTextItem(item.name + " Goal") label.setX(int(X)) label.setY(int(Y - obSize)) font = QFont("Bavaria") font.setPointSize(18) font.setWeight(QFont.Bold) label.setDefaultTextColor(self.red) label.setFont(font) self.scene.addItem(label) self.RobotShapes.append(label)
class Barometer(QWidget): def __init__(self, parent): super().__init__(parent) self.uas = None svgRenderer = QSvgRenderer('res/barometer.svg') bkgnd = QGraphicsSvgItem() bkgnd.setSharedRenderer(svgRenderer) bkgnd.setCacheMode(QGraphicsItem.NoCache) bkgnd.setElementId('background') scene = QGraphicsScene() scene.addItem(bkgnd) scene.setSceneRect(bkgnd.boundingRect()) self.needle = QGraphicsSvgItem() self.needle.setSharedRenderer(svgRenderer) self.needle.setCacheMode(QGraphicsItem.NoCache) self.needle.setElementId('needle') self.needle.setParentItem(bkgnd) self.needle.setPos( bkgnd.boundingRect().width() / 2 - self.needle.boundingRect().width() / 2, bkgnd.boundingRect().height() / 2 - self.needle.boundingRect().height() / 2) self.needle.setTransformOriginPoint( self.needle.boundingRect().width() / 2, self.needle.boundingRect().height() / 2) # textElement = svgRenderer.boundsOnElement('needle-text') self.digitalBaro = QGraphicsTextItem() self.digitalBaro.setDefaultTextColor(QColor(255, 255, 255)) self.digitalBaro.document().setDefaultTextOption( QTextOption(Qt.AlignCenter)) self.digitalBaro.setFont(QFont('monospace', 13, 60)) self.digitalBaro.setParentItem(bkgnd) txm = QTransform() txm.translate( bkgnd.boundingRect().center().x(), bkgnd.boundingRect().height() - 1.5 * self.digitalBaro.document().size().height()) self.digitalBaro.setTransform(txm, False) view = QGraphicsView(scene) view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) layout = QVBoxLayout() layout.addWidget(view) self.setLayout(layout) self.setBarometer(1000) def setBarometer(self, hbar): deg = ((hbar - 950) * 3 + 210) % 360 self.needle.setRotation(deg) self.digitalBaro.setPlainText('{:.1f}'.format(hbar)) self.digitalBaro.adjustSize() self.digitalBaro.setX(0 - self.digitalBaro.textWidth() / 2) def updateAirPressure(self, sourceUAS, timestamp, absPressure, diffPressure, temperature): unused(sourceUAS, timestamp, diffPressure, temperature) self.setBarometer(absPressure) def setActiveUAS(self, uas): uas.updateAirPressureSignal.connect(self.updateAirPressure) self.uas = uas
class QDMGraphicsNode(QGraphicsItem): def __init__(self, node, parent=None): super().__init__(parent) self.node = node self.content = self.node.content self._title_color = Qt.white self._title_font = QFont("Arial", 12) self.width = 180 self.height = 240 self.edge_size = 10 self.title_height = 24 self._padding = 4 self._pen_default = QPen(QColor(self.get_outline_color())) self._pen_selected = QPen(QColor("#e18b32")) self._title_brush = QBrush(QColor(self.get_title_color())) self._background_brush = QBrush(QColor(self.get_background_color())) self.initTitle() self.title = self.node.title # init content self.initContent() # init sockets #self.initSockets() self.setFlag(QGraphicsItem.ItemIsFocusable, True) self.initUI() def boundingRect(self): return QRectF( 0, 0, self.width, self.height ).normalized() def initUI(self): self.setFlag(QGraphicsItem.ItemIsSelectable) self.setFlag(QGraphicsItem.ItemIsMovable) def initTitle(self): self.title_item = QGraphicsTextItem(self) self.title_item.setDefaultTextColor(self._title_color) self.title_item.setFont(self._title_font) self.title_item.setTextWidth(self.width - 2 * self._padding) self.title_item.setX(self._padding) def get_title_color(self): return "#954a4a" def get_background_color(self): return "#2b2b2b" def get_outline_color(self): return "#181818" def initSockets(self): self.content.drawSocketItems() def initContent(self): self.grContent = QGraphicsProxyWidget(self) self.content.setGeometry(self.edge_size, self.title_height + self.edge_size, self.width - 2 * self.edge_size, self.height - 2 * self.edge_size - self.title_height) self.grContent.setWidget(self.content) @property def title(self): return self._title @title.setter def title(self, value): self._title = value self.title_item.setPlainText(self._title) def paint(self, painter, option, widget=None): # title path_title = QPainterPath() path_title.setFillRule(Qt.WindingFill) path_title.addRoundedRect(0, 0, self.width, self.title_height, self.edge_size, self.edge_size) path_title.addRect(0, self.title_height - self.edge_size, self.edge_size, self.edge_size) path_title.addRect(self.width - self.edge_size, self.title_height - self.edge_size, self.edge_size, self.edge_size) painter.setPen(Qt.NoPen) painter.setBrush(self._title_brush) painter.drawPath(path_title.simplified()) # content path_content = QPainterPath() path_content.setFillRule(Qt.WindingFill) path_content.addRoundedRect(0, self.title_height, self.width, self.height - self.title_height, self.edge_size, self.edge_size) path_content.addRect(0, self.title_height, self.edge_size, self.edge_size) path_content.addRect(self.width - self.edge_size, self.title_height, self.edge_size, self.edge_size) painter.setPen(Qt.NoPen) painter.setBrush(self._background_brush) painter.drawPath(path_content.simplified()) # outline path_outline = QPainterPath() path_outline.addRoundedRect(0, 0, self.width, self.height, self.edge_size, self.edge_size) painter.setPen(self._pen_default if not self.isSelected() else self._pen_selected) painter.setBrush(Qt.NoBrush) painter.drawPath(path_outline.simplified()) def mouseMoveEvent(self, event): super().mouseMoveEvent(event) self.node.update_linked_sockets() def keyReleaseEvent(self, event): super().keyReleaseEvent(event) if not self.hasFocus(): return if event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete: self.node.scene.removeNode(self.node)
def drawRobotCallback(self, result): for item in self.RobotShapes: self.scene.removeItem(item) self.RobotShapes.clear() self.RobotNames.clear() for item in self.robotMarkerShapes: self.augmentedRealityScene.removeItem(item) self.robotMarkerShapes.clear() frameRotation = 0 obSize = 70 controlledRobot = None for item in result.robots: shape = QGraphicsEllipseItem(int(item.pose.pose.pose.position.x*100 - obSize / 2), -int(item.pose.pose.pose.position.y*100 + obSize / 2), obSize, obSize) shape.setPen(QPen(self.black)) color = self.yellow if self.currentRobot is not None: if item.name == self.currentRobot.name: color = self.blue controlledRobot = item if self.helperRobot is not None: if self.helperRobot == item.name: color = self.purple shape.setBrush(QBrush(color, Qt.SolidPattern)) self.scene.addItem(shape) self.RobotShapes.append(shape) self.RobotNames.append(item.name) quat = item.pose.pose.pose.orientation siny_cosp = 2 * (quat.w * quat.z + quat.x * quat.y) cosy_cosp = 1 - 2 * (quat.y * quat.y + quat.z * quat.z) yaw = math.atan2(siny_cosp, cosy_cosp) #making the arrow startArrowX = int(item.pose.pose.pose.position.x*100-math.cos(yaw)*obSize/4) startArrowY = -int(item.pose.pose.pose.position.y*100-math.sin(yaw)*obSize/4) endArrowX =int(item.pose.pose.pose.position.x*100+math.cos(yaw)*obSize/2-math.cos(yaw)*obSize/4) endArrowY = -int(item.pose.pose.pose.position.y*100+math.sin(yaw)*obSize/2-math.sin(yaw)*obSize/4) line = QGraphicsLineItem(startArrowX, startArrowY, endArrowX, endArrowY) line.setPen(QPen(self.black, 5)) self.scene.addItem(line) self.RobotShapes.append(line) line = QGraphicsLineItem(endArrowX, endArrowY, endArrowX-math.cos(3.14/4+yaw)*obSize/4, endArrowY+math.sin(3.14/4+yaw)*obSize/4) line.setPen(QPen(self.black, 5)) self.scene.addItem(line) self.RobotShapes.append(line) line = QGraphicsLineItem(endArrowX, endArrowY, endArrowX- math.cos(3.14 / 4 - yaw) * obSize / 4, endArrowY- math.sin(3.14 / 4 - yaw) * obSize / 4) line.setPen(QPen(self.black, 5)) self.scene.addItem(line) self.RobotShapes.append(line) if self.currentRobot is not None: if item.name == self.currentRobot.name: self.OperatorMap.centerOn(int(item.pose.pose.pose.position.x * 100), -int(item.pose.pose.pose.position.y * 100)) deltaRotate = math.degrees(yaw)-90-self.previousMapRotation self.previousMapRotation = math.degrees(yaw)-90 self.OperatorMap.rotate(deltaRotate) frameRotation = math.degrees(yaw)-90 else: self.OperatorMap.rotate(-self.previousMapRotation) self.previousMapRotation = 0 frameRotation = 0 for item in result.robots: color = self.yellow if self.currentRobot is not None: if item.name == self.currentRobot.name: color = self.blue if self.helperRobot is not None: if self.helperRobot == item.name: color = self.purple label = QGraphicsTextItem(item.name) label.setX(int(item.pose.pose.pose.position.x * 100 + obSize * 1.1*math.cos(math.radians(-frameRotation-45)))) label.setY(int(-item.pose.pose.pose.position.y * 100 + obSize * 1.1*math.sin(math.radians(-frameRotation-45)))) label.setRotation(-frameRotation) font = QFont("Bavaria") font.setPointSize(18) font.setWeight(QFont.Bold) label.setDefaultTextColor(color) label.setFont(font) self.scene.addItem(label) self.RobotShapes.append(label) for item in self.RoomNames: item.setRotation(-frameRotation) if self.RobotWarningCB.isChecked(): for item in result.robots:#draw arrows to other bots if controlledRobot is not None: if item.name is not controlledRobot.name: deltaX = controlledRobot.pose.pose.pose.position.x - item.pose.pose.pose.position.x deltaY = controlledRobot.pose.pose.pose.position.y - item.pose.pose.pose.position.y robotDistance = math.sqrt( math.pow(deltaX, 2)+ math.pow(deltaY, 2)) if robotDistance<self.robotWarningDistance: color = self.yellow if self.helperRobot is not None: if self.helperRobot == item.name: color = self.purple quat = controlledRobot.pose.pose.pose.orientation siny_cosp = 2 * (quat.w * quat.z + quat.x * quat.y) cosy_cosp = 1 - 2 * (quat.y * quat.y + quat.z * quat.z) yaw = math.atan2(siny_cosp, cosy_cosp) difAngle = math.atan2(deltaY, deltaX) totalAngle = yaw-difAngle+math.pi/2 startArrowX = int(self.AugmentedRealityPanel.height()*math.cos(totalAngle)*0.45) startArrowY = int(self.AugmentedRealityPanel.height()*math.sin(totalAngle)*0.45) endArrowX = int(self.AugmentedRealityPanel.height()*math.cos(totalAngle)*0.49) endArrowY = int(self.AugmentedRealityPanel.height()*math.sin(totalAngle)*0.49) line = QGraphicsLineItem(startArrowX, startArrowY, endArrowX,endArrowY) line.setPen(QPen(color, 10)) self.augmentedRealityScene.addItem(line) self.robotMarkerShapes.append(line) line = QGraphicsLineItem(endArrowX, endArrowY, endArrowX - math.cos(3.14 / 4 + totalAngle) * self.AugmentedRealityPanel.height()*0.02, endArrowY - math.sin(3.14 / 4 + totalAngle) * self.AugmentedRealityPanel.height()*0.02) line.setPen(QPen(color, 10)) self.augmentedRealityScene.addItem(line) self.robotMarkerShapes.append(line) line = QGraphicsLineItem(endArrowX, endArrowY, endArrowX - math.cos(3.14 / 4 - totalAngle) * self.AugmentedRealityPanel.height()*0.02, endArrowY + math.sin(3.14 / 4 - totalAngle) * self.AugmentedRealityPanel.height()*0.02) line.setPen(QPen(color, 10)) self.augmentedRealityScene.addItem(line) self.robotMarkerShapes.append(line)