from common import * import weakref TILE_SIZE = (24,24) MAP_SIZE_IN_TILES = (512,512) MAP_SIZE = (MAP_SIZE_IN_TILES[0] * TILE_SIZE[0], MAP_SIZE_IN_TILES[1] * TILE_SIZE[1]) class KPLayer(object): def __repr__(self): return "" % self.name def __init__(self): self.name = '' self._visible = True @property def visible(self): return self._visible @visible.setter def visible(self, value): if self._visible == value: return self._visible = value self._visibilityChanged(value) def _visibilityChanged(self, value): pass def setActivated(self, value, listToUse=None): flag1 = QtGui.QGraphicsItem.ItemIsSelectable flag2 = QtGui.QGraphicsItem.ItemIsMovable if listToUse is None: listToUse = self.objects for obj in listToUse: item = obj.qtItem if item: item.setFlag(flag1, value) item.setFlag(flag2, value) class KPObject(object): def __init__(self): self.position = (0,0) self.size = (1,1) self.kind = 0 self.cache = [] self.tileset = None self.qtItem = None def updateCache(self): self.cache = self.kind.render(self.size) class KPTileLayer(KPLayer): def __repr__(self): return "" % (self.name, self.tileset) def __init__(self): KPLayer.__init__(self) self.tileset = '' self.objects = [] self.cache = ['DUMMY_FLAG'] self.updateCache() self.icon = KP.icon('LayerTile') def _visibilityChanged(self, value): for obj in self.objects: item = obj.qtItem if item: item.setVisible(value) def updateCache(self): if len(self.objects) == 0: if len(self.cache) != 0: self.cache = [] self.cacheBasePos = (0,0) self.cacheSize = (0,0) return x1, x2 = MAP_SIZE_IN_TILES[0] - 1, 0 y1, y2 = MAP_SIZE_IN_TILES[1] - 1, 0 for obj in self.objects: x, y = obj.position w, h = obj.size right, bottom = (x+w-1), (y+h-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 + 1, y2 - y1 + 1) width, height = size cache = [[-1 for i in xrange(width)] for j in xrange(height)] self.cache = cache self.cacheBasePos = (x1, y1) self.cacheSize = size # now generate the thing for obj in self.objects: oX, oY = obj.position baseX = oX - x1 y = oY - y1 for row in obj.cache: destRow = cache[y] x = baseX for tile in row: destRow[x] = tile x += 1 y += 1 class KPDoodad(object): def __init__(self): self.position = [0,0] self.size = [0,0] self.angle = 0 self.index = 0 self.animations = [] def setDefaultSize(self): source = KP.mainWindow.doodadSelector.getDoodad(self.index) pixmap = source.icon().pixmap(source.icon().availableSizes()[0]) self.size = [pixmap.width(), pixmap.height()] class KPDoodadLayer(KPLayer): def __repr__(self): return "" % self.name def __init__(self): KPLayer.__init__(self) self.objects = [] self.icon = KP.icon('LayerObjects') def _visibilityChanged(self, value): for obj in self.objects: item = obj.qtItem if item: item.setVisible(value) class KPNodeAction(object): def __init__(self): pass class KPNode(object): def __init__(self): self.position = (0,0) self.actions = [] self.exits = [] self.level = [0,0] self.isStop = False class KPPath(object): def __init__(self, startNode, endNode, cloneFrom=None): self._startNodeRef = weakref.ref(startNode) self._endNodeRef = weakref.ref(endNode) startNode.exits.append(self) endNode.exits.append(self) self.unlocks = 0 # 0 = always unlocked, 1 = unlocked from startNode, 2 = unlocked from endNode self.secret = 0 # 0 = unlocks from normal exit, 1 = unlocks from secret exit if cloneFrom is None: self.animation = None else: self.animation = cloneFrom.animation self.movementSpeed = 1.0 self.linkedLayer = None def setStart(self, newStart): currentStart = self._startNodeRef() if currentStart is not None: currentStart.exits.remove(self) newStart.exits.append(self) self._startNodeRef = weakref.ref(newStart) def setEnd(self, newEnd): currentEnd = self._endNodeRef() if currentEnd is not None: currentEnd.exits.remove(self) newEnd.exits.append(self) self._endNodeRef = weakref.ref(newEnd) class KPPathLayer(KPLayer): def __repr__(self): return "" % self.name def __init__(self): KPLayer.__init__(self) self.nodes = [] self.paths = [] self.icon = KP.icon('LayerPath') def _visibilityChanged(self, value): for objList in (self.nodes, self.paths): for obj in objList: item = obj.qtItem if item: item.setVisible(value) def setActivated(self, value): KPLayer.setActivated(self, value, self.nodes) flag = QtGui.QGraphicsItem.ItemIsSelectable for path in self.paths: item = path.qtItem if item: item.setFlag(flag, value) class KPMap(object): def __init__(self): self.nextLayerNumber = 1 self.pathLayer = self._createPathLayer() self.layers = [self.pathLayer] self.layerModel = KPMap.LayerModel(self.layers) self.nodes = [] self.paths = [] self.tilesets = {} self.loadedTilesets = {} self.loadTilesets() # LAYERS class LayerModel(QtCore.QAbstractListModel): def __init__(self, layerList): QtCore.QAbstractListModel.__init__(self) self.list = layerList def headerData(self, section, orientation, role = Qt.DisplayRole): return 'Layer' def rowCount(self, parent): return len(self.list) def data(self, index, role = Qt.DisplayRole): try: if index.isValid(): layer = self.list[index.row()] if (role == Qt.DisplayRole or role == Qt.EditRole): return layer.name elif role == Qt.DecorationRole: return layer.icon elif role == Qt.CheckStateRole: return (Qt.Checked if layer.visible else Qt.Unchecked) except IndexError: pass return QtCore.QVariant() def flags(self, index): if not index.isValid(): return Qt.ItemIsEnabled return Qt.ItemIsEditable | Qt.ItemIsUserCheckable \ | QtCore.QAbstractListModel.flags(self, index) def setData(self, index, value, role = Qt.EditRole): if index.isValid(): layer = self.list[index.row()] if role == Qt.EditRole: value = str(value.toString()) if len(value) > 0: layer.name = value self.dataChanged.emit(index, index) return True elif role == Qt.CheckStateRole: layer.visible = value.toBool() self.dataChanged.emit(index, index) return True return False def _createPathLayer(self): layer = KPPathLayer() layer.name = 'Paths' return layer def createNewTileLayer(self, tilesetName): layer = KPTileLayer() layer.name = "Tilemap - Layer %d" % self.nextLayerNumber self.nextLayerNumber += 1 layer.tileset = tilesetName return layer def createNewDoodadLayer(self): layer = KPDoodadLayer() layer.name = "Doodads - Layer %d" % self.nextLayerNumber self.nextLayerNumber += 1 return layer def appendLayer(self, layer): return self.insertLayer(len(self.layers), layer) def insertLayer(self, index, layer): self.layerModel.beginInsertRows(QtCore.QModelIndex(), index, index) self.layers.insert(index, layer) self.layerModel.endInsertRows() return index def moveLayer(self, fromIndex, toIndex): if fromIndex == toIndex: return if fromIndex < 0 or toIndex < 0: raise ValueError if fromIndex >= len(self.layers) or toIndex > len(self.layers): raise ValueError self.layerModel.beginMoveRows( QtCore.QModelIndex(), fromIndex, fromIndex, QtCore.QModelIndex(), toIndex) toMove = self.layers[fromIndex] newIndex = ((toIndex > fromIndex) and (toIndex - 1)) or toIndex del self.layers[fromIndex] self.layers.insert(newIndex, toMove) self.layerModel.endMoveRows() return newIndex def removeLayer(self, layer): if layer not in self.layers: raise ValueError index = self.layers.index(layer) self.layerModel.beginRemoveRows(QtCore.QModelIndex(), index, index) del self.layers[index] self.layerModel.endRemoveRows() def loadTilesets(self): import os from hashlib import sha256 as sha path = os.getcwd() + os.sep + 'Tilesets' if not os.path.exists(path): os.mkdir(path) for file in os.listdir(path): name = file[:-4] if file[-4:] == '.arc': filepath = path + os.sep + file filehandler = open(filepath) data = filehandler.read() filehandler.close() hash = sha(data).hexdigest() self.tilesets[name] = {'path': filepath, 'hash': hash} self.loadedTilesets[name] = KPTileset.loadFromArc(filepath) def reloadTileset(self, name): from hashlib import sha256 as sha info = self.tilesets[name] filehandler = open(info['path']) data = filehandler.read() filehandler.close() hash = sha(data).hexdigest() if info['hash'] != hash: self.loadedTilesets[name] = KPTileset.loadFromArc(info['path']) KP.mapscene.update() KP.mapscene.views()[0].update()