From aed27a87565f3ec0ac576bab0dc500890ac2d645 Mon Sep 17 00:00:00 2001 From: Treeki Date: Fri, 11 Nov 2011 19:28:11 +0100 Subject: buggy and unfinished painting of objects plus a plethora of bugfixes --- src/common.py | 3 +- src/editorui.py | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/main.py | 1 + src/mapdata.py | 29 +++++----- src/tileset.py | 8 +-- src/ui.py | 15 ++++- 6 files changed, 196 insertions(+), 29 deletions(-) diff --git a/src/common.py b/src/common.py index 2b965d7..cc68e99 100644 --- a/src/common.py +++ b/src/common.py @@ -2,8 +2,9 @@ import sys from PyQt4 import QtCore, QtGui from PyQt4.QtCore import Qt +from main import KP + from tileset import * from mapdata import * -from main import KP diff --git a/src/editorui.py b/src/editorui.py index 4eeca1d..557fe54 100644 --- a/src/editorui.py +++ b/src/editorui.py @@ -1,8 +1,92 @@ from common import * +from math import floor, ceil +import weakref + + +class KPEditorItem(QtGui.QGraphicsItem): + def __init__(self): + QtGui.QGraphicsItem.__init__(self) + self.setFlags( + self.ItemSendsGeometryChanges | + self.ItemIsSelectable | + self.ItemIsMovable + ) + + def itemChange(self, change, value): + if change == self.ItemPositionChange: + currentX, currentY = self.x(), self.y() + + # snap the item to 24x24 + newpos = value.toPyObject() + + x, y = newpos.x(), newpos.y() + + x = int((x + 12) / 24) * 24 + y = int((y + 12) / 24) * 24 + + if x < 0: x = 0 + if x > 12264: x = 12264 + if y < 0: y = 0 + if y > 12264: y = 12264 + + if x != currentX or y != currentY: + print "Position change" + 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 _itemMoved(self, oldX, oldY, newX, newY): + pass + + +class KPEditorObject(KPEditorItem): + 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() + + def _updatePosition(self): + obj = self._objRef() + x,y = obj.position + + self.setPos(x*24, y*24) + + 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) + + 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): + obj = self._objRef() + obj.position = (newX/24, newY/24) + self._layerRef().updateCache() + class KPMapScene(QtGui.QGraphicsScene): def __init__(self): - QtGui.QGraphicsScene.__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 @@ -14,10 +98,10 @@ class KPMapScene(QtGui.QGraphicsScene): areaWidth, areaHeight = rect.width(), rect.height() areaRight, areaBottom = areaLeft+areaWidth, areaTop+areaHeight - areaLeftT = areaLeft / 24 - areaTopT = areaTop / 24 - areaRightT = areaRight / 24 - areaBottomT = areaBottom / 24 + areaLeftT = floor(areaLeft / 24) + areaTopT = floor(areaTop / 24) + areaRightT = ceil(areaRight / 24) + areaBottomT = ceil(areaBottom / 24) for layer in KP.map.layers: left, top = layer.cacheBasePos @@ -33,11 +117,11 @@ class KPMapScene(QtGui.QGraphicsScene): if top > areaBottomT: continue # decide how much of the layer we'll actually draw - drawLeft = max(areaLeftT, left) - drawRight = min(areaRightT, right) + drawLeft = int(max(areaLeftT, left)) + drawRight = int(min(areaRightT, right)) - drawTop = max(areaTopT, top) - drawBottom = min(areaBottomT, bottom) + drawTop = int(max(areaTopT, top)) + drawBottom = int(min(areaBottomT, bottom)) srcY = drawTop - top destY = drawTop * 24 @@ -80,8 +164,73 @@ class KPMapScene(QtGui.QGraphicsScene): if item: item.setFlag(flag, value) + + class KPEditorWidget(QtGui.QGraphicsView): - pass + def __init__(self, scene, parent=None): + QtGui.QGraphicsView.__init__(self, scene, parent) + + 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 + + def _tryToPaint(self, event): + '''Called when a paint attempt is initiated''' + + if self.paintNext is None: return + + paint = self.paintNext + if isinstance(paint, KPTileObject): + 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) + + layer = self.scene().currentLayer + + obj = KPObject() + obj.position = (x,y) + obj.size = (1,1) + obj.tileset = layer.tileset + obj.kind = self.paintNextID + obj.updateCache() + layer.objects.append(obj) + layer.updateCache() + + item = KPEditorObject(obj, layer) + self.scene().addItem(item) + + self.painting = obj + self.paintingItem = item + + + + def mousePressEvent(self, event): + if event.button() == Qt.RightButton: + self._tryToPaint(event) + event.accept() + + else: + QtGui.QGraphicsView.mousePressEvent(self, event) diff --git a/src/main.py b/src/main.py index ebf762f..1d53521 100644 --- a/src/main.py +++ b/src/main.py @@ -3,6 +3,7 @@ from common import * class KP: @staticmethod def newMap(): + from mapdata import KPMap KP.map = KPMap() @staticmethod diff --git a/src/mapdata.py b/src/mapdata.py index 3938047..f8ededd 100644 --- a/src/mapdata.py +++ b/src/mapdata.py @@ -14,7 +14,7 @@ class KPObject(object): self.qtItem = None def updateCache(self): - self.cache = KP.map.tilesets[self.tileset].objects[self.kind].render(self.size) + self.cache = KP.map.loadedTilesets[self.tileset].objects[self.kind].render(self.size) class KPLayer(object): @@ -41,22 +41,24 @@ class KPLayer(object): y1, y2 = MAP_SIZE_IN_TILES[1] - 1, 0 for obj in self.objects: - pos, size = obj.position, obj.size + x, y = obj.position + w, h = obj.size + right, bottom = (x+w-1), (y+h-1) - if pos[0] < x1: - x1 = pos[0] - if pos[1] < y1: - y1 = pos[1] - if (pos[0] + size[0]) > x2: - x2 = pos[0] + size[0] - if (pos[1] + size[1]) > y2: - y2 = pos[1] + size[1] + if x < x1: + x1 = x + if y < y1: + y1 = y + if right > x2: + x2 = right + if bottom > y2: + y2 = bottom # create the cache # I was going to just resize it, but setting every tile to -1 # in Python would probably be slower than creating a new one ... - size = (x2 - x1, y2 - y1) + size = (x2 - x1 + 1, y2 - y1 + 1) width, height = size cache = [[-1 for i in xrange(width)] for j in xrange(height)] @@ -118,7 +120,7 @@ class KPMap(object): def __init__(self): self.nextLayerNumber = 1 - self.layers = [self.createNewLayer() for x in range(4)] + self.layers = [self.createNewLayer('Test') for x in range(4)] self.layerModel = KPMap.LayerModel(self.layers) self.nodes = [] self.paths = [] @@ -189,10 +191,11 @@ class KPMap(object): return False - def createNewLayer(self): + def createNewLayer(self, tilesetName): layer = KPLayer() layer.name = "Layer %d" % self.nextLayerNumber self.nextLayerNumber += 1 + layer.tileset = tilesetName return layer def appendLayer(self, layer): diff --git a/src/tileset.py b/src/tileset.py index 8d4bbb6..763c197 100644 --- a/src/tileset.py +++ b/src/tileset.py @@ -49,7 +49,7 @@ class KPTileObject(object): buf = [] beforeRepeat = [] - inRepeat = self.tiles.copy() + inRepeat = self.tiles[:] afterRepeat = [] if (self.wrap == 1) or (self.wrap == 3) or (self.wrap == 5): @@ -99,11 +99,11 @@ class KPTileObject(object): for x in xrange(width): if x < bC: - buf[x] = beforeRepeat[y] + buf[x] = beforeRepeat[x] elif x < middleUntil: - buf[x] = inRepeat[(y - bC) % iC] + buf[x] = inRepeat[(x - bC) % iC] else: - buf[x] = afterRepeat[y - bC - iC] + buf[x] = afterRepeat[x - bC - iC] return buf diff --git a/src/ui.py b/src/ui.py index d2ac143..0a126c3 100644 --- a/src/ui.py +++ b/src/ui.py @@ -112,6 +112,7 @@ class KPObjectSelector(QtGui.QWidget): # Borrowed the signals and junk from Reggie, figure we'll need em' + # Some more signals are set in setModel self.listView.clicked.connect(self.handleObjReplace) self.sorterMenu.aboutToShow.connect(self.fixUpMenuSize) self.sorterMenu.triggered.connect(self.toggleTopLevel) @@ -154,6 +155,9 @@ class KPObjectSelector(QtGui.QWidget): # a Quick Fix self.listView.setRowHidden(0, True) + # set up signals + self.listView.selectionModel().currentRowChanged.connect(self.handleRowChanged) + def toggleTopLevel(self, action): """Changes the top level group in the list view.""" @@ -175,7 +179,7 @@ class KPObjectSelector(QtGui.QWidget): @QtCore.pyqtSlot(QtCore.QModelIndex, QtCore.QModelIndex) - def currentChanged(self, current, previous): + def handleRowChanged(self, current, previous): """Throws a signal emitting the current object when changed""" i = current.row() object, depth = self.model.groupItem().getItem(i) @@ -230,7 +234,9 @@ class KPMainWindow(QtGui.QMainWindow): self.layerList.selectedLayerChanged.connect(self.scene.setCurrentLayer) self.objectSelector = KPObjectSelector() + self.objectSelector.objChanged.connect(self.handleSelectedObjectChanged) self.updateObjectSelector() + self.objectSelectorDock = QtGui.QDockWidget('Objects') self.objectSelectorDock.setWidget(self.objectSelector) @@ -246,6 +252,13 @@ class KPMainWindow(QtGui.QMainWindow): except IOError: tileset = KPTileset.loadFromArc('/home/me/Dropbox/NEWERsmbw/Test3.arc') self.objectSelector.setModel(tileset.getModel()) + + + @QtCore.pyqtSlot(int, KPTileObject) + def handleSelectedObjectChanged(self, index, obj): + print("New obj: %d, %r" % (index, obj)) + self.editor.paintNext = obj + self.editor.paintNextID = index -- cgit v1.2.3