diff --git a/src/nostalgia/core/color.hpp b/src/nostalgia/core/color.hpp index ae26b731..43dd8af4 100644 --- a/src/nostalgia/core/color.hpp +++ b/src/nostalgia/core/color.hpp @@ -129,12 +129,13 @@ constexpr float bluef(Color32 c) noexcept { [[nodiscard]] -constexpr Color16 color16(uint8_t r, uint8_t g, uint8_t b) noexcept { - return r | (g << 5) | (b << 10); +constexpr Color16 color16(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 0) noexcept { + return ox::min(r, 31) | (ox::min(g, 31) << 5) | (ox::min(b, 31) << 10) | (a << 15); } static_assert(color16(0, 31, 0) == 992); static_assert(color16(16, 31, 0) == 1008); static_assert(color16(16, 31, 8) == 9200); +static_assert(color16(16, 32, 8) == 9200); } diff --git a/src/nostalgia/core/context.hpp b/src/nostalgia/core/context.hpp index 24776dc6..a41e5b99 100644 --- a/src/nostalgia/core/context.hpp +++ b/src/nostalgia/core/context.hpp @@ -36,7 +36,6 @@ class ClipboardObject: public BaseClipboardObject { } }; -class Context; class Drawer; // User Input Output diff --git a/src/nostalgia/core/studio/CMakeLists.txt b/src/nostalgia/core/studio/CMakeLists.txt index b0ae7fbf..8e7d73f2 100644 --- a/src/nostalgia/core/studio/CMakeLists.txt +++ b/src/nostalgia/core/studio/CMakeLists.txt @@ -4,9 +4,9 @@ add_library( module.cpp #new_tilesheet_wizard.cpp #newpalettewizard.cpp - #paletteeditor.cpp + paletteeditor.cpp tilesheeteditor-imgui.cpp - tilesheeteditorview.cpp + tilesheeteditorview.cpp tilesheeteditormodel.cpp tilesheetpixelgrid.cpp tilesheetpixels.cpp diff --git a/src/nostalgia/core/studio/module.cpp b/src/nostalgia/core/studio/module.cpp index 096b75e3..e5e60d7b 100644 --- a/src/nostalgia/core/studio/module.cpp +++ b/src/nostalgia/core/studio/module.cpp @@ -2,21 +2,32 @@ * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. */ +#include "paletteeditor.hpp" #include "tilesheeteditor-imgui.hpp" #include "module.hpp" namespace nostalgia::core { -ox::Vector Module::editors(core::Context *ctx) { +ox::Vector Module::editors(core::Context *ctx) noexcept { return { { {"ng"}, - [ctx](const ox::String &path) { - return new TileSheetEditorImGui(ctx, path); + [ctx](const ox::String &path) -> ox::Result { + try { + return new TileSheetEditorImGui(ctx, path); + } catch (const ox::Exception &ex) { + return ex.toError(); + } + } + }, + { + {"npal"}, + [ctx](const ox::String &path) -> ox::Result { + return PaletteEditorImGui::make(ctx, path); } } }; } -} \ No newline at end of file +} diff --git a/src/nostalgia/core/studio/module.hpp b/src/nostalgia/core/studio/module.hpp index 16130a5d..dd7088fb 100644 --- a/src/nostalgia/core/studio/module.hpp +++ b/src/nostalgia/core/studio/module.hpp @@ -10,7 +10,7 @@ namespace nostalgia::core { class Module: public studio::Module { public: - ox::Vector editors(core::Context *ctx) override; + ox::Vector editors(core::Context *ctx) noexcept override; }; } diff --git a/src/nostalgia/core/studio/paletteeditor.cpp b/src/nostalgia/core/studio/paletteeditor.cpp index 94735427..d301f067 100644 --- a/src/nostalgia/core/studio/paletteeditor.cpp +++ b/src/nostalgia/core/studio/paletteeditor.cpp @@ -2,16 +2,14 @@ * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. */ -#include -#include -#include -#include -#include -#include +#include + +#include #include +#include +#include -#include "util.hpp" #include "paletteeditor.hpp" namespace nostalgia::core { @@ -24,359 +22,294 @@ enum class PaletteEditorCommandId { }; -class ColorChannelValidator: public QValidator { - - public: - explicit ColorChannelValidator(QLineEdit *parent); - - QValidator::State validate(QString &input, int&) const override; - +class AddColorCommand: public studio::UndoCommand { private: - [[nodiscard]] static QString convert(const QString &input); - -}; - -ColorChannelValidator::ColorChannelValidator(QLineEdit *parent): QValidator(parent) { - connect(parent, &QLineEdit::editingFinished, [parent] { - parent->setText(convert(parent->text())); - }); -} - -QString ColorChannelValidator::convert(const QString &input) { - int num = 0; - if (input[0] == '_') { - num = input.mid(1).toInt() >> 3; - } - return QString::number(num); -} - -QValidator::State ColorChannelValidator::validate(QString &input, int&) const { - if (input.size() == 0) { - return QValidator::State::Intermediate; - } - const auto convert = input[0] == '_'; - const auto max = convert ? 255 : 31; - const auto numTxt = convert ? input.mid(1) : input; - bool isNumber = false; - const auto num = numTxt.toInt(&isNumber); - if (isNumber && num >= 0 && num <= max) { - return QValidator::State::Acceptable; - } else if (numTxt == "") { - return QValidator::State::Intermediate; - } else { - return QValidator::State::Invalid; - } -} - - -class AddColorCommand: public QUndoCommand { - private: - PaletteEditor *m_editor = nullptr; + PaletteEditorImGui *m_editor = nullptr; Color16 m_color = 0; int m_idx = -1; public: - AddColorCommand(PaletteEditor *editor, Color16 color, int idx) { + AddColorCommand(PaletteEditorImGui *editor, Color16 color, int idx) noexcept { m_editor = editor; m_color = color; m_idx = idx; } - ~AddColorCommand() override = default; + ~AddColorCommand() noexcept override = default; - [[nodiscard]] int id() const override { + [[nodiscard]] + int commandId() const noexcept override { return static_cast(PaletteEditorCommandId::AddColor); } - void redo() override { + void redo() noexcept override { m_editor->addColor(m_idx, m_color); } - void undo() override { + void undo() noexcept override { m_editor->rmColor(m_idx); } }; -class RemoveColorCommand: public QUndoCommand { +class RemoveColorCommand: public studio::UndoCommand { private: - PaletteEditor *m_editor = nullptr; + PaletteEditorImGui *m_editor = nullptr; Color16 m_color = 0; int m_idx = -1; public: - RemoveColorCommand(PaletteEditor *editor, Color16 color, int idx) { + RemoveColorCommand(PaletteEditorImGui *editor, Color16 color, int idx) noexcept { m_editor = editor; m_color = color; m_idx = idx; } - ~RemoveColorCommand() override = default; + ~RemoveColorCommand() noexcept override = default; - [[nodiscard]] int id() const override { + [[nodiscard]] + int commandId() const noexcept override { return static_cast(PaletteEditorCommandId::RemoveColor); } - void redo() override { + void redo() noexcept override { m_editor->rmColor(m_idx); } - void undo() override { + void undo() noexcept override { m_editor->addColor(m_idx, m_color); } }; -class UpdateColorCommand: public QUndoCommand { +class UpdateColorCommand: public studio::UndoCommand { private: - PaletteEditor *m_editor = nullptr; + PaletteEditorImGui *m_editor = nullptr; Color16 m_oldColor = 0; Color16 m_newColor = 0; int m_idx = -1; public: - UpdateColorCommand(PaletteEditor *editor, int idx, Color16 oldColor, Color16 newColor) { + UpdateColorCommand(PaletteEditorImGui *editor, int idx, Color16 oldColor, Color16 newColor) noexcept { m_editor = editor; m_idx = idx; m_oldColor = oldColor; m_newColor = newColor; - setObsolete(m_oldColor == m_newColor); + //setObsolete(m_oldColor == m_newColor); } - ~UpdateColorCommand() override = default; + ~UpdateColorCommand() noexcept override = default; - [[nodiscard]] int id() const override { + bool mergeWith(const UndoCommand *cmd) noexcept final { + if (cmd->commandId() != static_cast(PaletteEditorCommandId::UpdateColor)) { + return false; + } + auto ucCmd = static_cast(cmd); + if (m_idx != ucCmd->m_idx) { + return false; + } + m_newColor = ucCmd->m_newColor; + return true; + } + + int commandId() const noexcept final { return static_cast(PaletteEditorCommandId::UpdateColor); } - void redo() override { + void redo() noexcept final { m_editor->updateColor(m_idx, m_newColor); } - void undo() override { + void undo() noexcept final { m_editor->updateColor(m_idx, m_oldColor); } }; -class MoveColorCommand: public QUndoCommand { +class MoveColorCommand: public studio::UndoCommand { private: - PaletteEditor *m_editor = nullptr; - int m_idx = -1; + PaletteEditorImGui *m_editor = nullptr; + std::size_t m_idx = 0; int m_offset = 0; public: - MoveColorCommand(PaletteEditor *editor, int idx, int offset) { + MoveColorCommand(PaletteEditorImGui *editor, std::size_t idx, int offset) noexcept { m_editor = editor; m_idx = idx; m_offset = offset; } - ~MoveColorCommand() override = default; + ~MoveColorCommand() noexcept override = default; - [[nodiscard]] int id() const override { + [[nodiscard]] + int commandId() const noexcept override { return static_cast(PaletteEditorCommandId::MoveColor); } - void redo() override { + void redo() noexcept override { m_editor->moveColor(m_idx, m_offset); } - void undo() override { - m_editor->moveColor(m_idx + m_offset, -m_offset); + void undo() noexcept override { + m_editor->moveColor(static_cast(m_idx) + m_offset, -m_offset); } }; -QWidget *PaletteEditorColorTableDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex &idx) const { - auto le = new QLineEdit(parent); - if (idx.column()) { - auto validator = new ColorChannelValidator(le); - le->setValidator(validator); +ox::Result PaletteEditorImGui::make(Context *ctx, const ox::String &path) noexcept { + auto out = ox::UniquePtr(new PaletteEditorImGui); + out->m_ctx = ctx; + out->m_itemPath = path; + const auto lastSlash = std::find(out->m_itemPath.rbegin(), out->m_itemPath.rend(), '/').offset(); + out->m_itemName = out->m_itemPath.substr(lastSlash + 1); + oxRequire(pal, core::readObj(out->m_ctx, out->m_itemPath)); + out->m_pal = *pal.get(); + out->undoStack()->changeTriggered.connect(out.get(), &PaletteEditorImGui::markUnsavedChanges); + return out.release(); +} + +const ox::String &PaletteEditorImGui::itemName() const { + return m_itemName; +} + +studio::UndoStack *PaletteEditorImGui::undoStack() noexcept { + return &m_undoStack; +} + +void PaletteEditorImGui::draw(core::Context*) noexcept { + static constexpr auto flags = ImGuiTableFlags_RowBg; + const auto paneSize = ImGui::GetContentRegionAvail(); + ImGui::BeginChild("PaletteEditor"); + { + ImGui::BeginChild("Colors", ImVec2(paneSize.x - 200, paneSize.y), false); + { + const auto colorsSz = ImGui::GetContentRegionAvail(); + static constexpr auto toolbarHeight = 40; + ImGui::BeginChild("Toolbar", ImVec2(colorsSz.x, toolbarHeight), true); + { + const auto sz = ImVec2(70, 24); + if (ImGui::Button("Add", sz)) { + m_undoStack.push(new AddColorCommand(this, 0, m_pal.colors.size())); + } + ImGui::SameLine(); + ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size()); + { + if (ImGui::Button("Remove", sz)) { + m_undoStack.push(new RemoveColorCommand(this, m_pal.colors[static_cast(m_selectedRow)], m_selectedRow)); + m_selectedRow = ox::min(m_pal.colors.size() - 1, m_selectedRow); + } + ImGui::SameLine(); + ImGui::BeginDisabled(m_selectedRow <= 0); + { + if (ImGui::Button("Move Up", sz)) { + m_undoStack.push(new MoveColorCommand(this, m_selectedRow, -1)); + --m_selectedRow; + } + } + ImGui::EndDisabled(); + ImGui::SameLine(); + ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size() - 1); + { + if (ImGui::Button("Move Down", sz)) { + m_undoStack.push(new MoveColorCommand(this, m_selectedRow, 1)); + ++m_selectedRow; + } + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + } + ImGui::EndChild(); + ImGui::BeginTable("Colors", 5, flags, ImVec2(colorsSz.x, colorsSz.y - (toolbarHeight + 5))); + { + ImGui::TableSetupColumn("Idx", ImGuiTableColumnFlags_WidthFixed, 25); + ImGui::TableSetupColumn("Red", ImGuiTableColumnFlags_WidthFixed, 50); + ImGui::TableSetupColumn("Green", ImGuiTableColumnFlags_WidthFixed, 50); + ImGui::TableSetupColumn("Blue", ImGuiTableColumnFlags_WidthFixed, 50); + ImGui::TableSetupColumn("Color Preview", ImGuiTableColumnFlags_NoHide); + ImGui::TableHeadersRow(); + for (auto i = 0u; const auto c : m_pal.colors) { + ImGui::PushID(static_cast(i)); + ImGui::TableNextRow(); + // Color No. + ImGui::TableNextColumn(); + ImGui::Text("%d", i); + // Red + ImGui::TableNextColumn(); + ImGui::Text("%d", red16(c)); + // Green + ImGui::TableNextColumn(); + ImGui::Text("%d", green16(c)); + // Blue + ImGui::TableNextColumn(); + ImGui::Text("%d", blue16(c)); + // ColorPreview + ImGui::TableNextColumn(); + const auto ic = ImGui::GetColorU32(ImVec4(redf(c), greenf(c), bluef(c), 1)); + ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic); + if (ImGui::Selectable("##ColorRow", i == m_selectedRow, ImGuiSelectableFlags_SpanAllColumns)) { + m_selectedRow = i; + } + ImGui::PopID(); + ++i; + } + } + ImGui::EndTable(); + } + ImGui::EndChild(); + if (m_selectedRow < m_pal.colors.size()) { + ImGui::SameLine(); + ImGui::BeginChild("ColorEditor", ImVec2(200, paneSize.y), true); + { + const auto c = m_pal.colors[m_selectedRow]; + int r = red16(c); + int g = green16(c); + int b = blue16(c); + int a = alpha16(c); + ImGui::InputInt("Red", &r, 1, 5); + ImGui::InputInt("Green", &g, 1, 5); + ImGui::InputInt("Blue", &b, 1, 5); + const auto newColor = color16(r, g, b, a); + if (c != newColor) { + m_undoStack.push(new UpdateColorCommand(this, m_selectedRow, c, newColor)); + } + } + ImGui::EndChild(); + } } - return le; + ImGui::EndChild(); } -void PaletteEditorColorTableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &idx) const { - if (idx.column() != 3) { - QStyledItemDelegate::paint(painter, opt, idx); - } else { - auto color = idx.model()->data(idx, Qt::DisplayRole).toString(); - painter->fillRect(opt.rect, QColor(color)); - } -} - - -static QTableWidgetItem *mkCell(const QString& v, bool editable = true) { - auto c = new QTableWidgetItem; - c->setText(v); - c->setFont(QFont("monospace")); - c->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); - if (!editable) { - c->setFlags(c->flags() & ~Qt::ItemIsEditable); - } - return c; -} - - -static QTableWidgetItem *mkCell(uint8_t v) { - return mkCell(QString("%1").arg(v), true); -} - - -PaletteEditor::PaletteEditor(QString path, const studio::Context *ctx, QWidget *parent): studio::Editor(parent) { - m_ctx = ctx; - m_itemPath = path; - - auto canvasLyt = new QVBoxLayout(this); - auto tb = new QToolBar(tr("Tile Sheet Options")); - m_addBtn = new QPushButton(tr("Add"), tb); - m_rmBtn = new QPushButton(tr("Remove"), tb); - m_moveUpBtn = new QPushButton(tr("Move Up"), tb); - m_moveDownBtn = new QPushButton(tr("Move Down"), tb); - m_rmBtn->setEnabled(false); - m_moveUpBtn->setEnabled(false); - m_moveDownBtn->setEnabled(false); - tb->addWidget(m_addBtn); - tb->addWidget(m_rmBtn); - tb->addWidget(m_moveUpBtn); - tb->addWidget(m_moveDownBtn); - canvasLyt->setMenuBar(tb); - - m_table = new QTableWidget(this); - m_table->setItemDelegate(&m_colorTableDelegate); - m_table->setColumnCount(4); - m_table->setSelectionBehavior(QAbstractItemView::SelectRows); - m_table->setSelectionMode(QAbstractItemView::SingleSelection); - m_table->setHorizontalHeaderLabels(QStringList() << tr("Red") << tr("Green") << tr("Blue") << tr("Color Preview")); - m_table->horizontalHeader()->setStretchLastSection(true); - m_table->verticalHeader()->hide(); - canvasLyt->addWidget(m_table); - connect(m_table, &QTableWidget::itemSelectionChanged, this, &PaletteEditor::colorSelected); - connect(m_addBtn, &QPushButton::clicked, this, &PaletteEditor::addColorClicked); - connect(m_rmBtn, &QPushButton::clicked, this, &PaletteEditor::rmColorClicked); - connect(m_moveUpBtn, &QPushButton::clicked, this, &PaletteEditor::moveColorUpClicked); - connect(m_moveDownBtn, &QPushButton::clicked, this, &PaletteEditor::moveColorDownClicked); - connect(m_table, &QTableWidget::cellChanged, this, &PaletteEditor::cellChanged); - m_pal = m_ctx->project->loadObj(m_itemPath); - load(); -} - -QString PaletteEditor::itemName() const { - return m_itemPath.mid(m_itemPath.lastIndexOf('/')); -} - -void PaletteEditor::addTableRow(int i, Color16 c) { - disconnect(m_table, &QTableWidget::cellChanged, this, &PaletteEditor::cellChanged); - m_table->insertRow(i); - m_table->setItem(i, 0, mkCell(red16(c))); - m_table->setItem(i, 1, mkCell(green16(c))); - m_table->setItem(i, 2, mkCell(blue16(c))); - m_table->setItem(i, 3, mkCell(toQColor(m_pal->colors[static_cast(i)]).name(QColor::HexRgb), false)); - connect(m_table, &QTableWidget::cellChanged, this, &PaletteEditor::cellChanged); -} - -void PaletteEditor::rmTableRow(int idx) { - disconnect(m_table, &QTableWidget::cellChanged, this, &PaletteEditor::cellChanged); - m_table->removeRow(idx); - connect(m_table, &QTableWidget::cellChanged, this, &PaletteEditor::cellChanged); -} - -void PaletteEditor::setTableRow(int idx, Color16 c) { - disconnect(m_table, &QTableWidget::cellChanged, this, &PaletteEditor::cellChanged); - m_table->item(idx, 0)->setText(QString::number(red16(c))); - m_table->item(idx, 1)->setText(QString::number(green16(c))); - m_table->item(idx, 2)->setText(QString::number(blue16(c))); - m_table->item(idx, 3)->setText(toQColor(m_pal->colors[static_cast(idx)]).name(QColor::HexRgb)); - connect(m_table, &QTableWidget::cellChanged, this, &PaletteEditor::cellChanged); -} - -void PaletteEditor::addColor(int idx, Color16 c) { - m_pal->colors.insert(static_cast(idx), c); - addTableRow(idx, c); +void PaletteEditorImGui::addColor(int idx, Color16 c) noexcept { + m_pal.colors.insert(static_cast(idx), c); setUnsavedChanges(true); } -void PaletteEditor::rmColor(int idx) { - rmTableRow(idx); - oxIgnoreError(m_pal->colors.erase(static_cast(idx))); +void PaletteEditorImGui::rmColor(int idx) noexcept { + oxIgnoreError(m_pal.colors.erase(static_cast(idx))); setUnsavedChanges(true); } -void PaletteEditor::updateColor(int idx, Color16 c) { - m_pal->colors[static_cast(idx)] = c; - setTableRow(idx, c); +void PaletteEditorImGui::updateColor(int idx, Color16 c) noexcept { + m_pal.colors[static_cast(idx)] = c; setUnsavedChanges(true); } -void PaletteEditor::moveColor(int idx, int offset) { - auto c = m_pal->colors[static_cast(idx)]; - oxIgnoreError(m_pal->colors.erase(static_cast(idx))); - m_pal->colors.insert(static_cast(idx + offset), c); - rmTableRow(idx); - addTableRow(idx + offset, c); +void PaletteEditorImGui::moveColor(int idx, int offset) noexcept { + const auto c = m_pal.colors[static_cast(idx)]; + oxIgnoreError(m_pal.colors.erase(static_cast(idx))); + m_pal.colors.insert(static_cast(idx + offset), c); setUnsavedChanges(true); } -void PaletteEditor::saveItem() { - m_ctx->project->writeObj(m_itemPath, m_pal.get()); +void PaletteEditorImGui::saveItem() { + //m_ctx->project->writeObj(m_itemPath, &m_pal); } -void PaletteEditor::load() { - disconnect(m_table, &QTableWidget::cellChanged, this, &PaletteEditor::cellChanged); - for (std::size_t i = 0; i < m_pal->colors.size(); ++i) { - auto c = m_pal->colors[i]; - addTableRow(i, c); - } - connect(m_table, &QTableWidget::cellChanged, this, &PaletteEditor::cellChanged); -} - -Color16 PaletteEditor::rowColor(int row) const { - auto r = static_cast(m_table->item(row, 0)->text().toInt()); - auto g = static_cast(m_table->item(row, 1)->text().toInt()); - auto b = static_cast(m_table->item(row, 2)->text().toInt()); - return color16(r, g, b); -} - -void PaletteEditor::colorSelected() { - auto selIdxs = m_table->selectionModel()->selectedIndexes(); - auto row = !selIdxs.empty() ? selIdxs[0].row() : -1; - if (row > -1) { - m_rmBtn->setEnabled(true); - m_moveUpBtn->setEnabled(row > 0); - m_moveDownBtn->setEnabled(row < m_table->rowCount() - 1); - } else { - m_rmBtn->setEnabled(false); - m_moveUpBtn->setEnabled(false); - m_moveDownBtn->setEnabled(false); - } -} - -void PaletteEditor::cellChanged(int row, int) { - auto oldColor = m_pal->colors[static_cast(row)]; - auto newColor = rowColor(row); - undoStack()->push(new UpdateColorCommand(this, row, oldColor, newColor)); -} - -void PaletteEditor::addColorClicked() { - auto row = m_table->rowCount(); - undoStack()->push(new AddColorCommand(this, 0, row)); -} - -void PaletteEditor::rmColorClicked() { - auto row = m_table->currentRow(); - undoStack()->push(new RemoveColorCommand(this, m_pal->colors[static_cast(row)], row)); -} - -void PaletteEditor::moveColorUpClicked() { - auto row = m_table->currentRow(); - undoStack()->push(new MoveColorCommand(this, row, -1)); -} - -void PaletteEditor::moveColorDownClicked() { - auto row = m_table->currentRow(); - undoStack()->push(new MoveColorCommand(this, row, 1)); +ox::Error PaletteEditorImGui::markUnsavedChanges(int) noexcept { + setUnsavedChanges(true); + return OxError(0); } } diff --git a/src/nostalgia/core/studio/paletteeditor.hpp b/src/nostalgia/core/studio/paletteeditor.hpp index 0614553e..6809f7ad 100644 --- a/src/nostalgia/core/studio/paletteeditor.hpp +++ b/src/nostalgia/core/studio/paletteeditor.hpp @@ -4,22 +4,14 @@ #pragma once -#include - +#include "nostalgia/studio/lib/undostack.hpp" #include #include +#include namespace nostalgia::core { -struct PaletteEditorColorTableDelegate: public QStyledItemDelegate { - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex &idx) const; - - void paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &idx) const; - -}; - -class PaletteEditor: public studio::Editor { +class PaletteEditorImGui: public studio::Editor { friend class AddColorCommand; friend class RemoveColorCommand; @@ -27,58 +19,40 @@ class PaletteEditor: public studio::Editor { friend class MoveColorCommand; private: - PaletteEditorColorTableDelegate m_colorTableDelegate; - const studio::Context *m_ctx = nullptr; - QString m_itemPath; - std::unique_ptr m_pal; - class QTableWidget *m_table = nullptr; - class QPushButton *m_addBtn = nullptr; - class QPushButton *m_rmBtn = nullptr; - class QPushButton *m_moveUpBtn = nullptr; - class QPushButton *m_moveDownBtn = nullptr; + Context *m_ctx = nullptr; + ox::String m_itemName; + ox::String m_itemPath; + Palette m_pal; + std::size_t m_selectedRow = 0; + studio::UndoStack m_undoStack; + + PaletteEditorImGui() noexcept = default; public: - PaletteEditor(QString path, const studio::Context *ctx, QWidget *parent); + static ox::Result make(Context *ctx, const ox::String &path) noexcept; /** * Returns the name of item being edited. */ - QString itemName() const override; + const ox::String &itemName() const override; + + void draw(core::Context*) noexcept override; + + studio::UndoStack *undoStack() noexcept final; protected: - void addColor(int idx, Color16 c); + void addColor(int idx, Color16 c) noexcept; - void rmColor(int idx); + void rmColor(int idx) noexcept; - void updateColor(int idx, Color16); + void updateColor(int idx, Color16) noexcept; - void moveColor(int idx, int offset); + void moveColor(int idx, int offset) noexcept; void saveItem() override; private: - void load(); - - [[nodiscard]] Color16 rowColor(int i) const; - - void addTableRow(int i, Color16 c); - - void rmTableRow(int i); - - void setTableRow(int idx, Color16 c); - - private slots: - void colorSelected(); - - void cellChanged(int row, int col); - - void addColorClicked(); - - void rmColorClicked(); - - void moveColorUpClicked(); - - void moveColorDownClicked(); + ox::Error markUnsavedChanges(int) noexcept; }; diff --git a/src/nostalgia/core/studio/tilesheeteditor-imgui.cpp b/src/nostalgia/core/studio/tilesheeteditor-imgui.cpp index 2befb634..db8a26be 100644 --- a/src/nostalgia/core/studio/tilesheeteditor-imgui.cpp +++ b/src/nostalgia/core/studio/tilesheeteditor-imgui.cpp @@ -17,7 +17,7 @@ TileSheetEditorImGui::TileSheetEditorImGui(Context *ctx, const ox::String &path) const auto lastSlash = std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset(); m_itemName = m_itemPath.substr(lastSlash + 1); // init palette idx - const auto palPath = model()->palPath(); + const auto &palPath = model()->palPath(); auto sctx = applicationData(m_ctx); const auto &palList = sctx->project->fileList(core::FileExt_npal + 1); for (std::size_t i = 0; const auto &pal : palList) { @@ -32,11 +32,11 @@ TileSheetEditorImGui::TileSheetEditorImGui(Context *ctx, const ox::String &path) m_subsheetEditor.inputSubmitted.connect(this, &TileSheetEditorImGui::updateActiveSubsheet); } -ox::String TileSheetEditorImGui::itemName() const noexcept { +const ox::String &TileSheetEditorImGui::itemName() const noexcept { return m_itemPath; } -ox::String TileSheetEditorImGui::itemDisplayName() const noexcept { +const ox::String &TileSheetEditorImGui::itemDisplayName() const noexcept { return m_itemName; } @@ -303,7 +303,7 @@ ox::Error TileSheetEditorImGui::markUnsavedChanges(int) noexcept { void TileSheetEditorImGui::SubSheetEditor::draw() noexcept { constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - constexpr auto popupName = "Edit SubSheet"; + constexpr auto popupName = "Edit Subsheet"; if (!m_show) { return; } diff --git a/src/nostalgia/core/studio/tilesheeteditor-imgui.hpp b/src/nostalgia/core/studio/tilesheeteditor-imgui.hpp index 50e8c1d8..7bf9ac42 100644 --- a/src/nostalgia/core/studio/tilesheeteditor-imgui.hpp +++ b/src/nostalgia/core/studio/tilesheeteditor-imgui.hpp @@ -58,9 +58,9 @@ class TileSheetEditorImGui: public studio::Editor { ~TileSheetEditorImGui() override = default; - ox::String itemName() const noexcept override; + const ox::String &itemName() const noexcept override; - ox::String itemDisplayName() const noexcept override; + const ox::String &itemDisplayName() const noexcept override; void exportFile() override; diff --git a/src/nostalgia/studio/lib/editor.cpp b/src/nostalgia/studio/lib/editor.cpp index f16a13a5..06d91b94 100644 --- a/src/nostalgia/studio/lib/editor.cpp +++ b/src/nostalgia/studio/lib/editor.cpp @@ -8,7 +8,7 @@ namespace nostalgia::studio { -ox::String Editor::itemDisplayName() const { +const ox::String &Editor::itemDisplayName() const { return itemName(); } diff --git a/src/nostalgia/studio/lib/editor.hpp b/src/nostalgia/studio/lib/editor.hpp index 5114a6a4..1c549893 100644 --- a/src/nostalgia/studio/lib/editor.hpp +++ b/src/nostalgia/studio/lib/editor.hpp @@ -30,10 +30,10 @@ class NOSTALGIASTUDIO_EXPORT Editor: public Widget { * Returns the name of item being edited. */ [[nodiscard]] - virtual ox::String itemName() const = 0; + virtual const ox::String &itemName() const = 0; [[nodiscard]] - virtual ox::String itemDisplayName() const; + virtual const ox::String &itemDisplayName() const; virtual void cut(); diff --git a/src/nostalgia/studio/lib/module.hpp b/src/nostalgia/studio/lib/module.hpp index 54bcbed0..58f641c6 100644 --- a/src/nostalgia/studio/lib/module.hpp +++ b/src/nostalgia/studio/lib/module.hpp @@ -14,7 +14,7 @@ namespace nostalgia::studio { struct EditorMaker { - using Func = std::function; + using Func = std::function(const ox::String&)>; ox::Vector fileTypes; Func make; }; @@ -27,4 +27,4 @@ class Module { }; -} \ No newline at end of file +} diff --git a/src/nostalgia/studio/lib/project.hpp b/src/nostalgia/studio/lib/project.hpp index faf3b90f..a3b6af3e 100644 --- a/src/nostalgia/studio/lib/project.hpp +++ b/src/nostalgia/studio/lib/project.hpp @@ -110,8 +110,8 @@ ox::Error Project::writeObj(const ox::String &path, auto *obj) const noexcept { // replace garbage last character with new line typeOut.back().value = '\n'; // write to FS - static constexpr auto descPath = "/.nostalgia/type_descriptors/"; - const auto typePath = ox::sfmt("{}{}", descPath, type->typeName); + static constexpr auto descPath = "/.nostalgia/type_descriptors"; + const auto typePath = ox::sfmt("{}/{}", descPath, type->typeName); oxReturnError(mkdir(descPath)); oxReturnError(writeBuff(typePath, typeOut)); fileUpdated.emit(path); @@ -136,7 +136,7 @@ ox::Error Project::subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&s case ProjectEvent::FileRecognized: { oxRequire(files, listFiles()); - for (auto f : files) { + for (const auto &f : files) { slot(f); } connect(this, &Project::fileRecognized, tgt, slot); diff --git a/src/nostalgia/studio/studioapp.cpp b/src/nostalgia/studio/studioapp.cpp index 61631b6e..64d6373d 100644 --- a/src/nostalgia/studio/studioapp.cpp +++ b/src/nostalgia/studio/studioapp.cpp @@ -182,7 +182,7 @@ void StudioUI::drawTabBar() noexcept { void StudioUI::drawTabs() noexcept { for (auto it = m_editors.begin(); it != m_editors.end();) { auto const &e = *it; - bool open = true; + auto open = true; if (ImGui::BeginTabItem(e->itemDisplayName().c_str(), &open)) { m_acitveEditor = e.get(); e->draw(m_ctx); @@ -289,14 +289,13 @@ ox::Error StudioUI::openFile(const ox::String &path) noexcept { if (!m_editorMakers.contains(ext)) { return OxError(1, "There is no editor for this file extension"); } - try { - auto editor = m_editorMakers[ext](path); - editor->closed.connect(this, &StudioUI::closeFile); - m_editors.emplace_back(editor); - } catch (const ox::Exception &ex) { - oxErrorf("Could not open Editor: {} ({}:{})", ex.msg, ex.file, ex.line); - return ex.toError(); + auto [editor, err] = m_editorMakers[ext](path); + if (err) { + oxErrorf("Could not open Editor: {} ({}:{})", err.msg, err.file, err.line); + return err; } + editor->closed.connect(this, &StudioUI::closeFile); + m_editors.emplace_back(editor); m_openFiles.emplace_back(path); // save to config studio::editConfig(m_ctx, [&](StudioConfig *config) {