[nostalgia/core] Add ability to save tile sheets and store columns and rows in ng file
This commit is contained in:
		| @@ -1 +0,0 @@ | |||||||
| <03><><03><> |  | ||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -34,8 +34,11 @@ struct NostalgiaPalette { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| struct NostalgiaGraphic { | struct NostalgiaGraphic { | ||||||
| 	static constexpr auto Fields = 4; | 	static constexpr auto Fields = 6; | ||||||
| 	uint8_t bpp = 0; | 	int8_t bpp = 0; | ||||||
|  | 	// rows and columns are really only used by TileSheetEditor | ||||||
|  | 	int rows = 1; | ||||||
|  | 	int columns = 1; | ||||||
| 	ox::FileAddress defaultPalette; | 	ox::FileAddress defaultPalette; | ||||||
| 	NostalgiaPalette pal; | 	NostalgiaPalette pal; | ||||||
| 	ox::Vector<uint8_t> tiles; | 	ox::Vector<uint8_t> tiles; | ||||||
| @@ -52,6 +55,8 @@ template<typename T> | |||||||
| ox::Error model(T *io, NostalgiaGraphic *ng) { | ox::Error model(T *io, NostalgiaGraphic *ng) { | ||||||
| 	io->setTypeInfo("nostalgia::core::NostalgiaGraphic", NostalgiaGraphic::Fields); | 	io->setTypeInfo("nostalgia::core::NostalgiaGraphic", NostalgiaGraphic::Fields); | ||||||
| 	oxReturnError(io->field("bpp", &ng->bpp)); | 	oxReturnError(io->field("bpp", &ng->bpp)); | ||||||
|  | 	oxReturnError(io->field("rows", &ng->rows)); | ||||||
|  | 	oxReturnError(io->field("columns", &ng->columns)); | ||||||
| 	oxReturnError(io->field("defaultPalette", &ng->defaultPalette)); | 	oxReturnError(io->field("defaultPalette", &ng->defaultPalette)); | ||||||
| 	oxReturnError(io->field("pal", &ng->pal)); | 	oxReturnError(io->field("pal", &ng->pal)); | ||||||
| 	oxReturnError(io->field("tiles", &ng->tiles)); | 	oxReturnError(io->field("tiles", &ng->tiles)); | ||||||
|   | |||||||
| @@ -104,6 +104,10 @@ Rectangle { | |||||||
| 		height: tileGrid.rows * tileGrid.baseTileSize * tileGrid.scaleFactor | 		height: tileGrid.rows * tileGrid.baseTileSize * tileGrid.scaleFactor | ||||||
| 		rows: sheetData ? sheetData.rows : 1 | 		rows: sheetData ? sheetData.rows : 1 | ||||||
| 		columns: sheetData ? sheetData.columns : 1 | 		columns: sheetData ? sheetData.columns : 1 | ||||||
|  | 		states: State { | ||||||
|  | 			name: "widthChanged" | ||||||
|  | 			PropertyChanges { target: tileGrid.width; width: tileGrid.columns * tileGrid.baseTileSize * tileGrid.scaleFactor } | ||||||
|  | 		} | ||||||
| 		Repeater { | 		Repeater { | ||||||
| 			model: tileGrid.rows * tileGrid.columns | 			model: tileGrid.rows * tileGrid.columns | ||||||
| 			Tile { | 			Tile { | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ constexpr auto PluginName = "NostalgiaCore"; | |||||||
| // Command IDs to use with QUndoCommand::id() | // Command IDs to use with QUndoCommand::id() | ||||||
| enum class CommandId { | enum class CommandId { | ||||||
| 	UpdatePixel = 1, | 	UpdatePixel = 1, | ||||||
|  | 	UpdateDimension = 2, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,14 +10,17 @@ | |||||||
| #include <QHeaderView> | #include <QHeaderView> | ||||||
| #include <QPointer> | #include <QPointer> | ||||||
| #include <QQmlContext> | #include <QQmlContext> | ||||||
|  | #include <QQuickItem> | ||||||
| #include <QQuickWidget> | #include <QQuickWidget> | ||||||
| #include <QSet> | #include <QSet> | ||||||
| #include <QSettings> | #include <QSettings> | ||||||
| #include <QSpinBox> | #include <QSpinBox> | ||||||
| #include <QSplitter> | #include <QSplitter> | ||||||
| #include <QUndoCommand> | #include <QUndoCommand> | ||||||
|  | #include <QTableWidget> | ||||||
| #include <QToolBar> | #include <QToolBar> | ||||||
| #include <QVBoxLayout> | #include <QVBoxLayout> | ||||||
|  | #include <memory> | ||||||
|  |  | ||||||
| #include "consts.hpp" | #include "consts.hpp" | ||||||
| #include "tilesheeteditor.hpp" | #include "tilesheeteditor.hpp" | ||||||
| @@ -53,6 +56,59 @@ struct LabeledSpinner: public QWidget { | |||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class UpdateDimensionsCommand: public QUndoCommand { | ||||||
|  | 	public: | ||||||
|  | 		enum class Dimension { | ||||||
|  | 			Rows, | ||||||
|  | 			Columns, | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 	private: | ||||||
|  | 		Dimension m_dimension = Dimension::Rows; | ||||||
|  | 		int m_oldVal = 0; | ||||||
|  | 		int m_newVal = 0; | ||||||
|  | 		SheetData *m_sheetData = nullptr; | ||||||
|  |  | ||||||
|  | 	public: | ||||||
|  | 		UpdateDimensionsCommand(SheetData *sheetData, Dimension dim, int oldVal, int newVal) { | ||||||
|  | 			m_sheetData = sheetData; | ||||||
|  | 			m_dimension = dim; | ||||||
|  | 			m_newVal = newVal; | ||||||
|  | 			m_oldVal = oldVal; | ||||||
|  | 			setObsolete(newVal == oldVal); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		virtual ~UpdateDimensionsCommand() = default; | ||||||
|  |  | ||||||
|  | 		int id() const override { | ||||||
|  | 			return static_cast<int>(CommandId::UpdateDimension); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void redo() override { | ||||||
|  | 			switch (m_dimension) { | ||||||
|  | 				case Dimension::Rows: | ||||||
|  | 					m_sheetData->setRows(m_newVal); | ||||||
|  | 					break; | ||||||
|  | 				case Dimension::Columns: | ||||||
|  | 					m_sheetData->setColumns(m_newVal); | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void undo() override { | ||||||
|  | 			switch (m_dimension) { | ||||||
|  | 				case Dimension::Rows: | ||||||
|  | 					m_sheetData->setRows(m_oldVal); | ||||||
|  | 					break; | ||||||
|  | 				case Dimension::Columns: | ||||||
|  | 					m_sheetData->setColumns(m_oldVal); | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| class UpdatePixelsCommand: public QUndoCommand { | class UpdatePixelsCommand: public QUndoCommand { | ||||||
| 	private: | 	private: | ||||||
| 		struct PixelUpdate { | 		struct PixelUpdate { | ||||||
| @@ -96,8 +152,8 @@ class UpdatePixelsCommand: public QUndoCommand { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		bool mergeWith(const QUndoCommand *cmd) override { | 		bool mergeWith(const QUndoCommand *cmd) override { | ||||||
| 			auto other = static_cast<const UpdatePixelsCommand*>(cmd); | 			auto other = dynamic_cast<const UpdatePixelsCommand*>(cmd); | ||||||
| 			if (m_cmdIdx == other->m_cmdIdx) { | 			if (other && m_cmdIdx == other->m_cmdIdx) { | ||||||
| 				m_pixelUpdates.unite(other->m_pixelUpdates); | 				m_pixelUpdates.unite(other->m_pixelUpdates); | ||||||
| 				return true; | 				return true; | ||||||
| 			} | 			} | ||||||
| @@ -107,7 +163,14 @@ class UpdatePixelsCommand: public QUndoCommand { | |||||||
| 		void redo() override { | 		void redo() override { | ||||||
| 			for (const auto &pu : m_pixelUpdates) { | 			for (const auto &pu : m_pixelUpdates) { | ||||||
| 				pu.item->setProperty("color", m_palette[m_newColorId]); | 				pu.item->setProperty("color", m_palette[m_newColorId]); | ||||||
| 				m_pixels[pu.item->property("pixelNumber").toInt()] = m_newColorId; | 				const auto index = pu.item->property("pixelNumber").toInt(); | ||||||
|  | 				// resize to appropriate number of tiles if pixel beyond current | ||||||
|  | 				// range | ||||||
|  | 				if (m_pixels.size() < index) { | ||||||
|  | 					auto sz = (index / 64 + 1) * 64; | ||||||
|  | 					m_pixels.resize(sz); | ||||||
|  | 				} | ||||||
|  | 				m_pixels[index] = m_newColorId; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -117,6 +180,7 @@ class UpdatePixelsCommand: public QUndoCommand { | |||||||
| 				m_pixels[pu.item->property("pixelNumber").toInt()] = pu.oldColorId; | 				m_pixels[pu.item->property("pixelNumber").toInt()] = pu.oldColorId; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -145,19 +209,49 @@ QStringList SheetData::palette() { | |||||||
| 	return m_palette; | 	return m_palette; | ||||||
| } | } | ||||||
|  |  | ||||||
| void SheetData::updatePixels(const studio::Context *ctx, QString ngPath, QString palPath) { | void SheetData::load(const studio::Context *ctx, QString ngPath, QString palPath) { | ||||||
| 	auto ng = ctx->project->loadObj<NostalgiaGraphic>(ngPath); | 	auto ng = ctx->project->loadObj<NostalgiaGraphic>(ngPath); | ||||||
| 	std::unique_ptr<NostalgiaPalette> npal; |  | ||||||
| 	if (palPath == "" && ng->defaultPalette.type() == ox::FileAddressType::Path) { | 	if (palPath == "" && ng->defaultPalette.type() == ox::FileAddressType::Path) { | ||||||
| 		palPath = ng->defaultPalette.getPath().value; | 		palPath = ng->defaultPalette.getPath().value; | ||||||
| 	} | 	} | ||||||
|  | 	m_tilesheetPath = ngPath; | ||||||
|  | 	m_currentPalettePath = palPath; | ||||||
|  | 	setRows(ng->rows); | ||||||
|  | 	setColumns(ng->columns); | ||||||
|  | 	if (palPath != "") { | ||||||
|  | 		setPalette(ctx, palPath); | ||||||
|  | 	} else { | ||||||
|  | 		setPalette(&ng->pal); | ||||||
|  | 	} | ||||||
|  | 	updatePixels(ng.get()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SheetData::save(const studio::Context *ctx, QString ngPath) { | ||||||
|  | 	auto ng = toNostalgiaGraphic(); | ||||||
|  | 	ctx->project->writeObj(ngPath, ng.get()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SheetData::setPalette(const NostalgiaPalette *npal) { | ||||||
|  | 	// load palette | ||||||
|  | 	m_palette.clear(); | ||||||
|  | 	for (std::size_t i = 0; i < npal->colors.size(); i++) { | ||||||
|  | 		const auto c = toQColor(npal->colors[i]); | ||||||
|  | 		const auto color = c.name(QColor::HexArgb); | ||||||
|  | 		m_palette.append(color); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SheetData::setPalette(const studio::Context *ctx, QString palPath) { | ||||||
|  | 	std::unique_ptr<NostalgiaPalette> npal; | ||||||
| 	try { | 	try { | ||||||
| 		npal = ctx->project->loadObj<NostalgiaPalette>(palPath); | 		npal = ctx->project->loadObj<NostalgiaPalette>(palPath); | ||||||
| 		qInfo() << "Opened palette" << palPath; | 		qInfo() << "Opened palette" << palPath; | ||||||
| 	} catch (ox::Error) { | 	} catch (ox::Error) { | ||||||
| 		qWarning() << "Could not open palette" << palPath; | 		qWarning() << "Could not open palette" << palPath; | ||||||
| 	} | 	} | ||||||
| 	updatePixels(ng.get(), npal.get()); | 	if (npal) { | ||||||
|  | 		setPalette(npal.get()); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| void SheetData::setSelectedColor(int index) { | void SheetData::setSelectedColor(int index) { | ||||||
| @@ -171,25 +265,24 @@ QUndoStack *SheetData::undoStack() { | |||||||
| void SheetData::setColumns(int columns) { | void SheetData::setColumns(int columns) { | ||||||
| 	m_columns = columns; | 	m_columns = columns; | ||||||
| 	emit columnsChanged(columns); | 	emit columnsChanged(columns); | ||||||
|  | 	emit changeOccurred(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void SheetData::setRows(int rows) { | void SheetData::setRows(int rows) { | ||||||
| 	m_rows = rows; | 	m_rows = rows; | ||||||
| 	emit rowsChanged(rows); | 	emit rowsChanged(rows); | ||||||
|  | 	emit changeOccurred(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void SheetData::updatePixels(const NostalgiaGraphic *ng, const NostalgiaPalette *npal) { | void SheetData::updateColumns(int columns) { | ||||||
| 	if (!npal) { | 	m_cmdStack.push(new UpdateDimensionsCommand(this, UpdateDimensionsCommand::Dimension::Columns, m_columns, columns)); | ||||||
| 		npal = &ng->pal; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	// load palette | void SheetData::updateRows(int rows) { | ||||||
| 	for (std::size_t i = 0; i < npal->colors.size(); i++) { | 	m_cmdStack.push(new UpdateDimensionsCommand(this, UpdateDimensionsCommand::Dimension::Rows, m_rows, rows)); | ||||||
| 		const auto c = toQColor(npal->colors[i]); |  | ||||||
| 		const auto color = c.name(QColor::HexArgb); |  | ||||||
| 		m_palette.append(color); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void SheetData::updatePixels(const NostalgiaGraphic *ng) { | ||||||
| 	if (ng->bpp == 8) { | 	if (ng->bpp == 8) { | ||||||
| 		for (std::size_t i = 0; i < ng->tiles.size(); i++) { | 		for (std::size_t i = 0; i < ng->tiles.size(); i++) { | ||||||
| 			m_pixels.push_back(ng->tiles[i]); | 			m_pixels.push_back(ng->tiles[i]); | ||||||
| @@ -209,6 +302,31 @@ void SheetData::updatePixels(const NostalgiaGraphic *ng, const NostalgiaPalette | |||||||
| 	emit paletteChanged(); | 	emit paletteChanged(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | std::unique_ptr<NostalgiaGraphic> SheetData::toNostalgiaGraphic() { | ||||||
|  | 	auto ng = std::make_unique<NostalgiaGraphic>(); | ||||||
|  | 	const auto highestColorIdx = static_cast<uint8_t>(*std::max_element(m_pixels.begin(), m_pixels.end())); | ||||||
|  | 	ng->defaultPalette = m_currentPalettePath.toUtf8().data(); | ||||||
|  | 	ng->bpp = highestColorIdx > 15 ? 8 : 4; | ||||||
|  | 	ng->columns = m_columns; | ||||||
|  | 	ng->rows = m_rows; | ||||||
|  | 	if (ng->bpp == 4) { | ||||||
|  | 		ng->tiles.resize(m_pixels.size() / 2); | ||||||
|  | 		for (int i = 0; i < m_pixels.size(); ++i) { | ||||||
|  | 			if (i & 1) { | ||||||
|  | 				ng->tiles[i / 2] |= static_cast<uint8_t>(m_pixels[i]) << 4; | ||||||
|  | 			} else { | ||||||
|  | 				ng->tiles[i / 2] = static_cast<uint8_t>(m_pixels[i]); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		ng->tiles.resize(m_pixels.size()); | ||||||
|  | 		for (int i = 0; i < m_pixels.size(); ++i) { | ||||||
|  | 			ng->tiles[i] = static_cast<uint8_t>(m_pixels[i]); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return ng; | ||||||
|  | } | ||||||
|  |  | ||||||
| void SheetData::beginCmd() { | void SheetData::beginCmd() { | ||||||
| 	++m_cmdIdx; | 	++m_cmdIdx; | ||||||
| } | } | ||||||
| @@ -220,6 +338,7 @@ void SheetData::endCmd() { | |||||||
|  |  | ||||||
| TileSheetEditor::TileSheetEditor(QString path, const studio::Context *ctx, QWidget *parent): studio::Editor(parent) { | TileSheetEditor::TileSheetEditor(QString path, const studio::Context *ctx, QWidget *parent): studio::Editor(parent) { | ||||||
| 	m_ctx = ctx; | 	m_ctx = ctx; | ||||||
|  | 	m_itemPath = path; | ||||||
| 	m_itemName = path.mid(path.lastIndexOf('/')); | 	m_itemName = path.mid(path.lastIndexOf('/')); | ||||||
| 	auto lyt = new QVBoxLayout(this); | 	auto lyt = new QVBoxLayout(this); | ||||||
| 	m_splitter = new QSplitter(this); | 	m_splitter = new QSplitter(this); | ||||||
| @@ -227,12 +346,29 @@ TileSheetEditor::TileSheetEditor(QString path, const studio::Context *ctx, QWidg | |||||||
| 	auto canvasLyt = new QVBoxLayout(canvasParent); | 	auto canvasLyt = new QVBoxLayout(canvasParent); | ||||||
| 	m_canvas = new QQuickWidget(canvasParent); | 	m_canvas = new QQuickWidget(canvasParent); | ||||||
| 	canvasLyt->addWidget(m_canvas); | 	canvasLyt->addWidget(m_canvas); | ||||||
| 	canvasLyt->setMenuBar(setupToolBar()); | 	auto tb = new QToolBar(tr("Tile Sheet Options")); | ||||||
|  | 	m_tilesX = new LabeledSpinner(tr("Tiles &X:"), 1, m_sheetData.columns()); | ||||||
|  | 	m_tilesY = new LabeledSpinner(tr("Tiles &Y:"), 1, m_sheetData.rows()); | ||||||
|  | 	tb->addWidget(m_tilesX); | ||||||
|  | 	tb->addWidget(m_tilesY); | ||||||
|  | 	canvasLyt->setMenuBar(tb); | ||||||
| 	lyt->addWidget(m_splitter); | 	lyt->addWidget(m_splitter); | ||||||
| 	m_splitter->addWidget(canvasParent); | 	m_splitter->addWidget(canvasParent); | ||||||
| 	m_splitter->addWidget(setupColorPicker(m_splitter)); | 	m_splitter->addWidget(setupColorPicker(m_splitter)); | ||||||
| 	m_splitter->setStretchFactor(0, 1); | 	m_splitter->setStretchFactor(0, 1); | ||||||
| 	m_sheetData.updatePixels(m_ctx, path); | 	connect(&m_sheetData, &SheetData::columnsChanged, [this](int val) { | ||||||
|  | 		disconnect(m_tilesX->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateColumns); | ||||||
|  | 		m_tilesX->spinBox->setValue(val); | ||||||
|  | 		connect(m_tilesX->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateColumns); | ||||||
|  | 	}); | ||||||
|  | 	connect(&m_sheetData, &SheetData::rowsChanged, [this](int val) { | ||||||
|  | 		disconnect(m_tilesY->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateRows); | ||||||
|  | 		m_tilesY->spinBox->setValue(val); | ||||||
|  | 		connect(m_tilesY->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateRows); | ||||||
|  | 	}); | ||||||
|  | 	m_sheetData.load(m_ctx, m_itemPath); | ||||||
|  | 	connect(m_tilesX->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateColumns); | ||||||
|  | 	connect(m_tilesY->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateRows); | ||||||
| 	m_canvas->rootContext()->setContextProperty("sheetData", &m_sheetData); | 	m_canvas->rootContext()->setContextProperty("sheetData", &m_sheetData); | ||||||
| 	m_canvas->setSource(QUrl::fromLocalFile(":/qml/TileSheetEditor.qml")); | 	m_canvas->setSource(QUrl::fromLocalFile(":/qml/TileSheetEditor.qml")); | ||||||
| 	m_canvas->setResizeMode(QQuickWidget::SizeRootObjectToView); | 	m_canvas->setResizeMode(QQuickWidget::SizeRootObjectToView); | ||||||
| @@ -249,24 +385,12 @@ QString TileSheetEditor::itemName() { | |||||||
| 	return m_itemName; | 	return m_itemName; | ||||||
| } | } | ||||||
|  |  | ||||||
| void TileSheetEditor::saveItem() { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| QUndoStack *TileSheetEditor::undoStack() { | QUndoStack *TileSheetEditor::undoStack() { | ||||||
| 	return m_sheetData.undoStack(); | 	return m_sheetData.undoStack(); | ||||||
| } | } | ||||||
|  |  | ||||||
| QWidget *TileSheetEditor::setupToolBar() { | void TileSheetEditor::saveItem() { | ||||||
| 	auto tb = new QToolBar(tr("Tile Sheet Options")); | 	m_sheetData.save(m_ctx, m_itemPath); | ||||||
| 	m_tilesX = new LabeledSpinner(tr("Tiles &X:"), 1, m_sheetData.columns()); |  | ||||||
| 	m_tilesY = new LabeledSpinner(tr("Tiles &Y:"), 1, m_sheetData.rows()); |  | ||||||
| 	tb->addWidget(m_tilesX); |  | ||||||
| 	tb->addWidget(m_tilesY); |  | ||||||
| 	connect(&m_sheetData, &SheetData::columnsChanged, m_tilesX->spinBox, &QSpinBox::setValue); |  | ||||||
| 	connect(&m_sheetData, &SheetData::rowsChanged, m_tilesY->spinBox, &QSpinBox::setValue); |  | ||||||
| 	connect(m_tilesX->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::setColumns); |  | ||||||
| 	connect(m_tilesY->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::setRows); |  | ||||||
| 	return tb; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| QWidget *TileSheetEditor::setupColorPicker(QWidget *parent) { | QWidget *TileSheetEditor::setupColorPicker(QWidget *parent) { | ||||||
| @@ -314,8 +438,6 @@ void TileSheetEditor::restoreState() { | |||||||
| 	QSettings settings(m_ctx->orgName, PluginName); | 	QSettings settings(m_ctx->orgName, PluginName); | ||||||
| 	settings.beginGroup("TileSheetEditor/" + m_itemName); | 	settings.beginGroup("TileSheetEditor/" + m_itemName); | ||||||
| 	m_splitter->restoreState(settings.value("m_splitter/state", m_splitter->saveState()).toByteArray()); | 	m_splitter->restoreState(settings.value("m_splitter/state", m_splitter->saveState()).toByteArray()); | ||||||
| 	m_sheetData.setRows(settings.value("m_sheetData/tileRows", 1).toInt()); |  | ||||||
| 	m_sheetData.setColumns(settings.value("m_sheetData/tileColumns", 1).toInt()); |  | ||||||
| 	m_colorPicker.colorTable->horizontalHeader()->restoreState(settings.value("m_colorPicker.colorTable/geometry", m_colorPicker.colorTable->horizontalHeader()->saveState()).toByteArray()); | 	m_colorPicker.colorTable->horizontalHeader()->restoreState(settings.value("m_colorPicker.colorTable/geometry", m_colorPicker.colorTable->horizontalHeader()->saveState()).toByteArray()); | ||||||
| 	settings.endGroup(); | 	settings.endGroup(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,14 +8,9 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QQuickItem> |  | ||||||
| #include <QSplitter> |  | ||||||
| #include <QStringList> | #include <QStringList> | ||||||
| #include <QStringView> |  | ||||||
| #include <QTableWidget> |  | ||||||
| #include <QUndoStack> | #include <QUndoStack> | ||||||
| #include <QVariant> | #include <QVariant> | ||||||
| #include <QWidget> |  | ||||||
|  |  | ||||||
| #include <nostalgia/core/gfx.hpp> | #include <nostalgia/core/gfx.hpp> | ||||||
| #include <nostalgia/studio/studio.hpp> | #include <nostalgia/studio/studio.hpp> | ||||||
| @@ -30,7 +25,9 @@ class SheetData: public QObject { | |||||||
| 	Q_PROPERTY(QStringList palette READ palette NOTIFY paletteChanged) | 	Q_PROPERTY(QStringList palette READ palette NOTIFY paletteChanged) | ||||||
|  |  | ||||||
| 	private: | 	private: | ||||||
| 		QQuickItem *m_prevPixelUpdated = nullptr; | 		class QQuickItem *m_prevPixelUpdated = nullptr; | ||||||
|  | 		QString m_tilesheetPath; | ||||||
|  | 		QString m_currentPalettePath; | ||||||
| 		uint64_t m_cmdIdx = 0; | 		uint64_t m_cmdIdx = 0; | ||||||
| 		QUndoStack m_cmdStack; | 		QUndoStack m_cmdStack; | ||||||
| 		QStringList m_palette; | 		QStringList m_palette; | ||||||
| @@ -54,7 +51,13 @@ class SheetData: public QObject { | |||||||
|  |  | ||||||
| 		QStringList palette(); | 		QStringList palette(); | ||||||
|  |  | ||||||
| 		void updatePixels(const studio::Context *ctx, QString ngPath, QString palPath = ""); | 		void load(const studio::Context *ctx, QString ngPath, QString palPath = ""); | ||||||
|  |  | ||||||
|  | 		void save(const studio::Context *ctx, QString ngPath); | ||||||
|  |  | ||||||
|  | 		void setPalette(const NostalgiaPalette *pal); | ||||||
|  |  | ||||||
|  | 		void setPalette(const studio::Context *ctx, QString palPath); | ||||||
|  |  | ||||||
| 		void setSelectedColor(int index); | 		void setSelectedColor(int index); | ||||||
|  |  | ||||||
| @@ -65,8 +68,20 @@ class SheetData: public QObject { | |||||||
|  |  | ||||||
| 		void setRows(int rows); | 		void setRows(int rows); | ||||||
|  |  | ||||||
|  | 		/** | ||||||
|  | 		 * Sets columns through a QUndoCommand. | ||||||
|  | 		 */ | ||||||
|  | 		void updateColumns(int columns); | ||||||
|  |  | ||||||
|  | 		/** | ||||||
|  | 		 * Sets rows through a QUndoCommand. | ||||||
|  | 		 */ | ||||||
|  | 		void updateRows(int rows); | ||||||
|  |  | ||||||
| 	private: | 	private: | ||||||
| 		void updatePixels(const NostalgiaGraphic *ng, const NostalgiaPalette *npal); | 		void updatePixels(const NostalgiaGraphic *ng); | ||||||
|  |  | ||||||
|  | 		[[nodiscard]] std::unique_ptr<NostalgiaGraphic> toNostalgiaGraphic(); | ||||||
|  |  | ||||||
| 	signals: | 	signals: | ||||||
| 		void changeOccurred(); | 		void changeOccurred(); | ||||||
| @@ -86,16 +101,17 @@ class TileSheetEditor: public studio::Editor { | |||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
|  |  | ||||||
| 	private: | 	private: | ||||||
|  | 		QString m_itemPath; | ||||||
| 		QString m_itemName; | 		QString m_itemName; | ||||||
| 		const studio::Context *m_ctx = nullptr; | 		const studio::Context *m_ctx = nullptr; | ||||||
| 		SheetData m_sheetData; | 		SheetData m_sheetData; | ||||||
| 		QSplitter *m_splitter = nullptr; | 		class QSplitter *m_splitter = nullptr; | ||||||
| 		struct LabeledSpinner *m_tilesX = nullptr; | 		struct LabeledSpinner *m_tilesX = nullptr; | ||||||
| 		struct LabeledSpinner *m_tilesY = nullptr; | 		struct LabeledSpinner *m_tilesY = nullptr; | ||||||
| 		class QQuickWidget* m_canvas = nullptr; | 		class QQuickWidget* m_canvas = nullptr; | ||||||
| 		struct { | 		struct { | ||||||
| 			QComboBox *palette = nullptr; | 			QComboBox *palette = nullptr; | ||||||
| 			QTableWidget *colorTable = nullptr; | 			class QTableWidget *colorTable = nullptr; | ||||||
| 		} m_colorPicker; | 		} m_colorPicker; | ||||||
|  |  | ||||||
| 	public: | 	public: | ||||||
| @@ -105,13 +121,12 @@ class TileSheetEditor: public studio::Editor { | |||||||
|  |  | ||||||
| 		QString itemName() override; | 		QString itemName() override; | ||||||
|  |  | ||||||
| 		void saveItem() override; |  | ||||||
|  |  | ||||||
| 		QUndoStack *undoStack() override; | 		QUndoStack *undoStack() override; | ||||||
|  |  | ||||||
| 	private: | 	protected: | ||||||
| 		QWidget *setupToolBar(); | 		void saveItem() override; | ||||||
|  |  | ||||||
|  | 	private: | ||||||
| 		QWidget *setupColorPicker(QWidget *widget); | 		QWidget *setupColorPicker(QWidget *widget); | ||||||
|  |  | ||||||
| 		void setColorTable(QStringList hexColors); | 		void setColorTable(QStringList hexColors); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user