diff options
author | Treeki <treeki@gmail.com> | 2011-11-21 15:25:54 +0100 |
---|---|---|
committer | Treeki <treeki@gmail.com> | 2011-11-21 15:25:54 +0100 |
commit | 30188c779e1b419f6818596a29f7f3c7edad42bb (patch) | |
tree | 4bf37618ec1721b6f41b1686d71a9d727333e104 /src/editorui.py | |
parent | 63ba5f8a58bd26f42712ca61d7d18a1858083443 (diff) | |
download | koopatlas-30188c779e1b419f6818596a29f7f3c7edad42bb.tar.gz koopatlas-30188c779e1b419f6818596a29f7f3c7edad42bb.zip |
some refactoring of editorui and co
Diffstat (limited to 'src/editorui.py')
-rw-r--r-- | src/editorui.py | 1227 |
1 files changed, 0 insertions, 1227 deletions
diff --git a/src/editorui.py b/src/editorui.py deleted file mode 100644 index 2ab3774..0000000 --- a/src/editorui.py +++ /dev/null @@ -1,1227 +0,0 @@ -from common import * -from math import floor, ceil -import weakref -import math - - -class KPEditorItem(QtGui.QGraphicsItem): - def __init__(self): - QtGui.QGraphicsItem.__init__(self) - self.setFlags( - self.ItemSendsGeometryChanges | - self.ItemIsSelectable | - self.ItemIsMovable - ) - - self.ignoreMovement = False - self.overrideSnap = False - - def itemChange(self, change, value): - if change == self.ItemPositionChange and not self.ignoreMovement: - currentX, currentY = self.x(), self.y() - - newpos = value.toPyObject() - - x, y = newpos.x(), newpos.y() - - if self.overrideSnap: - snapX, snapY = 1, 1 - else: - # snap the item - snapX, snapY = self.SNAP_TO - x = int((x + (snapX/2)) / snapX) * snapX - y = int((y + (snapY/2)) / snapY) * snapY - - if x < 0: x = 0 - if x >= (12288+snapX): x = (12288+snapX-1) - if y < 0: y = 0 - if y >= (12288+snapY): y = (12288+snapY-1) - - if x != currentX or y != currentY: - self._itemMoved(currentX, currentY, x, y) - - newpos.setX(x) - newpos.setY(y) - return newpos - - return QtGui.QGraphicsItem.itemChange(self, change, value) - - def boundingRect(self): - return self._boundingRect - - - def resizerPortionAt(self, x, y, originX=0, originY=0): - try: - leftBound, topBound = originX+5, originY+5 - rightBound, bottomBound = self._resizerEndXY - except AttributeError: - rect = self._boundingRect - leftBound, topBound = rect.x() + 5, rect.y() + 5 - rightBound, bottomBound = rect.right() - 5, rect.bottom() - 5 - - if y < topBound: - if x < leftBound: return 1 # TOP_LEFT - elif x >= rightBound: return 2 # TOP_RIGHT - else: return 5 # TOP - - elif y >= bottomBound: - if x < leftBound: return 3 # BOTTOM_LEFT - elif x >= rightBound: return 4 # BOTTOM_RIGHT - else: return 6 # BOTTOM - - else: - if x < leftBound: return 7 # LEFT - elif x >= rightBound: return 8 # RIGHT - else: return None - - - def _itemMoved(self, oldX, oldY, newX, newY): - pass - - -class KPEditorObject(KPEditorItem): - SNAP_TO = (24,24) - - def __init__(self, obj, layer): - KPEditorItem.__init__(self) - obj.qtItem = self - self._objRef = weakref.ref(obj) - self._layerRef = weakref.ref(layer) - self._updatePosition() - self._updateSize() - - self.setAcceptHoverEvents(True) - - self.resizing = None - - if not hasattr(KPEditorObject, 'SELECTION_PEN'): - KPEditorObject.SELECTION_PEN = QtGui.QPen(Qt.white, 1, Qt.DotLine) - - # I don't bother setting the ZValue because it doesn't quite matter: - # only one layer's objects are ever clickable, and drawBackground takes - # care of the layered drawing - - def _updatePosition(self): - self.ignoreMovement = True - x,y = self._objRef().position - self.setPos(x*24, y*24) - self.ignoreMovement = False - - def _updateSize(self): - self.prepareGeometryChange() - - obj = self._objRef() - w,h = obj.size - - self._boundingRect = QtCore.QRectF(0, 0, w*24, h*24) - self._selectionRect = QtCore.QRectF(0, 0, w*24-1, h*24-1) - - self._resizerEndXY = (w*24-5, h*24-5) - - - def paint(self, painter, option, widget): - if self.isSelected(): - painter.setPen(self.SELECTION_PEN) - painter.drawRect(self._selectionRect) - - - def hoverMoveEvent(self, event): - if self._layerRef() != KP.mapScene.currentLayer: - self.setCursor(Qt.ArrowCursor) - return - - pos = event.pos() - bit = self.resizerPortionAt(pos.x(), pos.y()) - - if bit == 1 or bit == 4: - self.setCursor(Qt.SizeFDiagCursor) - elif bit == 2 or bit == 3: - self.setCursor(Qt.SizeBDiagCursor) - elif bit == 7 or bit == 8: - self.setCursor(Qt.SizeHorCursor) - elif bit == 5 or bit == 6: - self.setCursor(Qt.SizeVerCursor) - else: - self.setCursor(Qt.ArrowCursor) - - - def mousePressEvent(self, event): - if event.button() == Qt.LeftButton: - pos = event.pos() - bit = self.resizerPortionAt(pos.x(), pos.y()) - - if self._layerRef() == KP.mapScene.currentLayer and bit: - event.accept() - - x, xSide, y, ySide = False, None, False, None - - if bit == 1 or bit == 7 or bit == 3: - x, xSide = True, 1 - elif bit == 2 or bit == 4 or bit == 8: - x, xSide = True, 0 - - if bit == 1 or bit == 2 or bit == 5: - y, ySide = True, 1 - elif bit == 3 or bit == 4 or bit == 6: - y, ySide = True, 0 - - self.resizing = (x, xSide, y, ySide) - return - - KPEditorItem.mousePressEvent(self, event) - - - def _tryAndResize(self, obj, axisIndex, mousePosition, stationarySide): - objPosition = obj.position[axisIndex] - objSize = obj.size[axisIndex] - - if stationarySide == 0: - # Resize the right/bottom side - relativeMousePosition = mousePosition - objPosition - newSize = relativeMousePosition + 1 - if newSize == objSize or newSize < 1: - return False - - if axisIndex == 1: - obj.size = (obj.size[0], newSize) - else: - obj.size = (newSize, obj.size[1]) - - else: - # Resize the left/top side - rightSide = objPosition + objSize - 1 - newLeftSide = mousePosition - - newPosition = newLeftSide - newSize = rightSide - newLeftSide + 1 - - if newSize < 1: - return False - if newPosition == objPosition and newSize == objSize: - return False - - if axisIndex == 1: - obj.position = (obj.position[0], newPosition) - obj.size = (obj.size[0], newSize) - else: - obj.position = (newPosition, obj.position[1]) - obj.size = (newSize, obj.size[1]) - - return True - - - def mouseMoveEvent(self, event): - if self.resizing: - obj = self._objRef() - scenePos = event.scenePos() - - hasChanged = False - resizeX, xSide, resizeY, ySide = self.resizing - - if resizeX: - hasChanged |= self._tryAndResize(obj, 0, int(scenePos.x() / 24), xSide) - if resizeY: - hasChanged |= self._tryAndResize(obj, 1, int(scenePos.y() / 24), ySide) - - if hasChanged: - obj.updateCache() - self._layerRef().updateCache() - self._updatePosition() - self._updateSize() - - else: - KPEditorItem.mouseMoveEvent(self, event) - - - def mouseReleaseEvent(self, event): - if self.resizing and event.button() == Qt.LeftButton: - self.resizing = None - else: - KPEditorItem.mouseReleaseEvent(self, event) - - - def _itemMoved(self, oldX, oldY, newX, newY): - obj = self._objRef() - obj.position = (newX/24, newY/24) - self._layerRef().updateCache() - - - def remove(self, withItem=False): - obj = self._objRef() - layer = self._layerRef() - - layer.objects.remove(obj) - layer.updateCache() - - if withItem: - self.scene().removeItem(self) - - -class KPEditorDoodad(KPEditorItem): - SNAP_TO = (12,12) - - def __init__(self, doodad, layer): - KPEditorItem.__init__(self) - - doodad.qtItem = self - self._doodadRef = weakref.ref(doodad) - self._layerRef = weakref.ref(layer) - - # TODO: refactor this to store source doodad data under KP.map - sourceItem = KP.mainWindow.doodadSelector.getDoodad(doodad.index) - self._sourceRef = weakref.ref(sourceItem) - - self.resizing = None - self.rotating = None - - self._updatePixmap() - self._updatePosition() - self._updateSize() - - self.setAcceptHoverEvents(True) - - if not hasattr(KPEditorDoodad, 'SELECTION_PEN'): - KPEditorDoodad.SELECTION_PEN = QtGui.QPen(Qt.red, 1, Qt.DotLine) - - - - def _updatePixmap(self): - source = self._sourceRef() - pixmap = source.icon().pixmap(source.icon().availableSizes()[0]) - - self.prepareGeometryChange() - w, h = pixmap.width(), pixmap.height() - - self.pixmap = pixmap - - - def _updatePosition(self): - # NOTE: EditorDoodads originate at the centre, not the top left like the others - doodad = self._doodadRef() - x,y = doodad.position - w,h = doodad.size - self.setPos(x+floor(w/2.0), y+floor(h/2.0)) - - - def _updateSize(self): - self.prepareGeometryChange() - - w,h = self._doodadRef().size - - self._boundingRect = QtCore.QRectF(-w/2, -h/2, w, h) - self._selectionRect = self._boundingRect.adjusted(0, 0, -1, -1) - - - def _updateTransform(self): - doodad = self._doodadRef() - - self.setRotation(doodad.angle) - - - def paint(self, painter, option, widget): - if self.isSelected(): - painter.setPen(self.SELECTION_PEN) - painter.drawRect(self._selectionRect) - - - def _itemMoved(self, oldX, oldY, newX, newY): - doodad = self._doodadRef() - w,h = doodad.size - doodad.position = [newX-floor(w/2.0), newY-floor(h/2.0)] - - - def hoverMoveEvent(self, event): - if self._layerRef() != KP.mapScene.currentLayer: - self.setCursor(Qt.ArrowCursor) - return - - pos = event.pos() - bit = self.resizerPortionAt(pos.x(), pos.y()) - - - if (event.modifiers() == Qt.ShiftModifier): - - if bit: - self.setCursor(Qt.OpenHandCursor) - else: - self.setCursor(Qt.ArrowCursor) - - else: - - if bit == 1 or bit == 4: - self.setCursor(Qt.SizeFDiagCursor) - elif bit == 2 or bit == 3: - self.setCursor(Qt.SizeBDiagCursor) - elif bit == 7 or bit == 8: - self.setCursor(Qt.SizeHorCursor) - elif bit == 5 or bit == 6: - self.setCursor(Qt.SizeVerCursor) - else: - self.setCursor(Qt.ArrowCursor) - - - def mousePressEvent(self, event): - if event.button() == Qt.LeftButton: - pos = event.pos() - bit = self.resizerPortionAt(pos.x(), pos.y()) - - if self._layerRef() == KP.mapScene.currentLayer and bit: - event.accept() - - if (event.modifiers() & Qt.ShiftModifier): - self.rotating = self.mapToScene(pos), self._doodadRef().angle - self.setCursor(Qt.ClosedHandCursor) - return - - else: - x, xSide, y, ySide = False, None, False, None - - if bit == 1 or bit == 7 or bit == 3: # left - x, xSide = True, 1 - - elif bit == 2 or bit == 4 or bit == 8: # right - x, xSide = True, 0 - - if bit == 1 or bit == 2 or bit == 5: # top - y, ySide = True, 1 - - elif bit == 3 or bit == 4 or bit == 6: # bottom - y, ySide = True, 0 - - self._updateSize() - self.resizing = (x, xSide, y, ySide) - return - - - KPEditorItem.mousePressEvent(self, event) - - - def _tryAndResize(self, obj, axisIndex, mousePosition, stationarySide): - - newSize = abs(mousePosition) * 2 - - if newSize < 10: - return False - - obj.size[axisIndex] = newSize - - return True - - - def _tryAndRotate(self, obj, mouseX, mouseY, originalPos, oldAngle, modifiers): - center = self.mapToScene(self.boundingRect().center()) - - objX = center.x() - objY = center.y() - - - origX = originalPos.x() - origY = originalPos.y() - - dy = origY - objY - dx = origX - objX - rads = math.atan2(dy, dx) - - origAngle = math.degrees(rads) - - dy = mouseY - objY - dx = mouseX - objX - rads = math.atan2(dy, dx) - - angle = math.degrees(rads) - - - # Move this to ItemChange() or something at some point. - finalAngle = angle - origAngle + oldAngle - - if (modifiers & Qt.ControlModifier): - finalAngle = int(finalAngle / 45.0) * 45.0 - - return True, finalAngle - - - def mouseMoveEvent(self, event): - if self.resizing: - obj = self._doodadRef() - - hasChanged = False - resizeX, xSide, resizeY, ySide = self.resizing - - if resizeX: - hasChanged |= self._tryAndResize(obj, 0, event.pos().x(), xSide) - if resizeY: - hasChanged |= self._tryAndResize(obj, 1, event.pos().y(), ySide) - - if hasChanged: - # Doodads aren't supposed to snap, they're all free flowing like the wind. - self._updateSize() - - - elif self.rotating: - obj = self._doodadRef() - scenePos = event.scenePos() - self.setTransformOriginPoint(self.boundingRect().center()) - - hasChanged = False - - hasChanged, angle = self._tryAndRotate(obj, scenePos.x(), scenePos.y(), self.rotating[0], self.rotating[1], event.modifiers()) - - if hasChanged: - obj.angle = angle - self._updateTransform() - - - else: - KPEditorItem.mouseMoveEvent(self, event) - - - def mouseReleaseEvent(self, event): - if self.resizing and event.button() == Qt.LeftButton: - self.resizing = None - # self._doodadRef().position = [self.x(), self.y()] - - elif self.rotating and event.button() == Qt.LeftButton: - self.rotating = None - - else: - KPEditorItem.mouseReleaseEvent(self, event) - - - def remove(self, withItem=False): - doodad = self._doodadRef() - layer = self._layerRef() - - layer.objects.remove(doodad) - - if withItem: - self.scene().removeItem(self) - - -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 - - self.setPalette(QtGui.QPalette(QtGui.QColor(0,0,0,0))) - - 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) - - painter.setBackgroundMode(Qt.TransparentMode) - painter.setBrush(QtGui.QColor(0,0,0,0)) - painter.setPen(QtGui.QColor(0,0,0,0)) - - 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): - QtGui.QGraphicsProxyWidget.__init__(self) - - self.setWidget(button) - self.setZValue(self.zValue()+1000) - self.hide() - - - class levelSlotSpinner(QtGui.QSpinBox): - - def __init__(self): - QtGui.QSpinBox.__init__(self) - - self.setRange(1, 99) - - self.setPalette(QtGui.QPalette(QtGui.QColor(0,0,0,0))) - - - - 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._tinyRect = QtCore.QRectF(-12, -12, 24, 24) - - - 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.button.stateToggled.connect(self.stateChange) - - - self.world = self.levelSlotSpinner() - self.worldProxy = self.hiddenProxy(self.world) - self.world.valueChanged.connect(self.worldChange) - - self.stage = self.levelSlotSpinner() - self.stageProxy = self.hiddenProxy(self.stage) - self.stage.valueChanged.connect(self.stageChange) - - - self._updatePosition() - - - - @QtCore.pyqtSlot(int) - def stateChange(self, state): - - node = self._nodeRef() - - if state == 1: - 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) - self.buttonProxy.setPos(self.x()+12, self.y()-24) - self.worldProxy.setPos(self.x()-42, self.y()+24) - self.stageProxy.setPos(self.x()+6, self.y()+24) - - - def _itemMoved(self, oldX, oldY, newX, newY): - node = self._nodeRef() - node.position = (newX-12, newY-12) - - self.buttonProxy.setPos(newX+12, newY-24) - self.worldProxy.setPos(newX-42, newY+24) - self.stageProxy.setPos(newX+6, newY+24) - - for exit in node.exits: - exit.qtItem.updatePosition() - - - def paint(self, painter, option, widget): - - 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,-1,1,1) - - elif node.isStop: - brush = QtGui.QBrush(QtGui.QColor(255, 220, 220)) - painter.setPen(QtGui.QColor(255, 255, 255)) - painter.setBrush(brush) - painter.drawEllipse(self._tinyRect) - selectionRect = self._tinyRect.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) - - self.scene().removeItem(self.buttonProxy) - self.scene().removeItem(self.stageProxy) - self.scene().removeItem(self.worldProxy) - - 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): - 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 - - self.updatePosition() - - 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) - - - def updatePosition(self): - path = self._pathRef() - - x1, y1 = path._startNodeRef().position - x2, y2 = path._endNodeRef().position - - self.setLine(QtCore.QLineF(x1+12, y1+12, x2+12, y2+12)) - - - def remove(self, withItem=False): - 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) - - - -class KPMapScene(QtGui.QGraphicsScene): - def __init__(self): - QtGui.QGraphicsScene.__init__(self, 0, 0, 512*24, 512*24) - - # todo: handle selectionChanged - # todo: look up why I used setItemIndexMethod(self.NoIndex) in Reggie - - self.currentLayer = None - KP.mapScene = self - - - def drawBackground(self, painter, rect): - painter.fillRect(rect, QtGui.QColor(209, 218, 236)) - - areaLeft, areaTop = rect.x(), rect.y() - areaWidth, areaHeight = rect.width(), rect.height() - areaRight, areaBottom = areaLeft+areaWidth, areaTop+areaHeight - - areaLeftT = floor(areaLeft / 24) - areaTopT = floor(areaTop / 24) - areaRightT = ceil(areaRight / 24) - areaBottomT = ceil(areaBottom / 24) - - # compile a list of doodads - visibleDoodadsByLayer = {} - - for obj in self.items(rect): - if not isinstance(obj, KPEditorDoodad): continue - - layer = obj._layerRef() - - try: - doodadList = visibleDoodadsByLayer[layer] - except KeyError: - doodadList = [] - visibleDoodadsByLayer[layer] = doodadList - - doodadList.append(obj) - - # now draw everything! - for layer in reversed(KP.map.layers): - if not layer.visible: continue - - if isinstance(layer, KPDoodadLayer): - try: - toDraw = visibleDoodadsByLayer[layer] - except KeyError: - continue - - for item in reversed(toDraw): - painter.save() - painter.setWorldTransform(item.sceneTransform(), True) - w, h = item._doodadRef().size - p = item._boundingRect - painter.drawPixmap(p.x(), p.y(), p.width(), p.height(), item.pixmap) - painter.restore() - - elif isinstance(layer, KPTileLayer): - left, top = layer.cacheBasePos - width, height = layer.cacheSize - right, bottom = left+width, top+height - - if width == 0 and height == 0: continue - - if right < areaLeftT: continue - if left > areaRightT: continue - - if bottom < areaTopT: continue - if top > areaBottomT: continue - - # decide how much of the layer we'll actually draw - drawLeft = int(max(areaLeftT, left)) - drawRight = int(min(areaRightT, right)) - - drawTop = int(max(areaTopT, top)) - drawBottom = int(min(areaBottomT, bottom)) - - srcY = drawTop - top - destY = drawTop * 24 - - baseSrcX = drawLeft - left - baseDestX = drawLeft * 24 - - rows = layer.cache - tileset = KP.map.loadedTilesets[layer.tileset] - tileList = tileset.tiles - - for y in xrange(drawTop, drawBottom): - srcX = baseSrcX - destX = baseDestX - row = rows[srcY] - - for x in xrange(drawLeft, drawRight): - tile = row[srcX] - if tile != -1: - painter.drawPixmap(destX, destY, tileList[tile]) - - srcX += 1 - destX += 24 - - srcY += 1 - destY += 24 - - - def setCurrentLayer(self, layer): - if self.currentLayer is not None: - self.currentLayer.setActivated(False) - - self.currentLayer = layer - self.currentLayer.setActivated(True) - - -class KPEditorWidget(QtGui.QGraphicsView): - def __init__(self, scene, parent=None): - QtGui.QGraphicsView.__init__(self, scene, parent) - - self.setRenderHints(QtGui.QPainter.Antialiasing) - - self.setAlignment(Qt.AlignLeft | Qt.AlignTop) - self.setDragMode(self.RubberBandDrag) - - self.xScrollBar = QtGui.QScrollBar(Qt.Horizontal, parent) - self.setHorizontalScrollBar(self.xScrollBar) - - self.yScrollBar = QtGui.QScrollBar(Qt.Vertical, parent) - self.setVerticalScrollBar(self.yScrollBar) - - self.centerOn(0,0) - - # set up stuff for painting - self.paintNext = None - self.paintNextID = None - self._resetPaintVars() - - def _resetPaintVars(self): - self.painting = None - self.paintingItem = None - self.paintBeginPosition = None - - def _tryToPaint(self, event): - '''Called when a paint attempt is initiated''' - - paint = self.paintNext - layer = self.scene().currentLayer - if not layer.visible: return - - if isinstance(layer, KPTileLayer): - if paint is None: return - - clicked = self.mapToScene(event.x(), event.y()) - x, y = clicked.x(), clicked.y() - if x < 0: x = 0 - if y < 0: y = 0 - - x = int(x / 24) - y = int(y / 24) - - obj = KPObject() - obj.position = (x,y) - obj.size = (1,1) - obj.tileset = layer.tileset - obj.kind = paint - obj.updateCache() - layer.objects.append(obj) - layer.updateCache() - - item = KPEditorObject(obj, layer) - self.scene().addItem(item) - - self.painting = obj - self.paintingItem = item - self.paintBeginPosition = (x, y) - - elif isinstance(layer, KPDoodadLayer): - if paint is None: return - - clicked = self.mapToScene(event.x(), event.y()) - x, y = clicked.x(), clicked.y() - if x < 0: x = 0 - if y < 0: y = 0 - - obj = KPDoodad() - obj.position = [x,y] - obj.index = self.paintNextID - obj.setDefaultSize() - layer.objects.append(obj) - - item = KPEditorDoodad(obj, layer) - self.scene().addItem(item) - - self.painting = obj - self.paintingItem = item - self.paintBeginPosition = (x, y) - - elif isinstance(layer, KPPathLayer): - # decide what's under the mouse - clicked = self.mapToScene(event.x(), event.y()) - x, y = clicked.x(), clicked.y() - itemsUnder = self.scene().items(clicked) - - for item in itemsUnder: - if isinstance(item, KPEditorNode): - # Paint a path to this node (if one is selected) - sourceItem, sourceNode = None, None - selected = self.scene().selectedItems() - - for selItem in selected: - if isinstance(item, KPEditorNode) and selItem != item: - sourceItem = selItem - sourceNode = selItem._nodeRef() - break - - if sourceItem is None: return - - # Make sure that no path already exists between these nodes - destNode = item._nodeRef() - - for pathToCheck in sourceNode.exits: - if pathToCheck._startNodeRef() == destNode: - return - if pathToCheck._endNodeRef() == destNode: - return - - # No node can have more than four paths, because there are only - # four directions registered by a Wiimote DPad. - - if len(sourceNode.exits) > 3: - return - - if len(destNode.exits) > 3: - return - - path = KPPath(sourceNode, destNode) - - KP.map.pathLayer.paths.append(path) - - item = KPEditorPath(path) - self.scene().addItem(item) - - return - - elif isinstance(item, KPEditorPath): - # Split this path into two... at this point - - origPath = item._pathRef() - - node = KPNode() - node.position = (x - 12, y - 12) - KP.map.pathLayer.nodes.append(node) - - # Start node => Original path => New node => New path => End node - - endNode = origPath._endNodeRef() - - origPath.setEnd(node) - origPath.qtItem.updatePosition() - - nodeItem = KPEditorNode(node) - self.scene().addItem(nodeItem) - self.scene().addItem(nodeItem.buttonProxy) - self.scene().addItem(nodeItem.stageProxy) - self.scene().addItem(nodeItem.worldProxy) - - self.painting = node - self.paintingItem = item - self.paintBeginPosition = (x - 12, y - 12) - - newPath = KPPath(node, endNode, origPath) - KP.map.pathLayer.paths.append(newPath) - - pathItem = KPEditorPath(newPath) - self.scene().addItem(pathItem) - - return - - # Paint a new node - node = KPNode() - node.position = (x - 12, y - 12) - KP.map.pathLayer.nodes.append(node) - - item = KPEditorNode(node) - self.scene().addItem(item) - self.scene().addItem(item.buttonProxy) - self.scene().addItem(item.stageProxy) - self.scene().addItem(item.worldProxy) - - # Paint a path to this node (if one is selected) - sourceItem, sourceNode = None, None - selected = self.scene().selectedItems() - - for selItem in selected: - if isinstance(item, KPEditorNode) and selItem != item: - sourceItem = selItem - sourceNode = selItem._nodeRef() - break - - # No node can have more than four paths, because there are only - # four directions registered by a Wiimote DPad. - - if not sourceItem is None: - if len(sourceNode.exits) > 3: - return - - # There, now you can draw paths easily in a row. - path = KPPath(sourceNode, node) - - KP.map.pathLayer.paths.append(path) - - pathitem = KPEditorPath(path) - self.scene().addItem(pathitem) - - - # Switch the selection to the recently drawn node, so you can keep on rolling. - self.scene().clearSelection() - item.setSelected(True) - - self.painting = node - self.paintingItem = item - self.paintBeginPosition = (x - 12, y - 12) - - - - def _movedWhilePainting(self, event): - '''Called when the mouse is moved while painting something''' - - obj = self.painting - item = self.paintingItem - - if isinstance(obj, KPObject): - clicked = self.mapToScene(event.x(), event.y()) - x, y = clicked.x(), clicked.y() - if x < 0: x = 0 - if y < 0: y = 0 - - x = int(x / 24) - y = int(y / 24) - - beginX, beginY = self.paintBeginPosition - - if x >= beginX: - objX = beginX - width = x - beginX + 1 - else: - objX = x - width = beginX - x + 1 - - if y >= beginY: - objY = beginY - height = y - beginY + 1 - else: - objY = y - height = beginY - y + 1 - - currentX, currentY = obj.position - currentWidth, currentHeight = obj.size - - # update everything if changed - changed = False - - if currentX != objX or currentY != objY: - obj.position = (objX, objY) - item._updatePosition() - changed = True - - if currentWidth != width or currentHeight != height: - obj.size = (width, height) - obj.updateCache() - item._updateSize() - changed = True - - if not changed: return - - item._layerRef().updateCache() - - - def mousePressEvent(self, event): - if event.button() == Qt.RightButton: - self._tryToPaint(event) - event.accept() - - else: - QtGui.QGraphicsView.mousePressEvent(self, event) - - - def mouseMoveEvent(self, event): - if event.buttons() == Qt.RightButton and self.painting: - self._movedWhilePainting(event) - event.accept() - - else: - QtGui.QGraphicsView.mouseMoveEvent(self, event) - - - def keyPressEvent(self, event): - if event.key() == QtCore.Qt.Key_Delete or event.key() == QtCore.Qt.Key_Backspace: - scene = self.scene() - - selection = scene.selectedItems() - if len(selection) > 0: - for obj in selection: - obj.setSelected(False) - obj.remove(True) - scene.update() - self.update() - return - - else: - QtGui.QGraphicsView.keyPressEvent(self, event) - - - - |