summaryrefslogtreecommitdiff
path: root/src/mapdata.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mapdata.py')
-rw-r--r--src/mapdata.py255
1 files changed, 247 insertions, 8 deletions
diff --git a/src/mapdata.py b/src/mapdata.py
index de00b10..1eb35c8 100644
--- a/src/mapdata.py
+++ b/src/mapdata.py
@@ -1,11 +1,31 @@
from common import *
import weakref
+import mapfile
+import base64
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])
+@mapfile.dumpClassAs(QtGui.QPixmap, 'pixmap')
+def dumpPixmap(pm):
+ buf = QtCore.QBuffer()
+ buf.open(buf.WriteOnly)
+ pm.save(buf, 'PNG')
+ data = str(buf.data())
+ buf.close()
+ return {'png': base64.b64encode(data)}
+
+@mapfile.loadClassFrom('pixmap')
+def loadPixmap(source):
+ pm = QtGui.QPixmap()
+ pm.loadFromData(base64.b64decode(source['png']), 'PNG')
+ return pm
+
+@mapfile.dumpable('layer')
class KPLayer(object):
+ __dump_attribs__ = ('name', '_visible')
+
def __repr__(self):
return "<KPLayer %r>" % self.name
@@ -42,7 +62,17 @@ class KPLayer(object):
item.setFlag(flag2, value)
+@mapfile.dumpable('object')
class KPObject(object):
+ __dump_attribs__ = ('position', 'size', 'tileset')
+
+ def _load(self, mapObj, src):
+ self.kind = mapObj.loadedTilesets[self.tileset].objects[src['kind']]
+ self.updateCache()
+
+ def _dump(self, mapObj, dest):
+ dest['kind'] = mapObj.loadedTilesets[self.tileset].objects.index(self.kind)
+
def __init__(self):
self.position = (0,0)
self.size = (1,1)
@@ -55,7 +85,13 @@ class KPObject(object):
self.cache = self.kind.render(self.size)
+@mapfile.dumpable('tile_layer')
class KPTileLayer(KPLayer):
+ __dump_attribs__ = KPLayer.__dump_attribs__ + ('tileset', 'objects')
+
+ def _load(self, mapObj, src):
+ self.updateCache()
+
def __repr__(self):
return "<KPTileLayer %r with %r>" % (self.name, self.tileset)
@@ -127,21 +163,84 @@ class KPTileLayer(KPLayer):
y += 1
+@mapfile.dumpable('doodad')
class KPDoodad(object):
+ __dump_attribs__ = ('position', 'size', 'angle', 'animations')
+
+ def _dump(self, mapObj, dest):
+ dest['sourceRef'] = mapObj.refDoodad(self.source)
+
+ def _load(self, mapObj, src):
+ self.source = mapObj.derefDoodad(src['sourceRef'])
+
def __init__(self):
self.position = [0,0]
self.size = [0,0]
self.angle = 0
- self.index = 0
+ self.source = None
self.animations = []
-
+ self.timelines = None
+
def setDefaultSize(self):
- source = KP.mainWindow.doodadSelector.getDoodad(self.index)
- pixmap = source.icon().pixmap(source.icon().availableSizes()[0])
+ pixmap = self.source[1]
self.size = [pixmap.width(), pixmap.height()]
+ def cleanUpAnimations(self):
+ myTimelines = self.timelines
+ if myTimelines is None: return
+
+ timelineList = KP.mapScene.timeLines
+
+ for timeline in myTimelines:
+ try:
+ timelineList.remove(timeline)
+ except ValueError:
+ pass
+
+ self.timelines = None
+
+ def setupAnimations(self):
+ self.cleanUpAnimations()
+ timelineList = KP.mapScene.timeLines
+ myTimelines = []
+
+ for anim in self.animations:
+ Loop, Curve, Frames, Type, StartVal, EndVal = anim
+
+ Timeline = QtCore.QTimeLine()
+
+ # Interpolate the correct modifier
+ if Curve == "Linear":
+ Timeline.setCurveShape(3)
+ elif Curve == "Sinusoidial":
+ Timeline.setCurveShape(4)
+ elif Curve == "Cosinoidial":
+ Timeline.setCurveShape(5)
+
+ Timeline.setFrameRange(StartVal, EndVal)
+
+ if Loop == "Contiguous":
+ Timeline.setLoopCount(1)
+ elif Loop == "Loop":
+ Timeline.setLoopCount(0) # Dollars *holds pinky to corner of mouth*
+ elif Loop == "Reversible Loop":
+ Timeline.setLoopCount(1)
+ Timeline.finished.connect(Timeline.toggleDirection)
+ Timeline.finished.connect(Timeline.start)
+
+ Timeline.setDuration(Frames/60.0*1000) # Wii goes at 60 frames per second
+
+ timelineList.append(Timeline)
+ myTimelines.append(Timeline)
+
+ self.timelines = myTimelines
+
+
+@mapfile.dumpable('doodad_layer')
class KPDoodadLayer(KPLayer):
+ __dump_attribs__ = KPLayer.__dump_attribs__ + ('objects',)
+
def __repr__(self):
return "<KPDoodadLayer %r>" % self.name
@@ -163,7 +262,20 @@ class KPNodeAction(object):
pass
+@mapfile.dumpable('node')
class KPNode(object):
+ __dump_attribs__ = (
+ 'position', 'actions', 'level', 'isStop', 'mapChange',
+ 'transition', 'mapID', 'foreignID')
+
+ def _dump(self, mapObj, dest):
+ dest['exitIDs'] = map(mapObj.refPath, self.exits)
+
+ def _load(self, mapObj, src):
+ self.exitIDs = src['exitIDs']
+ # The exits array will be created by KPPathLayer._load after the
+ # paths have all been created.
+
def __init__(self):
self.position = (0,0)
self.actions = []
@@ -176,8 +288,27 @@ class KPNode(object):
self.foreignID = None
+@mapfile.dumpable('path')
class KPPath(object):
- def __init__(self, startNode, endNode, cloneFrom=None):
+ __dump_attribs__ = ('unlocks', 'secret', 'animation', 'movementSpeed')
+
+ def _dump(self, mapObj, dest):
+ dest['startNodeLink'] = mapObj.refNode(self._startNodeRef())
+ dest['endNodeLink'] = mapObj.refNode(self._endNodeRef())
+ dest['linkedLayer'] = mapObj.refLayer(self.linkedLayer)
+
+ def _load(self, mapObj, src):
+ self._startNodeRef = weakref.ref(mapObj.derefNode(src['startNodeLink']))
+ self._endNodeRef = weakref.ref(mapObj.derefNode(src['endNodeLink']))
+ self.linkedLayer = mapObj.derefLayer(src['linkedLayer'])
+
+ def __init__(self, startNode=None, endNode=None, cloneFrom=None):
+ if startNode is None and endNode is None:
+ # null ctor, ignore this
+ # we're probably loaded from a file, so trust
+ # that everything is correct ... _load will set it all up
+ return
+
self._startNodeRef = weakref.ref(startNode)
self._endNodeRef = weakref.ref(endNode)
@@ -213,7 +344,15 @@ class KPPath(object):
self._endNodeRef = weakref.ref(newEnd)
+@mapfile.dumpable('path_layer')
class KPPathLayer(KPLayer):
+ __dump_attribs__ = KPLayer.__dump_attribs__ + ('nodes', 'paths')
+
+ def _load(self, mapObj, src):
+ for node in self.nodes:
+ node.exits = map(mapObj.derefPath, node.exitIDs)
+ del node.exitIDs
+
def __repr__(self):
return "<KPPathLayer %r>" % self.name
@@ -241,15 +380,41 @@ class KPPathLayer(KPLayer):
item.setFlag(flag, value)
+@mapfile.dumpable('map_root')
class KPMap(object):
+ __dump_attribs__ = ('layers', 'nextLayerNumber', 'doodadDefinitions')
+
+ def _preload(self, src):
+ # we need this early so we can use the deref methods!
+ for layer in self.layers:
+ if isinstance(layer, KPPathLayer):
+ self.pathLayer = layer
+
+ def _load(self, mapObj, source):
+ self.layerModel.list = self.layers
+ self.doodadModel.list = self.doodadDefinitions
+
+ def save(self):
+ path = self.filePath
+ if path is None:
+ raise "no path specified for this map"
+
+ import mapfile
+ dumped = mapfile.dump(self)
+ open(path, 'wb').write(dumped)
+
def __init__(self):
+ self.filePath = None
+
self.nextLayerNumber = 1
self.pathLayer = self._createPathLayer()
self.layers = [self.pathLayer]
self.layerModel = KPMap.LayerModel(self.layers)
- self.nodes = []
- self.paths = []
+
+ self.doodadDefinitions = []
+ self.doodadModel = KPMap.DoodadModel(self.doodadDefinitions)
+
self.tilesets = {}
self.loadedTilesets = {}
@@ -311,7 +476,6 @@ class KPMap(object):
return False
-
def _createPathLayer(self):
layer = KPPathLayer()
layer.name = 'Paths'
@@ -373,6 +537,81 @@ class KPMap(object):
self.layerModel.endRemoveRows()
+ # DOODADS
+ class DoodadModel(QtCore.QAbstractListModel):
+ def __init__(self, doodadList):
+ QtCore.QAbstractListModel.__init__(self)
+ self.list = doodadList
+
+
+ def headerData(self, section, orientation, role = Qt.DisplayRole):
+ return 'Doodad'
+
+ def rowCount(self, parent):
+ return len(self.list)
+
+ def data(self, index, role = Qt.DisplayRole):
+ try:
+ if index.isValid():
+ doodad = self.list[index.row()]
+
+ if role == Qt.DecorationRole:
+ return doodad[1]
+ elif role == Qt.ToolTipRole:
+ return doodad[0]
+
+ except IndexError:
+ pass
+
+ return QtCore.QVariant()
+
+ def flags(self, index):
+ if not index.isValid():
+ return Qt.ItemIsEnabled
+ return QtCore.QAbstractListModel.flags(self, index)
+
+ def addDoodad(self, title, image):
+ doodad = (title, image)
+
+ index = len(self.doodadDefinitions)
+ self.doodadModel.beginInsertRows(QtCore.QModelIndex(), index, index)
+ self.doodadDefinitions.append(doodad)
+ self.doodadModel.endInsertRows()
+
+ return doodad
+
+ def removeDoodad(self, doodad):
+ if doodad not in self.doodadDefinitions:
+ raise ValueError
+
+ index = self.doodadDefinitions.index(doodad)
+ self.doodadModel.beginRemoveRows(QtCore.QModelIndex(), index, index)
+ del self.doodadDefinitions[index]
+ self.doodadModel.endRemoveRows()
+
+
+ # REFERENCES
+ def refDoodad(self, doodad):
+ return -1 if (doodad is None) else self.doodadDefinitions.index(doodad)
+ def derefDoodad(self, ref):
+ return self.doodadDefinitions[ref] if (ref >= 0) else None
+
+ def refLayer(self, layer):
+ return -1 if (layer is None) else self.layers.index(layer)
+ def derefLayer(self, ref):
+ return self.layers[ref] if (ref >= 0) else None
+
+ def refPath(self, path):
+ return -1 if (path is None) else self.pathLayer.paths.index(path)
+ def derefPath(self, ref):
+ return self.pathLayer.paths[ref] if (ref >= 0) else None
+
+ def refNode(self, node):
+ return -1 if (node is None) else self.pathLayer.nodes.index(node)
+ def derefNode(self, ref):
+ return self.pathLayer.nodes[ref] if (ref >= 0) else None
+
+ # TILESETS
def loadTilesets(self):
import os
from hashlib import sha256 as sha