From e407ad72461fcba1372344a76bbee88428c746c5 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 1 Dec 2019 00:52:00 -0600 Subject: [PATCH] [nostalgia/core] Add basic color selection and basic tilesheet editing --- src/nostalgia/core/CMakeLists.txt | 1 + src/nostalgia/core/gfx.cpp | 26 +++++ src/nostalgia/core/gfx.hpp | 13 +++ src/nostalgia/core/sdl/gfx.cpp | 2 +- src/nostalgia/core/studio/CMakeLists.txt | 1 + src/nostalgia/core/studio/Pixel.qml | 6 + src/nostalgia/core/studio/TileSheetEditor.qml | 8 +- src/nostalgia/core/studio/tilesheeteditor.cpp | 108 +++++++++++++++--- src/nostalgia/core/studio/tilesheeteditor.hpp | 32 +++++- 9 files changed, 171 insertions(+), 26 deletions(-) diff --git a/src/nostalgia/core/CMakeLists.txt b/src/nostalgia/core/CMakeLists.txt index 5c6309ba..2f8a6650 100644 --- a/src/nostalgia/core/CMakeLists.txt +++ b/src/nostalgia/core/CMakeLists.txt @@ -17,6 +17,7 @@ elseif(NOSTALGIA_BUILD_TYPE STREQUAL "Native") add_subdirectory(userland) endif() if(NOSTALGIA_BUILD_STUDIO) + add_subdirectory(qt) add_subdirectory(studio) endif() diff --git a/src/nostalgia/core/gfx.cpp b/src/nostalgia/core/gfx.cpp index f70aa3f5..3949ffef 100644 --- a/src/nostalgia/core/gfx.cpp +++ b/src/nostalgia/core/gfx.cpp @@ -149,6 +149,32 @@ Color32 toColor32(Color16 nc) { return a | (b << 8) | (g << 16) | (r << 24); } + +uint8_t red32(Color32 c) { + return (c & 0x000000ff) >> 0; +} + +uint8_t green32(Color32 c) { + return (c & 0x0000ff00) >> 8; +} + +uint8_t blue32(Color32 c) { + return (c & 0x00ff0000) >> 16; +} + + +uint8_t red32(Color16 c) { + return ((c & 0b0000000000011111) >> 0) * 8; +} + +uint8_t green32(Color16 c) { + return ((c & 0b0000001111100000) >> 5) * 8; +} + +uint8_t blue32(Color16 c) { + return ((c & 0b0111110000000000) >> 10) * 8; +} + void puts(Context *ctx, int column, int row, const char *str) { for (int i = 0; str[i]; i++) { setTile(ctx, 0, column + i, row, charMap[static_cast(str[i])]); diff --git a/src/nostalgia/core/gfx.hpp b/src/nostalgia/core/gfx.hpp index 993c152b..fb23b964 100644 --- a/src/nostalgia/core/gfx.hpp +++ b/src/nostalgia/core/gfx.hpp @@ -71,6 +71,19 @@ ox::Error model(T *io, NostalgiaGraphic *ng) { [[nodiscard]] Color32 toColor32(Color16 nc); +[[nodiscard]] uint8_t red32(Color16 c); + +[[nodiscard]] uint8_t green32(Color16 c); + +[[nodiscard]] uint8_t blue32(Color16 c); + + +[[nodiscard]] uint8_t red32(Color32 c); + +[[nodiscard]] uint8_t green32(Color32 c); + +[[nodiscard]] uint8_t blue32(Color32 c); + void puts(Context *ctx, int column, int row, const char *str); void setTile(Context *ctx, int layer, int column, int row, uint8_t tile); diff --git a/src/nostalgia/core/sdl/gfx.cpp b/src/nostalgia/core/sdl/gfx.cpp index 61d9eedf..4fb29390 100644 --- a/src/nostalgia/core/sdl/gfx.cpp +++ b/src/nostalgia/core/sdl/gfx.cpp @@ -64,7 +64,7 @@ ox::Error initConsole(Context *ctx) { SDL_Color createSDL_Color(Color16 nc) { SDL_Color c; - // extract the color chanels and scale them up for a 24 bit color + // extract the color channels and scale them up for a 24 bit color c.r = ((nc & 0b0000000000011111) >> 0) * 8; c.g = ((nc & 0b0000001111100000) >> 5) * 8; c.b = ((nc & 0b0111110000000000) >> 10) * 8; diff --git a/src/nostalgia/core/studio/CMakeLists.txt b/src/nostalgia/core/studio/CMakeLists.txt index fa9d78ad..6f2cc2e6 100644 --- a/src/nostalgia/core/studio/CMakeLists.txt +++ b/src/nostalgia/core/studio/CMakeLists.txt @@ -14,6 +14,7 @@ target_link_libraries( Qt5::Widgets Qt5::QuickWidgets NostalgiaStudio + NostalgiaCore-Qt NostalgiaCore OxFS OxStd diff --git a/src/nostalgia/core/studio/Pixel.qml b/src/nostalgia/core/studio/Pixel.qml index 19053755..b991d4b4 100644 --- a/src/nostalgia/core/studio/Pixel.qml +++ b/src/nostalgia/core/studio/Pixel.qml @@ -26,4 +26,10 @@ Rectangle { anchors.horizontalCenter: pixel.horizontalCenter anchors.bottom: pixel.bottom } + + MouseArea { + anchors.fill: parent + onClicked: sheetData.updatePixels([pixel]) + } + } diff --git a/src/nostalgia/core/studio/TileSheetEditor.qml b/src/nostalgia/core/studio/TileSheetEditor.qml index 36a89d43..39b5464a 100644 --- a/src/nostalgia/core/studio/TileSheetEditor.qml +++ b/src/nostalgia/core/studio/TileSheetEditor.qml @@ -16,12 +16,12 @@ Rectangle { Grid { id: tileGrid property int baseTileSize: Math.min(parent.width / tileGrid.columns, parent.height / tileGrid.rows) - width: tileGrid.columns * tileGrid.baseTileSize * 0.85 - height: tileGrid.rows * tileGrid.baseTileSize * 0.85 + width: tileGrid.columns * tileGrid.baseTileSize * 0.90 + height: tileGrid.rows * tileGrid.baseTileSize * 0.90 anchors.horizontalCenter: tileSheetEditor.horizontalCenter anchors.verticalCenter: tileSheetEditor.verticalCenter - rows: 2 - columns: 2 + rows: sheetData.rows + columns: sheetData.columns Repeater { model: tileGrid.rows * tileGrid.columns Tile { diff --git a/src/nostalgia/core/studio/tilesheeteditor.cpp b/src/nostalgia/core/studio/tilesheeteditor.cpp index 87b44e3b..8b2ed192 100644 --- a/src/nostalgia/core/studio/tilesheeteditor.cpp +++ b/src/nostalgia/core/studio/tilesheeteditor.cpp @@ -6,7 +6,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include #include +#include #include #include #include @@ -17,11 +19,68 @@ namespace nostalgia::core { +QColor toQColor(Color16 nc) { + const auto r = red32(nc); + const auto g = green32(nc); + const auto b = blue32(nc); + const auto a = 255; + return QColor(r, g, b, a); +} + QString SheetData::pixel(int index) { return m_palette[m_pixels[index]]; } +void SheetData::updatePixels(QVariantList pixels) { + for (auto pi : pixels) { + // TODO: replace with push to QUndoStack + auto p = qobject_cast(pi.value()); + p->setProperty("color", m_palette[m_selectedColor]); + } +} + +int SheetData::columns() { + return m_columns; +} + +void SheetData::setColumns(int columns) { + m_columns = columns; + emit columnsChanged(); +} + +int SheetData::rows() { + return m_rows; +} + +void SheetData::setRows(int rows) { + m_rows = rows; + emit rowsChanged(); +} + +QStringList SheetData::palette() { + return m_palette; +} + +void SheetData::updatePixels(const studio::Context *ctx, QString ngPath, QString palPath) { + auto ng = ctx->project->loadObj(ngPath); + std::unique_ptr npal; + if (palPath == "" && ng->defaultPalette.type() == ox::FileAddressType::Path) { + palPath = ng->defaultPalette.getPath().value; + } + try { + npal = ctx->project->loadObj(palPath); + qInfo() << "Opened palette" << palPath; + } catch (ox::Error) { + qWarning() << "Could not open palette" << palPath; + } + updatePixels(ng.get(), npal.get()); +} + +void SheetData::setSelectedColor(int index) { + m_selectedColor = index; +} + void SheetData::updatePixels(const NostalgiaGraphic *ng, const NostalgiaPalette *npal) { if (!npal) { npal = &ng->pal; @@ -29,8 +88,8 @@ void SheetData::updatePixels(const NostalgiaGraphic *ng, const NostalgiaPalette // load palette for (std::size_t i = 0; i < npal->colors.size(); i++) { - auto c = toColor32(npal->colors[i]); - auto color = "#" + QString("%1").arg(QString::number(c, 16), 8, '0'); + const auto c = toQColor(npal->colors[i]); + const auto color = c.name(QColor::HexArgb); m_palette.append(color); } @@ -51,21 +110,6 @@ void SheetData::updatePixels(const NostalgiaGraphic *ng, const NostalgiaPalette } } -void SheetData::updatePixels(const studio::Context *ctx, QString ngPath, QString palPath) { - auto ng = ctx->project->loadObj(ngPath); - std::unique_ptr npal; - if (palPath == "" && ng->defaultPalette.type() == ox::FileAddressType::Path) { - palPath = ng->defaultPalette.getPath().value; - } - try { - npal = ctx->project->loadObj(palPath); - qInfo() << "Opened palette" << palPath; - } catch (ox::Error) { - qWarning() << "Could not open palette" << palPath; - } - return updatePixels(ng.get(), npal.get()); -} - TileSheetEditor::TileSheetEditor(QString path, const studio::Context *ctx, QWidget *parent): QWidget(parent) { m_ctx = ctx; @@ -80,6 +124,7 @@ TileSheetEditor::TileSheetEditor(QString path, const studio::Context *ctx, QWidg canvas->rootContext()->setContextProperty("sheetData", &m_sheetData); canvas->setSource(QUrl::fromLocalFile(":/qml/TileSheetEditor.qml")); canvas->setResizeMode(QQuickWidget::SizeRootObjectToView); + setColorTable(m_sheetData.palette()); restoreState(); } @@ -92,23 +137,48 @@ QWidget *TileSheetEditor::setupColorPicker(QWidget *parent) { auto lyt = new QVBoxLayout(colorPicker); m_colorPicker.palette = new QComboBox(colorPicker); m_colorPicker.colorTable = new QTableWidget(colorPicker); + m_colorPicker.colorTable->setColumnCount(2); + m_colorPicker.colorTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_colorPicker.colorTable->setSelectionMode(QAbstractItemView::SingleSelection); + m_colorPicker.colorTable->setHorizontalHeaderLabels(QStringList() << tr("Hex Code") << tr("Color")); + m_colorPicker.colorTable->horizontalHeader()->setStretchLastSection(true); + m_colorPicker.colorTable->verticalHeader()->hide(); + connect(m_colorPicker.colorTable, &QTableWidget::itemSelectionChanged, this, &TileSheetEditor::colorSelected); lyt->addWidget(m_colorPicker.palette); lyt->addWidget(m_colorPicker.colorTable); return colorPicker; } +void TileSheetEditor::setColorTable(QStringList hexColors) { + auto tbl = m_colorPicker.colorTable; + tbl->setRowCount(hexColors.size()); + for (int i = 0; i < hexColors.size(); i++) { + auto hexCode = new QTableWidgetItem; + hexCode->setText(hexColors[i]); + hexCode->setFont(QFont("monospace")); + tbl->setItem(i, 0, hexCode); + auto color = new QTableWidgetItem; + color->setBackground(QColor(hexColors[i])); + tbl->setItem(i, 1, color); + } +} + void TileSheetEditor::saveState() { QSettings settings(m_ctx->orgName, PluginName); - settings.beginGroup("TileSheetEditor/state"); + settings.beginGroup("TileSheetEditor"); settings.setValue("m_splitter/state", m_splitter->saveState()); settings.endGroup(); } void TileSheetEditor::restoreState() { QSettings settings(m_ctx->orgName, PluginName); - settings.beginGroup("TileSheetEditor/state"); + settings.beginGroup("TileSheetEditor"); m_splitter->restoreState(settings.value("m_splitter/state", m_splitter->saveState()).toByteArray()); settings.endGroup(); } +void TileSheetEditor::colorSelected() { + m_sheetData.setSelectedColor(m_colorPicker.colorTable->currentRow()); +} + } diff --git a/src/nostalgia/core/studio/tilesheeteditor.hpp b/src/nostalgia/core/studio/tilesheeteditor.hpp index 57eea508..1c8aa560 100644 --- a/src/nostalgia/core/studio/tilesheeteditor.hpp +++ b/src/nostalgia/core/studio/tilesheeteditor.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -21,20 +22,42 @@ namespace nostalgia::core { class SheetData: public QObject { Q_OBJECT + Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged) + Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged) private: QStringList m_palette; QVector m_pixels; + int m_columns = 2; + int m_rows = 2; + int m_selectedColor = 0; public: Q_INVOKABLE QString pixel(int index); - void updatePixels(const NostalgiaGraphic *ng, const NostalgiaPalette *npal); + Q_INVOKABLE void updatePixels(QVariantList pixels); + + int columns(); + + void setColumns(int columns); + + int rows(); + + void setRows(int rows); + + QStringList palette(); void updatePixels(const studio::Context *ctx, QString ngPath, QString palPath = ""); + void setSelectedColor(int index); + + private: + void updatePixels(const NostalgiaGraphic *ng, const NostalgiaPalette *npal); + signals: - void refreshTileSheet(); + void columnsChanged(); + + void rowsChanged(); }; @@ -59,10 +82,15 @@ class TileSheetEditor: public QWidget { private: QWidget *setupColorPicker(QWidget *widget); + void setColorTable(QStringList hexColors); + void saveState(); void restoreState(); + public slots: + void colorSelected(); + }; }