def move_hover_line(new_value: QPointF) -> None: x = new_value.x() plot_area = chart.plotArea() x_min = plot_area.left() x_max = plot_area.right() result.setVisible(x_min <= x <= x_max) result.setLine(x, plot_area.bottom(), x, plot_area.top())
def update_connc(self): delta = QPointF(self.prev_pos.x() - self.x(), self.prev_pos.y() - self.y()) for c in self.connectors: c.setPos(QPointF(c.x() - delta.x(), c.y() - delta.y())) pconnc: Connection for pconnc in c.prim_connc: pconnc.a = QPointF(c.x() + c.cpos[0] + Connector.SIZE / 2, c.y() + c.cpos[1] + Connector.SIZE / 2) sconnc: Connection for sconnc in c.scnd_connc: sconnc.b = QPointF(c.x() + c.cpos[0] + Connector.SIZE / 2, c.y() + c.cpos[1] + Connector.SIZE / 2) c: InteractiveComponent for c in self.fd_wx_consts: c.setPos(QPointF(c.x() - delta.x(), c.y() - delta.y())) self.prev_pos = self.pos()
def draw_simple_shape_to_scene(view: QGraphicsView, p_prev: QPointF, p_act: QPointF, to_gim: bool = True) -> None: if view.actual_selection.value in [2, 4]: width = math.fabs(p_prev.x() - p_act.x()) height = math.fabs(p_prev.y() - p_act.y()) xmin = min(p_prev.x(), p_act.x()) ymin = min(p_prev.y(), p_act.y()) item: QAbstractGraphicsShapeItem if view.actual_selection.value == 2: item = QGraphicsRectItem(0, 0, width, height) else: item = QGraphicsEllipseItem(0, 0, width, height) item.setPos(QPointF(xmin, ymin)) item.setPen(view.actual_pen) item.setBrush(view.actual_brush) DrawTools.set_item_flags(item) view.scene().addItem(item) view.gim.append_shape(item, item.type(), view.actual_pen, view.actual_brush) elif view.actual_selection.value in [3, 5, 6]: x = p_act.x() - p_prev.x() y = p_act.y() - p_prev.y() item: QGraphicsItem if view.actual_selection.value == 3: item = QGraphicsPolygonItem( QPolygonF( [QPointF(0, 0), QPointF(0 + x, 0), QPointF(x / 2, y)])) item.setBrush(view.actual_brush) else: item = QGraphicsLineItem(QLineF(0, 0, x, y)) item.setPos(p_prev) item.setPen(view.actual_pen) DrawTools.set_item_flags(item) view.scene().addItem(item) if to_gim: view.gim.append_shape(item, item.type(), view.actual_pen, view.actual_brush)
class ChipSceneViewer(QGraphicsView): selectionChanged = Signal(list) def __init__(self): super().__init__() scene = QGraphicsScene() self.setScene(scene) self.setRenderHint(QPainter.Antialiasing) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setMouseTracking(True) self._offset = QPointF(0, 0) self._zoom = 0 self.backgroundColor = QColor(40, 40, 40) self.gridSpacing = QSizeF(60, 60) self.gridThickness = 1 self.gridColor = QColor(100, 100, 100) self.gridZoomThreshold = -1.5 self.showGrid = True self.selectionBoxStrokeColor = QColor(52, 222, 235) self.selectionBoxFillColor = QColor(52, 222, 235, 50) self.selectionBoxThickness = 2 self._editing = True self._hoveredItems: List[ChipItem] = [] self._selectedItems: List[ChipItem] = [] self._sceneItems: Set[ChipItem] = set() self._boxSelectionRectAnchor = QPointF() self._currentCursorPosition = QPointF() self.selectionBox = self.scene().addRect(QRectF(), QPen(self.selectionBoxStrokeColor, self.selectionBoxThickness), QBrush(self.selectionBoxFillColor)) self.selectionBox.setVisible(False) self._state = State.IDLE self.UpdateView() def SetEditing(self, editing: bool): self._editing = editing self.showGrid = editing for item in self._sceneItems: item.SetEditDisplay(editing) if not editing: self.DeselectAll() def GetSelectedItems(self): return self._selectedItems def AddItem(self, item: ChipItem): if item not in self._sceneItems: self._sceneItems.add(item) item.Move(QPointF()) item.onRemoved.connect(self.RemoveItem) self.scene().addItem(item.GraphicsObject()) item.SetEditDisplay(self._editing) return item def RemoveItem(self, item: ChipItem): self.DeselectItem(item) if item in self._hoveredItems: self._hoveredItems.remove(item) if item in self._sceneItems: self._sceneItems.remove(item) self.scene().removeItem(item.GraphicsObject()) def GetItems(self): return self._sceneItems def RemoveAll(self): self._hoveredItems.clear() self._selectedItems.clear() for item in self._sceneItems.copy(): self.RemoveItem(item) def SelectItem(self, item: ChipItem): if item not in self._selectedItems: item.SetSelected(True) self._selectedItems.append(item) def ToggleSelectItem(self, item: ChipItem): if item in self._selectedItems: self.DeselectItem(item) else: self.SelectItem(item) def DeselectItem(self, item: ChipItem): if item in self._selectedItems: item.SetSelected(False) self._selectedItems.remove(item) def DeselectAll(self): for item in self._selectedItems.copy(): self.DeselectItem(item) def Recenter(self): itemsRect = QRectF() for item in self._sceneItems: itemsRect = itemsRect.united(item.GraphicsObject().boundingRect().translated(item.GraphicsObject().pos())) self._offset = itemsRect.center() self.UpdateView() def CenterItem(self, item: ChipItem): QApplication.processEvents() sceneCenter = self.mapToScene(self.rect().center()) currentCenter = item.GraphicsObject().sceneBoundingRect().center() delta = sceneCenter - currentCenter item.Move(delta) def UpdateView(self): matrix = QTransform() matrix.scale(2 ** self._zoom, 2 ** self._zoom) self.setTransform(matrix) self.setSceneRect(QRectF(self._offset.x(), self._offset.y(), 10, 10)) self.UpdateSelectionBox() self.UpdateHoveredItems() @staticmethod def GetSelectionMode(): if QApplication.keyboardModifiers() == Qt.ShiftModifier: return SelectionMode.MODIFY return SelectionMode.NORMAL def CreateSelectionRect(self) -> QRectF: cursorScene = self.mapToScene(self._currentCursorPosition.toPoint()) if self._state is State.SELECTING: selectionRect = QRectF(0, 0, abs(self._boxSelectionRectAnchor.x() - cursorScene.x()), abs(self._boxSelectionRectAnchor.y() - cursorScene.y())) selectionRect.moveCenter((cursorScene + self._boxSelectionRectAnchor) / 2.0) else: selectionRect = QRectF(cursorScene, QSizeF()) return selectionRect def UpdateHoveredItems(self): if self._state is State.PANNING: return if not self._editing or self._state is State.MOVING: hoveredChipItems = [] else: # What are we hovering over in the scene hoveredGraphicsItems = [item for item in self.scene().items(self.selectionBox.sceneBoundingRect())] hoveredChipItems = [item for item in self._sceneItems if item.GraphicsObject() in hoveredGraphicsItems] # Make sure we maintain the found order hoveredChipItems.sort(key=lambda x: hoveredGraphicsItems.index(x.GraphicsObject())) if self._state is not State.SELECTING: hoveredChipItems = hoveredChipItems[:1] for item in hoveredChipItems: if item not in self._hoveredItems and item.CanSelect(): item.SetHovered(True) for item in self._hoveredItems: if item not in hoveredChipItems: item.SetHovered(False) self._hoveredItems = hoveredChipItems def UpdateSelectionBox(self): if self._state == State.SELECTING: self.selectionBox.setVisible(True) self.selectionBox.prepareGeometryChange() else: self.selectionBox.setVisible(False) self.selectionBox.setRect(self.CreateSelectionRect()) def drawBackground(self, painter: QPainter, rect: QRectF): currentColor = self.backgroundBrush().color() if currentColor != self.backgroundColor: self.setBackgroundBrush(QBrush(self.backgroundColor)) super().drawBackground(painter, rect) if self._zoom <= self.gridZoomThreshold or not self.showGrid: return painter.setPen(QPen(self.gridColor, self.gridThickness)) lines = [] if self.gridSpacing.width() > 0: xStart = rect.left() - rect.left() % self.gridSpacing.width() while xStart <= rect.right(): line = QLineF(xStart, rect.bottom(), xStart, rect.top()) lines.append(line) xStart = xStart + self.gridSpacing.width() if self.gridSpacing.height() > 0: yStart = rect.top() - rect.top() % self.gridSpacing.height() while yStart <= rect.bottom(): line = QLineF(rect.left(), yStart, rect.right(), yStart) lines.append(line) yStart = yStart + self.gridSpacing.height() painter.drawLines(lines) def wheelEvent(self, event: QWheelEvent): numSteps = float(event.angleDelta().y()) / 1000 oldWorldPos = self.mapToScene(self._currentCursorPosition.toPoint()) self._zoom = min(self._zoom + numSteps, 0) self.UpdateView() newWorldPos = self.mapToScene(self._currentCursorPosition.toPoint()) delta = newWorldPos - oldWorldPos self._offset -= delta self.UpdateView() def mousePressEvent(self, event): if self._state != State.IDLE: return if event.button() == Qt.RightButton: self._state = State.PANNING elif event.button() == Qt.LeftButton and self._editing: if len(self._hoveredItems) == 0: self._state = State.SELECTING self._boxSelectionRectAnchor = self.mapToScene(self._currentCursorPosition.toPoint()) else: hoveredItem = self._hoveredItems[0] if self.GetSelectionMode() is SelectionMode.MODIFY: self.ToggleSelectItem(hoveredItem) self.selectionChanged.emit(self._selectedItems) else: if hoveredItem not in self._selectedItems: self.DeselectAll() self.SelectItem(hoveredItem) self.selectionChanged.emit(self._selectedItems) if hoveredItem.CanMove(self.mapToScene(self._currentCursorPosition.toPoint())): self._state = State.MOVING self.UpdateView() super().mousePressEvent(event) def mouseMoveEvent(self, event: QMouseEvent): # Update position movement newCursorPosition = event.localPos() if self._currentCursorPosition is None: deltaScene = QPointF() else: deltaScene = (self.mapToScene(newCursorPosition.toPoint()) - self.mapToScene(self._currentCursorPosition.toPoint())) self._currentCursorPosition = newCursorPosition if self._state is State.PANNING: self._offset -= deltaScene self.UpdateView() elif self._state is State.MOVING: for selectedItem in self._selectedItems: selectedItem.Move(deltaScene) self.UpdateView() super().mouseMoveEvent(event) def mouseReleaseEvent(self, event: QMouseEvent): super().mouseReleaseEvent(event) if self._state == State.PANNING: if event.button() == Qt.RightButton: self._state = State.IDLE elif self._state == State.SELECTING: if event.button() == Qt.LeftButton: self._state = State.IDLE if self.GetSelectionMode() is SelectionMode.MODIFY: for item in self._hoveredItems: self.ToggleSelectItem(item) else: self.DeselectAll() for item in self._hoveredItems: self.SelectItem(item) self.selectionChanged.emit(self._selectedItems) elif self._state == State.MOVING: if event.button() == Qt.LeftButton: self._state = State.IDLE self.UpdateView() super().mouseReleaseEvent(event) def keyReleaseEvent(self, event: QKeyEvent): if event.key() == Qt.Key.Key_Delete: self.DeleteSelected() if event.key() == Qt.Key.Key_D and event.modifiers() == Qt.Modifier.CTRL: self.DuplicateSelected() super().keyReleaseEvent(event) def DeleteSelected(self): for item in self.GetSelectedItems().copy(): if item.CanDelete(): item.RequestDelete() def DuplicateSelected(self): newItems = [] for item in self.GetSelectedItems(): if item.CanDuplicate(): newItem = item.Duplicate() newItem.Move(QPointF(50, 50)) self.AddItem(newItem) newItems.append(newItem) if newItems: self.DeselectAll() [self.SelectItem(item) for item in newItems] self.selectionChanged.emit(self.GetSelectedItems())
def centered_text(painter: QtGui.QPainter, pos: QPointF, text: str): rect = QRectF(pos.x() - 32767 * 0.5, pos.y() - 32767 * 0.5, 32767, 32767) painter.drawText(rect, QtGui.Qt.AlignCenter, text)
def qt_local_to_game_loc(self, pos: QPointF) -> NodeLocation: return NodeLocation((pos.x() / self.scale) + self.area_bounds.min_x, self.area_bounds.max_y - (pos.y() / self.scale), 0)
class GLWidget(QOpenGLWidget, QOpenGLFunctions): xRotationChanged = Signal(int) yRotationChanged = Signal(int) zRotationChanged = Signal(int) def __init__(self, parent=None): QOpenGLWidget.__init__(self, parent) QOpenGLFunctions.__init__(self) self.core = "--coreprofile" in QCoreApplication.arguments() self.xRot = 0 self.yRot = 0 self.zRot = 0 self.lastPos = QPointF() self.logo = Logo() self.vao = QOpenGLVertexArrayObject() self.logoVbo = QOpenGLBuffer() self.program = QOpenGLShaderProgram() self.projMatrixLoc = 0 self.mvMatrixLoc = 0 self.normalMatrixLoc = 0 self.lightPosLoc = 0 self.proj = QMatrix4x4() self.camera = QMatrix4x4() self.world = QMatrix4x4() self.transparent = "--transparent" in QCoreApplication.arguments() if self.transparent: fmt = self.format() fmt.setAlphaBufferSize(8) self.setFormat(fmt) def xRotation(self): return self.xRot def yRotation(self): return self.yRot def zRotation(self): return self.zRot def minimumSizeHint(self): return QSize(50, 50) def sizeHint(self): return QSize(400, 400) def normalizeAngle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle def setXRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.xRot: self.xRot = angle self.emit(SIGNAL("xRotationChanged(int)"), angle) self.update() def setYRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.yRot: self.yRot = angle self.emit(SIGNAL("yRotationChanged(int)"), angle) self.update() def setZRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.zRot: self.zRot = angle self.emit(SIGNAL("zRotationChanged(int)"), angle) self.update() def cleanup(self): self.makeCurrent() self.logoVbo.destroy() del self.program self.program = None self.doneCurrent() def vertexShaderSourceCore(self): return """#version 150 in vec4 vertex; in vec3 normal; out vec3 vert; out vec3 vertNormal; uniform mat4 projMatrix; uniform mat4 mvMatrix; uniform mat3 normalMatrix; void main() { vert = vertex.xyz; vertNormal = normalMatrix * normal; gl_Position = projMatrix * mvMatrix * vertex; }""" def fragmentShaderSourceCore(self): return """#version 150 in highp vec3 vert; in highp vec3 vertNormal; out highp vec4 fragColor; uniform highp vec3 lightPos; void main() { highp vec3 L = normalize(lightPos - vert); highp float NL = max(dot(normalize(vertNormal), L), 0.0); highp vec3 color = vec3(0.39, 1.0, 0.0); highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0); fragColor = vec4(col, 1.0); }""" def vertexShaderSource(self): return """attribute vec4 vertex; attribute vec3 normal; varying vec3 vert; varying vec3 vertNormal; uniform mat4 projMatrix; uniform mat4 mvMatrix; uniform mat3 normalMatrix; void main() { vert = vertex.xyz; vertNormal = normalMatrix * normal; gl_Position = projMatrix * mvMatrix * vertex; }""" def fragmentShaderSource(self): return """varying highp vec3 vert; varying highp vec3 vertNormal; uniform highp vec3 lightPos; void main() { highp vec3 L = normalize(lightPos - vert); highp float NL = max(dot(normalize(vertNormal), L), 0.0); highp vec3 color = vec3(0.39, 1.0, 0.0); highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0); gl_FragColor = vec4(col, 1.0); }""" def initializeGL(self): self.context().aboutToBeDestroyed.connect(self.cleanup) self.initializeOpenGLFunctions() self.glClearColor(0, 0, 0, 1) self.program = QOpenGLShaderProgram() if self.core: self.vertexShader = self.vertexShaderSourceCore() self.fragmentShader = self.fragmentShaderSourceCore() else: self.vertexShader = self.vertexShaderSource() self.fragmentShader = self.fragmentShaderSource() self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, self.vertexShader) self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, self.fragmentShader) self.program.bindAttributeLocation("vertex", 0) self.program.bindAttributeLocation("normal", 1) self.program.link() self.program.bind() self.projMatrixLoc = self.program.uniformLocation("projMatrix") self.mvMatrixLoc = self.program.uniformLocation("mvMatrix") self.normalMatrixLoc = self.program.uniformLocation("normalMatrix") self.lightPosLoc = self.program.uniformLocation("lightPos") self.vao.create() vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao) self.logoVbo.create() self.logoVbo.bind() float_size = ctypes.sizeof(ctypes.c_float) self.logoVbo.allocate(self.logo.constData(), self.logo.count() * float_size) self.setupVertexAttribs() self.camera.setToIdentity() self.camera.translate(0, 0, -1) self.program.setUniformValue(self.lightPosLoc, QVector3D(0, 0, 70)) self.program.release() vaoBinder = None def setupVertexAttribs(self): self.logoVbo.bind() f = QOpenGLContext.currentContext().functions() f.glEnableVertexAttribArray(0) f.glEnableVertexAttribArray(1) float_size = ctypes.sizeof(ctypes.c_float) null = VoidPtr(0) pointer = VoidPtr(3 * float_size) f.glVertexAttribPointer(0, 3, int(GL.GL_FLOAT), int(GL.GL_FALSE), 6 * float_size, null) f.glVertexAttribPointer(1, 3, int(GL.GL_FLOAT), int(GL.GL_FALSE), 6 * float_size, pointer) self.logoVbo.release() def paintGL(self): self.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) self.glEnable(GL.GL_DEPTH_TEST) self.glEnable(GL.GL_CULL_FACE) self.world.setToIdentity() self.world.rotate(180 - (self.xRot / 16), 1, 0, 0) self.world.rotate(self.yRot / 16, 0, 1, 0) self.world.rotate(self.zRot / 16, 0, 0, 1) vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao) self.program.bind() self.program.setUniformValue(self.projMatrixLoc, self.proj) self.program.setUniformValue(self.mvMatrixLoc, self.camera * self.world) normalMatrix = self.world.normalMatrix() self.program.setUniformValue(self.normalMatrixLoc, normalMatrix) self.glDrawArrays(GL.GL_TRIANGLES, 0, self.logo.vertexCount()) self.program.release() vaoBinder = None def resizeGL(self, width, height): self.proj.setToIdentity() self.proj.perspective(45, width / height, 0.01, 100) def mousePressEvent(self, event): self.lastPos = event.position() def mouseMoveEvent(self, event): pos = event.position() dx = pos.x() - self.lastPos.x() dy = pos.y() - self.lastPos.y() if event.buttons() & Qt.LeftButton: self.setXRotation(self.xRot + 8 * dy) self.setYRotation(self.yRot + 8 * dx) elif event.buttons() & Qt.RightButton: self.setXRotation(self.xRot + 8 * dy) self.setZRotation(self.zRot + 8 * dx) self.lastPos = pos
class MandelbrotWidget(QWidget): def __init__(self, parent=None): super(MandelbrotWidget, self).__init__(parent) self.thread = RenderThread() self.pixmap = QPixmap() self.pixmapOffset = QPointF() self.lastDragPos = QPointF() self.centerX = DefaultCenterX self.centerY = DefaultCenterY self.pixmapScale = DefaultScale self.curScale = DefaultScale self.thread.renderedImage.connect(self.updatePixmap) self.setWindowTitle("Mandelbrot") self.setCursor(Qt.CrossCursor) self.resize(550, 400) def paintEvent(self, event): painter = QPainter(self) painter.fillRect(self.rect(), Qt.black) if self.pixmap.isNull(): painter.setPen(Qt.white) painter.drawText(self.rect(), Qt.AlignCenter, "Rendering initial image, please wait...") return if self.curScale == self.pixmapScale: painter.drawPixmap(self.pixmapOffset, self.pixmap) else: scaleFactor = self.pixmapScale / self.curScale newWidth = int(self.pixmap.width() * scaleFactor) newHeight = int(self.pixmap.height() * scaleFactor) newX = self.pixmapOffset.x() + (self.pixmap.width() - newWidth) / 2 newY = self.pixmapOffset.y() + (self.pixmap.height() - newHeight) / 2 painter.save() painter.translate(newX, newY) painter.scale(scaleFactor, scaleFactor) exposed, _ = painter.transform().inverted() exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1) painter.drawPixmap(exposed, self.pixmap, exposed) painter.restore() text = "Use mouse wheel or the '+' and '-' keys to zoom. Press and " \ "hold left mouse button to scroll." metrics = painter.fontMetrics() textWidth = metrics.horizontalAdvance(text) painter.setPen(Qt.NoPen) painter.setBrush(QColor(0, 0, 0, 127)) painter.drawRect((self.width() - textWidth) / 2 - 5, 0, textWidth + 10, metrics.lineSpacing() + 5) painter.setPen(Qt.white) painter.drawText((self.width() - textWidth) / 2, metrics.leading() + metrics.ascent(), text) def resizeEvent(self, event): self.thread.render(self.centerX, self.centerY, self.curScale, self.size()) def keyPressEvent(self, event): if event.key() == Qt.Key_Plus: self.zoom(ZoomInFactor) elif event.key() == Qt.Key_Minus: self.zoom(ZoomOutFactor) elif event.key() == Qt.Key_Left: self.scroll(-ScrollStep, 0) elif event.key() == Qt.Key_Right: self.scroll(+ScrollStep, 0) elif event.key() == Qt.Key_Down: self.scroll(0, -ScrollStep) elif event.key() == Qt.Key_Up: self.scroll(0, +ScrollStep) else: super(MandelbrotWidget, self).keyPressEvent(event) def wheelEvent(self, event): numDegrees = event.angleDelta().y() / 8 numSteps = numDegrees / 15.0 self.zoom(pow(ZoomInFactor, numSteps)) def mousePressEvent(self, event): if event.buttons() == Qt.LeftButton: self.lastDragPos = event.position() def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: pos = event.position() self.pixmapOffset += pos - self.lastDragPos self.lastDragPos = pos self.update() def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.pixmapOffset += event.position() - self.lastDragPos self.lastDragPos = QPointF() deltaX = (self.width() - self.pixmap.width()) / 2 - self.pixmapOffset.x() deltaY = (self.height() - self.pixmap.height()) / 2 - self.pixmapOffset.y() self.scroll(deltaX, deltaY) def updatePixmap(self, image, scaleFactor): if not self.lastDragPos.isNull(): return self.pixmap = QPixmap.fromImage(image) self.pixmapOffset = QPointF() self.lastDragPosition = QPointF() self.pixmapScale = scaleFactor self.update() def zoom(self, zoomFactor): self.curScale *= zoomFactor self.update() self.thread.render(self.centerX, self.centerY, self.curScale, self.size()) def scroll(self, deltaX, deltaY): self.centerX += deltaX * self.curScale self.centerY += deltaY * self.curScale self.update() self.thread.render(self.centerX, self.centerY, self.curScale, self.size())