diff --git a/deps/nostalgia/release-notes.md b/deps/nostalgia/release-notes.md index 57449ad..7c31d92 100644 --- a/deps/nostalgia/release-notes.md +++ b/deps/nostalgia/release-notes.md @@ -4,6 +4,8 @@ * Add PaletteV5 to accommodate namespace change. * Add TileSheetV5. TileSheetV5 retains the bpp field for the sake of CompactTileSheet, but always store it pixel as 8 bpp for itself. +* Add ability to move subsheets in the subsheet tree. +* Add Flip X and Flip Y button for TileSheet Editor. * Replace file picker combo boxes with a browse button and file picker, and support for dragging files from the project explorer. * Add ability to create directories. diff --git a/deps/nostalgia/sample_project/Palettes/Dirt.npal b/deps/nostalgia/sample_project/Palettes/Dirt.npal index ffb649e..a53b907 100644 --- a/deps/nostalgia/sample_project/Palettes/Dirt.npal +++ b/deps/nostalgia/sample_project/Palettes/Dirt.npal @@ -1 +1,28 @@ -K1;0f75977f-1c52-45f8-9793-52ea2dc200a0;M2;net.drinkingtea.nostalgia.core.Palette;1;ûÿ³Ö +K1;0f75977f-1c52-45f8-9793-52ea2dc200a0;O1;net.drinkingtea.nostalgia.gfx.Palette;5;{ + "colorNames" : + [ + "Color 1", + "Color 2" + ], + "pages" : + [ + { + "colors" : + [ + { + "a" : 1, + "b" : 31, + "g" : 31, + "r" : 31 + }, + { + "a" : 1, + "b" : 22, + "g" : 22, + "r" : 22 + } + ], + "name" : "Page 1" + } + ] +} \ No newline at end of file diff --git a/deps/nostalgia/sample_project/Palettes/Logo.npal b/deps/nostalgia/sample_project/Palettes/Logo.npal index 6e2cb29..3e70d03 100644 --- a/deps/nostalgia/sample_project/Palettes/Logo.npal +++ b/deps/nostalgia/sample_project/Palettes/Logo.npal @@ -1 +1,36 @@ -K1;c79f21e2-f74f-4ad9-90ed-32b0ef7da6ed;M2;net.drinkingtea.nostalgia.core.Palette;1;PÛ{³ÖCˆ +K1;c79f21e2-f74f-4ad9-90ed-32b0ef7da6ed;O1;net.drinkingtea.nostalgia.gfx.Palette;5;{ + "colorNames" : + [ + "Color 1", + "Color 2", + "Color 3", + "Color 4" + ], + "pages" : + [ + { + "colors" : + [ + { + "b" : 5 + }, + { + "b" : 22, + "g" : 22, + "r" : 22 + }, + { + "b" : 27, + "g" : 27, + "r" : 27 + }, + { + "b" : 20, + "g" : 8, + "r" : 8 + } + ], + "name" : "Page 1" + } + ] +} \ No newline at end of file diff --git a/deps/nostalgia/sample_project/TileSheets/Logo.nts b/deps/nostalgia/sample_project/TileSheets/Logo.nts index 7c6be74..824bbd0 100644 Binary files a/deps/nostalgia/sample_project/TileSheets/Logo.nts and b/deps/nostalgia/sample_project/TileSheets/Logo.nts differ diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/include/nostalgia/gfx/tilesheet.hpp b/deps/nostalgia/src/nostalgia/modules/gfx/include/nostalgia/gfx/tilesheet.hpp index 3a67adc..3035511 100644 --- a/deps/nostalgia/src/nostalgia/modules/gfx/include/nostalgia/gfx/tilesheet.hpp +++ b/deps/nostalgia/src/nostalgia/modules/gfx/include/nostalgia/gfx/tilesheet.hpp @@ -289,7 +289,7 @@ constexpr ox::Error repair(TileSheetV4 &ts) noexcept { struct TileSheetV5 { - using SubSheetIdx = ox::Vector; + using SubSheetIdx = ox::Vector; struct SubSheet { static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.TileSheet.SubSheet"; @@ -445,23 +445,25 @@ TileSheet::SubSheetIdx validateSubSheetIdx(TileSheet const&ts, TileSheet::SubShe [[nodiscard]] TileSheet::SubSheet const&getSubSheet( - TileSheet::SubSheetIdx const&idx, + ox::SpanView const&idx, std::size_t idxIt, TileSheet::SubSheet const&pSubsheet) noexcept; [[nodiscard]] TileSheet::SubSheet &getSubSheet( - TileSheet::SubSheetIdx const&idx, + ox::SpanView const&idx, std::size_t idxIt, TileSheet::SubSheet &pSubsheet) noexcept; [[nodiscard]] -TileSheet::SubSheet const&getSubSheet(TileSheet const&ts, TileSheet::SubSheetIdx const&idx) noexcept; +TileSheet::SubSheet const&getSubSheet(TileSheet const&ts, ox::SpanView const &idx) noexcept; [[nodiscard]] -TileSheet::SubSheet &getSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept; +TileSheet::SubSheet &getSubSheet(TileSheet &ts, ox::SpanView const &idx) noexcept; -ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept; +ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const &idx) noexcept; + +ox::Error insertSubSheet(TileSheet &ts, ox::SpanView const &idx, TileSheet::SubSheet ss) noexcept; ox::Error rmSubSheet( TileSheet &ts, diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/CMakeLists.txt b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/CMakeLists.txt index df125ef..f8f42c8 100644 --- a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/CMakeLists.txt +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/CMakeLists.txt @@ -5,6 +5,7 @@ target_sources( deletetilescommand.cpp drawcommand.cpp flipcommand.cpp + movesubsheetcommand.cpp inserttilescommand.cpp palettechangecommand.cpp rmsubsheetcommand.cpp diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/commands.hpp b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/commands.hpp index 5d8302e..4cdebe6 100644 --- a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/commands.hpp +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/commands.hpp @@ -15,9 +15,10 @@ enum class CommandId { AddSubSheet, RmSubSheet, DeleteTile, - FlipXCommand, - FlipYCommand, + FlipX, + FlipY, InsertTile, + MoveSubSheet, UpdateSubSheet, Cut, Paste, diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/flipcommand.cpp b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/flipcommand.cpp index 6acc127..a3fd2ac 100644 --- a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/flipcommand.cpp +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/flipcommand.cpp @@ -31,7 +31,7 @@ ox::Error FlipXCommand::undo() noexcept { } int FlipXCommand::commandId() const noexcept { - return static_cast(CommandId::FlipXCommand); + return static_cast(CommandId::FlipX); } TileSheet::SubSheetIdx const &FlipXCommand::subsheetIdx() const noexcept { @@ -62,7 +62,7 @@ ox::Error FlipYCommand::undo() noexcept { } int FlipYCommand::commandId() const noexcept { - return static_cast(CommandId::FlipYCommand); + return static_cast(CommandId::FlipY); } TileSheet::SubSheetIdx const &FlipYCommand::subsheetIdx() const noexcept { diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/movesubsheetcommand.cpp b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/movesubsheetcommand.cpp new file mode 100644 index 0000000..d251d93 --- /dev/null +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/movesubsheetcommand.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include "movesubsheetcommand.hpp" + +namespace nostalgia::gfx { + +MoveSubSheetCommand::MoveSubSheetCommand( + TileSheet &img, + TileSheet::SubSheetIdx src, + TileSheet::SubSheetIdx dst) noexcept: + m_img{img}, + m_src{std::move(src)}, + m_dst{std::move(dst)} { +} + +ox::Error MoveSubSheetCommand::redo() noexcept { + m_active = &m_dst; + TileSheet::SubSheet ss = std::move(getSubSheet(m_img, m_src)); + OX_RETURN_ERROR(rmSubSheet(m_img, m_src)); + return insertSubSheet(m_img, m_dst, std::move(ss)); +} + +ox::Error MoveSubSheetCommand::undo() noexcept { + m_active = &m_src; + TileSheet::SubSheet ss = std::move(getSubSheet(m_img, m_dst)); + OX_RETURN_ERROR(rmSubSheet(m_img, m_dst)); + return insertSubSheet(m_img, m_src, std::move(ss)); +} + +int MoveSubSheetCommand::commandId() const noexcept { + return static_cast(CommandId::MoveSubSheet); +} + +TileSheet::SubSheetIdx const&MoveSubSheetCommand::subsheetIdx() const noexcept { + return *m_active; +} + +} diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/movesubsheetcommand.hpp b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/movesubsheetcommand.hpp new file mode 100644 index 0000000..06fc9dd --- /dev/null +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/movesubsheetcommand.hpp @@ -0,0 +1,33 @@ +/* + * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +#include "commands.hpp" + +namespace nostalgia::gfx { + +class MoveSubSheetCommand: public TileSheetCommand { + private: + TileSheet &m_img; + TileSheet::SubSheetIdx m_src; + TileSheet::SubSheetIdx m_dst; + TileSheet::SubSheetIdx *m_active = &m_dst; + + public: + MoveSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx src, TileSheet::SubSheetIdx dst) noexcept; + + ox::Error redo() noexcept final; + + ox::Error undo() noexcept final; + + [[nodiscard]] + int commandId() const noexcept final; + + [[nodiscard]] + TileSheet::SubSheetIdx const&subsheetIdx() const noexcept override; + +}; + +} diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp index c45a669..d9677cc 100644 --- a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp @@ -15,6 +15,16 @@ namespace nostalgia::gfx { namespace ig = studio::ig; +struct SubSheetRef { + static constexpr auto TypeName = "nostalgia.gfx.studio.SubSheetRef"; + static constexpr auto TypeVersion = 1; + TileSheet::SubSheetIdx subsheet{}; +}; + +OX_MODEL_BEGIN(SubSheetRef) + OX_MODEL_FIELD(subsheet) +OX_MODEL_END() + struct TileSheetEditorConfig { static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.studio.TileSheetEditorConfig"; static constexpr auto TypeVersion = 1; @@ -309,6 +319,16 @@ void TileSheetEditorImGui::drawSubsheetSelector( | (rowSelected ? ImGuiTreeNodeFlags_Selected : 0); ImGui::TableNextColumn(); auto const open = ImGui::TreeNodeEx(lbl.c_str(), flags); + std::ignore = ig::dragDropSource([&subsheet, &path] { + ImGui::Text("%s", subsheet.name.c_str()); + return ig::setDragDropPayload(SubSheetRef{path}); + }); + if (ig::DragDropTarget const dragDropTarget; dragDropTarget) { + auto const [ref, err] = ig::getDragDropPayload(); + if (!err) { + oxLogError(m_model.moveSubSheet(ref.subsheet, path)); + } + } ImGui::SameLine(); if (ImGui::IsItemClicked()) { setActiveSubsheet(path); @@ -330,7 +350,7 @@ void TileSheetEditorImGui::drawSubsheetSelector( ImGui::Text("--"); } if (open) { - for (auto i = 0ul; auto &child : subsheet.subsheets) { + for (uint32_t i{}; auto &child : subsheet.subsheets) { path.push_back(i); ImGui::PushID(static_cast(i)); ig::IndentStackItem const indentStackItem{-indentReduce}; diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp index ea42f57..d8e3cac 100644 --- a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp @@ -58,6 +58,7 @@ class TileSheetEditorImGui: public studio::Editor { ox::Vec2 m_prevMouseDownPos; TileSheetTool m_tool = TileSheetTool::Draw; bool m_palPathFocused{}; + ox::Vector, 1> m_deferredCmds; public: TileSheetEditorImGui(studio::StudioContext &sctx, ox::StringParam path); diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.cpp b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.cpp index 99ab1b7..788c5f3 100644 --- a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.cpp +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.cpp @@ -11,18 +11,19 @@ #include -#include "commands/commands.hpp" #include "commands/addsubsheetcommand.hpp" +#include "commands/commands.hpp" #include "commands/cutpastecommand.hpp" #include "commands/deletetilescommand.hpp" #include "commands/drawcommand.hpp" +#include "commands/flipcommand.hpp" #include "commands/inserttilescommand.hpp" #include "commands/palettechangecommand.hpp" #include "commands/rmsubsheetcommand.hpp" #include "commands/updatesubsheetcommand.hpp" #include "tilesheeteditormodel.hpp" -#include "commands/flipcommand.hpp" +#include "commands/movesubsheetcommand.hpp" namespace nostalgia::gfx { @@ -303,6 +304,10 @@ ox::Error TileSheetEditorModel::flipY() noexcept { return pushCommand(ox::make(m_img, m_activeSubsSheetIdx, a, b)); } +ox::Error TileSheetEditorModel::moveSubSheet(TileSheet::SubSheetIdx src, TileSheet::SubSheetIdx dst) noexcept { + return pushCommand(ox::make(m_img, std::move(src), std::move(dst))); +} + void TileSheetEditorModel::getFillPixels( TileSheet::SubSheet const&activeSubSheet, ox::Span pixels, diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.hpp b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.hpp index 9af2ec8..c6f930e 100644 --- a/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.hpp +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.hpp @@ -130,6 +130,8 @@ class TileSheetEditorModel: public ox::SignalHandler { ox::Error flipY() noexcept; + ox::Error moveSubSheet(TileSheet::SubSheetIdx src, TileSheet::SubSheetIdx dst) noexcept; + private: void getFillPixels( TileSheet::SubSheet const&activeSubSheet, diff --git a/deps/nostalgia/src/nostalgia/modules/gfx/src/tilesheet.cpp b/deps/nostalgia/src/nostalgia/modules/gfx/src/tilesheet.cpp index 078da34..fb4cc4e 100644 --- a/deps/nostalgia/src/nostalgia/modules/gfx/src/tilesheet.cpp +++ b/deps/nostalgia/src/nostalgia/modules/gfx/src/tilesheet.cpp @@ -177,7 +177,7 @@ TileSheet::SubSheetIdx validateSubSheetIdx( pIdx.resize(pIdxIt); return std::move(pIdx); } else { - currentIdx = pSubsheet.subsheets.size() - 1; + currentIdx = static_cast(pSubsheet.subsheets.size() - 1); } } return validateSubSheetIdx(std::move(pIdx), pIdxIt + 1, pSubsheet.subsheets[currentIdx]); @@ -188,9 +188,9 @@ TileSheet::SubSheetIdx validateSubSheetIdx(TileSheet const&ts, TileSheet::SubShe } TileSheet::SubSheet const&getSubSheet( - TileSheet::SubSheetIdx const&idx, + ox::SpanView const &idx, std::size_t const idxIt, - TileSheet::SubSheet const&pSubsheet) noexcept { + TileSheet::SubSheet const &pSubsheet) noexcept { if (idxIt == idx.size()) { return pSubsheet; } @@ -202,7 +202,7 @@ TileSheet::SubSheet const&getSubSheet( } TileSheet::SubSheet &getSubSheet( - TileSheet::SubSheetIdx const&idx, + ox::SpanView const &idx, std::size_t const idxIt, TileSheet::SubSheet &pSubsheet) noexcept { if (idxIt == idx.size()) { @@ -211,11 +211,11 @@ TileSheet::SubSheet &getSubSheet( return getSubSheet(idx, idxIt + 1, pSubsheet.subsheets[idx[idxIt]]); } -TileSheet::SubSheet const&getSubSheet(TileSheet const&ts, TileSheet::SubSheetIdx const&idx) noexcept { +TileSheet::SubSheet const&getSubSheet(TileSheet const &ts, ox::SpanView const &idx) noexcept { return gfx::getSubSheet(idx, 0, ts.subsheet); } -TileSheet::SubSheet &getSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept { +TileSheet::SubSheet &getSubSheet(TileSheet &ts, ox::SpanView const&idx) noexcept { return gfx::getSubSheet(idx, 0, ts.subsheet); } @@ -227,7 +227,20 @@ ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept parent.subsheets.emplace_back(++ts.idIt, "Subsheet 0", parent.columns, parent.rows); parent.subsheets.emplace_back(++ts.idIt, "Subsheet 1", 1, 1); } - return ox::Error(0); + return {}; +} + +ox::Error insertSubSheet(TileSheet &ts, ox::SpanView const&idx, TileSheet::SubSheet ss) noexcept { + if (idx.empty()) { + return ox::Error{1, "invalid insert idx"}; + } + auto &parent = getSubSheet(ts, {idx.data(), idx.size() - 1}); + auto const insertIdx = idx[idx.size() - 1]; + if (insertIdx > parent.subsheets.size()) { + return ox::Error{1, "invalid insert idx"}; + } + parent.subsheets.emplace(insertIdx, std::move(ss)); + return {}; } ox::Error rmSubSheet( diff --git a/deps/nostalgia/src/olympic/studio/applib/src/studioapp.cpp b/deps/nostalgia/src/olympic/studio/applib/src/studioapp.cpp index 64c6ba8..3b45c2d 100644 --- a/deps/nostalgia/src/olympic/studio/applib/src/studioapp.cpp +++ b/deps/nostalgia/src/olympic/studio/applib/src/studioapp.cpp @@ -349,10 +349,6 @@ void StudioUI::handleKeyInput() noexcept { m_activeEditorUpdatePending = m_activeEditor; } } - if (ImGui::IsKeyPressed(ImGuiKey_0)) { - m_activeEditor = m_editors[10 < m_editors.size() ? 10 : range].get(); - m_activeEditorUpdatePending = m_activeEditor; - } } } }