[jasper/world/studio/worldobjectseteditor] Add file drag/drop support

This commit is contained in:
Gary Talent 2025-01-19 14:32:41 -06:00
parent ac743834d3
commit 3df4e1662e
6 changed files with 72 additions and 44 deletions

View File

@ -7,19 +7,24 @@
#include "commands.hpp" #include "commands.hpp"
#include "addpalette.hpp" #include "addpalette.hpp"
#include <keel/media.hpp>
namespace jasper::world { namespace jasper::world {
AddPalette::AddPalette(WorldObjectSet &doc, ox::FileAddress palAddr) noexcept: AddPalette::AddPalette(WorldObjectSet &doc, ox::FileAddress palAddr, keel::Context &kctx) noexcept:
m_doc(doc), m_doc{doc},
m_palAddr(std::move(palAddr)) { m_palAddr{std::move(palAddr)},
m_kctx{kctx} {
} }
ox::Error AddPalette::redo() noexcept { ox::Error AddPalette::redo() noexcept {
m_doc.palettes.emplace_back(m_palAddr); m_doc.palettes.emplace_back(m_palAddr);
std::sort(m_doc.palettes.begin(), m_doc.palettes.end(), //std::sort(m_doc.palettes.begin(), m_doc.palettes.end(),
[](ox::FileAddress const&a, ox::FileAddress const&b) { // [this](ox::FileAddress const&a, ox::FileAddress const&b) {
return a.getPath().or_value("") < b.getPath().or_value(""); // auto const aPath = uuidUrlToPath(m_kctx, a.getPath().or_value("")).or_value("");
}); // auto const bPath = uuidUrlToPath(m_kctx, b.getPath().or_value("")).or_value("");
// return aPath < bPath;
// });
return {}; return {};
} }

View File

@ -16,8 +16,9 @@ class AddPalette: public studio::UndoCommand {
private: private:
WorldObjectSet &m_doc; WorldObjectSet &m_doc;
ox::FileAddress m_palAddr; ox::FileAddress m_palAddr;
keel::Context &m_kctx;
public: public:
AddPalette(WorldObjectSet &doc, ox::FileAddress palAddr) noexcept; AddPalette(WorldObjectSet &doc, ox::FileAddress palAddr, keel::Context &kctx) noexcept;
ox::Error redo() noexcept override; ox::Error redo() noexcept override;
ox::Error undo() noexcept override; ox::Error undo() noexcept override;
[[nodiscard]] [[nodiscard]]

View File

@ -5,36 +5,39 @@
#include "commands.hpp" #include "commands.hpp"
#include "changetilesheet.hpp" #include "changetilesheet.hpp"
#include <utility>
#include <keel/media.hpp>
namespace jasper::world { namespace jasper::world {
ChangeTileSheet::ChangeTileSheet( ChangeTileSheet::ChangeTileSheet(
keel::Context &kctx,
WorldObjectSet &doc, WorldObjectSet &doc,
ox::FileAddress newVal, ox::FileAddress newVal,
size_t newIdx, ox::String &path) noexcept:
size_t &selectedTilesheetIdx) noexcept: m_kctx{kctx},
m_doc(doc), m_doc(doc),
m_newVal(std::move(newVal)), m_valAlt(std::move(newVal)),
m_oldIdx(selectedTilesheetIdx), m_selectedTilesheet(path) {
m_newIdx(newIdx),
m_selectedTilesheetIdx(selectedTilesheetIdx) {
} }
ox::Error ChangeTileSheet::redo() noexcept { ox::Error ChangeTileSheet::redo() noexcept {
m_oldVal = std::move(m_doc.tilesheet); return swap();
m_doc.tilesheet = std::move(m_newVal);
m_selectedTilesheetIdx = m_newIdx;
return {};
} }
ox::Error ChangeTileSheet::undo() noexcept { ox::Error ChangeTileSheet::undo() noexcept {
m_newVal = std::move(m_doc.tilesheet); return swap();
m_doc.tilesheet = std::move(m_oldVal);
m_selectedTilesheetIdx = m_oldIdx;
return {};
} }
int ChangeTileSheet::commandId() const noexcept { int ChangeTileSheet::commandId() const noexcept {
return static_cast<int>(WorldObjCommand::ChangeTileSheet); return static_cast<int>(WorldObjCommand::ChangeTileSheet);
} }
ox::Error ChangeTileSheet::swap() noexcept {
std::swap(m_doc.tilesheet, m_valAlt);
OX_REQUIRE_M(path, m_doc.tilesheet.getPath());
m_selectedTilesheet = keel::uuidUrlToPath(m_kctx, path).or_value(path);
return {};
}
} }

View File

@ -14,22 +14,23 @@ namespace jasper::world {
class ChangeTileSheet: public studio::UndoCommand { class ChangeTileSheet: public studio::UndoCommand {
private: private:
keel::Context &m_kctx;
WorldObjectSet &m_doc; WorldObjectSet &m_doc;
ox::FileAddress m_newVal; ox::FileAddress m_valAlt;
ox::FileAddress m_oldVal; ox::String &m_selectedTilesheet;
size_t m_oldIdx{};
size_t m_newIdx{};
size_t &m_selectedTilesheetIdx;
public: public:
ChangeTileSheet( ChangeTileSheet(
keel::Context &kctx,
WorldObjectSet &doc, WorldObjectSet &doc,
ox::FileAddress newVal, ox::FileAddress newVal,
size_t newIdx, ox::String &path) noexcept;
size_t &selectedTilesheetIdx) noexcept;
ox::Error redo() noexcept override; ox::Error redo() noexcept override;
ox::Error undo() noexcept override; ox::Error undo() noexcept override;
[[nodiscard]] [[nodiscard]]
int commandId() const noexcept override; int commandId() const noexcept override;
private:
ox::Error swap() noexcept;
}; };
} }

View File

@ -29,11 +29,10 @@ WorldObjectSetEditorImGui::WorldObjectSetEditorImGui(
m_itemPath(itemPath()), m_itemPath(itemPath()),
m_doc(*readObj<WorldObjectSet>(keelCtx(m_sctx), itemPath()).unwrapThrow()), m_doc(*readObj<WorldObjectSet>(keelCtx(m_sctx), itemPath()).unwrapThrow()),
m_tileSheet(readObj<ncore::TileSheet>(keelCtx(m_sctx), m_doc.tilesheet).unwrapThrow()) { m_tileSheet(readObj<ncore::TileSheet>(keelCtx(m_sctx), m_doc.tilesheet).unwrapThrow()) {
auto const&tilesheetList = m_sctx.project->fileList(ncore::FileExt_ng);
auto &kctx = keelCtx(m_sctx); auto &kctx = keelCtx(m_sctx);
auto const [tsPath, err] = getPath(kctx, m_doc.tilesheet); auto const [tsPath, err] = getPath(kctx, m_doc.tilesheet);
if (!err) { if (!err) {
m_selectedTilesheetIdx = std::find(tilesheetList.begin(), tilesheetList.end(), tsPath).offset(); m_tilesheetPath = tsPath;
} }
loadObj(); loadObj();
undoStack()->changeTriggered.connect(this, &WorldObjectSetEditorImGui::handleCmd); undoStack()->changeTriggered.connect(this, &WorldObjectSetEditorImGui::handleCmd);
@ -91,16 +90,12 @@ void WorldObjectSetEditorImGui::buildPaletteDisplayNameList() noexcept {
} }
void WorldObjectSetEditorImGui::drawTileSheetSelector() noexcept { void WorldObjectSetEditorImGui::drawTileSheetSelector() noexcept {
auto const&tilesheetList = m_sctx.project->fileList(ncore::FileExt_ng); auto constexpr tsFlags = ImGuiInputTextFlags_ReadOnly;
auto sel = m_selectedTilesheetIdx; ig::InputText("Tile Sheet", m_tilesheetPath, tsFlags);
if (ig::ComboBox("Tile Sheet", tilesheetList, sel)) { if (ig::DragDropTarget const d; d) {
auto const [uuid, err] = keel::pathToUuid( auto const [fr, err] = ig::getDragDropPayload<studio::FileRef>("FileRef");
keelCtx(m_sctx.tctx), tilesheetList[sel]);
if (!err) { if (!err) {
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString()); std::ignore = setTileSheet(fr.path);
std::ignore = pushCommand<ChangeTileSheet>
(m_doc, ox::FileAddress(uuidUrl), sel, m_selectedTilesheetIdx);
loadObj();
} }
} }
} }
@ -287,6 +282,17 @@ void WorldObjectSetEditorImGui::drawPaletteList() noexcept {
drawPaletteListItems(); drawPaletteListItems();
ImGui::EndTable(); ImGui::EndTable();
} }
if (ig::DragDropTarget const d; d) {
auto const [fr, err] = ig::getDragDropPayload<studio::FileRef>("FileRef");
if (!err) {
auto const [uuid, err] = keel::pathToUuid(
keelCtx(m_sctx), fr.path);
if (!err) {
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString());
std::ignore = pushCommand<AddPalette>(m_doc, ox::FileAddress{uuidUrl}, keelCtx(m_sctx));
}
}
}
} }
void WorldObjectSetEditorImGui::drawPaletteListItems() noexcept { void WorldObjectSetEditorImGui::drawPaletteListItems() noexcept {
@ -320,7 +326,7 @@ void WorldObjectSetEditorImGui::drawAddPalettePopup() noexcept {
keelCtx(m_sctx.tctx), palettes[m_addPalPopup.selectedIdx]); keelCtx(m_sctx.tctx), palettes[m_addPalPopup.selectedIdx]);
if (!err) { if (!err) {
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString()); auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString());
std::ignore = pushCommand<AddPalette>(m_doc, ox::FileAddress(uuidUrl)); std::ignore = pushCommand<AddPalette>(m_doc, ox::FileAddress{uuidUrl}, keelCtx(m_sctx));
} }
} }
ImGui::EndPopup(); ImGui::EndPopup();
@ -336,6 +342,16 @@ void WorldObjectSetEditorImGui::rmPalette() noexcept {
std::ignore = pushCommand<RmPalette>(m_doc, m_selectedPal); std::ignore = pushCommand<RmPalette>(m_doc, m_selectedPal);
} }
ox::Error WorldObjectSetEditorImGui::setTileSheet(ox::StringViewCR path) noexcept {
auto const [uuid, err] = keel::pathToUuid(
keelCtx(m_sctx), path);
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString());
std::ignore = pushCommand<ChangeTileSheet>
(keelCtx(m_sctx), m_doc, ox::FileAddress{uuidUrl}, m_tilesheetPath);
loadObj();
return {};
}
ox::Error WorldObjectSetEditorImGui::handleCmd(studio::UndoCommand const*cmd) noexcept { ox::Error WorldObjectSetEditorImGui::handleCmd(studio::UndoCommand const*cmd) noexcept {
if (dynamic_cast<ChangeTileSheet const*>(cmd)) { if (dynamic_cast<ChangeTileSheet const*>(cmd)) {
auto &kctx = keelCtx(m_sctx.tctx); auto &kctx = keelCtx(m_sctx.tctx);

View File

@ -23,7 +23,7 @@ class WorldObjectSetEditorImGui: public studio::Editor {
ox::Vector<ox::String> m_paletteDisplayNames; ox::Vector<ox::String> m_paletteDisplayNames;
size_t m_selectedObj{}; size_t m_selectedObj{};
size_t m_selectedPal{}; size_t m_selectedPal{};
size_t m_selectedTilesheetIdx{}; ox::String m_tilesheetPath{};
struct { struct {
bool show{}; bool show{};
size_t selectedIdx{}; size_t selectedIdx{};
@ -70,6 +70,8 @@ class WorldObjectSetEditorImGui: public studio::Editor {
void rmPalette() noexcept; void rmPalette() noexcept;
ox::Error setTileSheet(ox::StringViewCR path) noexcept;
ox::Error handleCmd(studio::UndoCommand const*cmd) noexcept; ox::Error handleCmd(studio::UndoCommand const*cmd) noexcept;
ox::Error saveItem() noexcept final; ox::Error saveItem() noexcept final;