From 08236fc790e711afe886b6ef545511d35e4e5c6c Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 24 May 2025 01:44:07 -0500 Subject: [PATCH] Squashed 'deps/nostalgia/' changes from 312097a7..8419b137 8419b137 [turbine,studio] Fix some popup window resize weirdness, cleanup some function names ed1160ec [nostalgia] Update release notes 1e217780 [nostalgia/gfx/studio/tilesheet] Ensure config file has a Claw header 78379f58 [studio] Add ability to remember recent projects in config 4322f720 [keel] Fix ox::Result convert(Context &ctx, ox::BufferView const&src) 26f1a605 [ox/std] Make Vector::remove take a MaybeView_t c4c1d477 [keel] Cleanup ox::Error(0) instance fab012d3 [ox] Cleanup all ox::Error(0) instances git-subtree-dir: deps/nostalgia git-subtree-split: 8419b137e5dec1dabc15a0d34c7ce729970c3b7f --- deps/ox/src/ox/claw/write.hpp | 2 +- deps/ox/src/ox/event/signal.hpp | 4 +- .../src/ox/fs/filestore/filestoretemplate.hpp | 26 +-- deps/ox/src/ox/fs/filesystem/filesystem.hpp | 8 +- .../ox/src/ox/fs/filesystem/passthroughfs.cpp | 6 +- .../ox/src/ox/fs/filesystem/passthroughfs.hpp | 2 +- deps/ox/src/ox/fs/filesystem/pathiterator.cpp | 6 +- deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp | 6 +- deps/ox/src/ox/fs/tool.cpp | 4 +- deps/ox/src/ox/mc/read.hpp | 16 +- deps/ox/src/ox/mc/write.hpp | 14 +- deps/ox/src/ox/model/def.hpp | 2 +- deps/ox/src/ox/model/desctypes.hpp | 2 +- deps/ox/src/ox/model/descwrite.hpp | 6 +- deps/ox/src/ox/model/fieldcounter.hpp | 8 +- deps/ox/src/ox/model/modelops.hpp | 24 +-- deps/ox/src/ox/model/modelvalue.cpp | 2 +- deps/ox/src/ox/model/modelvalue.hpp | 10 +- deps/ox/src/ox/model/typenamecatcher.hpp | 12 +- deps/ox/src/ox/model/walk.hpp | 4 +- deps/ox/src/ox/oc/read.cpp | 8 +- deps/ox/src/ox/oc/read.hpp | 12 +- deps/ox/src/ox/oc/write.cpp | 2 +- deps/ox/src/ox/oc/write.hpp | 24 +-- deps/ox/src/ox/std/string.hpp | 2 +- deps/ox/src/ox/std/vector.hpp | 6 +- release-notes.md | 1 + .../tilesheeteditor/tilesheeteditor-imgui.cpp | 45 ++--- .../tilesheeteditor/tilesheeteditor-imgui.hpp | 6 +- .../keel/include/keel/assetmanager.hpp | 2 +- src/olympic/keel/include/keel/typeconv.hpp | 2 +- src/olympic/studio/applib/src/app.cpp | 8 +- .../studio/applib/src/deleteconfirmation.cpp | 5 + src/olympic/studio/applib/src/studioui.cpp | 174 +++++++++++++++--- src/olympic/studio/applib/src/studioui.hpp | 16 +- .../studio/modlib/include/studio/configio.hpp | 72 +++++--- src/olympic/studio/modlib/src/imguiutil.cpp | 3 + src/olympic/turbine/include/turbine/gfx.hpp | 15 +- src/olympic/turbine/src/glfw/turbine.cpp | 23 ++- 39 files changed, 388 insertions(+), 202 deletions(-) diff --git a/deps/ox/src/ox/claw/write.hpp b/deps/ox/src/ox/claw/write.hpp index d80c706..8a62a1d 100644 --- a/deps/ox/src/ox/claw/write.hpp +++ b/deps/ox/src/ox/claw/write.hpp @@ -39,7 +39,7 @@ struct TypeInfoCatcher { } constexpr Error field(...) noexcept { - return ox::Error(0); + return {}; } static constexpr auto opType() { diff --git a/deps/ox/src/ox/event/signal.hpp b/deps/ox/src/ox/event/signal.hpp index ac46e98..eb09f00 100644 --- a/deps/ox/src/ox/event/signal.hpp +++ b/deps/ox/src/ox/event/signal.hpp @@ -218,7 +218,7 @@ Error Signal::emitCheckError(Args... args) const noexcept { for (auto &f : m_slots) { f->call(args...); } - return ox::Error(0); + return {}; } catch (const ox::Exception &ex) { return ox::Error(ex.errCode, ex.msg, ex.src); } @@ -410,7 +410,7 @@ Error Signal::emitCheckError(Args... args) const noexcept { for (auto &f : m_slots) { OX_RETURN_ERROR(f->call(ox::forward(args)...)); } - return ox::Error(0); + return {}; } } diff --git a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp index dd75728..56e7337 100644 --- a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp +++ b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp @@ -230,7 +230,7 @@ template Error FileStoreTemplate::incLinks(uint64_t id) { OX_REQUIRE_M(item, find(static_cast(id)).validate()); ++item->links; - return ox::Error(0); + return {}; } template @@ -240,7 +240,7 @@ Error FileStoreTemplate::decLinks(uint64_t id) { if (item->links == 0) { OX_RETURN_ERROR(remove(item)); } - return ox::Error(0); + return {}; } template @@ -298,7 +298,7 @@ Error FileStoreTemplate::write(uint64_t id64, const void *data, FsSize_t dest->id.get(), dest.offset(), destData.size()); fsData->rootNode = dest.offset(); oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get()); - return ox::Error(0); + return {}; } } else { oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header."); @@ -427,7 +427,7 @@ Error FileStoreTemplate::resize() { oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize); OX_RETURN_ERROR(m_buffer->setSize(newSize)); oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size()); - return ox::Error(0); + return {}; } template @@ -479,7 +479,7 @@ Error FileStoreTemplate::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) { for (auto i = m_buffer->iterator(); i.valid(); i.next()) { OX_RETURN_ERROR(cb(i->fileType, i.ptr().offset(), i.ptr().end())); } - return ox::Error(0); + return {}; } template @@ -503,7 +503,7 @@ Error FileStoreTemplate::compact() { return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error { if (isFirstItem) { isFirstItem = false; - return ox::Error(0); + return {}; } if (!item.valid()) { return ox::Error(1); @@ -524,7 +524,7 @@ Error FileStoreTemplate::compact() { parent->right = item; } } - return ox::Error(0); + return {}; }); } @@ -552,7 +552,7 @@ Error FileStoreTemplate::placeItem(ItemPtr item) { item->left = root->left; item->right = root->right; oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get()); - return ox::Error(0); + return {}; } else { return placeItem(root, item); } @@ -573,7 +573,7 @@ Error FileStoreTemplate::placeItem(ItemPtr root, ItemPtr item, int depth item->right = right->right; } oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); - return ox::Error(0); + return {}; } else { return placeItem(right, item, depth + 1); } @@ -586,7 +586,7 @@ Error FileStoreTemplate::placeItem(ItemPtr root, ItemPtr item, int depth item->right = left->right; } oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); - return ox::Error(0); + return {}; } else { return placeItem(left, item, depth + 1); } @@ -624,7 +624,7 @@ Error FileStoreTemplate::unplaceItem(ItemPtr item) { } else { fsData->rootNode = 0; } - return ox::Error(0); + return {}; } else { return unplaceItem(root, item); } @@ -661,7 +661,7 @@ Error FileStoreTemplate::unplaceItem(ItemPtr root, ItemPtr item, int dep if (item->left) { OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->left))); } - return ox::Error(0); + return {}; } template @@ -669,7 +669,7 @@ Error FileStoreTemplate::remove(ItemPtr item) { if (item.valid()) { OX_RETURN_ERROR(unplaceItem(item)); OX_RETURN_ERROR(m_buffer->free(item)); - return ox::Error(0); + return {}; } return ox::Error(1); } diff --git a/deps/ox/src/ox/fs/filesystem/filesystem.hpp b/deps/ox/src/ox/fs/filesystem/filesystem.hpp index fa37811..47fc0bb 100644 --- a/deps/ox/src/ox/fs/filesystem/filesystem.hpp +++ b/deps/ox/src/ox/fs/filesystem/filesystem.hpp @@ -329,7 +329,7 @@ Error FileSystemTemplate::format(void *buff, uint64_t buff return ox::Error(1); } - return ox::Error(0); + return {}; } template @@ -346,7 +346,7 @@ Error FileSystemTemplate::move(StringViewCR src, StringVie OX_REQUIRE_M(inode, rootDir.find(src)); OX_RETURN_ERROR(rootDir.write(dest, inode)); OX_RETURN_ERROR(rootDir.remove(src)); - return ox::Error(0); + return {}; } template @@ -407,7 +407,7 @@ Error FileSystemTemplate::removePath(StringViewCR path, bo oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting."); return ox::Error(1); } - return ox::Error(0); + return {}; } template @@ -424,7 +424,7 @@ Result> FileSystemTemplate::ls(StringViewCR Vector out; OX_RETURN_ERROR(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) { out.emplace_back(name); - return ox::Error(0); + return ox::Error{}; })); return out; } diff --git a/deps/ox/src/ox/fs/filesystem/passthroughfs.cpp b/deps/ox/src/ox/fs/filesystem/passthroughfs.cpp index d6f3cf9..f1f8d07 100644 --- a/deps/ox/src/ox/fs/filesystem/passthroughfs.cpp +++ b/deps/ox/src/ox/fs/filesystem/passthroughfs.cpp @@ -60,7 +60,7 @@ Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept { if (ec.value()) { return ox::Error(1); } - return ox::Error(0); + return {}; } Result> PassThroughFS::ls(StringViewCR dir) const noexcept { @@ -148,7 +148,7 @@ Error PassThroughFS::readFilePath(StringViewCR path, void *buffer, std::size_t b oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what()); return ox::Error(2); } - return ox::Error(0); + return {}; } Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept { @@ -197,7 +197,7 @@ Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64 oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what()); return ox::Error(1); } - return ox::Error(0); + return {}; } Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept { diff --git a/deps/ox/src/ox/fs/filesystem/passthroughfs.hpp b/deps/ox/src/ox/fs/filesystem/passthroughfs.hpp index 4d9f255..199bcc5 100644 --- a/deps/ox/src/ox/fs/filesystem/passthroughfs.hpp +++ b/deps/ox/src/ox/fs/filesystem/passthroughfs.hpp @@ -99,7 +99,7 @@ Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept { for (auto &p : di) { OX_RETURN_ERROR(cb(p.path().filename().c_str(), 0)); } - return ox::Error(0); + return {}; } } diff --git a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp index 07c5dec..bd42383 100644 --- a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp +++ b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp @@ -36,7 +36,7 @@ Error PathIterator::dirPath(char *out, std::size_t outSize) { if (idx >= 0 && size < outSize) { ox::memcpy(out, m_path, size); out[size] = 0; - return ox::Error(0); + return {}; } else { return ox::Error(1); } @@ -85,7 +85,7 @@ Error PathIterator::next(StringView &fileName) { std::size_t size = 0; auto retval = ox::Error(1); if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) { - retval = ox::Error(0); + retval = {}; if (m_path[m_iterator] == '/') { m_iterator++; } @@ -118,7 +118,7 @@ Result PathIterator::nextSize() const { auto retval = ox::Error(1); auto it = m_iterator; if (it < m_maxSize && ox::strlen(&m_path[it])) { - retval = ox::Error(0); + retval = {}; if (m_path[it] == '/') { it++; } diff --git a/deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp b/deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp index 7171a8a..ac105e9 100644 --- a/deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp +++ b/deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp @@ -354,7 +354,7 @@ Error NodeBuffer::free(ItemPtr item) noexcept { } } m_header.bytesUsed -= item.size(); - return ox::Error(0); + return {}; } template @@ -370,7 +370,7 @@ Error NodeBuffer::setSize(std::size_t size) noexcept { m_header.size = static_cast(size); auto data = reinterpret_cast(this) + end; ox::memset(data, 0, size - end); - return ox::Error(0); + return {}; } } @@ -422,7 +422,7 @@ Error NodeBuffer::compact(F cb) noexcept { src = ptr(dest->next); dest = uninitializedPtr(dest.offset() + dest->fullSize()); } - return ox::Error(0); + return {}; } template diff --git a/deps/ox/src/ox/fs/tool.cpp b/deps/ox/src/ox/fs/tool.cpp index 8299296..af66735 100644 --- a/deps/ox/src/ox/fs/tool.cpp +++ b/deps/ox/src/ox/fs/tool.cpp @@ -48,7 +48,7 @@ static ox::Error runLs(ox::FileSystem *fs, ox::Span args) noexcept for (const auto &file : files) { oxOutf("{}\n", file); } - return ox::Error(0); + return {}; } static ox::Error runRead(ox::FileSystem *fs, ox::Span args) noexcept { @@ -60,7 +60,7 @@ static ox::Error runRead(ox::FileSystem *fs, ox::Span args) noexcep OX_ALLOW_UNSAFE_BUFFERS_BEGIN std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout); OX_ALLOW_UNSAFE_BUFFERS_END - return ox::Error(0); + return {}; } static ox::Error run(int argc, const char **argv) noexcept { diff --git a/deps/ox/src/ox/mc/read.hpp b/deps/ox/src/ox/mc/read.hpp index 282ce44..bbdfb6d 100644 --- a/deps/ox/src/ox/mc/read.hpp +++ b/deps/ox/src/ox/mc/read.hpp @@ -197,7 +197,7 @@ constexpr Error MetalClawReaderTemplate::field(const char*, bool *val) n OX_RETURN_ERROR(result); } ++m_field; - return ox::Error(0); + return {}; } // array handler @@ -256,7 +256,7 @@ constexpr Error MetalClawReaderTemplate::field(const char*, HashMap @@ -330,7 +330,7 @@ constexpr Error MetalClawReaderTemplate::field(const char*, BasicString< } } ++m_field; - return ox::Error(0); + return {}; } template @@ -370,7 +370,7 @@ constexpr Error MetalClawReaderTemplate::fieldCString(const char*, char data[size] = 0; } ++m_field; - return ox::Error(0); + return {}; } template @@ -388,7 +388,7 @@ constexpr Error MetalClawReaderTemplate::fieldCString(const char*, char data[size] = 0; } ++m_field; - return ox::Error(0); + return {}; } template @@ -416,7 +416,7 @@ constexpr Error MetalClawReaderTemplate::fieldCString(const char*, char } } ++m_field; - return ox::Error(0); + return {}; } template @@ -464,7 +464,7 @@ constexpr Error MetalClawReaderTemplate::readInteger(I *val) noexcept { } } ++m_field; - return ox::Error(0); + return {}; } template @@ -487,7 +487,7 @@ constexpr Error MetalClawReaderTemplate::field(const char*, CB cb) noexc } } ++m_field; - return ox::Error(0); + return {}; } template diff --git a/deps/ox/src/ox/mc/write.hpp b/deps/ox/src/ox/mc/write.hpp index abcb4c7..dfab98c 100644 --- a/deps/ox/src/ox/mc/write.hpp +++ b/deps/ox/src/ox/mc/write.hpp @@ -122,7 +122,7 @@ class MetalClawWriter { } OX_RETURN_ERROR(m_fieldPresence.set(static_cast(m_field), fieldSet)); ++m_field; - return ox::Error(0); + return {}; } }; @@ -184,7 +184,7 @@ constexpr Error MetalClawWriter::field(const char*, const bool *val) noe OX_RETURN_ERROR(m_fieldPresence.set(static_cast(m_field), *val)); } ++m_field; - return ox::Error(0); + return {}; } template @@ -201,7 +201,7 @@ constexpr Error MetalClawWriter::field(const char*, const BasicString(m_field), fieldSet)); ++m_field; - return ox::Error(0); + return {}; } template @@ -229,7 +229,7 @@ constexpr Error MetalClawWriter::fieldCString(const char*, const char *c } OX_RETURN_ERROR(m_fieldPresence.set(static_cast(m_field), fieldSet)); ++m_field; - return ox::Error(0); + return {}; } template @@ -255,7 +255,7 @@ constexpr Error MetalClawWriter::fieldCString(const char*, const char *v } OX_RETURN_ERROR(m_fieldPresence.set(static_cast(m_field), fieldSet)); ++m_field; - return ox::Error(0); + return {}; } template @@ -319,7 +319,7 @@ OX_ALLOW_UNSAFE_BUFFERS_END } OX_RETURN_ERROR(m_fieldPresence.set(static_cast(m_field), fieldSet)); ++m_field; - return ox::Error(0); + return {}; } template @@ -356,7 +356,7 @@ constexpr Error MetalClawWriter::field(const char*, const HashMap(m_field), fieldSet)); ++m_field; - return ox::Error(0); + return {}; } template diff --git a/deps/ox/src/ox/model/def.hpp b/deps/ox/src/ox/model/def.hpp index 4546f3c..dcf2a12 100644 --- a/deps/ox/src/ox/model/def.hpp +++ b/deps/ox/src/ox/model/def.hpp @@ -13,7 +13,7 @@ // oxModelFwdDecl is necessary because Apple-Clang is broken... #define OX_MODEL_FWD_DECL(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith auto *o) noexcept #define OX_MODEL_BEGIN(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith auto *o) noexcept { OX_RETURN_ERROR(io->template setTypeInfo()); -#define OX_MODEL_END() return ox::Error(0); } +#define OX_MODEL_END() return {}; } #define OX_MODEL_FIELD(fieldName) OX_RETURN_ERROR(io->field(#fieldName, &o->fieldName)); #define OX_MODEL_FIELD_RENAME(objFieldName, serFieldName) OX_RETURN_ERROR(io->field(#serFieldName, &o->objFieldName)); #define OX_MODEL_FRIEND(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith auto *o) noexcept diff --git a/deps/ox/src/ox/model/desctypes.hpp b/deps/ox/src/ox/model/desctypes.hpp index 843c22f..4bbb736 100644 --- a/deps/ox/src/ox/model/desctypes.hpp +++ b/deps/ox/src/ox/model/desctypes.hpp @@ -244,7 +244,7 @@ constexpr Error model(TypeDescReader *io, CommonPtrWith auto // defaultValue is unused now, but placeholder for backwards compatibility int defaultValue = 0; oxReturnError(io->field("defaultValue", &defaultValue)); - return ox::Error(0); + return {}; } #endif diff --git a/deps/ox/src/ox/model/descwrite.hpp b/deps/ox/src/ox/model/descwrite.hpp index 4270871..c07d494 100644 --- a/deps/ox/src/ox/model/descwrite.hpp +++ b/deps/ox/src/ox/model/descwrite.hpp @@ -205,7 +205,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t, const auto t = type(p); oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated"); m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v + 1, subscriptStack, buildTypeId(*t)); - return ox::Error(0); + return {}; } return ox::Error(1); } @@ -220,7 +220,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t) auto const lvls = detail::indirectionLevels_v + 1; SubscriptStack subscriptStack{lvls}; m_type->fieldList.emplace_back(t, String(name), lvls, subscriptStack, buildTypeId(*t)); - return ox::Error(0); + return {}; } return ox::Error(1); } @@ -231,7 +231,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, UnionView val const auto t = type(val); oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated"); m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName)); - return ox::Error(0); + return {}; } return ox::Error(1); } diff --git a/deps/ox/src/ox/model/fieldcounter.hpp b/deps/ox/src/ox/model/fieldcounter.hpp index 206b6fc..8b51d7d 100644 --- a/deps/ox/src/ox/model/fieldcounter.hpp +++ b/deps/ox/src/ox/model/fieldcounter.hpp @@ -31,25 +31,25 @@ class FieldCounter { template constexpr ox::Error field(StringViewCR, U) noexcept { ++fields; - return ox::Error(0); + return {}; } template constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept { ++fields; - return ox::Error(0); + return {}; } template constexpr Error field(StringViewCR, Handler) { ++fields; - return ox::Error(0); + return {}; } template constexpr Error fieldCString(Args&&...) noexcept { ++fields; - return ox::Error(0); + return {}; } static constexpr auto opType() noexcept { diff --git a/deps/ox/src/ox/model/modelops.hpp b/deps/ox/src/ox/model/modelops.hpp index 4f98356..bf562e9 100644 --- a/deps/ox/src/ox/model/modelops.hpp +++ b/deps/ox/src/ox/model/modelops.hpp @@ -56,19 +56,19 @@ class MemberList { template constexpr Error field(const char*, T *v) noexcept { vars[m_i++] = static_cast(v); - return ox::Error(0); + return {}; } template constexpr Error field(const char*, T *v, int) noexcept { vars[m_i++] = static_cast(v); - return ox::Error(0); + return {}; } template constexpr Error field(const char*, UnionView u) noexcept { vars[m_i++] = static_cast(u.get()); - return ox::Error(0); + return {}; } template @@ -107,7 +107,7 @@ class Copier { auto &dst = *cbit_cast(m_dst->vars[m_i]); dst = src; ++m_i; - return ox::Error(0); + return {}; } } @@ -119,7 +119,7 @@ class Copier { dst = src; } ++m_i; - return ox::Error(0); + return {}; } template @@ -128,7 +128,7 @@ class Copier { auto &src = *u.get(); dst = src; ++m_i; - return ox::Error(0); + return {}; } template @@ -168,7 +168,7 @@ class Mover { dst = std::move(src); src = FT{}; ++m_i; - return ox::Error(0); + return {}; } } @@ -181,7 +181,7 @@ class Mover { src = FT{}; } ++m_i; - return ox::Error(0); + return {}; } template @@ -190,7 +190,7 @@ class Mover { auto &src = *u.get(); dst = std::move(src); ++m_i; - return ox::Error(0); + return {}; } template @@ -228,7 +228,7 @@ class Equals { const auto &dst = std::bit_cast(*m_other->vars[m_i]); ++m_i; if (dst == src) { - return ox::Error(0); + return {}; } else { this->value = false; return ox::Error(1); @@ -246,7 +246,7 @@ class Equals { } } ++m_i; - return ox::Error(0); + return {}; } template @@ -255,7 +255,7 @@ class Equals { const auto &src = *u.get(); ++m_i; if (dst == src) { - return ox::Error(0); + return {}; } else { this->value = false; return ox::Error(1); diff --git a/deps/ox/src/ox/model/modelvalue.cpp b/deps/ox/src/ox/model/modelvalue.cpp index 93744fb..f735717 100644 --- a/deps/ox/src/ox/model/modelvalue.cpp +++ b/deps/ox/src/ox/model/modelvalue.cpp @@ -18,6 +18,6 @@ static_assert([]() -> ox::Error { } //oxReturnError(v.set(5)); return {}; -}() == ox::Error(0)); +}() == ox::Error{}); } diff --git a/deps/ox/src/ox/model/modelvalue.hpp b/deps/ox/src/ox/model/modelvalue.hpp index 030f648..28585c9 100644 --- a/deps/ox/src/ox/model/modelvalue.hpp +++ b/deps/ox/src/ox/model/modelvalue.hpp @@ -972,7 +972,7 @@ constexpr Error model(auto *h, CommonPtrWith auto *obj) noexcept { for (auto &f : obj->m_fieldsOrder) { OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value)); } - return ox::Error(0); + return {}; } constexpr Error model(auto *h, CommonPtrWith auto *obj) noexcept { @@ -981,7 +981,7 @@ constexpr Error model(auto *h, CommonPtrWith auto *obj) noexcept { for (auto &f : obj->m_fieldsOrder) { OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value)); } - return ox::Error(0); + return {}; } constexpr ModelValue::ModelValue(const ModelValue &other) noexcept { @@ -1129,7 +1129,7 @@ constexpr Error ModelValue::setType( OX_RETURN_ERROR(m_data.uni->setType(type)); } oxAssert(m_type != Type::Undefined, "No type set"); - return ox::Error(0); + return {}; } template @@ -1184,7 +1184,7 @@ constexpr Error ModelValue::set(const T &v) noexcept { safeDelete(&value); } value = v; - return ox::Error(0); + return {}; } template @@ -1199,7 +1199,7 @@ constexpr Error ModelValue::set(T &&v) noexcept { safeDelete(&value); } value = std::move(v); - return ox::Error(0); + return {}; } constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept { diff --git a/deps/ox/src/ox/model/typenamecatcher.hpp b/deps/ox/src/ox/model/typenamecatcher.hpp index 6d907c8..418a2e0 100644 --- a/deps/ox/src/ox/model/typenamecatcher.hpp +++ b/deps/ox/src/ox/model/typenamecatcher.hpp @@ -38,17 +38,17 @@ struct TypeNameCatcher { template constexpr Error field(const char*, T*, std::size_t) noexcept { - return ox::Error(0); + return {}; } template constexpr Error field(const char*, T) noexcept { - return ox::Error(0); + return {}; } template constexpr Error fieldCString(Args&&...) noexcept { - return ox::Error(0); + return {}; } static constexpr auto opType() noexcept { @@ -77,17 +77,17 @@ struct TypeInfoCatcher { template constexpr Error field(const char*, T*, std::size_t) noexcept { - return ox::Error(0); + return {}; } template constexpr Error field(const char*, T) noexcept { - return ox::Error(0); + return {}; } template constexpr Error fieldCString(const char*, T) noexcept { - return ox::Error(0); + return {}; } static constexpr auto opType() noexcept { diff --git a/deps/ox/src/ox/model/walk.hpp b/deps/ox/src/ox/model/walk.hpp index e92fdab..e43cc2b 100644 --- a/deps/ox/src/ox/model/walk.hpp +++ b/deps/ox/src/ox/model/walk.hpp @@ -127,7 +127,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat } } walker->popNamePath(); - return ox::Error(0); + return {}; } template @@ -141,7 +141,7 @@ constexpr Error model(Reader *rdr, DataWalker *walker) noexcept { for (const auto &field : fields) { OX_RETURN_ERROR(parseField(field, rdr, walker)); } - return ox::Error(0); + return {}; } template diff --git a/deps/ox/src/ox/oc/read.cpp b/deps/ox/src/ox/oc/read.cpp index a3a71e2..38eb1a7 100644 --- a/deps/ox/src/ox/oc/read.cpp +++ b/deps/ox/src/ox/oc/read.cpp @@ -37,7 +37,7 @@ OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept: } Error OrganicClawReader::field(const char *key, bool *val) noexcept { - auto err = ox::Error(0); + ox::Error err{}; if (targetValid()) { const auto &jv = value(key); if (jv.empty()) { @@ -53,7 +53,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept { } Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept { - auto err = ox::Error(0); + ox::Error err{}; const char *begin = nullptr, *end = nullptr; const auto &jv = value(key); if (targetValid()) { @@ -81,7 +81,7 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu } Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept { - auto err = ox::Error(0); + ox::Error err{}; const char *begin = nullptr, *end = nullptr; const auto &jv = value(key); auto &data = *val; @@ -106,7 +106,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept { } Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept { - auto err = ox::Error(0); + ox::Error err{}; const char *begin = nullptr, *end = nullptr; const auto &jv = value(key); if (targetValid()) { diff --git a/deps/ox/src/ox/oc/read.hpp b/deps/ox/src/ox/oc/read.hpp index bf449cd..60593ac 100644 --- a/deps/ox/src/ox/oc/read.hpp +++ b/deps/ox/src/ox/oc/read.hpp @@ -137,7 +137,7 @@ class OrganicClawReader { template Error OrganicClawReader::field(const char *key, T *val) noexcept { - auto err = ox::Error(0); + ox::Error err{}; try { if constexpr (is_integer_v) { if (targetValid()) { @@ -190,7 +190,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept { template Error OrganicClawReader::field(const char *key, UnionView val) noexcept { - auto err = ox::Error(0); + ox::Error err{}; if (targetValid()) { const auto &jv = value(key); if (jv.empty() || jv.isObject()) { @@ -207,7 +207,7 @@ Error OrganicClawReader::field(const char *key, UnionView val) noexcep template Error OrganicClawReader::field(const char *key, BasicString *val) noexcept { - auto err = ox::Error(0); + ox::Error err{}; if (targetValid()) { const auto &jv = value(key); if (jv.empty()) { @@ -224,7 +224,7 @@ Error OrganicClawReader::field(const char *key, BasicString *val) noexcept { template Error OrganicClawReader::field(const char *key, IString *val) noexcept { - auto err = ox::Error(0); + ox::Error err{}; if (targetValid()) { const auto &jv = value(key); if (jv.empty()) { @@ -257,7 +257,7 @@ OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_RETURN_ERROR(handler.field("", &val[i])); OX_ALLOW_UNSAFE_BUFFERS_END } - return ox::Error(0); + return {}; } template @@ -274,7 +274,7 @@ Error OrganicClawReader::field(const char *key, HashMap *val) noexcep const auto k = keys[i].c_str(); OX_RETURN_ERROR(handler.field(k, &val->operator[](k))); } - return ox::Error(0); + return {}; } Error readOC(BufferView buff, auto &val) noexcept { diff --git a/deps/ox/src/ox/oc/write.cpp b/deps/ox/src/ox/oc/write.cpp index 31770ac..392cbf4 100644 --- a/deps/ox/src/ox/oc/write.cpp +++ b/deps/ox/src/ox/oc/write.cpp @@ -23,7 +23,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in value(key) = *val; } ++m_fieldIt; - return ox::Error(0); + return {}; } Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept { diff --git a/deps/ox/src/ox/oc/write.hpp b/deps/ox/src/ox/oc/write.hpp index 37cbc6d..f7358c1 100644 --- a/deps/ox/src/ox/oc/write.hpp +++ b/deps/ox/src/ox/oc/write.hpp @@ -46,7 +46,7 @@ class OrganicClawWriter { value(key) = *val; } ++m_fieldIt; - return ox::Error(0); + return {}; } Error field(const char *key, const int16_t *val) noexcept { @@ -54,7 +54,7 @@ class OrganicClawWriter { value(key) = *val; } ++m_fieldIt; - return ox::Error(0); + return {}; } Error field(const char *key, const int32_t *val) noexcept { @@ -62,7 +62,7 @@ class OrganicClawWriter { value(key) = *val; } ++m_fieldIt; - return ox::Error(0); + return {}; } Error field(const char *key, const int64_t *val) noexcept { @@ -70,7 +70,7 @@ class OrganicClawWriter { value(key) = *val; } ++m_fieldIt; - return ox::Error(0); + return {}; } @@ -79,7 +79,7 @@ class OrganicClawWriter { value(key) = *val; } ++m_fieldIt; - return ox::Error(0); + return {}; } Error field(const char *key, const uint16_t *val) noexcept { @@ -87,7 +87,7 @@ class OrganicClawWriter { value(key) = *val; } ++m_fieldIt; - return ox::Error(0); + return {}; } Error field(const char *key, const uint32_t *val) noexcept { @@ -95,7 +95,7 @@ class OrganicClawWriter { value(key) = *val; } ++m_fieldIt; - return ox::Error(0); + return {}; } Error field(const char *key, const uint64_t *val) noexcept { @@ -103,7 +103,7 @@ class OrganicClawWriter { value(key) = *val; } ++m_fieldIt; - return ox::Error(0); + return {}; } Error field(char const*key, bool const*val) noexcept { @@ -151,7 +151,7 @@ class OrganicClawWriter { value(key) = val->c_str(); } ++m_fieldIt; - return ox::Error(0); + return {}; } Error fieldCString(const char*, const char *const*val, int len) noexcept; @@ -211,7 +211,7 @@ OX_ALLOW_UNSAFE_BUFFERS_END value(key) = w.m_json; } ++m_fieldIt; - return ox::Error(0); + return {}; } template @@ -237,7 +237,7 @@ Error OrganicClawWriter::field(const char *key, const T *val) noexcept { } } ++m_fieldIt; - return ox::Error(0); + return {}; } template @@ -251,7 +251,7 @@ Error OrganicClawWriter::field(const char *key, UnionView val) noexcep } } ++m_fieldIt; - return ox::Error(0); + return {}; } Result writeOC(const auto &val) noexcept { diff --git a/deps/ox/src/ox/std/string.hpp b/deps/ox/src/ox/std/string.hpp index 1dcb284..615e621 100644 --- a/deps/ox/src/ox/std/string.hpp +++ b/deps/ox/src/ox/std/string.hpp @@ -182,7 +182,7 @@ class BasicString { // make sure last element is a null terminator m_buff[currentLen + strLen] = 0; // this can't fail, but it returns an Error to match BString::append - return ox::Error(0); + return {}; } constexpr Error append(ox::StringView sv) noexcept { diff --git a/deps/ox/src/ox/std/vector.hpp b/deps/ox/src/ox/std/vector.hpp index a8868bd..faab065 100644 --- a/deps/ox/src/ox/std/vector.hpp +++ b/deps/ox/src/ox/std/vector.hpp @@ -311,7 +311,7 @@ class Vector: detail::VectorAllocator { */ constexpr Error unordered_erase(std::size_t pos) noexcept(useNoexcept); - constexpr Error remove(T const &val); + constexpr Error remove(MaybeView_t const &val); constexpr void reserve(std::size_t cap) noexcept(useNoexcept); @@ -658,11 +658,11 @@ constexpr Error Vector::unordered_erase(std::size --m_size; m_items[pos] = std::move(m_items[m_size]); m_items[m_size].~T(); - return ox::Error(0); + return {}; } template -constexpr ox::Error Vector::remove(T const &val) { +constexpr ox::Error Vector::remove(MaybeView_t const &val) { for (size_t i{}; auto const &v : *this) { if (v == val) { return erase(i).error; diff --git a/release-notes.md b/release-notes.md index 06d6a9c..5b72b78 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,5 +1,6 @@ # d2025.06.0 +* Add ability to remember recent projects in config * PaletteEditor: Add RGB key shortcuts for focusing color channels # d2025.05.1 diff --git a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp index bd1c00f..fff75c9 100644 --- a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp +++ b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp @@ -36,7 +36,7 @@ OX_MODEL_BEGIN(TileSheetEditorConfig) OX_MODEL_END() static ox::Vector normalizePixelSizes( - ox::Vector const&inPixels) noexcept { + ox::Vector const &inPixels) noexcept { ox::Vector outPixels; outPixels.reserve(inPixels.size()); outPixels.resize(inPixels.size()); @@ -47,7 +47,7 @@ static ox::Vector normalizePixelSizes( } static ox::Vector normalizePixelArrangement( - ox::Vector const&inPixels, + ox::Vector const &inPixels, int const cols, int const scale) { auto const scalePt = ox::Point{scale, scale}; @@ -67,10 +67,10 @@ static ox::Vector normalizePixelArrangement( } static ox::Error toPngFile( - ox::CStringView const&path, + ox::CStringViewCR path, ox::Vector &&pixels, - Palette const&pal, - size_t page, + Palette const &pal, + size_t const page, unsigned const width, unsigned const height) noexcept { for (auto &c : pixels) { @@ -88,7 +88,7 @@ static ox::Error toPngFile( } TileSheetEditorImGui::TileSheetEditorImGui(studio::Context &sctx, ox::StringParam path): - Editor(sctx, std::move(path)), + Editor{sctx, std::move(path)}, m_sctx{sctx}, m_tctx{m_sctx.tctx}, m_palPicker{"Palette Chooser", keelCtx(sctx), FileExt_npal}, @@ -98,8 +98,11 @@ TileSheetEditorImGui::TileSheetEditorImGui(studio::Context &sctx, ox::StringPara m_subsheetEditor.inputSubmitted.connect(this, &TileSheetEditorImGui::updateActiveSubsheet); m_exportMenu.inputSubmitted.connect(this, &TileSheetEditorImGui::exportSubsheetToPng); // load config - auto const&config = studio::readConfig( - keelCtx(m_sctx), itemPath()); + auto &kctx = keelCtx(m_sctx); + auto const ip = itemPath(); + oxLogError(studio::headerizeConfigFile(kctx, ip)); + auto const &config = + studio::readConfig(kctx, ip); if (config.ok()) { m_model.setActiveSubsheet(validateSubSheetIdx(m_model.img(), config.value.activeSubsheet)); } @@ -192,7 +195,7 @@ void TileSheetEditorImGui::draw(studio::Context&) noexcept { if (ig::mainWinHasFocus() && m_tool == TileSheetTool::Select) { if (ImGui::IsKeyDown(ImGuiKey_ModCtrl) && !m_palPathFocused) { if (ImGui::IsKeyPressed(ImGuiKey_A)) { - auto const&img = m_model.activeSubSheet(); + auto const &img = m_model.activeSubSheet(); m_model.setSelection({{}, {img.columns * TileWidth - 1, img.rows * TileHeight - 1}}); } else if (ImGui::IsKeyPressed(ImGuiKey_G)) { m_model.clearSelection(); @@ -271,14 +274,14 @@ void TileSheetEditorImGui::draw(studio::Context&) noexcept { auto constexpr btnSize = ImVec2{btnHeight, btnHeight}; if (ig::PushButton("+", btnSize)) { auto insertOnIdx = m_model.activeSubSheetIdx(); - auto const&parent = m_model.activeSubSheet(); + auto const &parent = m_model.activeSubSheet(); m_model.addSubsheet(insertOnIdx); insertOnIdx.emplace_back(parent.subsheets.size() - 1); setActiveSubsheet(insertOnIdx); } ImGui::SameLine(); if (ig::PushButton("-", btnSize)) { - auto const&activeSubsheetIdx = m_model.activeSubSheetIdx(); + auto const &activeSubsheetIdx = m_model.activeSubSheetIdx(); if (!activeSubsheetIdx.empty()) { m_model.rmSubsheet(activeSubsheetIdx); } @@ -378,7 +381,7 @@ void TileSheetEditorImGui::drawSubsheetSelector( } [[nodiscard]] -ox::Vec2 TileSheetEditorImGui::clickPos(ImVec2 const&winPos, ox::Vec2 clickPos) noexcept { +ox::Vec2 TileSheetEditorImGui::clickPos(ImVec2 const &winPos, ox::Vec2 clickPos) noexcept { clickPos.x -= winPos.x + 10; clickPos.y -= winPos.y + 10; return clickPos; @@ -400,7 +403,7 @@ void TileSheetEditorImGui::navigateTo(ox::StringViewCR arg) noexcept { } void TileSheetEditorImGui::showSubsheetEditor() noexcept { - auto const&sheet = m_model.activeSubSheet(); + auto const &sheet = m_model.activeSubSheet(); if (!sheet.subsheets.empty()) { m_subsheetEditor.show(sheet.name, -1, -1); } else { @@ -411,8 +414,8 @@ void TileSheetEditorImGui::showSubsheetEditor() noexcept { ox::Error TileSheetEditorImGui::exportSubsheetToPng(int const scale) const noexcept { OX_REQUIRE(path, studio::saveFile({{"PNG", "png"}})); // subsheet to png - auto const&s = m_model.activeSubSheet(); - auto const&pal = m_model.pal(); + auto const &s = m_model.activeSubSheet(); + auto const &pal = m_model.pal(); auto const width = s.columns * TileWidth; auto const height = s.rows * TileHeight; auto pixels = normalizePixelSizes(s.pixels); @@ -430,7 +433,7 @@ ox::Error TileSheetEditorImGui::exportSubsheetToPng(int const scale) const noexc return err; } -void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept { +void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const &fbSize) noexcept { auto const winPos = ImGui::GetWindowPos(); auto const fbSizei = ox::Size{static_cast(fbSize.x), static_cast(fbSize.y)}; if (m_framebuffer.width != fbSizei.width || m_framebuffer.height != fbSizei.height) { @@ -451,7 +454,7 @@ void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept { {0, 1}, {1, 0}); // handle input, this must come after drawing - auto const&io = ImGui::GetIO(); + auto const &io = ImGui::GetIO(); auto const mousePos = ox::Vec2{ImGui::GetMousePos()}; if (ImGui::IsItemHovered()) { auto const wheel = io.MouseWheel; @@ -556,9 +559,9 @@ void TileSheetEditorImGui::drawPaletteMenu() noexcept { ImGui::TableSetupColumn("Color16", 0, 3); ImGui::TableHeadersRow(); { - auto const&pal = m_model.pal(); + auto const &pal = m_model.pal(); if (pal.pages.size() > m_model.palettePage()) { - for (auto i = 0u; auto const&c: pal.pages[m_model.palettePage()].colors) { + for (auto i = 0u; auto const &c: pal.pages[m_model.palettePage()].colors) { ImGui::TableNextRow(); ImGui::PushID(static_cast(i)); // Column: color idx @@ -580,7 +583,7 @@ void TileSheetEditorImGui::drawPaletteMenu() noexcept { auto const ic = ImGui::GetColorU32({redf(c), greenf(c), bluef(c), 1}); ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic); ImGui::TableNextColumn(); - auto const&name = i < pal.colorNames.size() ? pal.colorNames[i].c_str() : ""; + auto const &name = i < pal.colorNames.size() ? pal.colorNames[i].c_str() : ""; ImGui::Text("%s", name); ImGui::TableNextColumn(); ImGui::Text("(%02d, %02d, %02d)", red16(c), green16(c), blue16(c)); @@ -594,7 +597,7 @@ void TileSheetEditorImGui::drawPaletteMenu() noexcept { } ox::Error TileSheetEditorImGui::updateActiveSubsheet( - ox::StringView const&name, int const cols, int const rows) noexcept { + ox::StringViewCR name, int const cols, int const rows) noexcept { return m_model.updateSubsheet(m_model.activeSubSheetIdx(), name, cols, rows); } diff --git a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp index 53cac5b..9276144 100644 --- a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp +++ b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp @@ -82,7 +82,7 @@ class TileSheetEditorImGui: public studio::Editor { void drawSubsheetSelector(TileSheet::SubSheet&, TileSheet::SubSheetIdx &path); [[nodiscard]] - static ox::Vec2 clickPos(ImVec2 const&winPos, ox::Vec2 clickPos) noexcept; + static ox::Vec2 clickPos(ImVec2 const &winPos, ox::Vec2 clickPos) noexcept; protected: ox::Error saveItem() noexcept override; @@ -94,11 +94,11 @@ class TileSheetEditorImGui: public studio::Editor { ox::Error exportSubsheetToPng(int scale) const noexcept; - void drawTileSheet(ox::Vec2 const&fbSize) noexcept; + void drawTileSheet(ox::Vec2 const &fbSize) noexcept; void drawPaletteMenu() noexcept; - ox::Error updateActiveSubsheet(ox::StringView const&name, int cols, int rows) noexcept; + ox::Error updateActiveSubsheet(ox::StringViewCR name, int cols, int rows) noexcept; void setActiveSubsheet(TileSheet::SubSheetIdx path) noexcept; diff --git a/src/olympic/keel/include/keel/assetmanager.hpp b/src/olympic/keel/include/keel/assetmanager.hpp index 0730e62..62cda92 100644 --- a/src/olympic/keel/include/keel/assetmanager.hpp +++ b/src/olympic/keel/include/keel/assetmanager.hpp @@ -154,7 +154,7 @@ class AssetRef: public ox::SignalHandler { private: constexpr ox::Error emitUpdated() const noexcept { updated.emit(); - return ox::Error(0); + return {}; } }; diff --git a/src/olympic/keel/include/keel/typeconv.hpp b/src/olympic/keel/include/keel/typeconv.hpp index e3aafd7..f5e0d68 100644 --- a/src/olympic/keel/include/keel/typeconv.hpp +++ b/src/olympic/keel/include/keel/typeconv.hpp @@ -260,7 +260,7 @@ ox::Result convertObjToObj( template ox::Result convert(Context &ctx, ox::BufferView const&src) noexcept { OX_REQUIRE(out, convert(ctx, src, ox::ModelTypeName_v, ox::ModelTypeVersion_v)); - return std::move(wrapCast(out)); + return std::move(wrapCast(*out)); } template diff --git a/src/olympic/studio/applib/src/app.cpp b/src/olympic/studio/applib/src/app.cpp index 7f41eba..8507638 100644 --- a/src/olympic/studio/applib/src/app.cpp +++ b/src/olympic/studio/applib/src/app.cpp @@ -43,7 +43,7 @@ static ox::Error runApp( oxLogError(turbine::setWindowIcon(*ctx, WindowIcons())); turbine::setWindowTitle(*ctx, keelCtx(*ctx).appName); turbine::setKeyEventHandler(*ctx, keyEventHandler); - turbine::setRefreshWithin(*ctx, 0); + turbine::requireRefreshWithin(*ctx, 0); StudioUI ui(*ctx, projectDataDir); StudioUIDrawer drawer(ui); turbine::gl::addDrawer(*ctx, &drawer); @@ -71,9 +71,9 @@ static ox::Error run( } ox::Error run( - ox::StringView project, - ox::StringView appName, - ox::StringView projectDataDir, + ox::StringView const project, + ox::StringView const appName, + ox::StringView const projectDataDir, ox::SpanView args) noexcept { return studio::run(ox::sfmt("{} {}", project, appName), projectDataDir, args); } diff --git a/src/olympic/studio/applib/src/deleteconfirmation.cpp b/src/olympic/studio/applib/src/deleteconfirmation.cpp index 5613543..e05ad40 100644 --- a/src/olympic/studio/applib/src/deleteconfirmation.cpp +++ b/src/olympic/studio/applib/src/deleteconfirmation.cpp @@ -2,6 +2,8 @@ * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. */ +#include + #include #include "deleteconfirmation.hpp" @@ -43,6 +45,9 @@ void DeleteConfirmation::draw(Context &ctx) noexcept { ImGui::OpenPopup(title().c_str()); m_stage = Stage::Open; m_open = true; + // require extended refresh in case new contents require resize + // this can take around a second + turbine::requireRefreshFor(ctx.tctx, 1000); [[fallthrough]]; case Stage::Open: drawWindow(ctx.tctx, m_open, [this] { diff --git a/src/olympic/studio/applib/src/studioui.cpp b/src/olympic/studio/applib/src/studioui.cpp index a6d0d6e..c807c77 100644 --- a/src/olympic/studio/applib/src/studioui.cpp +++ b/src/olympic/studio/applib/src/studioui.cpp @@ -7,6 +7,8 @@ #include +#include + #include #include #include @@ -17,6 +19,8 @@ #include "font.hpp" #include "studioui.hpp" +#include + #ifdef OX_OS_Darwin #define STUDIO_CTRL "Cmd" #else @@ -54,7 +58,7 @@ void registerModule(Module const*mod) noexcept { } -struct StudioConfig { +struct StudioConfigV1 { static constexpr auto TypeName = "net.drinkingtea.studio.StudioConfig"; static constexpr auto TypeVersion = 1; ox::String projectPath; @@ -63,13 +67,65 @@ struct StudioConfig { bool showProjectExplorer = true; }; -OX_MODEL_BEGIN(StudioConfig) +OX_MODEL_BEGIN(StudioConfigV1) OX_MODEL_FIELD_RENAME(activeTabItemName, active_tab_item_name) OX_MODEL_FIELD_RENAME(projectPath, project_path) OX_MODEL_FIELD_RENAME(openFiles, open_files) OX_MODEL_FIELD_RENAME(showProjectExplorer, show_project_explorer) OX_MODEL_END() + +struct StudioConfigV2 { + static constexpr auto TypeName = "net.drinkingtea.studio.StudioConfig"; + static constexpr auto TypeVersion = 2; + struct ProjectConfig { + static constexpr auto TypeName = "net.drinkingtea.studio.ProjectConfig"; + static constexpr auto TypeVersion = 2; + ox::String projectPath; + ox::String activeTabItemName; + ox::Vector openFiles; + }; + ox::Vector projects; + bool showProjectExplorer = true; + + [[nodiscard]] + constexpr ProjectConfig const *project() const { + return projects.empty() ? nullptr : &projects[0]; + } + + [[nodiscard]] + constexpr ProjectConfig *project() { + return projects.empty() ? nullptr : &projects[0]; + } +}; + +OX_MODEL_BEGIN(StudioConfigV2::ProjectConfig) + OX_MODEL_FIELD_RENAME(activeTabItemName, active_tab_item_name) + OX_MODEL_FIELD_RENAME(projectPath, project_path) + OX_MODEL_FIELD_RENAME(openFiles, open_files) +OX_MODEL_END() + +OX_MODEL_BEGIN(StudioConfigV2) + OX_MODEL_FIELD(projects) + OX_MODEL_FIELD_RENAME(showProjectExplorer, show_project_explorer) +OX_MODEL_END() + +static ox::Error convertStudioConfigV1ToStudioConfigV2( + keel::Context&, + StudioConfigV1 &src, + StudioConfigV2 &dst) noexcept { + dst.projects.emplace_back(StudioConfigV2::ProjectConfig{ + .projectPath = std::move(src.projectPath), + .activeTabItemName = std::move(src.activeTabItemName), + .openFiles = std::move(src.openFiles), + }); + dst.showProjectExplorer = src.showProjectExplorer; + return {}; +} + +using StudioConfig = StudioConfigV2; + + StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexcept: m_sctx{*this, ctx}, m_tctx{ctx}, @@ -87,6 +143,9 @@ StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexce // and hopefully it will change at some point. io.Fonts->AddFontFromMemoryTTF(const_cast(font.data()), static_cast(font.size()), 13, &fontCfg); } + auto &kctx = keelCtx(m_tctx); + kctx.converters.emplace_back(keel::Converter::make()); + oxLogError(headerizeConfigFile(kctx)); turbine::setApplicationData(m_tctx, &m_sctx); turbine::setShutdownHandler(m_tctx, shutdownHandler); m_projectExplorer.fileChosen.connect(this, &StudioUI::openFile); @@ -102,21 +161,14 @@ StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexce m_newMenu.finished.connect(this, &StudioUI::openFile); m_closeAppConfirm.response.connect(this, &StudioUI::handleCloseAppResponse); m_closeFileConfirm.response.connect(this, &StudioUI::handleCloseFileResponse); + m_removeRecentProject.dlg.response.connect(this, &StudioUI::handleRemoveRecentProjectResponse); loadModules(); // open project and files auto const [config, err] = studio::readConfig(keelCtx(m_tctx)); m_showProjectExplorer = config.showProjectExplorer; if (!err) { - auto const openProjErr = openProjectPath(config.projectPath); - if (!openProjErr) { - for (auto const&f: config.openFiles) { - auto const openFileErr = openFileActiveTab(f, config.activeTabItemName == f); - if (openFileErr) { - oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr)); - continue; - } - m_activeEditor = m_editors.back().value->get(); - } + if (auto const pc = config.project()) { + oxLogError(openProjectPath(pc->projectPath)); } } else { if constexpr(!ox::defines::Debug) { @@ -142,7 +194,7 @@ void StudioUI::navigateTo(ox::StringParam path, ox::StringParam navArgs) noexcep void StudioUI::draw() noexcept { glutils::clearScreen(); drawMenu(); - auto const&viewport = *ImGui::GetMainViewport(); + auto const &viewport = *ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport.WorkPos); ImGui::SetNextWindowSize(viewport.WorkSize); ImGui::SetNextWindowViewport(viewport.ID); @@ -194,6 +246,18 @@ void StudioUI::drawMenu() noexcept { if (ImGui::MenuItem("Open Project...", STUDIO_CTRL "+O")) { m_taskRunner.add(*ox::make(this, &StudioUI::openProjectPath)); } + if (ImGui::BeginMenu("Recent Projects", m_recentProjects.size() > 1)) { + for (size_t i = 1; i < m_recentProjects.size(); ++i) { + auto const &p = m_recentProjects[i]; + if (ImGui::MenuItem(p.c_str())) { + if (openProjectPath(p)) { + m_removeRecentProject.idx = i; + m_removeRecentProject.dlg.open(); + } + } + } + ImGui::EndMenu(); + } if (ImGui::MenuItem( "Save", STUDIO_CTRL "+S", @@ -270,7 +334,7 @@ void StudioUI::drawTabBar() noexcept { void StudioUI::drawTabs() noexcept { for (auto it = m_editors.begin(); it != m_editors.end();) { - auto const&e = *it; + auto const &e = *it; auto open = true; auto const unsavedChanges = e->unsavedChanges() ? ImGuiTabItemFlags_UnsavedDocument : 0; auto const selected = m_activeEditorUpdatePending == e.get() ? ImGuiTabItemFlags_SetSelected : 0; @@ -279,9 +343,11 @@ void StudioUI::drawTabs() noexcept { if (m_activeEditor != e.get()) [[unlikely]] { m_activeEditor = e.get(); studio::editConfig(keelCtx(m_tctx), [&](StudioConfig &config) { - config.activeTabItemName = m_activeEditor->itemPath(); + if (auto const pc = config.project()) { + pc->activeTabItemName = m_activeEditor->itemPath(); + } }); - turbine::setRefreshWithin(m_tctx, 0); + turbine::requireRefreshWithin(m_tctx, 0); } else [[likely]] { if (m_activeEditorUpdatePending == e.get()) [[unlikely]] { m_activeEditorUpdatePending = nullptr; @@ -337,14 +403,14 @@ void StudioUI::drawTabs() noexcept { } } -void StudioUI::loadEditorMaker(EditorMaker const&editorMaker) noexcept { - for (auto const&ext : editorMaker.fileTypes) { +void StudioUI::loadEditorMaker(EditorMaker const &editorMaker) noexcept { + for (auto const &ext : editorMaker.fileTypes) { m_editorMakers[ext] = editorMaker.make; } } -void StudioUI::loadModule(Module const&mod) noexcept { - for (auto const&editorMaker : mod.editors(m_sctx)) { +void StudioUI::loadModule(Module const &mod) noexcept { + for (auto const &editorMaker : mod.editors(m_sctx)) { loadEditorMaker(editorMaker); } for (auto &im : mod.itemMakers(m_sctx)) { @@ -464,14 +530,16 @@ ox::Error StudioUI::renameFile(ox::StringViewCR path) noexcept { return m_renameFile.openPath(path); } -ox::Error StudioUI::handleMoveFile(ox::StringViewCR oldPath, ox::StringViewCR newPath, ox::UUID const&) noexcept { +ox::Error StudioUI::handleMoveFile(ox::StringViewCR oldPath, ox::StringViewCR newPath, ox::UUID const &) noexcept { for (auto &f : m_openFiles) { if (f == oldPath) { f = newPath; editConfig(keelCtx(m_sctx), [&](StudioConfig &cfg) { - auto p = find(cfg.openFiles.begin(), cfg.openFiles.end(), oldPath); - *p = newPath; - cfg.activeTabItemName = newPath; + if (auto const pc = cfg.project()) { + auto p = find(pc->openFiles.begin(), pc->openFiles.end(), oldPath); + *p = newPath; + pc->activeTabItemName = newPath; + } }); break; } @@ -546,8 +614,36 @@ ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept { m_openFiles.clear(); m_editors.clear(); studio::editConfig(keelCtx(m_tctx), [&](StudioConfig &config) { - config.projectPath = ox::String(m_project->projectPath()); - config.openFiles.clear(); + auto const pcIt = std::find_if( + config.projects.begin(), config.projects.end(), + [this](StudioConfig::ProjectConfig const &pc) { + return pc.projectPath == m_project->projectPath(); + }); + if (pcIt != config.projects.end()) { + auto p = std::move(*pcIt); + std::ignore = config.projects.erase(pcIt); + auto &pc = *config.projects.emplace(0, std::move(p)); + for (auto const &f: pc.openFiles) { + auto const openFileErr = openFileActiveTab(f, pc.activeTabItemName == f); + if (openFileErr) { + oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr)); + continue; + } + m_activeEditor = m_editors.back().value->get(); + } + } else { + config.projects.emplace(0, StudioConfig::ProjectConfig{ + .projectPath = ox::String{m_project->projectPath()}, + .activeTabItemName = {}, + .openFiles = {}, + }); + } + config.projects.resize(ox::min(10, config.projects.size())); + m_recentProjects.clear(); + m_recentProjects.reserve(config.projects.size()); + for (auto const &p : config.projects) { + m_recentProjects.emplace_back(p.projectPath); + } }); return m_projectExplorer.refreshProjectTreeModel(); } @@ -593,8 +689,10 @@ ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool const makeActi } // save to config studio::editConfig(keelCtx(m_tctx), [&path](StudioConfig &config) { - if (!config.openFiles.contains(path)) { - config.openFiles.emplace_back(path); + if (auto const pc = config.project()) { + if (!pc->openFiles.contains(path)) { + pc->openFiles.emplace_back(path); + } } }); return {}; @@ -618,6 +716,22 @@ ox::Error StudioUI::handleCloseFileResponse(ig::PopupResponse const response) no return {}; } +ox::Error StudioUI::handleRemoveRecentProjectResponse(ig::PopupResponse const response) noexcept { + if (response == ig::PopupResponse::OK) { + auto const p = std::move(m_recentProjects[m_removeRecentProject.idx]); + studio::editConfig(keelCtx(m_tctx), [&p](StudioConfig &config) { + std::ignore = config.projects.erase( + std::remove_if( + config.projects.begin(), config.projects.end(), + [&p](StudioConfig::ProjectConfig const &pc) { + return pc.projectPath == p; + })); + }); + return m_recentProjects.erase(m_removeRecentProject.idx).error; + } + return {}; +} + ox::Error StudioUI::closeCurrentFile() noexcept { for (auto &e : m_editors) { if (m_activeEditor == e.get()) { @@ -636,7 +750,9 @@ ox::Error StudioUI::closeFile(ox::StringViewCR path) noexcept { std::ignore = m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path)); // save to config studio::editConfig(keelCtx(m_tctx), [&](StudioConfig &config) { - std::ignore = config.openFiles.erase(std::remove(config.openFiles.begin(), config.openFiles.end(), path)); + if (auto const pc = config.project()) { + std::ignore = pc->openFiles.erase(std::remove(pc->openFiles.begin(), pc->openFiles.end(), path)); + } }); return {}; } diff --git a/src/olympic/studio/applib/src/studioui.hpp b/src/olympic/studio/applib/src/studioui.hpp index ee9ee1b..b56fe9a 100644 --- a/src/olympic/studio/applib/src/studioui.hpp +++ b/src/olympic/studio/applib/src/studioui.hpp @@ -44,6 +44,7 @@ class StudioUI: public ox::SignalHandler { bool m_closeActiveTab{}; ox::Vector> m_queuedMoves; ox::Vector> m_queuedDirMoves; + ox::Vector m_recentProjects; NewMenu m_newMenu{keelCtx(m_tctx)}; AboutPopup m_aboutPopup{m_tctx}; DeleteConfirmation m_deleteConfirmation; @@ -57,7 +58,11 @@ class StudioUI: public ox::SignalHandler { MakeCopyPopup m_copyFilePopup; RenameFile m_renameFile; NewProject m_newProject{m_projectDataDir}; - ox::Array const m_widgets { + struct { + ig::QuestionPopup dlg{"Remove From Recents?", "Unable to load project. Remove from recent projects?"}; + size_t idx{}; + } m_removeRecentProject; + ox::Array const m_widgets { &m_closeFileConfirm, &m_closeAppConfirm, &m_copyFilePopup, @@ -68,6 +73,7 @@ class StudioUI: public ox::SignalHandler { &m_newDirDialog, &m_renameFile, &m_messagePopup, + &m_removeRecentProject.dlg, }; bool m_showProjectExplorer = true; struct NavAction { @@ -100,9 +106,9 @@ class StudioUI: public ox::SignalHandler { void drawTabs() noexcept; - void loadEditorMaker(EditorMaker const&editorMaker) noexcept; + void loadEditorMaker(EditorMaker const &editorMaker) noexcept; - void loadModule(Module const&mod) noexcept; + void loadModule(Module const &mod) noexcept; void loadModules() noexcept; @@ -124,7 +130,7 @@ class StudioUI: public ox::SignalHandler { ox::Error renameFile(ox::StringViewCR path) noexcept; - ox::Error handleMoveFile(ox::StringViewCR oldPath, ox::StringViewCR newPath, ox::UUID const&id) noexcept; + ox::Error handleMoveFile(ox::StringViewCR oldPath, ox::StringViewCR newPath, ox::UUID const &id) noexcept; ox::Error handleDeleteDir(ox::StringViewCR path) noexcept; @@ -144,6 +150,8 @@ class StudioUI: public ox::SignalHandler { ox::Error handleCloseFileResponse(ig::PopupResponse response) noexcept; + ox::Error handleRemoveRecentProjectResponse(ig::PopupResponse response) noexcept; + ox::Error closeCurrentFile() noexcept; ox::Error closeFile(ox::StringViewCR path) noexcept; diff --git a/src/olympic/studio/modlib/include/studio/configio.hpp b/src/olympic/studio/modlib/include/studio/configio.hpp index dae06f9..b155b3a 100644 --- a/src/olympic/studio/modlib/include/studio/configio.hpp +++ b/src/olympic/studio/modlib/include/studio/configio.hpp @@ -4,21 +4,21 @@ #pragma once +#include #include #include -#include #include #include #include -#include #include +#include #include namespace studio { namespace detail { -inline ox::String slashesToPct(ox::StringView str) noexcept { +inline ox::String slashesToPct(ox::StringViewCR str) noexcept { auto out = ox::String{str}; for (auto&c: out) { if (c == '/' || c == '\\') { @@ -30,78 +30,102 @@ inline ox::String slashesToPct(ox::StringView str) noexcept { } [[nodiscard]] -ox::String configPath(keel::Context const&ctx) noexcept; +ox::String configPath(keel::Context const&kctx) noexcept; template -ox::Result readConfig(keel::Context &ctx, ox::StringViewCR name) noexcept { +ox::Result readConfig(keel::Context &kctx, ox::StringViewCR name) noexcept { oxAssert(name != "", "Config type has no TypeName"); auto const path = ox::sfmt("/{}.json", detail::slashesToPct(name)); - ox::PassThroughFS fs(configPath(ctx)); + ox::PassThroughFS fs(configPath(kctx)); auto const [buff, err] = fs.read(path); if (err) { //oxErrf("Could not read config file: {} - {}\n", path, toStr(err)); return err; } - return ox::readOC(buff); + OX_REQUIRE(id, ox::readClawTypeId(buff)); + ox::Result out; + if (id != ox::ModelTypeId_v) { + out = keel::convert(kctx, buff); + } else { + out = ox::readClaw(buff); + } + OX_RETURN_ERROR(out); + OX_RETURN_ERROR(keel::ensureValid(out.value)); + return out; } template -ox::Result readConfig(keel::Context &ctx) noexcept { +ox::Result readConfig(keel::Context &kctx) noexcept { constexpr auto TypeName = ox::requireModelTypeName(); - return readConfig(ctx, TypeName); + return readConfig(kctx, TypeName); } template -ox::Error writeConfig(keel::Context &ctx, ox::StringViewCR name, T const&data) noexcept { +ox::Error writeConfig(keel::Context &kctx, ox::StringViewCR name, T const&data) noexcept { oxAssert(name != "", "Config type has no TypeName"); auto const path = ox::sfmt("/{}.json", detail::slashesToPct(name)); - ox::PassThroughFS fs(configPath(ctx)); + ox::PassThroughFS fs(configPath(kctx)); if (auto const err = fs.mkdir("/", true)) { //oxErrf("Could not create config directory: {} - {}\n", path, toStr(err)); return err; } - OX_REQUIRE_M(buff, ox::writeOC(data)); + OX_REQUIRE_M(buff, ox::writeClaw(data, ox::ClawFormat::Organic)); *buff.back().value = '\n'; if (auto const err = fs.write(path, buff.data(), buff.size())) { //oxErrf("Could not read config file: {} - {}\n", path, toStr(err)); - return ox::Error(2, "Could not read config file"); + return ox::Error{2, "Could not read config file"}; } return {}; } template -ox::Error writeConfig(keel::Context &ctx, T const&data) noexcept { +ox::Error writeConfig(keel::Context &kctx, T const&data) noexcept { constexpr auto TypeName = ox::requireModelTypeName(); - return writeConfig(ctx, TypeName, data); + return writeConfig(kctx, TypeName, data); } template -void openConfig(keel::Context &ctx, ox::StringViewCR name, Func f) noexcept { +void openConfig(keel::Context &kctx, ox::StringViewCR name, Func f) noexcept { oxAssert(name != "", "Config type has no TypeName"); - auto const [c, err] = readConfig(ctx, name); + auto const [c, err] = readConfig(kctx, name); oxLogError(err); f(c); } template -void openConfig(keel::Context &ctx, Func f) noexcept { +void openConfig(keel::Context &kctx, Func f) noexcept { constexpr auto TypeName = ox::requireModelTypeName(); - openConfig(ctx, TypeName, f); + openConfig(kctx, TypeName, f); } template -void editConfig(keel::Context &ctx, ox::StringViewCR name, Func f) noexcept { +void editConfig(keel::Context &kctx, ox::StringViewCR name, Func f) noexcept { oxAssert(name != "", "Config type has no TypeName"); - auto [c, err] = readConfig(ctx, name); + auto [c, err] = readConfig(kctx, name); oxLogError(err); f(c); - oxLogError(writeConfig(ctx, name, c)); + oxLogError(writeConfig(kctx, name, c)); } template -void editConfig(keel::Context &ctx, Func f) noexcept { +void editConfig(keel::Context &kctx, Func f) noexcept { constexpr auto TypeName = ox::requireModelTypeName(); - editConfig(ctx, TypeName, f); + editConfig(kctx, TypeName, f); +} + +/** + * Older config files didn't use ClawHeaders, so they can't + * use the normal conversion system. + * Functions like this shouldn't be necessary moving forward. + */ +template +ox::Error headerizeConfigFile(keel::Context &kctx, ox::StringViewCR name = ox::ModelTypeName_v) noexcept { + auto const path = ox::sfmt("/{}.json", name); + ox::PassThroughFS fs(configPath(kctx)); + OX_REQUIRE_M(buff, fs.read(path)); + OX_REQUIRE_M(cv1, ox::readOC(buff)); + OX_RETURN_ERROR(ox::writeClaw(cv1, ox::ClawFormat::Organic).moveTo(buff)); + return fs.write(path, buff); } } diff --git a/src/olympic/studio/modlib/src/imguiutil.cpp b/src/olympic/studio/modlib/src/imguiutil.cpp index 9c61820..e4886d9 100644 --- a/src/olympic/studio/modlib/src/imguiutil.cpp +++ b/src/olympic/studio/modlib/src/imguiutil.cpp @@ -275,6 +275,9 @@ void QuestionPopup::draw(Context &ctx) noexcept { ImGui::OpenPopup(m_title.c_str()); m_stage = Stage::Open; m_open = true; + // require extended refresh in case new contents require resize + // this can take around a second + turbine::requireRefreshFor(ctx.tctx, 1000); [[fallthrough]]; case Stage::Open: centerNextWindow(ctx.tctx); diff --git a/src/olympic/turbine/include/turbine/gfx.hpp b/src/olympic/turbine/include/turbine/gfx.hpp index c512423..1b2a55c 100644 --- a/src/olympic/turbine/include/turbine/gfx.hpp +++ b/src/olympic/turbine/include/turbine/gfx.hpp @@ -49,6 +49,19 @@ ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept; * @param ctx - Context * @param ms - milliseconds */ -void setRefreshWithin(Context &ctx, int ms) noexcept; +void requireRefreshWithin(Context &ctx, int ms) noexcept; + +/** + * Stimulates screen to draw for a period of a short period of + * time (168 ms on GLFW implementation). + * @param ctx - Context + */ +void requireRefresh(Context &ctx) noexcept; + +/** + * Stimulates screen to draw for a specified period of time. + * @param ctx - Context + */ +void requireRefreshFor(Context &ctx, int ms) noexcept; } diff --git a/src/olympic/turbine/src/glfw/turbine.cpp b/src/olympic/turbine/src/glfw/turbine.cpp index 53666d8..ff02f4d 100644 --- a/src/olympic/turbine/src/glfw/turbine.cpp +++ b/src/olympic/turbine/src/glfw/turbine.cpp @@ -155,6 +155,10 @@ static ox::Result toGlfwImgPixels(ox::SpanView const &iconPng return out; } +static void setMandatoryRefreshPeriod(Context &ctx, TimeMs const newVal) { + ctx.mandatoryRefreshPeriodEnd = ox::max(ctx.mandatoryRefreshPeriodEnd, newVal); +} + ox::Error setWindowIcon(Context &ctx, ox::SpanView> const &iconPngs) noexcept { if constexpr(ox::defines::OS != ox::OS::Darwin) { ox::Vector src; @@ -216,10 +220,19 @@ ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept { return {}; } -void setRefreshWithin(Context &ctx, int ms) noexcept { +void requireRefreshWithin(Context &ctx, int const ms) noexcept { ctx.refreshWithinMs = ox::min(ms, ctx.refreshWithinMs); } +void requireRefresh(Context &ctx) noexcept { + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod); +} + +void requireRefreshFor(Context &ctx, int ms) noexcept { + ms = ox::max(0, ms); + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + static_cast(ms)); +} + static void draw(Context &ctx) noexcept { // draw start #if TURBINE_USE_IMGUI @@ -288,12 +301,12 @@ static void handleGlfwCursorPosEvent(GLFWwindow*, double, double) noexcept { static void handleGlfwMouseButtonEvent(GLFWwindow *window, int, int, int) noexcept { auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); - ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod); } static void handleGlfwKeyEvent(GLFWwindow *window, int const key, int, int const action, int) noexcept { auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); - ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod); if (action == GLFW_PRESS) { handleKeyPress(ctx, key, true); } else if (action == GLFW_RELEASE) { @@ -303,7 +316,7 @@ static void handleGlfwKeyEvent(GLFWwindow *window, int const key, int, int const static void handleGlfwWindowCloseEvent(GLFWwindow *window) noexcept { auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); - ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod); ctx.running = ctx.shutdownHandler ? !ctx.shutdownHandler(ctx) : false; glfwSetWindowShouldClose(window, !ctx.running); glfwPostEmptyEvent(); @@ -316,7 +329,7 @@ ox::Result> init( using namespace std::chrono; ctx->startTime = static_cast( duration_cast(system_clock::now().time_since_epoch()).count()); - ctx->mandatoryRefreshPeriodEnd = ticksMs(*ctx) + config::MandatoryRefreshPeriod; + setMandatoryRefreshPeriod(*ctx, ticksMs(*ctx) + config::MandatoryRefreshPeriod); // init GLFW context glfwInit(); glfwSetErrorCallback(handleGlfwError);