Compare commits
No commits in common. "27b38ed250e3cbd3b2539e771b3352dd2d87962b" and "19a4120113fa29a35c4bc60beb92da687ff1ac43" have entirely different histories.
27b38ed250
...
19a4120113
15
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
15
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
@ -99,21 +99,6 @@ class FileSystem {
|
|||||||
|
|
||||||
Result<FileStat> stat(const FileAddress &addr) const noexcept;
|
Result<FileStat> stat(const FileAddress &addr) const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline bool exists(uint64_t inode) const noexcept {
|
|
||||||
return statInode(inode).ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline bool exists(ox::StringView path) const noexcept {
|
|
||||||
return statPath(path).ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline bool exists(FileAddress const&addr) const noexcept {
|
|
||||||
return stat(addr).ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
virtual uint64_t spaceNeeded(uint64_t size) const noexcept = 0;
|
virtual uint64_t spaceNeeded(uint64_t size) const noexcept = 0;
|
||||||
|
|
||||||
|
@ -4,10 +4,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef OX_BARE_METAL
|
|
||||||
#include <functional>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <ox/event/signal.hpp>
|
#include <ox/event/signal.hpp>
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
#include <ox/model/typenamecatcher.hpp>
|
#include <ox/model/typenamecatcher.hpp>
|
||||||
@ -182,11 +178,9 @@ constexpr AssetRef<T>::AssetRef(AssetRef &&h) noexcept: m_ctr(h.m_ctr) {
|
|||||||
h.m_ctr = nullptr;
|
h.m_ctr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Context;
|
|
||||||
|
|
||||||
class AssetManager {
|
class AssetManager {
|
||||||
private:
|
private:
|
||||||
class AssetTypeManagerBase: public ox::SignalHandler {
|
class AssetTypeManagerBase {
|
||||||
public:
|
public:
|
||||||
virtual ~AssetTypeManagerBase() = default;
|
virtual ~AssetTypeManagerBase() = default;
|
||||||
|
|
||||||
@ -195,24 +189,17 @@ class AssetManager {
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class AssetTypeManager: public AssetTypeManagerBase {
|
class AssetTypeManager: public AssetTypeManagerBase {
|
||||||
public:
|
|
||||||
using Loader = std::function<ox::Result<T>(ox::StringView assetId)>;
|
|
||||||
private:
|
private:
|
||||||
Loader m_loader{};
|
|
||||||
ox::HashMap<ox::String, ox::UPtr<AssetContainer<T>>> m_cache;
|
ox::HashMap<ox::String, ox::UPtr<AssetContainer<T>>> m_cache;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AssetTypeManager(Loader loader) noexcept: m_loader(loader) {}
|
ox::Result<AssetRef<T>> getAsset(ox::StringView const&assetId) const noexcept {
|
||||||
|
auto out = m_cache.at(assetId);
|
||||||
ox::Result<AssetRef<T>> getAsset(ox::StringView const assetId) const noexcept {
|
oxReturnError(out);
|
||||||
oxRequire(out, m_cache.at(assetId));
|
return AssetRef<T>(out.value->get());
|
||||||
if (!out || !*out) {
|
|
||||||
return OxError(1, "asset is null");
|
|
||||||
}
|
|
||||||
return AssetRef<T>(out->get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<AssetRef<T>> setAsset(ox::StringView const assetId, T const&obj) noexcept {
|
ox::Result<AssetRef<T>> setAsset(ox::StringView const&assetId, T const&obj) noexcept {
|
||||||
auto &p = m_cache[assetId];
|
auto &p = m_cache[assetId];
|
||||||
if (!p) {
|
if (!p) {
|
||||||
p = ox::make_unique<AssetContainer<T>>(obj);
|
p = ox::make_unique<AssetContainer<T>>(obj);
|
||||||
@ -223,7 +210,7 @@ class AssetManager {
|
|||||||
return AssetRef<T>(p.get());
|
return AssetRef<T>(p.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<AssetRef<T>> setAsset(ox::StringView const assetId, T &&obj) noexcept {
|
ox::Result<AssetRef<T>> setAsset(ox::StringView const&assetId, T &&obj) noexcept {
|
||||||
auto &p = m_cache[assetId];
|
auto &p = m_cache[assetId];
|
||||||
if (!p) {
|
if (!p) {
|
||||||
p = ox::make_unique<AssetContainer<T>>(obj);
|
p = ox::make_unique<AssetContainer<T>>(obj);
|
||||||
@ -234,30 +221,6 @@ class AssetManager {
|
|||||||
return AssetRef<T>(p.get());
|
return AssetRef<T>(p.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<AssetRef<T>> loadAsset(ox::StringView const assetId) noexcept {
|
|
||||||
auto &p = m_cache[assetId];
|
|
||||||
oxRequireM(obj, m_loader(assetId));
|
|
||||||
if (!p) {
|
|
||||||
p = ox::make_unique<AssetContainer<T>>(std::move(obj));
|
|
||||||
} else {
|
|
||||||
p->set(std::move(obj));
|
|
||||||
p->updated.emit();
|
|
||||||
}
|
|
||||||
return AssetRef<T>(p.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Error reloadAsset(ox::StringView const assetId) noexcept {
|
|
||||||
auto &p = m_cache[assetId];
|
|
||||||
oxRequireM(obj, m_loader(assetId));
|
|
||||||
if (!p) {
|
|
||||||
p = ox::make_unique<AssetContainer<T>>(std::move(obj));
|
|
||||||
} else {
|
|
||||||
p->set(std::move(obj));
|
|
||||||
p->updated.emit();
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void gc() noexcept final {
|
void gc() noexcept final {
|
||||||
for (auto const&ack : m_cache.keys()) {
|
for (auto const&ack : m_cache.keys()) {
|
||||||
auto &ac = m_cache[ack];
|
auto &ac = m_cache[ack];
|
||||||
@ -269,58 +232,29 @@ class AssetManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ox::HashMap<ox::String, ox::UPtr<AssetTypeManagerBase>> m_assetTypeManagers;
|
ox::HashMap<ox::String, ox::UPtr<AssetTypeManagerBase>> m_assetTypeManagers;
|
||||||
struct FileTracker {
|
|
||||||
ox::Signal<ox::Error(ox::StringView assetId)> updated;
|
|
||||||
};
|
|
||||||
ox::HashMap<ox::String, FileTracker> m_fileTrackers;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<AssetTypeManager<T>*> getTypeManager() noexcept {
|
AssetTypeManager<T> *getTypeManager() noexcept {
|
||||||
constexpr auto &typeId = ox::ModelTypeId_v<T>;
|
constexpr auto typeName = ox::requireModelTypeName<T>();
|
||||||
static_assert(typeId != "", "Types must have TypeName to use AssetManager");
|
static_assert(ox::StringView(typeName) != "", "Types must have TypeName to use AssetManager");
|
||||||
auto &am = m_assetTypeManagers[typeId];
|
auto &am = m_assetTypeManagers[typeName];
|
||||||
auto const out = dynamic_cast<AssetTypeManager<T>*>(am.get());
|
if (!am) {
|
||||||
if (!out) {
|
am = ox::make_unique<AssetTypeManager<T>>();
|
||||||
return OxError(1, "no AssetTypeManager for type");
|
|
||||||
}
|
}
|
||||||
return out;
|
return dynamic_cast<AssetTypeManager<T>*>(am.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void initTypeManager(auto const&makeLoader, Context &ctx) noexcept {
|
ox::Result<AssetRef<T>> getAsset(ox::CRStringView assetId) noexcept {
|
||||||
constexpr auto &typeId = ox::ModelTypeId_v<T>;
|
auto m = getTypeManager<T>();
|
||||||
static_assert(typeId != "", "Types must have TypeName to use AssetManager");
|
|
||||||
auto &am = m_assetTypeManagers[typeId];
|
|
||||||
if (!am) {
|
|
||||||
am = ox::make_unique<AssetTypeManager<T>>(makeLoader(ctx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ox::Result<AssetRef<T>> getAsset(ox::StringView assetId) noexcept {
|
|
||||||
oxRequire(m, getTypeManager<T>());
|
|
||||||
return m->getAsset(assetId);
|
return m->getAsset(assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<AssetRef<T>> setAsset(ox::StringView assetId, T const&obj) noexcept {
|
ox::Result<AssetRef<T>> setAsset(ox::CRStringView assetId, T const&obj) noexcept {
|
||||||
oxRequire(m, getTypeManager<T>());
|
auto m = getTypeManager<T>();
|
||||||
oxReturnError(m->setAsset(assetId, obj));
|
return m->setAsset(assetId, obj);
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Error reloadAsset(ox::StringView assetId) noexcept {
|
|
||||||
m_fileTrackers[assetId].updated.emit(assetId);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ox::Result<AssetRef<T>> loadAsset(ox::StringView assetId) noexcept {
|
|
||||||
oxRequire(m, getTypeManager<T>());
|
|
||||||
oxRequire(out, m->loadAsset(assetId));
|
|
||||||
m_fileTrackers[assetId].updated.connect(m, &AssetTypeManager<T>::reloadAsset);
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc() noexcept {
|
void gc() noexcept {
|
||||||
|
@ -32,43 +32,14 @@ oxModelEnd()
|
|||||||
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&file) noexcept;
|
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&file) noexcept;
|
||||||
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::CRStringView file) noexcept;
|
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::CRStringView file) noexcept;
|
||||||
|
|
||||||
|
|
||||||
void createUuidMapping(Context &ctx, ox::StringView filePath, ox::UUID const&uuid) noexcept;
|
|
||||||
|
|
||||||
ox::Error buildUuidMap(Context &ctx) noexcept;
|
|
||||||
|
|
||||||
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept;
|
|
||||||
|
|
||||||
ox::Result<ox::UUID> getUuid(Context &ctx, ox::FileAddress const&fileAddr) noexcept;
|
|
||||||
|
|
||||||
ox::Result<ox::UUID> getUuid(Context &ctx, ox::StringView path) noexcept;
|
|
||||||
|
|
||||||
ox::Result<ox::CStringView> getPath(Context &ctx, ox::FileAddress const&fileAddr) noexcept;
|
|
||||||
|
|
||||||
ox::Result<ox::CStringView> getPath(Context &ctx, ox::CStringView fileId) noexcept;
|
|
||||||
|
|
||||||
constexpr ox::Result<ox::UUID> uuidUrlToUuid(ox::StringView uuidUrl) noexcept {
|
|
||||||
return ox::UUID::fromString(substr(uuidUrl, 7));
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<ox::CStringView> uuidUrlToPath(Context &ctx, ox::StringView uuid) noexcept;
|
|
||||||
|
|
||||||
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept;
|
|
||||||
|
|
||||||
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
|
|
||||||
|
|
||||||
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept;
|
|
||||||
|
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr auto makeLoader(Context &ctx) {
|
ox::Result<keel::AssetRef<T>> readObjFile(
|
||||||
return [&ctx](ox::StringView assetId) -> ox::Result<T> {
|
keel::Context &ctx,
|
||||||
ox::StringView path;
|
ox::StringView assetId,
|
||||||
oxRequire(p, ctx.uuidToPath.at(assetId));
|
bool forceLoad) noexcept {
|
||||||
path = *p;
|
constexpr auto readConvert = [](Context &ctx, const ox::Buffer &buff) -> ox::Result<T> {
|
||||||
oxRequire(buff, ctx.rom->read(path));
|
|
||||||
auto [obj, err] = readAsset<T>(buff);
|
auto [obj, err] = readAsset<T>(buff);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
||||||
@ -78,34 +49,25 @@ constexpr auto makeLoader(Context &ctx) {
|
|||||||
}
|
}
|
||||||
return std::move(obj);
|
return std::move(obj);
|
||||||
};
|
};
|
||||||
};
|
ox::StringView path;
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ox::Result<keel::AssetRef<T>> readObjFile(
|
|
||||||
keel::Context &ctx,
|
|
||||||
ox::StringView assetId,
|
|
||||||
bool forceLoad) noexcept {
|
|
||||||
ox::UUIDStr uuidStr;
|
|
||||||
if (beginsWith(assetId, "uuid://")) {
|
if (beginsWith(assetId, "uuid://")) {
|
||||||
assetId = substr(assetId, 7);
|
assetId = substr(assetId, 7);
|
||||||
oxRequire(p, keel::uuidToPath(ctx, assetId));
|
oxRequire(p, ctx.uuidToPath.at(assetId));
|
||||||
|
path = *p;
|
||||||
} else {
|
} else {
|
||||||
auto const [uuid, uuidErr] = getUuid(ctx, assetId);
|
path = assetId;
|
||||||
if (!uuidErr) {
|
|
||||||
uuidStr = uuid.toString();
|
|
||||||
assetId = uuidStr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (forceLoad) {
|
if (forceLoad) {
|
||||||
ctx.assetManager.initTypeManager<T>(detail::makeLoader<T>, ctx);
|
oxRequire(buff, ctx.rom->read(path));
|
||||||
oxRequire(cached, ctx.assetManager.loadAsset<T>(assetId));
|
oxRequire(obj, readConvert(ctx, buff));
|
||||||
|
oxRequire(cached, ctx.assetManager.setAsset(assetId, obj));
|
||||||
return cached;
|
return cached;
|
||||||
} else {
|
} else {
|
||||||
auto [cached, err] = ctx.assetManager.getAsset<T>(assetId);
|
auto [cached, err] = ctx.assetManager.getAsset<T>(assetId);
|
||||||
if (err) {
|
if (err) {
|
||||||
ctx.assetManager.initTypeManager<T>(detail::makeLoader<T>, ctx);
|
oxRequire(buff, ctx.rom->read(path));
|
||||||
oxReturnError(ctx.assetManager.loadAsset<T>(assetId).moveTo(cached));
|
oxRequire(obj, readConvert(ctx, buff));
|
||||||
|
oxReturnError(ctx.assetManager.setAsset(assetId, obj).moveTo(cached));
|
||||||
}
|
}
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
@ -127,24 +89,37 @@ ox::Result<keel::AssetRef<T>> readObjNoCache(
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ox::Error reloadAsset(keel::Context &ctx, ox::StringView assetId) noexcept;
|
void createUuidMapping(Context &ctx, ox::StringView filePath, ox::UUID const&uuid) noexcept;
|
||||||
|
|
||||||
|
ox::Error buildUuidMap(Context &ctx) noexcept;
|
||||||
|
|
||||||
|
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept;
|
||||||
|
|
||||||
|
constexpr ox::Result<ox::UUID> uuidUrlToUuid(ox::StringView uuidUrl) noexcept {
|
||||||
|
return ox::UUID::fromString(substr(uuidUrl, 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<ox::CStringView> uuidUrlToPath(Context &ctx, ox::StringView uuid) noexcept;
|
||||||
|
|
||||||
|
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept;
|
||||||
|
|
||||||
|
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
|
||||||
|
|
||||||
|
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<AssetRef<T>> setAsset(
|
ox::Result<AssetRef<T>> setAsset(keel::Context &ctx, ox::StringView assetId, T const&asset) noexcept {
|
||||||
keel::Context &ctx,
|
|
||||||
ox::StringView assetId,
|
|
||||||
T const&asset) noexcept {
|
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
if (assetId.len() == 0) {
|
if (assetId.len() == 0) {
|
||||||
return OxError(1, "Invalid asset ID");
|
return OxError(1, "Invalid asset ID");
|
||||||
}
|
}
|
||||||
ox::UUIDStr uuidStr;
|
ox::UUIDStr idStr;
|
||||||
if (assetId[0] == '/') {
|
if (assetId[0] == '/') {
|
||||||
oxRequire(id, ctx.pathToUuid.at(assetId));
|
auto const [id, err] = ctx.pathToUuid.at(assetId);
|
||||||
uuidStr = id->toString();
|
oxReturnError(err);
|
||||||
assetId = uuidStr;
|
idStr = id->toString();
|
||||||
|
assetId = idStr;
|
||||||
}
|
}
|
||||||
ctx.assetManager.initTypeManager<T>(detail::makeLoader<T>, ctx);
|
|
||||||
return ctx.assetManager.setAsset(assetId, asset);
|
return ctx.assetManager.setAsset(assetId, asset);
|
||||||
#else
|
#else
|
||||||
return OxError(1, "Not supported on this platform");
|
return OxError(1, "Not supported on this platform");
|
||||||
|
@ -83,49 +83,6 @@ ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<ox::UUID> getUuid(Context &ctx, ox::FileAddress const&fileAddr) noexcept {
|
|
||||||
oxRequire(path, fileAddr.getPath());
|
|
||||||
return getUuid(ctx, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<ox::UUID> getUuid(Context &ctx, ox::StringView path) noexcept {
|
|
||||||
if (beginsWith(path, "uuid://")) {
|
|
||||||
auto const uuid = substr(path, 7);
|
|
||||||
return ox::UUID::fromString(uuid);
|
|
||||||
} else {
|
|
||||||
return pathToUuid(ctx, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<ox::CStringView> getPath(Context &ctx, ox::FileAddress const&fileAddr) noexcept {
|
|
||||||
oxRequire(path, fileAddr.getPath());
|
|
||||||
if (beginsWith(path, "uuid://")) {
|
|
||||||
auto const uuid = substr(path, 7);
|
|
||||||
#ifndef OX_BARE_METAL
|
|
||||||
oxRequireM(out, ctx.uuidToPath.at(uuid));
|
|
||||||
return ox::CStringView{*out};
|
|
||||||
#else
|
|
||||||
return OxError(1, "UUID to path conversion not supported on this platform");
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
return ox::CStringView{path};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<ox::CStringView> getPath(Context &ctx, ox::CStringView fileId) noexcept {
|
|
||||||
if (beginsWith(fileId, "uuid://")) {
|
|
||||||
auto const uuid = substr(fileId, 7);
|
|
||||||
#ifndef OX_BARE_METAL
|
|
||||||
oxRequireM(out, ctx.uuidToPath.at(uuid));
|
|
||||||
return ox::CStringView{*out};
|
|
||||||
#else
|
|
||||||
return OxError(1, "UUID to path conversion not supported on this platform");
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
return ox::CStringView{fileId};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<ox::CStringView> uuidUrlToPath(Context &ctx, ox::StringView uuid) noexcept {
|
ox::Result<ox::CStringView> uuidUrlToPath(Context &ctx, ox::StringView uuid) noexcept {
|
||||||
uuid = substr(uuid, 7);
|
uuid = substr(uuid, 7);
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
@ -166,21 +123,6 @@ ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error reloadAsset(keel::Context &ctx, ox::StringView assetId) noexcept {
|
|
||||||
ox::UUIDStr uuidStr;
|
|
||||||
if (beginsWith(assetId, "uuid://")) {
|
|
||||||
assetId = substr(assetId, 7);
|
|
||||||
oxRequire(p, keel::uuidToPath(ctx, assetId));
|
|
||||||
} else {
|
|
||||||
auto const [uuid, uuidErr] = getUuid(ctx, assetId);
|
|
||||||
if (!uuidErr) {
|
|
||||||
uuidStr = uuid.toString();
|
|
||||||
assetId = uuidStr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ctx.assetManager.reloadAsset(assetId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -234,10 +176,6 @@ ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const
|
|||||||
return static_cast<std::size_t>(p.preloadAddr) + ctx.preloadSectionOffset;
|
return static_cast<std::size_t>(p.preloadAddr) + ctx.preloadSectionOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error reloadAsset(keel::Context&, ox::StringView) noexcept {
|
|
||||||
return OxError(1, "reloadAsset is unsupported on this platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -148,19 +148,6 @@ bool BeginPopup(turbine::Context &ctx, ox::CStringView popupName, bool &show, Im
|
|||||||
*/
|
*/
|
||||||
bool ComboBox(ox::CStringView lbl, ox::SpanView<ox::String> list, size_t &selectedIdx) noexcept;
|
bool ComboBox(ox::CStringView lbl, ox::SpanView<ox::String> list, size_t &selectedIdx) noexcept;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param lbl
|
|
||||||
* @param callback
|
|
||||||
* @param selectedIdx
|
|
||||||
* @return true if new value selected, false otherwise
|
|
||||||
*/
|
|
||||||
bool ComboBox(
|
|
||||||
ox::CStringView lbl,
|
|
||||||
std::function<ox::CStringView(size_t)> const&f,
|
|
||||||
size_t strCnt,
|
|
||||||
size_t &selectedIdx) noexcept;
|
|
||||||
|
|
||||||
bool FileComboBox(
|
bool FileComboBox(
|
||||||
ox::CStringView lbl,
|
ox::CStringView lbl,
|
||||||
studio::StudioContext &sctx,
|
studio::StudioContext &sctx,
|
||||||
|
@ -31,7 +31,7 @@ enum class ProjectEvent {
|
|||||||
constexpr ox::Result<ox::StringView> fileExt(ox::CRStringView path) noexcept {
|
constexpr ox::Result<ox::StringView> fileExt(ox::CRStringView path) noexcept {
|
||||||
auto const extStart = ox::find(path.crbegin(), path.crend(), '.').offset();
|
auto const extStart = ox::find(path.crbegin(), path.crend(), '.').offset();
|
||||||
if (!extStart) {
|
if (!extStart) {
|
||||||
return OxError(1, "file path does not have valid extension");
|
return OxError(1, "Cannot open a file without valid extension.");
|
||||||
}
|
}
|
||||||
return substr(path, extStart + 1);
|
return substr(path, extStart + 1);
|
||||||
}
|
}
|
||||||
@ -47,7 +47,6 @@ constexpr ox::StringView parentDir(ox::StringView path) noexcept {
|
|||||||
|
|
||||||
class Project {
|
class Project {
|
||||||
private:
|
private:
|
||||||
ox::SmallMap<ox::String, ox::Optional<ox::ClawFormat>> m_typeFmt;
|
|
||||||
keel::Context &m_ctx;
|
keel::Context &m_ctx;
|
||||||
ox::String m_path;
|
ox::String m_path;
|
||||||
ox::String m_projectDataDir;
|
ox::String m_projectDataDir;
|
||||||
@ -76,15 +75,7 @@ class Project {
|
|||||||
ox::Error writeObj(
|
ox::Error writeObj(
|
||||||
ox::CRStringView path,
|
ox::CRStringView path,
|
||||||
T const&obj,
|
T const&obj,
|
||||||
ox::ClawFormat fmt) noexcept;
|
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept;
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a MetalClaw object to the project at the given path.
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
ox::Error writeObj(
|
|
||||||
ox::CRStringView path,
|
|
||||||
T const&obj) noexcept;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<T> loadObj(ox::CRStringView path) const noexcept;
|
ox::Result<T> loadObj(ox::CRStringView path) const noexcept;
|
||||||
@ -139,24 +130,16 @@ ox::Error Project::writeObj(ox::CRStringView path, T const&obj, ox::ClawFormat f
|
|||||||
oxReturnError(ox::buildTypeDef(&m_typeStore, &obj));
|
oxReturnError(ox::buildTypeDef(&m_typeStore, &obj));
|
||||||
}
|
}
|
||||||
oxRequire(desc, m_typeStore.get<T>());
|
oxRequire(desc, m_typeStore.get<T>());
|
||||||
auto const descPath = ox::sfmt("{}/{}", m_typeDescPath, buildTypeId(*desc));
|
auto const descExists = m_fs.stat(ox::sfmt("{}/{}", m_typeDescPath, buildTypeId(*desc))).error != 0;
|
||||||
auto const descExists = m_fs.exists(descPath);
|
|
||||||
if (!descExists) {
|
if (!descExists) {
|
||||||
oxReturnError(writeTypeStore());
|
oxReturnError(writeTypeStore());
|
||||||
}
|
}
|
||||||
oxReturnError(keel::reloadAsset(m_ctx, path));
|
oxReturnError(keel::setAsset(m_ctx, path, obj));
|
||||||
oxRequire(uuid, pathToUuid(m_ctx, path));
|
oxRequire(uuid, pathToUuid(m_ctx, path));
|
||||||
fileUpdated.emit(path, uuid);
|
fileUpdated.emit(path, uuid);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ox::Error Project::writeObj(ox::CRStringView path, T const&obj) noexcept {
|
|
||||||
oxRequire(ext, fileExt(path));
|
|
||||||
auto const fmt = m_typeFmt[ext].or_value(ox::ClawFormat::Metal);
|
|
||||||
return writeObj(path, obj, fmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<T> Project::loadObj(ox::CRStringView path) const noexcept {
|
ox::Result<T> Project::loadObj(ox::CRStringView path) const noexcept {
|
||||||
oxRequire(buff, loadBuff(path));
|
oxRequire(buff, loadBuff(path));
|
||||||
|
@ -9,11 +9,7 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
struct Selection {
|
struct Selection {ox::Point a, b;};
|
||||||
ox::Point a, b;
|
|
||||||
constexpr Selection() noexcept = default;
|
|
||||||
constexpr Selection(ox::Point const&pA, ox::Point const&pB) noexcept: a(pA), b(pB) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr auto iterateSelection(studio::Selection const&sel, auto const&cb) {
|
constexpr auto iterateSelection(studio::Selection const&sel, auto const&cb) {
|
||||||
constexpr auto retErr = ox::is_same_v<decltype(cb(0, 0)), ox::Error>;
|
constexpr auto retErr = ox::is_same_v<decltype(cb(0, 0)), ox::Error>;
|
||||||
|
@ -100,26 +100,6 @@ bool ComboBox(
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ComboBox(
|
|
||||||
ox::CStringView lbl,
|
|
||||||
std::function<ox::CStringView(size_t)> const&f,
|
|
||||||
size_t strCnt,
|
|
||||||
size_t &selectedIdx) noexcept {
|
|
||||||
bool out{};
|
|
||||||
auto const first = selectedIdx < strCnt ? f(selectedIdx).c_str() : "";
|
|
||||||
if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
|
|
||||||
for (auto i = 0u; i < strCnt; ++i) {
|
|
||||||
const auto selected = (selectedIdx == i);
|
|
||||||
if (ImGui::Selectable(f(i).c_str(), selected) && selectedIdx != i) {
|
|
||||||
selectedIdx = i;
|
|
||||||
out = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndCombo();
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileComboBox(
|
bool FileComboBox(
|
||||||
ox::CStringView lbl,
|
ox::CStringView lbl,
|
||||||
studio::StudioContext &sctx,
|
studio::StudioContext &sctx,
|
||||||
|
@ -56,13 +56,9 @@ ox::FileSystem &Project::romFs() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Error Project::mkdir(ox::CRStringView path) const noexcept {
|
ox::Error Project::mkdir(ox::CRStringView path) const noexcept {
|
||||||
auto const [stat, err] = m_fs.stat(path);
|
|
||||||
if (err) {
|
|
||||||
oxReturnError(m_fs.mkdir(path, true));
|
oxReturnError(m_fs.mkdir(path, true));
|
||||||
fileUpdated.emit(path, {});
|
fileUpdated.emit(path, {});
|
||||||
}
|
return {};
|
||||||
return stat.fileType == ox::FileType::Directory ?
|
|
||||||
ox::Error{} : OxError(1, "path exists as normal file");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<ox::FileStat> Project::stat(ox::CRStringView path) const noexcept {
|
ox::Result<ox::FileStat> Project::stat(ox::CRStringView path) const noexcept {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user