Compare commits
13 Commits
e27eee50f0
...
release-d2
| Author | SHA1 | Date | |
|---|---|---|---|
| 17c9f673bd | |||
| 870fb9c6e3 | |||
| 31b39982c5 | |||
| 5476417be2 | |||
| e03be694c2 | |||
| 490c0368bc | |||
| a24fc407c5 | |||
| e38b85b4f4 | |||
| f7c3c02c4c | |||
| 8f0f1fea39 | |||
| 2f36a3f6f0 | |||
| 07e5bf9054 | |||
| aacff3daf9 |
3
deps/ox/src/ox/std/memory.hpp
vendored
3
deps/ox/src/ox/std/memory.hpp
vendored
@@ -213,8 +213,7 @@ class UniquePtr {
|
||||
return m_t;
|
||||
}
|
||||
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr void reset(UniquePtr<U, UDeleter> &&other = UniquePtr()) {
|
||||
constexpr void reset(UniquePtr &&other = UniquePtr()) {
|
||||
auto t = m_t;
|
||||
m_t = other.release();
|
||||
Deleter()(t);
|
||||
|
||||
2
deps/ox/src/ox/std/stringliteral.hpp
vendored
2
deps/ox/src/ox/std/stringliteral.hpp
vendored
@@ -19,7 +19,7 @@ namespace ox {
|
||||
*/
|
||||
class StringLiteral: public detail::BaseStringView {
|
||||
public:
|
||||
consteval StringLiteral() noexcept = default;
|
||||
constexpr StringLiteral() noexcept = default;
|
||||
|
||||
constexpr StringLiteral(StringLiteral const &sv) noexcept = default;
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
# d2025.07.0
|
||||
|
||||
* Add sub-command for exporting TileSheets as PNG files.
|
||||
* Add 'Reload Project' menu item under File.
|
||||
* Fix opening a project to mark an unopenable file as closed in the config file on startup.
|
||||
|
||||
# d2025.06.0
|
||||
|
||||
* Add ability to remember recent projects in config
|
||||
|
||||
@@ -21,9 +21,28 @@ constexpr ox::Array<ox::StringLiteral, 2> FileExts_TileSheet{
|
||||
FileExt_ng,
|
||||
};
|
||||
|
||||
constexpr ox::Array<ox::StringLiteral, 2> FileExts_Palette{
|
||||
FileExt_npal,
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool isTileSheet(ox::StringViewCR path) noexcept {
|
||||
return endsWith(path, FileExt_nts) || endsWith(path, FileExt_ng);
|
||||
return ox::any_of(
|
||||
FileExts_TileSheet.begin(),
|
||||
FileExts_TileSheet.end(),
|
||||
[path](ox::StringLiteral const &ext) {
|
||||
return endsWith(path, ext);
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool isPalette(ox::StringViewCR path) noexcept {
|
||||
return ox::any_of(
|
||||
FileExts_Palette.begin(),
|
||||
FileExts_Palette.end(),
|
||||
[path](ox::StringLiteral const &ext) {
|
||||
return endsWith(path, ext);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ PaletteEditorImGui::PaletteEditorImGui(studio::Context &sctx, ox::StringParam pa
|
||||
Editor(sctx, std::move(path)),
|
||||
m_sctx(sctx),
|
||||
m_tctx(sctx.tctx),
|
||||
m_pal(*keel::readObj<Palette>(keelCtx(m_tctx), itemPath()).unwrapThrow()) {
|
||||
m_pal(m_sctx.project->loadObj<Palette>(itemPath()).unwrapThrow()) {
|
||||
undoStack()->changeTriggered.connect(this, &PaletteEditorImGui::handleCommand);
|
||||
m_pageRenameDlg.inputSubmitted.connect(this, &PaletteEditorImGui::renamePage);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ TileSheetEditorModel::TileSheetEditorModel(
|
||||
m_sctx{sctx},
|
||||
m_tctx{m_sctx.tctx},
|
||||
m_path{std::move(path)},
|
||||
m_img{*readObj<TileSheet>(keelCtx(m_tctx), m_path).unwrapThrow()},
|
||||
m_img{m_sctx.project->loadObj<TileSheet>(m_path).unwrapThrow()},
|
||||
// ignore failure to load palette
|
||||
m_pal{readObj<Palette>(keelCtx(m_tctx), m_img.defaultPalette).value},
|
||||
m_undoStack{undoStack} {
|
||||
|
||||
@@ -15,7 +15,7 @@ target_link_libraries(
|
||||
|
||||
target_compile_definitions(
|
||||
NostalgiaStudio PUBLIC
|
||||
OLYMPIC_APP_VERSION="dev build"
|
||||
OLYMPIC_APP_VERSION="d2025.07.0"
|
||||
)
|
||||
|
||||
install(
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<string>APPL</string>
|
||||
|
||||
<key>CFBundleVersion</key>
|
||||
<string>dev build</string>
|
||||
<string>d2025.07.0</string>
|
||||
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>12.0.0</string>
|
||||
|
||||
@@ -25,12 +25,11 @@ ox::Error writeUuidHeader(ox::Writer_c auto &writer, ox::UUID const&uuid) noexce
|
||||
|
||||
template<typename T>
|
||||
ox::Result<T> readAsset(ox::BufferView buff) noexcept {
|
||||
std::size_t offset = 0;
|
||||
auto const err = readUuidHeader(buff).error;
|
||||
if (!err) {
|
||||
offset = K1HdrSz; // the size of K1 headers
|
||||
buff += K1HdrSz; // the size of K1 headers
|
||||
}
|
||||
auto out = ox::readClaw<T>(buff + offset);
|
||||
auto out = ox::readClaw<T>(buff);
|
||||
OX_RETURN_ERROR(out);
|
||||
OX_RETURN_ERROR(ensureValid(out.value));
|
||||
return out;
|
||||
|
||||
@@ -64,11 +64,13 @@ class AssetContainer {
|
||||
|
||||
protected:
|
||||
constexpr void incRefs() const noexcept {
|
||||
oxAssert(m_references < ox::MaxValue<decltype(m_references)>, "reference count exceeds maximum");
|
||||
++m_references;
|
||||
}
|
||||
|
||||
constexpr void decRefs() const noexcept {
|
||||
--m_references;
|
||||
oxAssert(m_references >= 0, "negative references");
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@@ -162,6 +164,7 @@ template<typename T>
|
||||
constexpr AssetRef<T>::AssetRef(AssetContainer<T> const*c) noexcept: m_ctr(c) {
|
||||
if (m_ctr) {
|
||||
m_ctr->updated.connect(this, &AssetRef::emitUpdated);
|
||||
m_ctr->incRefs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -261,6 +261,9 @@ namespace keel {
|
||||
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs, DuplicateSet &duplicateSet) noexcept {
|
||||
ctx.rom = std::move(fs);
|
||||
clearUuidMap(ctx);
|
||||
#ifndef OX_BARE_METAL
|
||||
ctx.assetManager.gc();
|
||||
#endif
|
||||
return buildUuidMap(ctx, &duplicateSet);
|
||||
}
|
||||
|
||||
|
||||
@@ -250,6 +250,9 @@ void StudioUI::drawMenu() noexcept {
|
||||
if (ImGui::MenuItem("Open Project...", STUDIO_CTRL "+O")) {
|
||||
m_taskRunner.add(*ox::make<FileDialogManager>(this, &StudioUI::openProjectPath));
|
||||
}
|
||||
if (ImGui::MenuItem("Reload Project")) {
|
||||
oxLogError(openProjectPath(m_project->projectPath()));
|
||||
}
|
||||
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];
|
||||
@@ -636,6 +639,9 @@ ox::Error StudioUI::createOpenProject(ox::StringViewCR path) noexcept {
|
||||
|
||||
ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept {
|
||||
OX_REQUIRE_M(fs, keel::loadRomFs(path.view()));
|
||||
m_project.reset();
|
||||
m_openFiles.clear();
|
||||
m_editors.clear();
|
||||
keel::DuplicateSet ds;
|
||||
OX_RETURN_ERROR(keel::setRomFs(keelCtx(m_tctx), std::move(fs), ds));
|
||||
if (ds.size()) {
|
||||
@@ -649,8 +655,8 @@ ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept {
|
||||
m_messagePopup.show(msg);
|
||||
}
|
||||
OX_RETURN_ERROR(
|
||||
ox::make_unique_catch<Project>(keelCtx(m_tctx), std::move(path), m_projectDataDir)
|
||||
.moveTo(m_project));
|
||||
ox::make_unique_catch<Project>(keelCtx(m_tctx), std::move(path), m_projectDataDir)
|
||||
.moveTo(m_project));
|
||||
m_sctx.project = m_project.get();
|
||||
m_activeEditor = nullptr;
|
||||
m_activeEditorOnLastDraw = nullptr;
|
||||
@@ -665,8 +671,6 @@ ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept {
|
||||
m_project->dirDeleted.connect(this, &StudioUI::handleDeleteDir);
|
||||
m_project->fileDeleted.connect(this, &StudioUI::handleDeleteFile);
|
||||
m_project->fileMoved.connect(this, &StudioUI::handleMoveFile);
|
||||
m_openFiles.clear();
|
||||
m_editors.clear();
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) {
|
||||
auto const pcIt = std::find_if(
|
||||
config.projects.begin(), config.projects.end(),
|
||||
|
||||
@@ -189,6 +189,10 @@ ox::Result<T> Project::loadObj(ox::StringViewCR path) const noexcept {
|
||||
if constexpr(ox::is_same_v<T, ox::ModelObject>) {
|
||||
return keel::readAsset(m_typeStore, buff);
|
||||
} else {
|
||||
OX_REQUIRE(typeId, keel::readAssetTypeId(buff));
|
||||
if (typeId != ox::ModelTypeId_v<T>) {
|
||||
return keel::convert<T>(m_kctx, buff);
|
||||
}
|
||||
return keel::readAsset<T>(buff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,18 @@ namespace studio {
|
||||
|
||||
void navigateTo(Context &ctx, ox::StringParam filePath, ox::StringParam navArgs) noexcept {
|
||||
ox::String path = std::move(filePath);
|
||||
if (beginsWith(path, "uuid://")) {
|
||||
if (keel::isUuidUrl(path)) {
|
||||
auto const [p, err] = keel::uuidUrlToPath(keelCtx(ctx), path);
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
path = p;
|
||||
}
|
||||
//if (
|
||||
// auto const [np, err] = ctx.navStack.back();
|
||||
// !err && np->filePath == path && np->navArgs == navArgs.view()) {
|
||||
// return;
|
||||
//}
|
||||
ctx.navStack.resize(ctx.navIdx + 1);
|
||||
ctx.navStack.emplace_back(ox::String{path}, ox::String{navArgs.view()});
|
||||
try {
|
||||
@@ -49,8 +54,9 @@ void navigateBack(Context &ctx) noexcept {
|
||||
}
|
||||
|
||||
void navigateForward(Context &ctx) noexcept {
|
||||
while (ctx.navIdx < ctx.navStack.size()) {
|
||||
auto const &n = ctx.navStack[ctx.navIdx];
|
||||
auto const nextIdx = ctx.navIdx + 1;
|
||||
while (nextIdx < ctx.navStack.size()) {
|
||||
auto const &n = ctx.navStack[nextIdx];
|
||||
try {
|
||||
ctx.navCallback(n.filePath, n.navArgs);
|
||||
} catch (std::exception const &e) {
|
||||
@@ -58,7 +64,7 @@ void navigateForward(Context &ctx) noexcept {
|
||||
oxErrf("navigateForward failed: {}", e.what());
|
||||
}
|
||||
if (!ctx.project->exists(n.filePath)) {
|
||||
std::ignore = ctx.navStack.erase(ctx.navIdx);
|
||||
std::ignore = ctx.navStack.erase(nextIdx);
|
||||
continue;
|
||||
}
|
||||
++ctx.navIdx;
|
||||
|
||||
Reference in New Issue
Block a user