Skip to content

Commit

Permalink
Add initial version of palette editor
Browse files Browse the repository at this point in the history
  • Loading branch information
koolkdev committed Sep 2, 2017
1 parent ea2d8cd commit bc68fea
Showing 1 changed file with 184 additions and 0 deletions.
184 changes: 184 additions & 0 deletions palette_editor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import sys
from PyQt4 import QtGui, QtCore
from functools import partial

import parse_game_config
import parse_stage_config

class Window(QtGui.QMainWindow):

def __init__(self):
super(Window, self).__init__()

choose_file = QtGui.QFileDialog.getOpenFileName(self, "Open Config File", "", "Sonic Mania Config File (GameConfig.bin; StageConfig.bin)");

if not choose_file:
sys.exit()

self.filename = str(choose_file)
try:
if self.filename.endswith("GameConfig.bin"):
self.cfg = parse_game_config.CFG.parse(open(self.filename, "rb").read())
else:
self.cfg = parse_stage_config.CFG.parse(open(self.filename, "rb").read())
except:
msg = QtGui.QMessageBox()
msg.setIcon(QtGui.QMessageBox.Critical)

msg.setText("Failed to load configuration file")
msg.setWindowTitle("Error")
msg.setStandardButtons(QtGui.QMessageBox.Close)

msg.exec_()
sys.exit()

self.setGeometry(50, 50, 530, 560)
self.setWindowTitle("Sonic Mania Palette Editor")
#self.setWindowIcon(QtGui.QIcon('pythonlogo.png'))

saveAction = QtGui.QAction("&Save", self)
saveAction.setShortcut("Ctrl+S")
saveAction.triggered.connect(self.save)

exitAction = QtGui.QAction("&Exit", self)
exitAction.setShortcut("Ctrl+Q")
exitAction.triggered.connect(self.close_application)

self.statusBar()

mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('&File')
fileMenu.addAction(saveAction)
fileMenu.addAction(exitAction)

self.checkboxs = []
for i in xrange(16):
checkBox = QtGui.QCheckBox("", self)
checkBox.move(10, 70 + i * 30)
checkBox.stateChanged.connect(partial(self.click_checkbox, i))
self.checkboxs.append(checkBox)

self.columns = []
for i in xrange(16):
pixels = []
self.columns.append(pixels)
for j in xrange(16):
pixel = QtGui.QPushButton("", self)
pixels.append(pixel)
pixel.resize(25, 25)
self.update_pixel_color(i, j, None)
pixel.move(34 + j * 30, 72 + i * 30)
pixel.clicked.connect(partial(self.set_color, i, j))

for i in xrange(8):
palette = QtGui.QPushButton("#%d" % i, self)
palette.resize(60, palette.height())
palette.move(15 + i * 63, 32)
palette.clicked.connect(partial(self.load_palette, i))

self.current_palette = 0
self.changes = False
self.load_palette(0)

self.show()

def save(self):
if self.changes:
choice = QtGui.QMessageBox.question(self, 'Warning',
"Are you sure that you want to save the changes?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
if choice == QtGui.QMessageBox.Yes:
try:
if self.filename.endswith("GameConfig.bin"):
open(self.filename, "wb").write(parse_game_config.CFG.build(self.cfg))
else:
open(self.filename, "wb").write(parse_stage_config.CFG.build(self.cfg))
self.changes = False
except:
msg = QtGui.QMessageBox()
msg.setIcon(QtGui.QMessageBox.Critical)

msg.setText("Failed to save configuration file")
msg.setWindowTitle("Error")
msg.setStandardButtons(QtGui.QMessageBox.Close)

msg.exec_()

def update_pixel_color(self, col, row, color):
if color is None:
self.columns[col][row].setStyleSheet("QWidget { background-color: rgb(220,220,220); border-color: rgb(150,150,150); border-width: 1; border-style: outset; }")
else:
self.columns[col][row].setStyleSheet("QWidget { background-color: rgb(%d,%d,%d); border-color: black; border-width: 1; border-style: outset; }" % (color["R"], color["G"], color["B"]))

def update_column_colors(self, col, pixels):
for i in xrange(16):
if pixels:
self.update_pixel_color(col, i, pixels[i])
else:
self.update_pixel_color(col, i, None)

def load_palette(self, index):
before_changes = self.changes
self.current_palette = index
for i in xrange(16):
if self.cfg.Palettes[index].Bitmap & (1 << i):
self.checkboxs[i].setChecked(True)
self.update_column_colors(i, self.cfg.Palettes[index].Columns[i].Pixels)
else:
self.checkboxs[i].setChecked(False)
self.update_column_colors(i, None)
self.changes = before_changes

def click_checkbox(self, col, state):
if state == QtCore.Qt.Checked:
if not self.cfg.Palettes[self.current_palette].Columns[col].Pixels:
pixels = [{"R":0,"G":0,"B":0} for i in xrange(16)]
self.cfg.Palettes[self.current_palette].Columns[col].Pixels = pixels
self.cfg.Palettes[self.current_palette].Bitmap |= 1 << col
self.update_column_colors(col, self.cfg.Palettes[self.current_palette].Columns[col].Pixels)
else:
self.cfg.Palettes[self.current_palette].Bitmap &= ~(1 << col)
self.update_column_colors(col, None)
self.changes = True

def set_color(self, col, row):
if self.checkboxs[col].isChecked():
dlg = QtGui.QColorDialog(self)
current_pixel = self.cfg.Palettes[self.current_palette].Columns[col].Pixels[row]
dlg.setCurrentColor(QtGui.QColor(current_pixel["R"], current_pixel["G"], current_pixel["B"]))
if dlg.exec_():
color = dlg.selectedColor()
self.changes = True
pixel = {"R": color.red(), "G": color.green(), "B": color.blue()}
self.cfg.Palettes[self.current_palette].Columns[col].Pixels[row] = pixel
self.update_pixel_color(col, row, pixel)

def close_application(self):
if not self.changes:
sys.exit()
choice = QtGui.QMessageBox.question(self, 'Warning',
"There are unsaved changes, exit?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
if choice == QtGui.QMessageBox.Yes:
sys.exit()
else:
pass

def closeEvent(self, event):
if self.changes:
choice = QtGui.QMessageBox.question(self, 'Warning',
"There are unsaved changes, exit?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
if choice == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
else:
event.accept()

def run():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())

run()

0 comments on commit bc68fea

Please sign in to comment.