Squashed 'deps/nostalgia/' changes from 5e90f8d4..3b874c6e
3b874c6e [turbine] Fix refresh logic to handle default refresh within value 6cf7bf96 [ox/std] Hopefully fix MSVC build e34df255 [nostalgia] Update developer-handbook non-error return 7eab2f92 [studio/modlib] Comment out logging in configio 3824788a [ox/std] Add non-const operator[] to Pair 1eac7e1e [ox/std] Add Pair 8798d2d7 [nostalgia/core] Fix getTileIdx(TileSheet, SubSheetId) f82db690 [nostalgia/core] Make load TileSheet functions take CompactTileSheet, in addition to FileAddresses 0dfa7c30 [studio/modlib] Make TaskRunner check that task is not null 2afade24 Merge commit 'fc2dec64389824a251fb258f6fd0a9074e521cc2' 3635702e [nostalgia] Cleanup config IO 6cbafc75 [nostalgia,keel] Make repair return ox::Error 0d7b89a0 [turbine] Add TimeMs alias to uint64_t e8f5c911 [studio/applib] Change updateHandler to 10 second interval 3cb3bc12 [nostalgia/core] Add valid and repair functions for PaletteV3 a2cec10c [keel] Add valid and repair functions for AssetManager git-subtree-dir: deps/nostalgia git-subtree-split: 3b874c6e6aa0b80783fc9d712c31bc837326337c
This commit is contained in:
@@ -21,6 +21,17 @@ class AssetManager;
|
||||
template<typename T>
|
||||
class AssetRef;
|
||||
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool valid(auto const&) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::Error repair(auto const&) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
template<typename T>
|
||||
class AssetContainer {
|
||||
@@ -215,6 +226,9 @@ class AssetManager {
|
||||
ox::Result<AssetRef<T>> loadAsset(ox::StringView const assetId) noexcept {
|
||||
auto &p = m_cache[assetId];
|
||||
oxRequireM(obj, m_loader(assetId));
|
||||
if (!valid(obj) && repair(obj)) {
|
||||
return OxError(1, "asset is invalid state and could not be repaired");
|
||||
}
|
||||
if (!p) {
|
||||
p = ox::make_unique<AssetContainer<T>>(std::move(obj));
|
||||
} else {
|
||||
|
@@ -200,8 +200,8 @@ void StudioUI::drawTabs() noexcept {
|
||||
if (ImGui::BeginTabItem(e->itemDisplayName().c_str(), &open, flags)) {
|
||||
if (m_activeEditor != e.get()) {
|
||||
m_activeEditor = e.get();
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||
config->activeTabItemName = m_activeEditor->itemPath();
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
||||
config.activeTabItemName = m_activeEditor->itemPath();
|
||||
});
|
||||
}
|
||||
if (m_activeEditorUpdatePending == e.get()) {
|
||||
@@ -255,8 +255,8 @@ void StudioUI::loadModules() noexcept {
|
||||
|
||||
void StudioUI::toggleProjectExplorer() noexcept {
|
||||
m_showProjectExplorer = !m_showProjectExplorer;
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||
config->showProjectExplorer = m_showProjectExplorer;
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
||||
config.showProjectExplorer = m_showProjectExplorer;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -339,9 +339,9 @@ ox::Error StudioUI::openProjectPath(ox::CRStringView path) noexcept {
|
||||
m_project->fileDeleted.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel);
|
||||
m_openFiles.clear();
|
||||
m_editors.clear();
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||
config->projectPath = ox::String(m_project->projectPath());
|
||||
config->openFiles.clear();
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
||||
config.projectPath = ox::String(m_project->projectPath());
|
||||
config.openFiles.clear();
|
||||
});
|
||||
return m_projectExplorer.refreshProjectTreeModel();
|
||||
}
|
||||
@@ -392,9 +392,9 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
|
||||
m_activeEditorUpdatePending = editor;
|
||||
}
|
||||
// save to config
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||
if (!config->openFiles.contains(path)) {
|
||||
config->openFiles.emplace_back(path);
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
||||
if (!config.openFiles.contains(path)) {
|
||||
config.openFiles.emplace_back(path);
|
||||
}
|
||||
});
|
||||
return {};
|
||||
@@ -406,8 +406,8 @@ ox::Error StudioUI::closeFile(ox::CRStringView path) noexcept {
|
||||
}
|
||||
std::ignore = m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path));
|
||||
// save to config
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||
std::ignore = config->openFiles.erase(std::remove(config->openFiles.begin(), config->openFiles.end(), path));
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
||||
std::ignore = config.openFiles.erase(std::remove(config.openFiles.begin(), config.openFiles.end(), path));
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
@@ -17,17 +17,29 @@
|
||||
|
||||
namespace studio {
|
||||
|
||||
namespace detail {
|
||||
inline ox::String slashesToPct(ox::StringView str) noexcept {
|
||||
auto out = ox::String{str};
|
||||
for (auto&c: out) {
|
||||
if (c == '/' || c == '\\') {
|
||||
c = '%';
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String configPath(keel::Context const&ctx) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<T> readConfig(keel::Context &ctx, ox::CRStringView name) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
auto const path = ox::sfmt("/{}.json", name);
|
||||
auto const path = ox::sfmt("/{}.json", detail::slashesToPct(name));
|
||||
ox::PassThroughFS fs(configPath(ctx));
|
||||
auto const [buff, err] = fs.read(path);
|
||||
if (err) {
|
||||
oxErrf("Could not read config file: {}\n", toStr(err));
|
||||
//oxErrf("Could not read config file: {} - {}\n", path, toStr(err));
|
||||
return err;
|
||||
}
|
||||
return ox::readOC<T>(buff);
|
||||
@@ -40,25 +52,25 @@ ox::Result<T> readConfig(keel::Context &ctx) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeConfig(keel::Context &ctx, ox::CRStringView name, T *data) noexcept {
|
||||
ox::Error writeConfig(keel::Context &ctx, ox::CRStringView name, T const&data) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
auto const path = ox::sfmt("/{}.json", name);
|
||||
auto const path = ox::sfmt("/{}.json", detail::slashesToPct(name));
|
||||
ox::PassThroughFS fs(configPath(ctx));
|
||||
if (auto const err = fs.mkdir("/", true)) {
|
||||
oxErrf("Could not create config directory: {}\n", toStr(err));
|
||||
//oxErrf("Could not create config directory: {} - {}\n", path, toStr(err));
|
||||
return err;
|
||||
}
|
||||
oxRequireM(buff, ox::writeOC(*data));
|
||||
oxRequireM(buff, ox::writeOC(data));
|
||||
*buff.back().value = '\n';
|
||||
if (auto const err = fs.write(path, buff.data(), buff.size())) {
|
||||
oxErrf("Could not read config file: {}\n", toStr(err));
|
||||
//oxErrf("Could not read config file: {} - {}\n", path, toStr(err));
|
||||
return OxError(2, "Could not read config file");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeConfig(keel::Context &ctx, T *data) noexcept {
|
||||
ox::Error writeConfig(keel::Context &ctx, T const&data) noexcept {
|
||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||
return writeConfig(ctx, TypeName, data);
|
||||
}
|
||||
@@ -68,7 +80,7 @@ void openConfig(keel::Context &ctx, ox::CRStringView name, Func f) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
auto const [c, err] = readConfig<T>(ctx, name);
|
||||
oxLogError(err);
|
||||
f(&c);
|
||||
f(c);
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
@@ -82,8 +94,8 @@ void editConfig(keel::Context &ctx, ox::CRStringView name, Func f) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
auto [c, err] = readConfig<T>(ctx, name);
|
||||
oxLogError(err);
|
||||
f(&c);
|
||||
oxLogError(writeConfig(ctx, name, &c));
|
||||
f(c);
|
||||
oxLogError(writeConfig(ctx, name, c));
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
|
@@ -10,6 +10,7 @@ namespace studio {
|
||||
|
||||
void TaskRunner::update(turbine::Context &ctx) noexcept {
|
||||
std::ignore = m_tasks.erase(std::remove_if(m_tasks.begin(), m_tasks.end(), [&](ox::UPtr<studio::Task> &t) {
|
||||
if (!t) { return true; }
|
||||
auto const done = t->update(ctx) == TaskState::Done;
|
||||
if (done) {
|
||||
t->finished.emit();
|
||||
|
@@ -14,6 +14,8 @@
|
||||
|
||||
namespace turbine {
|
||||
|
||||
using TimeMs = uint64_t;
|
||||
|
||||
ox::Result<ContextUPtr> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept;
|
||||
|
||||
ox::Error run(Context &ctx) noexcept;
|
||||
@@ -21,7 +23,7 @@ ox::Error run(Context &ctx) noexcept;
|
||||
// Returns the number of milliseconds that have passed since the start of the
|
||||
// program.
|
||||
[[nodiscard]]
|
||||
uint64_t ticksMs(Context const&ctx) noexcept;
|
||||
TimeMs ticksMs(Context const&ctx) noexcept;
|
||||
|
||||
void requestShutdown(Context &ctx) noexcept;
|
||||
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <keel/keel.hpp>
|
||||
#include <turbine/context.hpp>
|
||||
#include <turbine/gfx.hpp>
|
||||
#include <turbine/turbine.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
#include "turbine.hpp"
|
||||
@@ -71,7 +72,7 @@ ox::Result<ContextUPtr> init(
|
||||
void shutdown(Context&) noexcept {
|
||||
}
|
||||
|
||||
uint64_t ticksMs(Context const&) noexcept {
|
||||
TimeMs ticksMs(Context const&) noexcept {
|
||||
return g_timerMs;
|
||||
}
|
||||
|
||||
|
@@ -8,12 +8,13 @@
|
||||
#include <turbine/context.hpp>
|
||||
#include <turbine/gfx.hpp>
|
||||
#include <turbine/event.hpp>
|
||||
#include <turbine/turbine.hpp>
|
||||
|
||||
namespace turbine {
|
||||
|
||||
class Context {
|
||||
public:
|
||||
UpdateHandler updateHandler = [](Context&) -> int {return 0;};
|
||||
UpdateHandler updateHandler = [](Context&) -> int {return -1;};
|
||||
keel::Context keelCtx;
|
||||
KeyEventHandler keyEventHandler = nullptr;
|
||||
ox::AnyPtr applicationData;
|
||||
@@ -24,7 +25,7 @@ class Context {
|
||||
struct GLFWwindow *window = nullptr;
|
||||
int refreshWithinMs = 0;
|
||||
ox::Vector<gl::Drawer*, 5> drawers;
|
||||
int64_t startTime = 0;
|
||||
TimeMs startTime = 0;
|
||||
uint64_t wakeupTime = 0;
|
||||
uint64_t keysDown = 0;
|
||||
uint64_t prevFpsCheckTime = 0;
|
||||
|
@@ -45,7 +45,8 @@ ox::Result<ContextUPtr> init(
|
||||
auto ctx = ox::make_unique<Context>();
|
||||
oxReturnError(keel::init(ctx->keelCtx, std::move(fs), appName));
|
||||
using namespace std::chrono;
|
||||
ctx->startTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
||||
ctx->startTime = static_cast<TimeMs>(
|
||||
duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count());
|
||||
glfwInit();
|
||||
oxReturnError(initGfx(*ctx));
|
||||
glfwSetWindowSizeCallback(ctx->window, draw);
|
||||
@@ -67,24 +68,26 @@ static void tickFps(Context &ctx, uint64_t nowMs) noexcept {
|
||||
}
|
||||
|
||||
ox::Error run(Context &ctx) noexcept {
|
||||
int sleepTime = 0;
|
||||
uint64_t sleepTime = 0;
|
||||
while (!glfwWindowShouldClose(ctx.window)) {
|
||||
ctx.refreshWithinMs = 10 * 1000; // refresh within 10 seconds
|
||||
glfwPollEvents();
|
||||
auto const ticks = ticksMs(ctx);
|
||||
if (ctx.wakeupTime <= ticks) {
|
||||
sleepTime = ctx.updateHandler(ctx);
|
||||
if (sleepTime >= 0) {
|
||||
ctx.wakeupTime = ticks + static_cast<unsigned>(sleepTime);
|
||||
auto const st = ctx.updateHandler(ctx);
|
||||
if (st >= 0) {
|
||||
ctx.wakeupTime = ticks + static_cast<unsigned>(st);
|
||||
sleepTime = static_cast<uint64_t>(st);
|
||||
} else {
|
||||
ctx.wakeupTime = ~uint64_t(0);
|
||||
sleepTime = ctx.wakeupTime - ticks;
|
||||
}
|
||||
} else {
|
||||
sleepTime = static_cast<int>(ctx.wakeupTime - ticks);
|
||||
sleepTime = ctx.wakeupTime - ticks;
|
||||
}
|
||||
tickFps(ctx, ticks);
|
||||
draw(ctx);
|
||||
auto const realSleepTime = ox::min(ctx.refreshWithinMs, sleepTime);
|
||||
auto const realSleepTime = ox::min(static_cast<uint64_t>(ctx.refreshWithinMs), sleepTime);
|
||||
if (realSleepTime) {
|
||||
if (ctx.uninterruptedRefreshes) {
|
||||
--ctx.uninterruptedRefreshes;
|
||||
@@ -108,10 +111,10 @@ void shutdown(Context &ctx) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t ticksMs(Context const&ctx) noexcept {
|
||||
TimeMs ticksMs(Context const&ctx) noexcept {
|
||||
using namespace std::chrono;
|
||||
auto const now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
||||
return static_cast<uint64_t>(now - ctx.startTime);
|
||||
return static_cast<TimeMs>(now) - ctx.startTime;
|
||||
}
|
||||
|
||||
bool buttonDown(Context const&ctx, Key key) noexcept {
|
||||
|
Reference in New Issue
Block a user