[nostalgia/core/studio] Add SubSheet editor

This commit is contained in:
Gary Talent 2022-03-05 11:40:54 -06:00
parent 921cb97a14
commit 2f7c62f2ef
4 changed files with 107 additions and 1 deletions

View File

@ -16,6 +16,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);
undoStack()->changeTriggered.connect(this, &TileSheetEditorImGui::markUnsavedChanges);
m_subsheetEditor.inputSubmitted.connect(model(), &TileSheetEditorModel::updateActiveSubsheet);
}
ox::String TileSheetEditorImGui::itemName() const noexcept {
@ -61,7 +62,8 @@ void TileSheetEditorImGui::draw(core::Context*) noexcept {
ImGui::EndChild();
ImGui::BeginChild("child2", ImVec2(m_palViewWidth - 24, paneSize.y / 2.07f), true);
{
const auto btnSize = ImVec2(18, 18);
constexpr auto btnHeight = 18;
const auto btnSize = ImVec2(18, btnHeight);
if (ImGui::Button("+", btnSize)) {
auto insertOnIdx = model()->activeSubSheetIdx();
const auto &parent = *model()->activeSubSheet();
@ -76,6 +78,15 @@ void TileSheetEditorImGui::draw(core::Context*) noexcept {
model()->rmSubsheet(activeSubsheetIdx);
}
}
ImGui::SameLine();
if (ImGui::Button("Edit", ImVec2(36, btnHeight))) {
const auto sheet = model()->activeSubSheet();
if (sheet->subsheets.size()) {
m_subsheetEditor.show(sheet->name, -1, -1);
} else {
m_subsheetEditor.show(sheet->name, sheet->columns, sheet->rows);
}
}
TileSheet::SubSheetIdx path;
constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
if (ImGui::BeginTable("Subsheets", 3, flags)) {
@ -90,6 +101,8 @@ void TileSheetEditorImGui::draw(core::Context*) noexcept {
ImGui::EndChild();
}
ImGui::EndChild();
m_subsheetEditor.draw();
ImGui::ShowDemoWindow();
}
void TileSheetEditorImGui::drawSubsheetSelector(TileSheet::SubSheet *subsheet, TileSheet::SubSheetIdx *path) noexcept {
@ -105,6 +118,8 @@ void TileSheetEditorImGui::drawSubsheetSelector(TileSheet::SubSheet *subsheet, T
| (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
ImGui::TableNextColumn();
const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
Str newName = subsheet->name.c_str();
ImGui::SameLine();
if (ImGui::IsItemClicked()) {
model()->setActiveSubsheet(*path);
}
@ -223,4 +238,31 @@ ox::Error TileSheetEditorImGui::markUnsavedChanges(int) noexcept {
return OxError(0);
}
void TileSheetEditorImGui::SubSheetEditor::draw() noexcept {
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
constexpr auto popupName = "Edit SubSheet";
if (m_show) {
ImGui::OpenPopup(popupName);
ImGui::SetNextWindowSize(ImVec2(235, 125));
}
if (ImGui::BeginPopupModal(popupName, &m_show, modalFlags)) {
ImGui::InputText("Name", m_name.data(), m_name.cap());
if (m_cols != -1) {
ImGui::InputInt("Columns", &m_cols);
ImGui::InputInt("Rows", &m_rows);
}
if (ImGui::Button("OK")) {
ImGui::CloseCurrentPopup();
m_show = false;
inputSubmitted.emit(m_name.c_str(), m_cols, m_rows);
}
ImGui::SameLine();
if (ImGui::Button("Cancel")) {
ImGui::CloseCurrentPopup();
m_show = false;
}
ImGui::EndPopup();
}
}
}

View File

@ -21,6 +21,22 @@ namespace nostalgia::core {
class TileSheetEditorImGui: public studio::Editor {
private:
class SubSheetEditor {
ox::BString<100> m_name;
int m_cols = 0;
int m_rows = 0;
bool m_show;
public:
ox::Signal<ox::Error(const ox::String &name, int cols, int rows)> inputSubmitted;
constexpr void show(const ox::String &name, int cols, int rows) noexcept {
m_show = true;
m_name = name.c_str();
m_cols = cols;
m_rows = rows;
}
void draw() noexcept;
};
SubSheetEditor m_subsheetEditor;
ox::String m_itemPath;
ox::String m_itemName;
glutils::FrameBuffer m_framebuffer;

View File

@ -55,6 +55,11 @@ void TileSheetEditorModel::rmSubsheet(const TileSheet::SubSheetIdx &idx) noexcep
pushCommand(new RmSubSheetCommand(&m_img, idx));
}
ox::Error TileSheetEditorModel::updateActiveSubsheet(const ox::String &name, int cols, int rows) noexcept {
pushCommand(new UpdateSubSheetCommand(&m_img, m_activeSubsSheetIdx, name, cols, rows));
return OxError(0);
}
void TileSheetEditorModel::setActiveSubsheet(const TileSheet::SubSheetIdx &idx) noexcept {
m_activeSubsSheetIdx = idx;
this->activeSubsheetChanged.emit(m_activeSubsSheetIdx);

View File

@ -19,6 +19,7 @@ enum class CommandId {
Draw = 1,
AddSubSheet = 2,
RmSubSheet = 3,
UpdateSubSheet = 4,
};
constexpr bool operator==(CommandId c, int i) noexcept {
@ -180,6 +181,46 @@ struct RmSubSheetCommand: public studio::UndoCommand {
};
struct UpdateSubSheetCommand: public studio::UndoCommand {
private:
TileSheet *m_img = nullptr;
TileSheet::SubSheetIdx m_idx;
TileSheet::SubSheet m_sheet;
ox::String m_newName;
int m_newCols = 0;
int m_newRows = 0;
public:
constexpr UpdateSubSheetCommand(TileSheet *img, const TileSheet::SubSheetIdx &idx,
const ox::String &name, int cols, int rows) noexcept {
m_img = img;
m_idx = idx;
m_sheet = img->getSubSheet(idx);
m_newName = name;
m_newCols = cols;
m_newRows = rows;
}
void redo() noexcept final {
auto &sheet = m_img->getSubSheet(m_idx);
sheet.name = m_newName;
sheet.columns = m_newCols;
sheet.rows = m_newRows;
sheet.pixels.resize(static_cast<std::size_t>(m_newCols * m_newRows * PixelsPerTile));
}
void undo() noexcept final {
auto &sheet = m_img->getSubSheet(m_idx);
sheet = m_sheet;
}
[[nodiscard]]
int commandId() const noexcept final {
return static_cast<int>(CommandId::UpdateSubSheet);
}
};
struct TileSheetClipboard {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard";
static constexpr auto TypeVersion = 1;
@ -262,6 +303,8 @@ class TileSheetEditorModel: public ox::SignalHandler {
void rmSubsheet(const TileSheet::SubSheetIdx &idx) noexcept;
ox::Error updateActiveSubsheet(const ox::String &name, int cols, int rows) noexcept;
void setActiveSubsheet(const TileSheet::SubSheetIdx&) noexcept;
constexpr const TileSheet::SubSheet *activeSubSheet() const noexcept {