[jasper/world] Simplify WorldEditor - remove ObjSet selector
All checks were successful
Build / build (push) Successful in 1m34s

This commit is contained in:
Gary Talent 2025-05-15 21:29:16 -05:00
parent b7aff140bf
commit dd266b23b2
2 changed files with 66 additions and 45 deletions

View File

@ -74,7 +74,7 @@ constexpr ox::Point fbPtToTileAddr(
}
WorldEditorImGui::WorldEditorImGui(studio::Context &sctx, ox::StringParam path):
Editor(sctx, std::move(path)),
Editor{sctx, std::move(path)},
m_sctx{sctx},
m_objSetPicker{"Object Set Chooser", keelCtx(m_sctx), FileExt_jwob},
m_doc{*keel::readObj<WorldDoc>(keelCtx(m_sctx), itemPath()).unwrapThrow()} {
@ -88,6 +88,7 @@ WorldEditorImGui::WorldEditorImGui(studio::Context &sctx, ox::StringParam path):
keelCtx(m_sctx), itemPath(), [this](WorldEditorConfig const&config) {
m_view.setAnimate(config.animateBg);
});
undoStack()->changeTriggered.connect(this, &WorldEditorImGui::handleUndoStackChange);
}
void WorldEditorImGui::draw(studio::Context&) noexcept {
@ -187,23 +188,57 @@ ox::Error WorldEditorImGui::saveItem() noexcept {
return m_sctx.project->writeObj(itemPath(), m_doc, ox::ClawFormat::Organic);
}
void WorldEditorImGui::drawObjSetSelector() noexcept {
ig::IDStackItem const idStackItem("ObjSetSelector");
void WorldEditorImGui::drawObjSelector() noexcept {
ig::IDStackItem const idStackItem("ObjSelector");
if (ig::PushButton("+", SqrBtnSize)) {
m_objSetPicker.open();
}
ImGui::SameLine();
ImGui::BeginDisabled(m_objMgr.selectedObjSet.len() == 0);
if (ig::PushButton("-", SqrBtnSize)) {
rmObjSet();
}
ig::ListBox("Object Sets", [this](size_t i) -> ox::CStringView {
auto const&uuidUrl = m_doc.objSets[i].path;
auto [setName, err] = uuidUrlToPath(keelCtx(m_sctx), uuidUrl);
if (err) {
setName = uuidUrl;
ImGui::EndDisabled();
ImGui::BeginChild("ObjTree");
{
for (auto const&[uuidUrl, setId, set] : m_objSets) {
auto flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
auto [setName, err] = uuidUrlToPath(keelCtx(m_sctx), uuidUrl);
auto const uuid = substr(uuidUrl, 7);
if (err) {
setName = uuidUrl;
}
if (uuid == m_objMgr.selectedObjSet) {
flags |= ImGuiTreeNodeFlags_Selected;
}
if (ImGui::TreeNodeEx(setName.c_str(), flags)) {
if (ImGui::IsItemClicked()) {
m_objMgr.selectedObjSet = uuid;
}
for (auto const&obj : set->objects) {
if (ImGui::TreeNodeEx(obj.name.c_str(), ImGuiTreeNodeFlags_Leaf)) {
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
studio::navigateTo(m_sctx, setName, obj.name);
}
ImGui::TreePop();
}
ig::dragDropSource([&] {
std::ignore = ig::setDragDropPayload("WorldTile", WorldTileDragDrop{
.setId = setId,
.objId = obj.id,
});
ImGui::Text("%s", obj.name.c_str());
});
}
ImGui::TreePop();
} else {
if (ImGui::IsItemClicked()) {
m_objMgr.selectedObjSet = uuid;
}
}
}
return setName;
}, m_doc.objSets.size(), m_palMgr.selectedIdx);
}
ImGui::EndChild();
if (ig::DragDropTarget const d; d) {
auto const [fr, err] = ig::getDragDropPayload<studio::FileRef>("FileRef");
if (!err && endsWith(fr.path, FileExt_jwob)) {
@ -212,35 +247,6 @@ void WorldEditorImGui::drawObjSetSelector() noexcept {
}
}
void WorldEditorImGui::drawObjSelector() noexcept {
ig::IDStackItem const idStackItem("ObjSelector");
for (auto const&[uuidUrl, setId, set] : m_objSets) {
constexpr auto flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
auto [setName, err] = uuidUrlToPath(keelCtx(m_sctx), uuidUrl);
if (err) {
setName = uuidUrl;
}
if (ImGui::TreeNodeEx(setName.c_str(), flags)) {
for (auto const&obj : set->objects) {
if (ImGui::TreeNodeEx(obj.name.c_str(), ImGuiTreeNodeFlags_Leaf)) {
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
studio::navigateTo(m_sctx, setName, obj.name);
}
ImGui::TreePop();
}
ig::dragDropSource([&] {
std::ignore = ig::setDragDropPayload("WorldTile", WorldTileDragDrop{
.setId = setId,
.objId = obj.id,
});
ImGui::Text("%s", obj.name.c_str());
});
}
ImGui::TreePop();
}
}
}
void WorldEditorImGui::drawPropEditor() noexcept {
if (m_sizeEditor.show) {
constexpr auto popupSz = ImVec2{285, 0};
@ -285,7 +291,6 @@ void WorldEditorImGui::drawMenu() noexcept {
void WorldEditorImGui::drawResources() noexcept {
ig::IDStackItem const idStackItem("Resources");
drawObjSetSelector();
drawObjSelector();
}
@ -399,7 +404,13 @@ ox::Error WorldEditorImGui::addObjSet(ox::StringViewCR path) noexcept {
}
void WorldEditorImGui::rmObjSet() noexcept {
std::ignore = pushCommand<RmObjectSet>(m_doc, m_palMgr.selectedIdx);
auto const idx = ox::find_if(
m_doc.objSets.begin(), m_doc.objSets.end(), [this](ObjectSetEntry const &e) {
return substr(e.path, 7) == m_objMgr.selectedObjSet;
});
if (idx != m_doc.objSets.end()) {
std::ignore = pushCommand<RmObjectSet>(m_doc, idx.offset());
}
}
ox::Error WorldEditorImGui::handleDepUpdate(ox::StringViewCR, ox::UUID const&uuid) noexcept {
@ -458,4 +469,14 @@ ox::Error WorldEditorImGui::addDependency(ox::FileAddress const&fileAddr) noexce
return {};
}
ox::Error WorldEditorImGui::handleUndoStackChange(studio::UndoCommand const*cmd) noexcept {
if (dynamic_cast<AddObjectSet const*>(cmd)) {
return loadObjectSets();
}
if (dynamic_cast<RmObjectSet const*>(cmd)) {
return loadObjectSets();
}
return {};
}
}

View File

@ -40,8 +40,8 @@ class WorldEditorImGui: public studio::Editor {
WorldStaticLoader m_loader{keelCtx(m_sctx), m_worldStatic, m_doc};
WorldEditorView m_view{m_sctx, m_worldStatic};
struct {
size_t selectedIdx{};
} m_palMgr;
ox::UUIDStr selectedObjSet;
} m_objMgr;
struct {
bool show{};
int columns{};
@ -67,8 +67,6 @@ class WorldEditorImGui: public studio::Editor {
ox::Error saveItem() noexcept final;
private:
void drawObjSetSelector() noexcept;
void drawObjSelector() noexcept;
void drawPropEditor() noexcept;
@ -101,6 +99,8 @@ class WorldEditorImGui: public studio::Editor {
ox::Error addDependency(ox::FileAddress const&fileAddr) noexcept;
ox::Error handleUndoStackChange(studio::UndoCommand const*) noexcept;
[[nodiscard]]
constexpr bool popupOpen() const noexcept {
return m_sizeEditor.show;