summaryrefslogtreecommitdiff
path: root/src/editorui.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/editorui.py')
-rw-r--r--src/editorui.py310
1 files changed, 168 insertions, 142 deletions
diff --git a/src/editorui.py b/src/editorui.py
index 5dd68b5..98d57f2 100644
--- a/src/editorui.py
+++ b/src/editorui.py
@@ -12,23 +12,26 @@ class KPEditorItem(QtGui.QGraphicsItem):
self.ItemIsSelectable |
self.ItemIsMovable
)
+
+ self.overrideSnap = False
def itemChange(self, change, value):
- if change == self.ItemPositionChange:
+ if change == self.ItemPositionChange and not self.overrideSnap:
currentX, currentY = self.x(), self.y()
- # snap the item to 24x24
+ # snap the item
+ snapX, snapY = self.SNAP_TO
newpos = value.toPyObject()
x, y = newpos.x(), newpos.y()
- x = int((x + 12) / 24) * 24
- y = int((y + 12) / 24) * 24
+ x = int((x + (snapX/2)) / snapX) * snapX
+ y = int((y + (snapY/2)) / snapY) * snapY
if x < 0: x = 0
- if x > 12264: x = 12264
+ if x >= (12288+snapX): x = (12288+snapX-1)
if y < 0: y = 0
- if y > 12264: y = 12264
+ if y >= (12288+snapY): y = (12288+snapY-1)
if x != currentX or y != currentY:
self._itemMoved(currentX, currentY, x, y)
@@ -42,11 +45,46 @@ class KPEditorItem(QtGui.QGraphicsItem):
def boundingRect(self):
return self._boundingRect
+
+ RESIZER_TOP_LEFT = 1
+ RESIZER_TOP_RIGHT = 2
+ RESIZER_BOTTOM_LEFT = 3
+ RESIZER_BOTTOM_RIGHT = 4
+ RESIZER_TOP = 5
+ RESIZER_BOTTOM = 6
+ RESIZER_LEFT = 7
+ RESIZER_RIGHT = 8
+
+ def resizerPortionAt(self, x, y):
+ try:
+ rightBound, bottomBound = self._resizerEndXY
+ except AttributeError:
+ rect = self._boundingRect
+ rightBound, bottomBound = rect.right() - 5, rect.bottom() - 5
+
+ if y < 5:
+ if x < 5: return 1 # TOP_LEFT
+ elif x >= rightBound: return 2 # TOP_RIGHT
+ else: return 5 # TOP
+
+ elif y >= bottomBound:
+ if x < 5: return 3 # BOTTOM_LEFT
+ elif x >= rightBound: return 4 # BOTTOM_RIGHT
+ else: return 6 # BOTTOM
+
+ else:
+ if x < 5: 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
@@ -64,9 +102,7 @@ class KPEditorObject(KPEditorItem):
# care of the layered drawing
def _updatePosition(self):
- obj = self._objRef()
- x,y = obj.position
-
+ x,y = self._objRef().position
self.setPos(x*24, y*24)
def _updateSize(self):
@@ -87,34 +123,6 @@ class KPEditorObject(KPEditorItem):
painter.drawRect(self._selectionRect)
- RESIZER_TOP_LEFT = 1
- RESIZER_TOP_RIGHT = 2
- RESIZER_BOTTOM_LEFT = 3
- RESIZER_BOTTOM_RIGHT = 4
- RESIZER_TOP = 5
- RESIZER_BOTTOM = 6
- RESIZER_LEFT = 7
- RESIZER_RIGHT = 8
-
- def resizerPortionAt(self, x, y):
- rightBound, bottomBound = self._resizerEndXY
-
- if y < 5:
- if x < 5: return 1 # TOP_LEFT
- elif x >= rightBound: return 2 # TOP_RIGHT
- else: return 5 # TOP
-
- elif y >= bottomBound:
- if x < 5: return 3 # BOTTOM_LEFT
- elif x >= rightBound: return 4 # BOTTOM_RIGHT
- else: return 6 # BOTTOM
-
- else:
- if x < 5: return 7 # LEFT
- elif x >= rightBound: return 8 # RIGHT
- else: return None
-
-
def hoverMoveEvent(self, event):
if self._layerRef() != KP.mapScene.currentLayer:
self.setCursor(Qt.ArrowCursor)
@@ -165,6 +173,8 @@ class KPEditorObject(KPEditorItem):
objPosition = obj.position[axisIndex]
objSize = obj.size[axisIndex]
+ mousePosition = int(mousePosition / 12) * 12
+
if stationarySide == 0:
# Resize the right/bottom side
@@ -215,10 +225,14 @@ class KPEditorObject(KPEditorItem):
hasChanged |= self._tryAndResize(obj, 1, int(scenePos.y() / 24), ySide)
if hasChanged:
+ # TODO: move overrides into updatePosition?
+ # TODO: snapping for resizing
+ self.overrideSnap = True
obj.updateCache()
self._layerRef().updateCache()
self._updatePosition()
self._updateSize()
+ self.overrideSnap = False
else:
KPEditorItem.mouseMoveEvent(self, event)
@@ -238,19 +252,18 @@ class KPEditorObject(KPEditorItem):
def remove(self):
-
obj = self._objRef()
layer = self._layerRef()
- index = layer.objects.index(obj)
- layer.objects.pop(index)
+ layer.objects.remove(obj)
layer.updateCache()
- del obj
-class KPEditorDoodad(QtGui.QGraphicsPixmapItem):
+class KPEditorDoodad(KPEditorItem):
+ SNAP_TO = (12,12)
+
def __init__(self, doodad, layer):
- QtGui.QGraphicsPixmapItem.__init__(self)
+ KPEditorItem.__init__(self)
self.setFlags(
self.ItemSendsGeometryChanges |
self.ItemIsSelectable |
@@ -261,56 +274,68 @@ class KPEditorDoodad(QtGui.QGraphicsPixmapItem):
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._updateTransform()
+
self.setAcceptHoverEvents(True)
- self.setTransformationMode(1)
- def paint(self, painter, option, widget):
+ def _updatePixmap(self):
+ source = self._sourceRef()
+ pixmap = source.icon().pixmap(source.icon().availableSizes()[0])
- try:
- QtGui.QGraphicsPixmapItem.paint(self, painter, option, widget)
- except:
- pass
+ self.prepareGeometryChange()
+ w, h = pixmap.width(), pixmap.height()
- if self.isSelected():
- painter.setPen(QtGui.QPen(Qt.white, 1, Qt.DotLine))
- painter.drawRect(self.boundingRect().adjusted(-1,-1,1,1))
-
-
- def _itemMoved(self, oldX, oldY, newX, newY):
- doodad = self._doodadRef()
- doodad.position = (newX, newY)
+ self.pixmap = pixmap
+ def _updatePosition(self):
+ x,y = self._doodadRef().position
+ self.setPos(x, y)
- def itemChange(self, change, value):
+ def _updateSize(self):
+ self.prepareGeometryChange()
- return QtGui.QGraphicsItem.itemChange(self, change, value)
+ w,h = self._doodadRef().size
+ self.setTransformOriginPoint(w/2, h/2)
+ self._boundingRect = QtCore.QRectF(0, 0, w, h)
+ self._selectionRect = QtCore.QRectF(0, 0, w-1, h-1)
- def resizerPortionAt(self, x, y):
+ self._resizerEndXY = (w-5, h-5)
- rightBound = self.boundingRect().right() - 5
- bottomBound = self.boundingRect().bottom() - 5
+ def _updateTransform(self):
+ doodad = self._doodadRef()
+ pixmap = self.pixmap
+ displaceX, displaceY = pixmap.width()/2, pixmap.height()/2
- if y < 5:
- if x < 5: return 1 # TOP_LEFT
- elif x >= rightBound: return 2 # TOP_RIGHT
- else: return 5 # TOP
+ transform = QtGui.QTransform()
+ transform.translate(displaceX, displaceY)
+ transform.rotate(doodad.angle)
+ transform.translate(-displaceX, -displaceY)
+ self.setTransform(transform)
- elif y >= bottomBound:
- if x < 5: return 3 # BOTTOM_LEFT
- elif x >= rightBound: return 4 # BOTTOM_RIGHT
- else: return 6 # BOTTOM
- else:
- if x < 5: return 7 # LEFT
- elif x >= rightBound: return 8 # RIGHT
- else: return None
+ def paint(self, painter, option, widget):
+ if self.isSelected():
+ painter.setPen(QtGui.QPen(Qt.white, 1, Qt.DotLine))
+ painter.drawRect(self._selectionRect)
+ def _itemMoved(self, oldX, oldY, newX, newY):
+ doodad = self._doodadRef()
+ doodad.position = (newX, newY)
+
+
def hoverMoveEvent(self, event):
if self._layerRef() != KP.mapScene.currentLayer:
self.setCursor(Qt.ArrowCursor)
@@ -320,7 +345,7 @@ class KPEditorDoodad(QtGui.QGraphicsPixmapItem):
bit = self.resizerPortionAt(pos.x(), pos.y())
- if (event.modifiers() == Qt.AltModifier):
+ if (event.modifiers() == Qt.ShiftModifier):
if bit:
self.setCursor(Qt.OpenHandCursor)
@@ -349,56 +374,69 @@ class KPEditorDoodad(QtGui.QGraphicsPixmapItem):
if self._layerRef() == KP.mapScene.currentLayer and bit:
event.accept()
- if (event.modifiers() == Qt.AltModifier):
+ if (event.modifiers() & Qt.ShiftModifier):
self.rotating = self.mapToScene(pos), self._doodadRef().angle
self.setCursor(Qt.ClosedHandCursor)
return
else:
- self.resizing = bit
+ 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, bit, mousePosition, modifiers):
-
- itemPos = self.mapFromScene(mousePosition)
-
- x2 = self.boundingRect().right() + 5.0
- y2 = self.boundingRect().bottom() + 5.0
-
-
- if bit == 1:
- relativeScale = min([(x2 - itemPos.x()) / x2, (y2 - itemPos.y()) / y2])
- elif bit == 2:
- relativeScale = min([itemPos.x() / x2, (y2 - itemPos.y()) / y2])
- elif bit == 3:
- relativeScale = min([(x2 - itemPos.x()) / x2, itemPos.y() / y2])
- elif bit == 4:
- relativeScale = min([itemPos.x() / x2, itemPos.y() / y2])
- elif bit == 5:
- relativeScale = (y2 - itemPos.y()) / y2
- elif bit == 6:
- relativeScale = itemPos.y() / y2
- elif bit == 7:
- relativeScale = (x2 - itemPos.x()) / x2
- elif bit == 8:
- relativeScale = itemPos.x() / x2
+ 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:
- return False, 0
+ # Resize the left/top side
+ rightSide = objPosition + objSize - 1
+ newLeftSide = mousePosition
+ newPosition = newLeftSide
+ newSize = rightSide - newLeftSide + 1
- if relativeScale > 1.0:
- relativeScale = 1.0
+ if newSize < 1:
+ return False
+ if newPosition == objPosition and newSize == objSize:
+ return False
- if relativeScale < 0.1:
- relativeScale = 0.1
-
- self.setTransformOriginPoint(self.boundingRect().center())
+ 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, relativeScale
+ return True
def _tryAndRotate(self, obj, mouseX, mouseY, originalPos, oldAngle, modifiers):
@@ -417,9 +455,6 @@ class KPEditorDoodad(QtGui.QGraphicsPixmapItem):
origAngle = math.degrees(rads)
-
-
-
dy = mouseY - objY
dx = mouseX - objX
rads = math.atan2(dy, dx)
@@ -428,34 +463,30 @@ class KPEditorDoodad(QtGui.QGraphicsPixmapItem):
# Move this to ItemChange() or something at some point.
- #
- # if (modifiers == Qt.ShiftModifier):
- # if int(angle / 45.0) == int(oldAngle / 45.0):
- # return False, 0
- # else:
- # angle = int(angle / 45.0) * 45.0
+ finalAngle = angle - origAngle + oldAngle
- return True, angle - origAngle + oldAngle
+ if (modifiers & Qt.ControlModifier):
+ finalAngle = int(finalAngle / 45.0) * 45.0
+ return True, finalAngle
- def mouseMoveEvent(self, event):
-
- # Fucking Transform can't do independent transforms with doing matrix math directly.
- # And before anyone asks, using QTransform.scale() is no good.
+ def mouseMoveEvent(self, event):
if self.resizing:
obj = self._doodadRef()
scenePos = event.scenePos()
hasChanged = False
- bit = self.resizing
+ resizeX, xSide, resizeY, ySide = self.resizing
- hasChanged, scale = self._tryAndResize(bit, scenePos, event.modifiers())
+ if resizeX:
+ hasChanged |= self._tryAndResize(obj, 0, scenePos.x(), xSide)
+ if resizeY:
+ hasChanged |= self._tryAndResize(obj, 1, scenePos.y(), ySide)
if hasChanged:
- obj.scale = scale
-
- self.setScale(scale)
+ self._updatePosition()
+ self._updateSize()
elif self.rotating:
@@ -468,7 +499,7 @@ class KPEditorDoodad(QtGui.QGraphicsPixmapItem):
if hasChanged:
obj.angle = angle
- self.setRotation(angle)
+ self._updateTransform()
else:
@@ -486,12 +517,10 @@ class KPEditorDoodad(QtGui.QGraphicsPixmapItem):
def remove(self):
-
doodad = self._doodadRef()
layer = self._layerRef()
- index = layer.objects.index(doodad)
- layer.objects.pop(index)
+ layer.objects.remove(doodad)
del doodad
@@ -632,10 +661,12 @@ class KPMapScene(QtGui.QGraphicsScene):
except KeyError:
continue
- for item in toDraw:
- item.paint(painter, QtGui.QStyleOptionGraphicsItem(), self)
- # painter.setWorldTransform(item.transform(), True)
- # painter.drawPixmap(0, 0, item.pixmap)
+ for item in reversed(toDraw):
+ painter.save()
+ painter.setWorldTransform(item.sceneTransform(), True)
+ w, h = item._doodadRef().size
+ painter.drawPixmap(0, 0, w, h, item.pixmap)
+ painter.restore()
elif isinstance(layer, KPTileLayer):
left, top = layer.cacheBasePos
@@ -771,18 +802,13 @@ class KPEditorWidget(QtGui.QGraphicsView):
if not layer.visible: return
if not isinstance(layer, KPDoodadLayer): return
- size = paint.icon().availableSizes()[0]
-
obj = KPDoodad()
obj.position = (x,y)
- obj.size = (size.width(), size.height())
obj.index = self.paintNextID
+ obj.setDefaultSize()
layer.objects.append(obj)
item = KPEditorDoodad(obj, layer)
- item.setPixmap(paint.icon().pixmap(size))
- item.setTransformOriginPoint(item.boundingRect().center())
- item.setPos(x, y)
self.scene().addItem(item)
self.painting = obj