[jasper/world]/studio] Make World refer to obj sets with UUIDs
Some checks failed
Build / build (push) Failing after 30s

This commit is contained in:
Gary Talent 2024-05-22 00:37:03 -05:00
parent 8e9274a84b
commit 299a91fd66
8 changed files with 63 additions and 32 deletions

View File

@ -110,13 +110,17 @@ void loadTile(ObjectCache const&objCache, TileStatic &dst, TileDoc const&src) no
ox::Result<WorldStatic> loadWorldStatic(ObjectCache const&objCache, WorldDoc const&doc) noexcept;
[[nodiscard]]
auto &tile(ox::CommonRefWith<WorldStatic> auto &ws, size_t lyr, ox::Integer_c auto col, ox::Integer_c auto row) noexcept {
auto &tile(
ox::CommonRefWith<WorldStatic> auto&ws,
size_t lyr,
ox::Integer_c auto col,
ox::Integer_c auto row) noexcept {
auto const idx = static_cast<size_t>(row) * static_cast<size_t>(ws.columns) + static_cast<size_t>(col);
return ws.map[lyr].tiles[idx];
}
[[nodiscard]]
auto &cbb(ox::CommonRefWith<WorldStatic> auto &ws, size_t lyr) noexcept {
auto &cbb(ox::CommonRefWith<WorldStatic> auto&ws, size_t lyr) noexcept {
return ws.map[lyr].cbb;
}

View File

@ -11,7 +11,7 @@
namespace jasper::world {
class StudioModule: public studio::Module {
static class: public studio::Module {
public:
ox::Vector<studio::EditorMaker> editors(studio::StudioContext &ctx) const noexcept override {
return {
@ -21,13 +21,14 @@ class StudioModule: public studio::Module {
}
ox::Vector<ox::UPtr<studio::ItemMaker>> itemMakers(studio::StudioContext&) const noexcept override {
ox::Vector<ox::UPtr<studio::ItemMaker>> out;
out.emplace_back(ox::make<studio::ItemMakerT<WorldObjectSet>>("World Object Set", "WorldObjectSets", FileExt_jwob, ox::ClawFormat::Organic));
out.emplace_back(ox::make<studio::ItemMakerT<WorldDoc>>("World", "Worlds", FileExt_jwld, ox::ClawFormat::Organic));
out.emplace_back(ox::make<studio::ItemMakerT<WorldObjectSet>>(
"World Object Set", "WorldObjectSets", FileExt_jwob, ox::ClawFormat::Organic));
out.emplace_back(ox::make<studio::ItemMakerT<WorldDoc>>(
"World", "Worlds", FileExt_jwld, ox::ClawFormat::Organic));
return out;
}
};
} mod;
static StudioModule const mod;
studio::Module const*studioModule() noexcept {
return &mod;
}

View File

@ -7,14 +7,14 @@
namespace jasper::world {
AddObjectSet::AddObjectSet(WorldDoc &doc, ox::StringView objSetPath):
AddObjectSet::AddObjectSet(WorldDoc &doc, ox::UUID const&objSetUuid):
m_doc(doc),
m_path(ox::String(objSetPath)) {
m_path(ox::sfmt("uuid://{}", objSetUuid.toString())) {
for (auto const&o : m_doc.objSets) {
if (o.path > objSetPath) {
if (o.path > m_path) {
break;
} else if (o.path == objSetPath) {
throw ox::Exception(OxError(1, "Path already exists in doc"));
} else if (o.path == m_path) {
throw OxException(1, "Path already exists in doc");
}
++m_insertIdx;
}

View File

@ -18,7 +18,7 @@ class AddObjectSet: public studio::UndoCommand {
size_t m_insertIdx{};
ox::String m_path;
public:
AddObjectSet(WorldDoc &doc, ox::StringView objSetPath);
AddObjectSet(WorldDoc &doc, ox::UUID const&objSetUuid);
void redo() noexcept override;
void undo() noexcept override;
[[nodiscard]]

View File

@ -7,7 +7,8 @@
namespace jasper::world {
ModifyTilesCommand::ModifyTilesCommand(WorldDoc &doc,
ModifyTilesCommand::ModifyTilesCommand(
WorldDoc &doc,
WorldStatic &worldStatic,
ObjectCache &objCache,
ox::Vector<Mod> mods):
@ -15,6 +16,17 @@ ModifyTilesCommand::ModifyTilesCommand(WorldDoc &doc,
m_worldStatic(worldStatic),
m_objCache(objCache),
m_mods(std::move(mods)) {
bool noChanges = true;
for (auto const&mod : m_mods) {
auto const&docTile = tile(m_doc, mod.layer, mod.tileAddr.x, mod.tileAddr.y);
if (docTile.obj.worldObjectId != mod.objId || docTile.obj.worldObjectSetId != mod.setId) {
noChanges = false;
break;
}
}
if (noChanges) {
throw studio::NoChangesException();
}
}
void ModifyTilesCommand::redo() noexcept {

View File

@ -47,6 +47,14 @@ static WorldDoc makeValid(WorldDoc doc) noexcept {
}
[[nodiscard]]
static ox::Vec2 dropPos(ox::Vec2 dropPos) noexcept {
auto const winPos = ImGui::GetWindowPos();
dropPos.x -= winPos.x;
dropPos.y -= winPos.y;
return dropPos;
}
[[nodiscard]]
constexpr ox::Point fbPtToTileAddr(
ox::Vec2 const&fbPt,
ox::Vec2 const&mapSz) noexcept {
@ -98,7 +106,7 @@ void WorldEditorImGui::onActivated() noexcept {
}
ox::Error WorldEditorImGui::saveItem() noexcept {
return m_sctx.project->writeObj(itemPath(), m_doc, ox::ClawFormat::Organic);
return m_sctx.project->writeObj(itemPath(), m_doc, ox::ClawFormat::Metal);
}
void WorldEditorImGui::drawObjSetSelector() noexcept {
@ -111,14 +119,23 @@ void WorldEditorImGui::drawObjSetSelector() noexcept {
rmObjSet();
}
ig::ListBox("Object Sets", [this](size_t i) -> ox::CStringView {
return m_doc.objSets[i].path;
auto const&uuidUrl = m_doc.objSets[i].path;
auto [setName, err] = uuidUrlToPath(keelCtx(m_sctx.tctx), uuidUrl);
if (err) {
setName = uuidUrl;
}
return setName;
}, m_doc.objSets.size(), m_palMgr.selectedIdx);
}
void WorldEditorImGui::drawObjSelector() noexcept {
ig::IDStackItem const idStackItem("ObjSelector");
for (auto const&[setName, setId, set] : m_objSets) {
for (auto const&[uuidUrl, setId, set] : m_objSets) {
constexpr auto flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
auto [setName, err] = uuidUrlToPath(keelCtx(m_sctx.tctx), 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)) {
@ -155,14 +172,6 @@ void WorldEditorImGui::drawResources() noexcept {
drawObjSelector();
}
[[nodiscard]]
static ox::Vec2 dropPos(ox::Vec2 dropPos) noexcept {
auto const winPos = ImGui::GetWindowPos();
dropPos.x -= winPos.x;
dropPos.y -= winPos.y;
return dropPos;
}
void WorldEditorImGui::drawWorldView() noexcept {
ig::IDStackItem const idStackItem("WorldView");
auto const paneSize = ImGui::GetContentRegionAvail();
@ -221,7 +230,8 @@ void WorldEditorImGui::drawWorldView() noexcept {
}
ox::Error WorldEditorImGui::addObjSet(ox::StringView path) noexcept {
pushCommand<AddObjectSet>(m_doc, path);
oxRequire(uuid, keel::pathToUuid(keelCtx(m_sctx.tctx), path));
pushCommand<AddObjectSet>(m_doc, uuid);
return {};
}
@ -247,7 +257,7 @@ ox::Error WorldEditorImGui::loadObjectSets() noexcept {
return {};
}
ox::Error WorldEditorImGui::undoStackChanged(const studio::UndoCommand *) {
ox::Error WorldEditorImGui::undoStackChanged(studio::UndoCommand const*) {
oxReturnError(m_view.setupWorld());
return {};
}

View File

@ -19,6 +19,10 @@ namespace jasper::world {
class WorldEditorImGui: public studio::Editor {
private:
struct Selection {
ox::Point begin, end;
};
ox::Optional<Selection> m_selection;
uint8_t m_activeLayer{};
studio::StudioContext &m_sctx;
studio::ig::FilePicker m_objSetPicker{

View File

@ -8,8 +8,6 @@
namespace jasper::world {
namespace ncore = nostalgia::core;
World::World(WorldStatic const&worldStatic) noexcept:
m_worldStatic(worldStatic) {
}
@ -37,9 +35,11 @@ void World::setupLayer(
uint_t cbb) const noexcept {
ncore::setBgStatus(ctx, lyr, true);
ncore::setBgCbb(ctx, lyr, cbb);
for (auto y = 0; y < m_worldStatic.rows; ++y) {
for (auto x = 0; x < m_worldStatic.columns; ++x) {
auto &t = tile(m_worldStatic, lyr, static_cast<size_t>(x), static_cast<size_t>(y));
auto const rows = ox::min<int>(m_worldStatic.rows, ncore::tileRows(ctx) / 2);
auto const columns = ox::min<int>(m_worldStatic.columns, ncore::tileColumns(ctx) / 2);
for (auto y = 0; y < rows; ++y) {
for (auto x = 0; x < columns; ++x) {
auto &t = tile(m_worldStatic, lyr, x, y);
auto const tx = x * 2;
auto const ty = y * 2;
ncore::setBgTile(ctx, lyr, tx + 0, ty + 0, {