[keel,studio] Add support for New Item templates
Some checks failed
Build / build (push) Failing after 1m3s

This commit is contained in:
2025-01-18 20:16:29 -06:00
parent b29b9a9b3a
commit 92e9d9cbfc
12 changed files with 341 additions and 93 deletions

View File

@@ -214,7 +214,8 @@ bool ListBox(
ox::CStringViewCR name,
std::function<ox::CStringView(size_t)> const&f,
size_t strCnt,
size_t &selIdx) noexcept;
size_t &selIdx,
ImVec2 const&sz = {0, 0}) noexcept;
/**
*

View File

@@ -4,7 +4,9 @@
#pragma once
#include <ox/claw/claw.hpp>
#include <algorithm>
#include <ox/model/typenamecatcher.hpp>
#include <keel/media.hpp>
#include <turbine/context.hpp>
@@ -13,75 +15,212 @@
namespace studio {
class ItemMaker {
class ItemTemplate {
private:
ox::String const m_name{"Default"};
public:
ox::String const typeName;
ox::String const parentDir;
ox::String const fileExt;
constexpr explicit ItemMaker(
explicit ItemTemplate() noexcept = default;
explicit ItemTemplate(ox::StringParam name) noexcept: m_name{std::move(name)} {}
virtual ~ItemTemplate() = default;
[[nodiscard]]
constexpr ox::String const&name() const noexcept {
return m_name;
}
constexpr bool operator<=>(ItemTemplate const&other) const noexcept {
return m_name != other.name() ? (m_name < other.name() ? -1 : 1) : 0;
}
[[nodiscard]]
ox::CStringView displayName() const noexcept {
return m_name;
}
[[nodiscard]]
virtual ox::CStringView typeName() const noexcept = 0;
[[nodiscard]]
virtual int typeVersion() const noexcept = 0;
virtual ox::Result<ox::UAnyPtr> getItem(
keel::Context &ctx, ox::StringViewCR name, int version) noexcept = 0;
};
template<typename T>
class ItemTemplateT: public ItemTemplate {
private:
T const m_item;
public:
constexpr ItemTemplateT() noexcept = default;
explicit ItemTemplateT(ox::StringParam name, T item) noexcept:
ItemTemplate{std::move(name)}, m_item{std::move(item)} {}
[[nodiscard]]
ox::CStringView typeName() const noexcept final {
return ox::ModelTypeName_v<T>;
}
[[nodiscard]]
int typeVersion() const noexcept final {
return ox::ModelTypeVersion_v<T>;
}
ox::Result<ox::UAnyPtr> getItem(
keel::Context &kctx, ox::StringViewCR name, int const version) noexcept final {
if (ox::ModelTypeVersion_v<T> != version || ox::ModelTypeName_v<T> != name) {
OX_REQUIRE_M(item, keel::convert(kctx, m_item, name, version));
auto out = ox::Result<ox::UAnyPtr>{item->moveToCopy()};
ox::safeDelete(item.release());
return out;
}
return ox::UAnyPtr{new T{m_item}};
}
};
class ItemMaker {
private:
ox::Vector<ox::UPtr<ItemTemplate>> m_templates;
ox::String const m_parentDir;
ox::String const m_fileExt;
ox::String const m_typeDisplayName;
public:
constexpr ItemMaker(
ox::StringParam pName,
ox::StringParam pParentDir,
ox::StringParam pFileExt) noexcept:
typeName{std::move(pName)},
parentDir{std::move(pParentDir)},
fileExt{std::move(pFileExt)} {
m_parentDir{std::move(pParentDir)},
m_fileExt{std::move(pFileExt)},
m_typeDisplayName{std::move(pName)} {
}
virtual ~ItemMaker() noexcept = default;
[[nodiscard]]
virtual ox::String itemPath(ox::StringView pName) const noexcept {
return ox::sfmt("/{}/{}.{}", parentDir, pName, fileExt);
ox::String const&typeDisplayName() const noexcept {
return m_typeDisplayName;
}
bool installTemplate(ox::UPtr<ItemTemplate> &tmpl) {
if (typeName() == tmpl->typeName() &&
typeVersion() <= tmpl->typeVersion()) {
m_templates.emplace_back(std::move(tmpl));
// begin() + 1 because 'Default' should always be first
std::sort(m_templates.begin() + 1, m_templates.end());
return true;
}
return false;
}
bool installTemplate(ox::UPtr<ItemTemplate> &&tmpl) {
return installTemplate(tmpl);
}
constexpr ox::Vector<ox::UPtr<ItemTemplate>> const&itemTemplates() const noexcept {
return m_templates;
}
[[nodiscard]]
ox::String itemPath(ox::StringViewCR pName) const noexcept {
return ox::sfmt("/{}/{}.{}", m_parentDir, pName, m_fileExt);
}
[[nodiscard]]
virtual ox::StringView typeName() const noexcept = 0;
[[nodiscard]]
virtual int typeVersion() const noexcept = 0;
/**
* Returns path of the file created.
* @param ctx
* @param pName
* @param pTemplateIdx
* @return path of file or error in Result
*/
virtual ox::Result<ox::String> write(StudioContext &ctx, ox::StringView pName) const noexcept = 0;
virtual ox::Result<ox::String> write(
StudioContext &ctx, ox::StringViewCR pName, size_t pTemplateIdx) const noexcept = 0;
};
template<typename T>
class ItemMakerT: public ItemMaker {
class ItemMakerT final: public ItemMaker {
private:
T const m_item;
ox::ClawFormat const m_fmt;
public:
constexpr ItemMakerT(
ox::StringParam pDisplayName,
ox::StringParam pParentDir,
ox::StringParam fileExt,
ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept:
ItemMaker(std::move(pDisplayName), std::move(pParentDir), std::move(fileExt)),
m_fmt(pFmt) {
ox::ClawFormat const pFmt = ox::ClawFormat::Metal) noexcept:
ItemMaker(
std::move(pDisplayName),
std::move(pParentDir),
std::move(fileExt)),
m_fmt{pFmt} {
installTemplate(ox::make_unique<ItemTemplateT<T>>());
}
constexpr ItemMakerT(
ox::StringParam pDisplayName,
ox::StringParam pParentDir,
ox::StringParam fileExt,
T pItem,
ox::ClawFormat pFmt) noexcept:
ItemMaker(std::move(pDisplayName), std::move(pParentDir), std::move(fileExt)),
m_item(std::move(pItem)),
m_fmt(pFmt) {
T const&pItem,
ox::ClawFormat const pFmt) noexcept:
ItemMaker(
std::move(pDisplayName),
std::move(pParentDir),
std::move(fileExt)),
m_fmt{pFmt} {
installTemplate(ox::make_unique<ItemTemplateT<T>>(std::move(pItem)));
}
constexpr ItemMakerT(
ox::StringParam pDisplayName,
ox::StringParam pParentDir,
ox::StringParam fileExt,
T &&pItem,
ox::ClawFormat pFmt) noexcept:
ItemMaker(std::move(pDisplayName), std::move(pParentDir), std::move(fileExt)),
m_item(std::move(pItem)),
m_fmt(pFmt) {
ox::ClawFormat const pFmt) noexcept:
ItemMaker(
std::move(pDisplayName),
std::move(pParentDir),
std::move(fileExt)),
m_fmt{pFmt} {
installTemplate(ox::make_unique<ItemTemplateT<T>>(std::move(pItem)));
}
ox::Result<ox::String> write(studio::StudioContext &sctx, ox::StringView const pName) const noexcept override {
ox::StringView typeName() const noexcept override {
return ox::ModelTypeName_v<T>;
}
int typeVersion() const noexcept override {
return ox::ModelTypeVersion_v<T>;
}
ox::Result<ox::String> write(
StudioContext &sctx,
ox::StringViewCR pName,
size_t const pTemplateIdx) const noexcept override {
auto const path = itemPath(pName);
createUuidMapping(keelCtx(sctx.tctx), path, ox::UUID::generate().unwrap());
OX_RETURN_ERROR(sctx.project->writeObj(path, m_item, m_fmt));
auto const&templates = itemTemplates();
auto const tmplIdx = pTemplateIdx < templates.size() ? pTemplateIdx : 0;
OX_REQUIRE_M(tmpl, templates[tmplIdx]->getItem(
keelCtx(sctx), typeName(), typeVersion()));
auto item = tmpl.template get<T>();
OX_RETURN_ERROR(sctx.project->writeObj(path, *item, m_fmt));
tmpl.free();
return path;
}
};
}

View File

@@ -31,6 +31,8 @@ class Module {
virtual ox::Vector<ox::UPtr<ItemMaker>> itemMakers(studio::StudioContext&) const;
virtual ox::Vector<ox::UPtr<ItemTemplate>> itemTemplates(studio::StudioContext&) const;
};
template<typename Editor>

View File

@@ -47,7 +47,7 @@ class Popup {
return m_title;
}
void drawWindow(turbine::Context &ctx, bool *open, std::function<void()> const&drawContents);
void drawWindow(turbine::Context &ctx, bool &open, std::function<void()> const&drawContents);
};