summaryrefslogtreecommitdiff
path: root/src/editorui.py
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2011-11-21 15:25:54 +0100
committerTreeki <treeki@gmail.com>2011-11-21 15:25:54 +0100
commit30188c779e1b419f6818596a29f7f3c7edad42bb (patch)
tree4bf37618ec1721b6f41b1686d71a9d727333e104 /src/editorui.py
parent63ba5f8a58bd26f42712ca61d7d18a1858083443 (diff)
downloadkoopatlas-30188c779e1b419f6818596a29f7f3c7edad42bb.tar.gz
koopatlas-30188c779e1b419f6818596a29f7f3c7edad42bb.zip
some refactoring of editorui and co
Diffstat (limited to 'src/editorui.py')
-rw-r--r--src/editorui.py1227
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)
-
-
-
-