from common import * from editorcommon import * import weakref class KPEditorNode(KPEditorItem): SNAP_TO = (12,12) class ToggleButton(QtGui.QPushButton): stateToggled = QtCore.pyqtSignal(int) def __init__(self): QtGui.QPushButton.__init__(self) self.setIconSize(QtCore.QSize(24, 24)) self.setFixedSize(24, 24) self.iconList = [QtGui.QIcon("Resources/Through.png"), QtGui.QIcon("Resources/Level.png"), QtGui.QIcon("Resources/Stop.png")] self.state = 0 if not hasattr(KPEditorNode.ToggleButton, 'PALETTE'): KPEditorNode.ToggleButton.PALETTE = QtGui.QPalette(Qt.transparent) self.setPalette(self.PALETTE) self.released.connect(self.toggle) def toggle(self): self.state += 1 if self.state == 3: self.state = 0 self.stateToggled.emit(self.state) def paintEvent(self, event): painter = QtGui.QPainter(self) if self.isDown(): self.iconList[self.state].paint(painter, self.contentsRect(), Qt.AlignCenter, QtGui.QIcon.Disabled) else: self.iconList[self.state].paint(painter, self.contentsRect()) painter.end() class HiddenProxy(QtGui.QGraphicsProxyWidget): def __init__(self, button, parent, x, y): QtGui.QGraphicsProxyWidget.__init__(self, parent) self.setWidget(button) self.setPos(x, y) self.setZValue(parent.zValue()+1000) self.hide() class LevelSlotSpinner(QtGui.QSpinBox): def __init__(self): QtGui.QSpinBox.__init__(self) self.setRange(1, 99) if not hasattr(KPEditorNode.LevelSlotSpinner, 'PALETTE'): palette = QtGui.QApplication.palette(self) palette.setColor(QtGui.QPalette.Window, Qt.transparent) KPEditorNode.LevelSlotSpinner.PALETTE = palette self.setPalette(self.PALETTE) def __init__(self, node): KPEditorItem.__init__(self) node.qtItem = self self._nodeRef = weakref.ref(node) self.setZValue(101) self._boundingRect = QtCore.QRectF(-24, -24, 48, 48) self._levelRect = self._boundingRect self._stopRect = QtCore.QRectF(-12, -12, 24, 24) self._tinyRect = QtCore.QRectF(-6, -6, 12, 12) if not hasattr(KPEditorNode, 'SELECTION_PEN'): KPEditorNode.SELECTION_PEN = QtGui.QPen(Qt.blue, 1, Qt.DotLine) self.button = self.ToggleButton() self.buttonProxy = self.HiddenProxy(self.button, self, 12, -24) self.button.stateToggled.connect(self.stateChange) self.world = self.LevelSlotSpinner() self.worldProxy = self.HiddenProxy(self.world, self, -42, 24) self.world.valueChanged.connect(self.worldChange) self.stage = self.LevelSlotSpinner() self.stageProxy = self.HiddenProxy(self.stage, self, 6, 24) self.stage.valueChanged.connect(self.stageChange) self._updatePosition() @QtCore.pyqtSlot(int) def stateChange(self, state): node = self._nodeRef() if state == 1: node.isStop = True node.level = [1, 1] self.world.setValue(node.level[0]) self.stage.setValue(node.level[1]) elif state == 2: node.isStop = True node.level = [0,0] else: node.isStop = False node.level = [0,0] self.update() @QtCore.pyqtSlot(int) def worldChange(self, world): node = self._nodeRef() node.level[0] = world @QtCore.pyqtSlot(int) def stageChange(self, stage): node = self._nodeRef() node.level[1] = stage def _updatePosition(self): node = self._nodeRef() x, y = node.position self.setPos(x+12, y+12) def _itemMoved(self, oldX, oldY, newX, newY): node = self._nodeRef() node.position = (newX-12, newY-12) for exit in node.exits: exit.qtItem.updatePosition() def paint(self, painter, option, widget): painter.setRenderHint(QtGui.QPainter.Antialiasing) node = self._nodeRef() selectionRect = None if node.level != [0,0]: painter.setBrush(QtGui.QColor(0, 0, 0, 0)) painter.setPen(QtGui.QColor(0, 0, 0, 0)) painter.drawPixmap(self._boundingRect.topLeft(), QtGui.QPixmap("Resources/BlackLevel.png")) selectionRect = self._boundingRect.adjusted(1,5,-1,-5) elif node.isStop: brush = QtGui.QBrush(QtGui.QColor(255, 220, 220)) painter.setPen(QtGui.QColor(255, 255, 255)) painter.setBrush(brush) painter.drawEllipse(self._stopRect) selectionRect = self._stopRect.adjusted(-1,-1,1,1) else: brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) painter.setPen(QtGui.QColor(255, 255, 255)) painter.setBrush(brush) painter.drawEllipse(self._tinyRect) selectionRect = self._tinyRect.adjusted(-1,-1,1,1) if self.isSelected(): painter.setPen(self.SELECTION_PEN) painter.setBrush(QtGui.QColor(0,0,0,0)) painter.drawEllipse(selectionRect) self.buttonProxy.show() if node.level != [0,0]: self.worldProxy.show() self.stageProxy.show() else: self.worldProxy.hide() self.stageProxy.hide() else: self.buttonProxy.hide() self.worldProxy.hide() self.stageProxy.hide() def remove(self, withItem=False): node = self._nodeRef() layer = KP.map.pathLayer layer.nodes.remove(node) if len(node.exits) == 2: # let's try to join the two! pathOne, pathTwo = node.exits start1, end1 = pathOne._startNodeRef(), pathOne._endNodeRef() start2, end2 = pathTwo._startNodeRef(), pathTwo._endNodeRef() if start1 == node: start = end1 else: start = start1 if start2 == node: end = end2 else: end = start2 # make sure no path already exists between these nodes nope = False for pathToCheck in start.exits: if pathToCheck._startNodeRef() == end: nope = True elif pathToCheck._endNodeRef() == end: nope = True if not nope: joinedPath = KPPath(start, end, pathOne) layer.paths.append(joinedPath) item = KPEditorPath(joinedPath) self.scene().addItem(item) for path in (pathOne, pathTwo): path.qtItem.remove(True) else: # we can't join them so just nuke them for exit in node.exits[:]: exit.qtItem.remove(True) if withItem: self.scene().removeItem(self) class KPEditorPath(QtGui.QGraphicsLineItem): class PathOptionsMenuButton(QtGui.QPushButton): class PathOptionsWidget(QtGui.QWidget): def __init__(self, pathRef): QtGui.QWidget.__init__(self) self._pathRef = pathRef TopLayout = QtGui.QGridLayout() Layout = QtGui.QGridLayout() # Make an exclusive button group for our animations. AnimationList = ["Walk", "WalkSand", "WalkSnow", "WalkIce", "Jump", "JumpSand", "JumpSnow", "SpinJump", "Ladder", "LadderLeft", "LadderRight", "Fall", "Swim", "Run", "Pipe", "Door"] self.ExclusiveButtons = QtGui.QButtonGroup() i = 0 j = 1 id = 0 for anim in AnimationList: newButton = QtGui.QPushButton(QtGui.QIcon("Resources/Anm/" + anim), "") newButton.setCheckable(True) newButton.setIconSize(QtCore.QSize(38, 38)) newButton.setToolTip(anim) self.ExclusiveButtons.addButton(newButton, id) Layout.addWidget(newButton, j, i) if id == 0: newButton.setChecked(True) id += 1 i += 1 if i == 4: i = 0 j += 1 # Movement Speed Spin Box self.moveSpeedSpinner = QtGui.QDoubleSpinBox() self.moveSpeedSpinner.setMinimum(0.0) self.moveSpeedSpinner.setMaximum(256.0) self.moveSpeedSpinner.setDecimals(2) self.moveSpeedSpinner.setSingleStep(0.05) self.moveSpeedSpinner.setValue(1.0) TopLayout.addWidget(self.moveSpeedSpinner, 1, 0) # Layer Combo Box self.linkedLayer = QtGui.QComboBox(self) self.linkedLayer.setModel(KP.map.layerModel) TopLayout.addWidget(self.linkedLayer, 1, 1, 1, 3) # Connections self.ExclusiveButtons.buttonReleased.connect(self.updatePathAnim) self.moveSpeedSpinner.valueChanged.connect(self.updateMoveSpeed) self.linkedLayer.currentIndexChanged.connect(self.updateLinkLayer) # Layout TopLayout.addWidget(QtGui.QLabel("Speed:"), 0, 0) TopLayout.addWidget(QtGui.QLabel("Layer Shown on Unlock:"), 0, 1, 1, 3) Layout.addLayout(TopLayout, 0, 0, 1, 4) self.setLayout(Layout) @QtCore.pyqtSlot(float) def updateMoveSpeed(self, speed): path = self._pathRef() path.movementSpeed = speed path.qtItem.update() @QtCore.pyqtSlot(int) def updatePathAnim(self, buttonID): path = self._pathRef() path.animation = buttonID path.qtItem.update() @QtCore.pyqtSlot(int) def updateLinkLayer(self, layerIndex): path = self._pathRef() path.linkedLayer = KP.map.layers[layerIndex] def __init__(self, pathRef): QtGui.QPushButton.__init__(self) self.setText("Options") self.menu = QtGui.QMenu(self) layout = QtGui.QVBoxLayout() layout.addWidget(self.PathOptionsWidget(pathRef)) self.menu.setLayout(layout) menuPalette = self.menu.palette() menuPalette.setColor(QtGui.QPalette.Window, Qt.black) self.menu.setPalette(menuPalette) # dropShadow = QtGui.QGraphicsDropShadowEffect() # self.menu.setGraphicsEffect(dropShadow) self.setMenu(self.menu) palette = self.palette() palette.setColor(QtGui.QPalette.ButtonText, Qt.black) palette.setColor(QtGui.QPalette.Window, Qt.transparent) self.setPalette(palette) class UnlockButton(QtGui.QPushButton): def __init__(self, pathRef): QtGui.QPushButton.__init__(self) self.setFixedSize(48,48) self.iconList = [QtGui.QIcon("Resources/Key.png"), QtGui.QIcon("Resources/SecretKey.png")] self.unlockIcon = QtGui.QIcon("Resources/Unlock.png") self.arrowIcon = [QtGui.QIcon("Resources/KeyArrow.png"), QtGui.QIcon("Resources/SecretKeyArrow.png")] self._pathRef = pathRef self.secret = 0 self.path = 0 if not hasattr(KPEditorPath.UnlockButton, 'PALETTE'): KPEditorPath.UnlockButton.PALETTE = QtGui.QPalette(Qt.transparent) self.setPalette(self.PALETTE) self.released.connect(self.toggle) def toggle(self): path = self._pathRef() if KP.app.keyboardModifiers() == Qt.ShiftModifier: if self.secret == 1: self.secret = 0 else: self.secret = 1 path.secret = self.secret else: self.path += 1 if self.path > 2: self.path = 0 path.unlocks = self.path def paintEvent(self, event): painter = QtGui.QPainter(self) contentsRect = self.contentsRect() smallRect = QtCore.QRect(12, 12, 24, 24) painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform) if self.path > 0: painter.save() displaceX, displaceY = contentsRect.width() / 2, contentsRect.height() / 2 pathItem = self._pathRef().qtItem.line() if self.path == 1: angle = 90 - pathItem.angle() else: angle = 270 - pathItem.angle() painter.translate(displaceX, displaceY) painter.rotate(angle) painter.translate(-displaceX, -displaceY) self.arrowIcon[self.secret].paint(painter, contentsRect, Qt.AlignCenter) painter.restore() if self.isDown(): self.iconList[self.secret].paint(painter, smallRect, Qt.AlignCenter, QtGui.QIcon.Disabled) else: self.iconList[self.secret].paint(painter, smallRect, Qt.AlignCenter) else: if self.isDown(): self.unlockIcon.paint(painter, smallRect, Qt.AlignCenter, QtGui.QIcon.Disabled) else: self.unlockIcon.paint(painter, smallRect, Qt.AlignCenter) painter.end() class HiddenProxy(QtGui.QGraphicsProxyWidget): def __init__(self, button, parent, x, y): QtGui.QGraphicsProxyWidget.__init__(self, parent) self.setWidget(button) self.setPos(x, y) self.setZValue(parent.zValue()+1000) self.hide() def __init__(self, path): QtGui.QGraphicsLineItem.__init__(self) self.setFlag(self.ItemIsSelectable, True) self.setZValue(100) startNode = path._startNodeRef().qtItem endNode = path._endNodeRef().qtItem self._startNodeRef = weakref.ref(startNode) self._endNodeRef = weakref.ref(endNode) self._pathRef = weakref.ref(path) path.qtItem = self if not hasattr(KPEditorPath, 'PEN'): KPEditorPath.BRUSH = QtGui.QBrush(QtGui.QColor(255, 255, 255, 140)) KPEditorPath.PEN = QtGui.QPen(KPEditorPath.BRUSH, 8, Qt.SolidLine, Qt.RoundCap) self.setPen(KPEditorPath.PEN) if not hasattr(KPEditorPath, 'SELECTION_PEN'): KPEditorPath.SELECTION_PEN = QtGui.QPen(Qt.blue, 1, Qt.DotLine) self.unlock = self.UnlockButton(self._pathRef) self.unlockProxy = self.HiddenProxy(self.unlock, self, -24, -24) self.options = self.PathOptionsMenuButton(self._pathRef) self.optionsProxy = self.HiddenProxy(self.options, self, -54, +24) self.updatePosition() def updatePosition(self): path = self._pathRef() sn = path._startNodeRef() en = path._endNodeRef() if sn is None or en is None: return x1, y1 = path._startNodeRef().position x2, y2 = path._endNodeRef().position originLine = QtCore.QLineF(x1+12, y1+12, x2+12, y2+12) self.setPos(originLine.pointAt(0.5)) dy = originLine.dy()/2 dx = originLine.dx()/2 self.setLine(QtCore.QLineF(-dx, -dy, dx, dy)) def paint(self, painter, option, widget): painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setPen(KPEditorPath.PEN) painter.drawLine(self.line()) if self.isSelected(): painter.setPen(self.SELECTION_PEN) painter.setBrush(QtGui.QColor(0,0,0,0)) painter.drawPath(self.shape()) self.unlockProxy.show() self.optionsProxy.show() else: self.unlockProxy.hide() self.optionsProxy.hide() def remove(self, withItem=False): if hasattr(self, 'hasBeenRemovedAlready'): return self.hasBeenRemovedAlready = True path = self._pathRef() layer = KP.map.pathLayer layer.paths.remove(path) for ref in (self._startNodeRef, self._endNodeRef): node = ref()._nodeRef() try: node.exits.remove(path) except ValueError: pass if withItem: self.scene().removeItem(self)