diff options
| author | Treeki <treeki@gmail.com> | 2012-09-26 05:38:44 +0200 | 
|---|---|---|
| committer | Treeki <treeki@gmail.com> | 2012-09-26 05:38:44 +0200 | 
| commit | 64df3b0e7503b2da43d5448f788bb560e5a6881c (patch) | |
| tree | 878c5caaebfa82e938158651c86daaa4834fd022 /src | |
| parent | 04d6d49eed7b952f3ba61f1364e538c6e5c8d5a2 (diff) | |
| download | koopatlas-64df3b0e7503b2da43d5448f788bb560e5a6881c.tar.gz koopatlas-64df3b0e7503b2da43d5448f788bb560e5a6881c.zip | |
added world change nodes. I hope this works.
Diffstat (limited to '')
| -rw-r--r-- | src/editorui/paths.py | 39 | ||||
| -rw-r--r-- | src/exporter.py | 31 | ||||
| -rw-r--r-- | src/mapdata.py | 28 | ||||
| -rw-r--r-- | src/ui.py | 7 | ||||
| -rw-r--r-- | src/worldeditor.py | 163 | 
5 files changed, 246 insertions, 22 deletions
| diff --git a/src/editorui/paths.py b/src/editorui/paths.py index 2ddea4c..69a08e6 100644 --- a/src/editorui/paths.py +++ b/src/editorui/paths.py @@ -16,9 +16,7 @@ class KPEditorNode(KPEditorItem):  			self.setIconSize(QtCore.QSize(24, 24))  			self.setFixedSize(24, 24) -			self.iconList = [QtGui.QIcon("Resources/Through.png"), -							 QtGui.QIcon("Resources/Level.png"), -							 QtGui.QIcon("Resources/Exit.png")] +			self.iconList = [KP.icon('Through'), KP.icon('Level'), KP.icon('Exit'), KP.icon('WorldChange')]  			self.state = 0 @@ -32,7 +30,7 @@ class KPEditorNode(KPEditorItem):  		def toggle(self):  			self.state += 1 -			if self.state == 3: +			if self.state == 4:  				self.state = 0  			self.stateToggled.emit(self.state) @@ -121,6 +119,7 @@ class KPEditorNode(KPEditorItem):  		self._boundingRect = QtCore.QRectF(-24, -24, 48, 48)  		self._levelRect = self._boundingRect  		self._stopRect = QtCore.QRectF(-12, -12, 24, 24) +		self._worldChangeRect = QtCore.QRectF(-16, -16, 32, 32)  		self._tinyRect = QtCore.QRectF(-6, -6, 12, 12)  		self.isLayerSelected = False @@ -165,12 +164,20 @@ class KPEditorNode(KPEditorItem):  		self.transitionProxy = self.HiddenProxy(self.transition, self, -102, 24)  		self.transition.currentIndexChanged.connect(self.transitionChange) +		self.worldDefID = self.LevelSlotSpinner() +		self.worldDefID.setRange(0,255) +		self.worldDefIDProxy = self.HiddenProxy(self.worldDefID, self, 60, 24) +		self.worldDefID.valueChanged.connect(self.worldDefIDChange) +  		if node.foreignID != None:  			self.foreignID.setValue(node.foreignID)  		if node.mapChange != None:  			self.mapChange.setText(node.mapChange) +		if node.worldDefID != None: +			self.worldDefID.setValue(node.worldDefID) +  		self.transition.setCurrentIndex(node.transition) @@ -187,6 +194,7 @@ class KPEditorNode(KPEditorItem):  		node.mapID = None  		node.foreignID = None  		node.level = None +		node.worldDefID = None  		if state == 1:  			node.level = [1, 1] @@ -212,6 +220,9 @@ class KPEditorNode(KPEditorItem):  			self.mapChange.setText('None.arc')  			self.transition.setCurrentIndex(0) +		elif state == 3: +			node.worldDefID = 0 +  		self.update()  		KP.mainWindow.pathNodeList.update() @@ -254,6 +265,12 @@ class KPEditorNode(KPEditorItem):  	@QtCore.pyqtSlot(int) +	def worldDefIDChange(self, ID): +		node = self._nodeRef() +		node.worldDefID = ID + + +	@QtCore.pyqtSlot(int)  	def transitionChange(self, index):  		node = self._nodeRef() @@ -326,6 +343,12 @@ class KPEditorNode(KPEditorItem):  			selectionRect = self._boundingRect.adjusted(1,5,-1,-5) +		elif node.worldDefID != None: +			painter.setBrush(QtGui.QColor(0, 0, 0, 0)) +			painter.setPen(QtGui.QColor(0, 0, 0, 0)) +			painter.drawPixmap(self._worldChangeRect.topLeft(), QtGui.QPixmap("Resources/WorldChange.png")) +			selectionRect = self._worldChangeRect +  		elif len(node.exits) != 2:  			if self.isLayerSelected:  				brush = QtGui.QBrush(QtGui.QColor(255, 40, 40)) @@ -352,6 +375,8 @@ class KPEditorNode(KPEditorItem):  			painter.setBrush(QtGui.QColor(0,0,0,0))  			painter.drawEllipse(selectionRect) +			# WHAT THE FUCK SINCE WHEN DO YOU SHOW/HIDE WIDGETS IN A PAINT EVENT +			# oh well, I don't feel like refactoring this  			self.buttonProxy.show()  			if node.level: @@ -374,6 +399,11 @@ class KPEditorNode(KPEditorItem):  				self.transition.hide()  				self.mapChange.hide() +			if node.worldDefID != None: +				self.worldDefID.show() +			else: +				self.worldDefID.hide() +  		else:  			self.buttonProxy.hide()  			self.worldProxy.hide() @@ -382,6 +412,7 @@ class KPEditorNode(KPEditorItem):  			self.foreignID.hide()  			self.transition.hide()  			self.mapChange.hide() +			self.worldDefID.hide()  	def remove(self, withItem=False): diff --git a/src/exporter.py b/src/exporter.py index ad352d3..eeca252 100644 --- a/src/exporter.py +++ b/src/exporter.py @@ -193,11 +193,12 @@ class KPMapExporter:  		# now that we've got that, we can pack the first part of the file  		version = 1 -		headerSize = 0x24 +		headerSize = 0x2C  		tsInfoOffsetInHeader = 0x10 -		data = bytearray(struct.pack('>4sIIIIIIII', 'KP_m', version, len(self.layers), headerSize + len(sectorData), 0, 0, 0, headerSize, 0)) +		data = bytearray(struct.pack('>4sIIIIIIIIII', 'KP_m', version, len(self.layers), headerSize + len(sectorData), 0, 0, 0, headerSize, 0, 0, len(self.map.worlds)))  		requiredFixUps.append((0x18, 'UnlockBytecode'))  		requiredFixUps.append((0x20, self.map.bgName)) +		requiredFixUps.append((0x24, '_WorldDefList'))  		stringsToAdd.add(self.map.bgName)  		# list of layer pointers goes here.. or will, later @@ -395,6 +396,32 @@ class KPMapExporter:  					data += struct.pack('>bbbbfi', available, 0, 0, 0, path.movementSpeed, path.animation) +		# align it to 4 bytes before we write the world defs +		padding = ((len(data) + 4) & ~4) - len(data) +		data += ('\0' * padding) + +		offsets['_WorldDefList'] = len(data) +		for world in self.map.worlds: +			requiredFixUps.append((len(data), world.name)) +			stringsToAdd.add(world.name) +			data += zero32 + +			fst1,fst2 = world.fsTextColours +			fsh1,fsh2 = world.fsHintColours +			ht1,ht2 = world.hudTextColours +			htf = world.hudHintTransform + +			data += struct.pack('>BBBB BBBB BBBB BBBB BBBB BBBB hhh BB', +					fst1[0],fst1[1],fst1[2],fst1[3], +					fst2[0],fst2[1],fst2[2],fst2[3], +					fsh1[0],fsh1[1],fsh1[2],fsh1[3], +					fsh2[0],fsh2[1],fsh2[2],fsh2[3], +					ht1[0],ht1[1],ht1[2],ht1[3], +					ht2[0],ht2[1],ht2[2],ht2[3], +					htf[0],htf[1],htf[2], +					world.uniqueKey, world.musicTrackID +					) +  		# now that we're almost done... pack the strings  		for string in stringsToAdd:  			offsets[string] = len(data) diff --git a/src/mapdata.py b/src/mapdata.py index 2c88f9b..5bfe9d5 100644 --- a/src/mapdata.py +++ b/src/mapdata.py @@ -427,7 +427,7 @@ class KPDoodadLayer(KPLayer):  class KPNode(object):    	__dump_attribs__ = (  			'position', 'actions', 'level', 'hasSecret', 'mapChange', -			'transition', 'mapID', 'foreignID') +			'transition', 'mapID', 'foreignID', 'worldDefID')  	def _dump(self, mapObj, dest):  		dest['exitIDs'] = map(mapObj.refPath, self.exits) @@ -447,6 +447,7 @@ class KPNode(object):  		self.transition = 0  		self.mapID = None  		self.foreignID = None +		self.worldDefID = None  	def isStop(self):  		return True if (self.level or self.mapChange or len(self.exits) != 2) else False @@ -548,18 +549,19 @@ class KPPathLayer(KPLayer):  @mapfile.dumpable('world_definition')  class KPWorldDef(object): -	__dump_attribs__ = ('name', 'fs_hint_colours', 'fs_text_colours', 'hud_hint_colours', 'hud_text_colours', 'music_track_id') +	__dump_attribs__ = ('uniqueKey', 'name', 'fsHintColours', 'fsTextColours', 'hudHintTransform', 'hudTextColours', 'musicTrackID')  	def __init__(self): +		self.uniqueKey = -1  		self.name = 'Untitled World' -		self.fs_hint_colours = (0x000000FF,0x000000FF) -		self.fs_text_colours = (0xFFFFFFFF,0xFFFFFFFF) +		self.fsHintColours = ((0,0,0,255),(0,0,0,255)) +		self.fsTextColours = ((255,255,255,255),(255,255,255,255)) -		self.hud_hint_transform = (0,0,0) -		self.hud_text_colours = (0xFFFFFFFF,0xFFFFFFFF) +		self.hudHintTransform = (0,0,0) +		self.hudTextColours = ((255,255,255,255),(255,255,255,255)) -		self.music_track_id = 0 +		self.musicTrackID = 0  @mapfile.dumpable('map_root') @@ -581,11 +583,6 @@ class KPMap(object):  		else:  			self.version = 1 -		if 'bgName' in source: -			self.bgName = source['bgName'] -		else: -			self.bgName = '/Maps/Water.brres' -  	def _dump(self, mapObj, dest):  		dest['version'] = self.version  		dest['bgName'] = self.bgName @@ -624,7 +621,14 @@ class KPMap(object):  		self.doodadModel = KPMap.DoodadModel(self.doodadDefinitions)  		self.worlds = [] +		self.nextWorldKey = 1 + +		self.bgName = '/Maps/Water.brres' +	def allocateWorldDefKey(self): +		key = self.nextWorldKey +		self.nextWorldKey += 1 +		return key  	# LAYERS  	class LayerModel(QtCore.QAbstractListModel): @@ -1140,6 +1140,7 @@ class KPMainWindow(QtGui.QMainWindow):  		m = mb.addMenu('Map')  		self.ma = m.addAction('Set Background...',			self.setMapBackground) +		self.ma = m.addAction('World Editor...',			self.showWorldEditor)  		w = mb.addMenu('Window')  		self.wa = w.addAction('Show Grid',					self.showGrid, QKeySequence("Ctrl+G")) @@ -1635,6 +1636,12 @@ class KPMainWindow(QtGui.QMainWindow):  		if newBG is not None:  			KP.map.bgName = newBG +	@QtCore.pyqtSlot() +	def showWorldEditor(self): +		from worldeditor import KPWorldEditor +		dlg = KPWorldEditor(KP.map, self) +		dlg.show() +  # Window  ########################  	@QtCore.pyqtSlot() diff --git a/src/worldeditor.py b/src/worldeditor.py index a2262ae..35e42a6 100644 --- a/src/worldeditor.py +++ b/src/worldeditor.py @@ -1,17 +1,172 @@  from common import * +import re + +def editableColourStr(array): +	return '#%02X%02X%02X (%d)' % tuple(array) + +NICE_STR_RE = re.compile('^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})\s*(?:\((\d+)\))?$') +def colourFromNiceStr(thing): +	match = NICE_STR_RE.match(thing) +	try: +		if match: +			r,g,b,a = match.groups() +			return (int(r,16), int(g,16), int(b,16), int(a) if a != None else 255) +	except: +		pass +	return None + +class KPWorldTableModel(QtCore.QAbstractTableModel): +	FIELDS = ('Name', 'Track ID', +			'FS Text 1', 'FS Text 2', +			'FS Hint 1', 'FS Hint 2', +			'HUD Text 1', 'HUD Text 2', +			'HUD Hue', 'HUD Saturation', 'HUD Lightness') + +	def __init__(self, kpmap, parent=None): +		QtCore.QAbstractTableModel.__init__(self, parent) + +		self.currentMap = kpmap +		self.worlds = kpmap.worlds +	 +	def columnCount(self, parent): +		return len(self.FIELDS) +	def headerData(self, section, orientation, role): +		if orientation == Qt.Horizontal: +			if role == Qt.DisplayRole: +				return self.FIELDS[section] +		else: +			if role == Qt.DisplayRole: +				return str(self.worlds[section].uniqueKey) + +		return QtCore.QVariant() + +	def rowCount(self, parent): +		if parent.isValid(): +			return 0 +		else: +			return len(self.worlds) +	 +	def data(self, index, role): +		if index.isValid(): +			entry = self.worlds[index.row()] +			col = index.column() + +			if role == Qt.DisplayRole or role == Qt.EditRole: +				if col == 0: +					return entry.name +				elif col == 1: +					return entry.musicTrackID +				elif col == 2 or col == 3: +					return editableColourStr(entry.fsTextColours[col - 2]) +				elif col == 4 or col == 5: +					return editableColourStr(entry.fsHintColours[col - 4]) +				elif col == 6 or col == 7: +					return editableColourStr(entry.hudTextColours[col - 6]) +				elif col >= 8 and col <= 10: +					return entry.hudHintTransform[col - 8] + +			if role == Qt.DecorationRole: +				if col == 2 or col == 3: +					return QtGui.QColor(*entry.fsTextColours[col - 2]) +				elif col == 4 or col == 5: +					return QtGui.QColor(*entry.fsHintColours[col - 4]) +				elif col == 6 or col == 7: +					return QtGui.QColor(*entry.hudTextColours[col - 6]) + +		return QtCore.QVariant() + +	def flags(self, index): +		return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable + +	def setData(self, index, value, role): +		if index.isValid(): +			if role == Qt.EditRole: +				success = False + +				entry = self.worlds[index.row()] +				col = index.column() + +				if col == 0: +					entry.name = str(value.toString()) +					success = True +				elif col == 1: +					v,ok = value.toInt() +					if ok: +						entry.musicTrackID = v +						success = True +				elif col >= 2 and col <= 7: +					newCol = colourFromNiceStr(str(value.toString())) +					if newCol: +						success = True +						if col == 2: +							entry.fsTextColours = (newCol, entry.fsTextColours[1]) +						elif col == 3: +							entry.fsTextColours = (entry.fsTextColours[0], newCol) +						elif col == 4: +							entry.fsHintColours = (newCol, entry.fsHintColours[1]) +						elif col == 5: +							entry.fsHintColours = (entry.fsHintColours[0], newCol) +						elif col == 6: +							entry.hudTextColours = (newCol, entry.hudTextColours[1]) +						elif col == 7: +							entry.hudTextColours = (entry.hudTextColours[0], newCol) +				elif col >= 8 and col <= 10: +					v,ok = value.toInt() +					if ok: +						new = list(entry.hudHintTransform) +						new[col - 8] = v +						entry.hudHintTransform = new +						success = True + +				if success: +					self.dataChanged.emit(index, index) +				return success + +		return False + + +	def addEntryToEnd(self): +		self.beginInsertRows(QtCore.QModelIndex(), len(self.worlds), len(self.worlds)) +		entry = KPWorldDef() +		entry.uniqueKey = self.currentMap.allocateWorldDefKey() +		self.worlds.append(entry) +		self.endInsertRows() + +	def removeRows(self, row, count, parent): +		if not parent.isValid(): +			if row >= 0 and (row + count) <= len(self.worlds): +				self.beginRemoveRows(parent, row, row+count-1) +				for i in xrange(count): +					del self.worlds[row] +				self.endRemoveRows() + +  class KPWorldEditor(QtGui.QWidget): -	def __init__(self, parent=None): -		QtGui.QWidget.__init__(self, parent) +	def __init__(self, kpmap, parent=None): +		QtGui.QWidget.__init__(self, parent, Qt.Window)  		self.setWindowTitle('World Editor')  		self.dataView = QtGui.QTableView(self) +  		self.addButton = QtGui.QPushButton('Add', self) -		self.removedButton = QtGui.QPushButton('Remove', self) +		self.removeButton = QtGui.QPushButton('Remove', self)  		layout = QtGui.QGridLayout(self)  		layout.addWidget(self.dataView, 0, 0, 1, 2)  		layout.addWidget(self.addButton, 1, 0, 1, 1)  		layout.addWidget(self.removeButton, 1, 1, 1, 1) -		self.currentWorlds = None +		self.model = KPWorldTableModel(kpmap, self) +		self.dataView.setModel(self.model) + +		self.addButton.clicked.connect(self.model.addEntryToEnd) +		self.removeButton.clicked.connect(self.removeCurrentEntry) +	 +	def removeCurrentEntry(self): +		what = self.dataView.selectionModel().currentIndex() +		if what.isValid(): +			what = what.row() +			key = self.model.worlds[what].uniqueKey +			self.model.removeRows(what, 1, QtCore.QModelIndex()) + | 
