diff options
Diffstat (limited to '')
-rw-r--r-- | src/editorui/doodads.py | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/src/editorui/doodads.py b/src/editorui/doodads.py new file mode 100644 index 0000000..5a02248 --- /dev/null +++ b/src/editorui/doodads.py @@ -0,0 +1,248 @@ +from common import * +from editorcommon import * +import weakref +from math import floor, ceil +import math + + +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) + + + |