|
|
|
@@ -81,8 +81,8 @@ constexpr bool inside(auto const val, int const min, int const max) noexcept {
|
|
|
|
|
WorldEditorImGui::WorldEditorImGui(studio::StudioContext &sctx, ox::StringView path):
|
|
|
|
|
Editor(path),
|
|
|
|
|
m_sctx(sctx),
|
|
|
|
|
m_doc(makeValid(*readObj<WorldDoc>(keelCtx(m_sctx.tctx), path).unwrapThrow())),
|
|
|
|
|
m_objCache(buildObjCache(keelCtx(m_sctx.tctx), m_doc).unwrapThrow()),
|
|
|
|
|
m_doc(makeValid(*readObj<WorldDoc>(keelCtx(m_sctx), path).unwrapThrow())),
|
|
|
|
|
m_objCache(buildObjCache(keelCtx(m_sctx), m_doc).unwrapThrow()),
|
|
|
|
|
m_worldStatic(loadWorldStatic(m_objCache, m_doc)),
|
|
|
|
|
m_view(m_sctx.tctx, m_worldStatic) {
|
|
|
|
|
oxThrowError(loadObjectSets());
|
|
|
|
@@ -116,7 +116,8 @@ void WorldEditorImGui::onActivated() noexcept {
|
|
|
|
|
|
|
|
|
|
void WorldEditorImGui::copy() noexcept {
|
|
|
|
|
if (m_selection) {
|
|
|
|
|
auto mods = ox::make_unique<TileClipboard>(m_selection->size());
|
|
|
|
|
auto const assetId = this->assetId().unwrapThrow();
|
|
|
|
|
auto mods = ox::make_unique<TileClipboard>(assetId, m_selection->size());
|
|
|
|
|
studio::iterateSelection(*m_selection, [this, &mods](int32_t x, int32_t y) {
|
|
|
|
|
auto &t = tile(m_doc, m_activeLayer, x, y);
|
|
|
|
|
x -= m_selection->a.x;
|
|
|
|
@@ -177,6 +178,14 @@ void WorldEditorImGui::paste() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WorldEditorImGui::acceptsClipboardPayload() const noexcept {
|
|
|
|
|
auto const [cb, noCb] = getClipboardObject<TileClipboard>(m_sctx.tctx);
|
|
|
|
|
if (noCb) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return cb && cb->assetId() == assetId().or_value({});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ox::Error WorldEditorImGui::saveItem() noexcept {
|
|
|
|
|
return m_sctx.project->writeObj(itemPath(), m_doc, ox::ClawFormat::Organic);
|
|
|
|
|
}
|
|
|
|
@@ -192,7 +201,7 @@ void WorldEditorImGui::drawObjSetSelector() noexcept {
|
|
|
|
|
}
|
|
|
|
|
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.tctx), uuidUrl);
|
|
|
|
|
auto [setName, err] = uuidUrlToPath(keelCtx(m_sctx), uuidUrl);
|
|
|
|
|
if (err) {
|
|
|
|
|
setName = uuidUrl;
|
|
|
|
|
}
|
|
|
|
@@ -204,7 +213,7 @@ 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.tctx), uuidUrl);
|
|
|
|
|
auto [setName, err] = uuidUrlToPath(keelCtx(m_sctx), uuidUrl);
|
|
|
|
|
if (err) {
|
|
|
|
|
setName = uuidUrl;
|
|
|
|
|
}
|
|
|
|
@@ -370,7 +379,7 @@ ox::Error WorldEditorImGui::handleDrop(float fbPaneScale) noexcept {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ox::Error WorldEditorImGui::addObjSet(ox::StringView path) noexcept {
|
|
|
|
|
oxRequire(uuid, keel::pathToUuid(keelCtx(m_sctx.tctx), path));
|
|
|
|
|
oxRequire(uuid, getUuid(keelCtx(m_sctx), path));
|
|
|
|
|
std::ignore = pushCommand<AddObjectSet>(m_doc, uuid);
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
@@ -380,9 +389,9 @@ void WorldEditorImGui::rmObjSet() noexcept {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ox::Error WorldEditorImGui::handleDepUpdate(ox::StringView, ox::UUID const&uuid) noexcept {
|
|
|
|
|
auto &kctx = keelCtx(m_sctx.tctx);
|
|
|
|
|
auto &kctx = keelCtx(m_sctx);
|
|
|
|
|
auto const objSetMatches = [&uuid, &kctx](ObjectSetEntry const&set) {
|
|
|
|
|
auto const [setUuid, err] = keel::getUuid(kctx, set.path);
|
|
|
|
|
auto const [setUuid, err] = getUuid(kctx, set.path);
|
|
|
|
|
return !err && setUuid == uuid;
|
|
|
|
|
};
|
|
|
|
|
auto const depMatches = [&uuid](ox::SmallMap<ox::UUID, bool>::Pair const&set) {
|
|
|
|
@@ -391,7 +400,7 @@ ox::Error WorldEditorImGui::handleDepUpdate(ox::StringView, ox::UUID const&uuid)
|
|
|
|
|
auto const depUpdated = ox::any_of(m_doc.objSets.begin(), m_doc.objSets.end(), objSetMatches)
|
|
|
|
|
|| ox::any_of(m_dependencies.pairs().begin(), m_dependencies.pairs().end(), depMatches);
|
|
|
|
|
if (depUpdated) {
|
|
|
|
|
oxReturnError(buildObjCache(keelCtx(m_sctx.tctx), m_doc).moveTo(m_objCache));
|
|
|
|
|
oxReturnError(buildObjCache(keelCtx(m_sctx), m_doc).moveTo(m_objCache));
|
|
|
|
|
oxReturnError(loadWorldStatic(m_objCache, m_doc).moveTo(m_worldStatic));
|
|
|
|
|
oxReturnError(loadObjectSets());
|
|
|
|
|
}
|
|
|
|
@@ -401,7 +410,7 @@ ox::Error WorldEditorImGui::handleDepUpdate(ox::StringView, ox::UUID const&uuid)
|
|
|
|
|
ox::Error WorldEditorImGui::loadObjectSets() noexcept {
|
|
|
|
|
m_objSets.clear();
|
|
|
|
|
m_dependencies.clear();
|
|
|
|
|
auto &kctx = keelCtx(m_sctx.tctx);
|
|
|
|
|
auto &kctx = keelCtx(m_sctx);
|
|
|
|
|
for (auto const&set : m_doc.objSets) {
|
|
|
|
|
oxRequireM(os, readObj<WorldObjectSet>(kctx, set.path));
|
|
|
|
|
oxLogError(addDependency(os->tilesheet));
|
|
|
|
@@ -434,9 +443,13 @@ void WorldEditorImGui::clearSelection() noexcept {
|
|
|
|
|
m_view.clearSelection();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ox::Result<ox::UUID> WorldEditorImGui::assetId() const noexcept {
|
|
|
|
|
return getUuid(keelCtx(m_sctx), itemPath());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ox::Error WorldEditorImGui::addDependency(ox::FileAddress const&fileAddr) noexcept {
|
|
|
|
|
auto &kctx = keelCtx(m_sctx.tctx);
|
|
|
|
|
oxRequire(uuid, keel::getUuid(kctx, fileAddr));
|
|
|
|
|
auto &kctx = keelCtx(m_sctx);
|
|
|
|
|
oxRequire(uuid, getUuid(kctx, fileAddr));
|
|
|
|
|
m_dependencies[uuid] = true;
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|