[keel,studio] Add support for New Item templates
Some checks failed
Build / build (push) Failing after 1m3s
Some checks failed
Build / build (push) Failing after 1m3s
This commit is contained in:
parent
b29b9a9b3a
commit
92e9d9cbfc
@ -20,6 +20,8 @@ class Wrap {
|
|||||||
virtual ox::CStringView typeName() const noexcept = 0;
|
virtual ox::CStringView typeName() const noexcept = 0;
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
virtual int typeVersion() const noexcept = 0;
|
virtual int typeVersion() const noexcept = 0;
|
||||||
|
[[nodiscard]]
|
||||||
|
virtual ox::UAnyPtr moveToCopy() noexcept = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -27,6 +29,11 @@ class WrapT: public Wrap {
|
|||||||
public:
|
public:
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
virtual constexpr T &obj() noexcept = 0;
|
virtual constexpr T &obj() noexcept = 0;
|
||||||
|
|
||||||
|
ox::UAnyPtr moveToCopy() noexcept final {
|
||||||
|
return new T{std::move(obj())};
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -184,7 +191,18 @@ ox::Result<ox::UPtr<Wrap>> convert(
|
|||||||
auto &src,
|
auto &src,
|
||||||
ox::StringViewCR dstTypeName,
|
ox::StringViewCR dstTypeName,
|
||||||
int const dstTypeVersion) noexcept {
|
int const dstTypeVersion) noexcept {
|
||||||
return convert(ctx, WrapRef{src}, dstTypeName, dstTypeVersion);
|
WrapRef ref{src};
|
||||||
|
return convert(ctx, static_cast<Wrap&>(ref), dstTypeName, dstTypeVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<ox::UPtr<Wrap>> convert(
|
||||||
|
keel::Context &ctx,
|
||||||
|
auto const&src,
|
||||||
|
ox::StringViewCR dstTypeName,
|
||||||
|
int const dstTypeVersion) noexcept {
|
||||||
|
auto srcCpy = src;
|
||||||
|
WrapRef ref{srcCpy};
|
||||||
|
return convert(ctx, ref, dstTypeName, dstTypeVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename DstType>
|
template<typename DstType>
|
||||||
|
@ -14,7 +14,7 @@ namespace studio {
|
|||||||
|
|
||||||
NewMenu::NewMenu() noexcept {
|
NewMenu::NewMenu() noexcept {
|
||||||
setTitle("New Item");
|
setTitle("New Item");
|
||||||
setSize({230, 140});
|
setSize({280, 180});
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewMenu::open() noexcept {
|
void NewMenu::open() noexcept {
|
||||||
@ -33,7 +33,7 @@ bool NewMenu::isOpen() const noexcept {
|
|||||||
return m_open;
|
return m_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewMenu::draw(studio::StudioContext &sctx) noexcept {
|
void NewMenu::draw(StudioContext &sctx) noexcept {
|
||||||
switch (m_stage) {
|
switch (m_stage) {
|
||||||
case Stage::Opening:
|
case Stage::Opening:
|
||||||
ImGui::OpenPopup(title().c_str());
|
ImGui::OpenPopup(title().c_str());
|
||||||
@ -46,51 +46,73 @@ void NewMenu::draw(studio::StudioContext &sctx) noexcept {
|
|||||||
case Stage::NewItemName:
|
case Stage::NewItemName:
|
||||||
drawNewItemName(sctx);
|
drawNewItemName(sctx);
|
||||||
break;
|
break;
|
||||||
|
case Stage::NewItemTemplate:
|
||||||
|
drawNewItemTemplate(sctx);
|
||||||
|
break;
|
||||||
case Stage::Closed:
|
case Stage::Closed:
|
||||||
m_open = false;
|
m_open = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewMenu::addItemMaker(ox::UniquePtr<studio::ItemMaker> &&im) noexcept {
|
void NewMenu::addItemMaker(ox::UPtr<ItemMaker> &&im) noexcept {
|
||||||
m_types.emplace_back(std::move(im));
|
m_types.emplace_back(std::move(im));
|
||||||
std::sort(
|
std::sort(
|
||||||
m_types.begin(), m_types.end(),
|
m_types.begin(), m_types.end(),
|
||||||
[](ox::UPtr<ItemMaker> const&im1, ox::UPtr<ItemMaker> const&im2) {
|
[](ox::UPtr<ItemMaker> const&im1, ox::UPtr<ItemMaker> const&im2) {
|
||||||
return im1->typeName < im2->typeName;
|
return im1->typeDisplayName() < im2->typeDisplayName();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewMenu::drawNewItemType(studio::StudioContext &sctx) noexcept {
|
void NewMenu::installItemTemplate(ox::UPtr<ItemTemplate> &tmplt) noexcept {
|
||||||
drawWindow(sctx.tctx, &m_open, [this] {
|
for (auto const&im : m_types) {
|
||||||
auto const allocSz = m_types.size() * sizeof(char const*);
|
if (im->installTemplate(tmplt)) {
|
||||||
auto mem = ox_malloca(allocSz, char const*, nullptr);
|
break;
|
||||||
auto items = ox::Span{mem.get(), allocSz};
|
|
||||||
for (auto i = 0u; auto const&im : m_types) {
|
|
||||||
items[i] = im->typeName.c_str();
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
ImGui::ListBox("Item Type", &m_selectedType, items.data(), static_cast<int>(m_types.size()));
|
}
|
||||||
drawFirstPageButtons();
|
}
|
||||||
|
|
||||||
|
void NewMenu::drawNewItemType(StudioContext const&sctx) noexcept {
|
||||||
|
drawWindow(sctx.tctx, m_open, [this] {
|
||||||
|
ig::ListBox("Item Type", [&](size_t const i) -> ox::CStringView {
|
||||||
|
return m_types[i]->typeDisplayName();
|
||||||
|
}, m_types.size(), m_selectedType, {200, 100});
|
||||||
|
auto const&im = *m_types[m_selectedType];
|
||||||
|
drawFirstPageButtons(im.itemTemplates().size() == 1 ?
|
||||||
|
Stage::NewItemName : Stage::NewItemTemplate);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewMenu::drawNewItemName(studio::StudioContext &sctx) noexcept {
|
void NewMenu::drawNewItemTemplate(StudioContext &sctx) noexcept {
|
||||||
drawWindow(sctx.tctx, &m_open, [this, &sctx] {
|
drawWindow(sctx.tctx, m_open, [this] {
|
||||||
auto const typeIdx = static_cast<std::size_t>(m_selectedType);
|
auto const&templates =
|
||||||
if (typeIdx < m_types.size()) {
|
m_types[m_selectedType]->itemTemplates();
|
||||||
|
ig::ListBox("Template", [&](size_t const i) -> ox::CStringView {
|
||||||
|
return templates[i]->name();
|
||||||
|
}, templates.size(), m_selectedTemplate, {200, 100});
|
||||||
|
drawButtons(Stage::NewItemType, Stage::NewItemName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewMenu::drawNewItemName(StudioContext &sctx) noexcept {
|
||||||
|
drawWindow(sctx.tctx, m_open, [this, &sctx] {
|
||||||
|
if (m_selectedType < m_types.size()) {
|
||||||
ig::InputText("Name", m_itemName);
|
ig::InputText("Name", m_itemName);
|
||||||
}
|
}
|
||||||
drawLastPageButtons(sctx);
|
drawLastPageButtons(sctx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewMenu::drawFirstPageButtons() noexcept {
|
void NewMenu::drawButtons(Stage const prev, Stage const next) noexcept {
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 130);
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 198);
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
|
||||||
auto const btnSz = ImVec2(60, 20);
|
constexpr ImVec2 btnSz{60, 20};
|
||||||
|
if (ImGui::Button("Back", btnSz)) {
|
||||||
|
m_stage = prev;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Next", btnSz)) {
|
if (ImGui::Button("Next", btnSz)) {
|
||||||
m_stage = Stage::NewItemName;
|
m_stage = next;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Cancel", btnSz)) {
|
if (ImGui::Button("Cancel", btnSz)) {
|
||||||
@ -99,34 +121,50 @@ void NewMenu::drawFirstPageButtons() noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewMenu::drawLastPageButtons(studio::StudioContext &sctx) noexcept {
|
void NewMenu::drawFirstPageButtons(Stage const next) noexcept {
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 138);
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 130);
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
|
||||||
if (ImGui::Button("Back")) {
|
constexpr ImVec2 btnSz{60, 20};
|
||||||
m_stage = Stage::NewItemType;
|
if (ImGui::Button("Next", btnSz)) {
|
||||||
|
m_stage = next;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Finish")) {
|
if (ImGui::Button("Cancel", btnSz)) {
|
||||||
finish(sctx);
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Quit")) {
|
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
m_stage = Stage::Closed;
|
m_stage = Stage::Closed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewMenu::finish(studio::StudioContext &sctx) noexcept {
|
void NewMenu::drawLastPageButtons(StudioContext &sctx) noexcept {
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 198);
|
||||||
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
|
||||||
|
constexpr ImVec2 btnSz{60, 20};
|
||||||
|
if (ImGui::Button("Back", btnSz)) {
|
||||||
|
m_stage = Stage::NewItemType;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Finish", btnSz)) {
|
||||||
|
finish(sctx);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Quit", btnSz)) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
m_stage = Stage::Closed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewMenu::finish(StudioContext &sctx) noexcept {
|
||||||
if (m_itemName.len() == 0) {
|
if (m_itemName.len() == 0) {
|
||||||
oxLogError(ox::Error(1, "New file error: no file name"));
|
oxLogError(ox::Error{1, "New file error: no file name"});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto const&typeMaker = *m_types[static_cast<std::size_t>(m_selectedType)];
|
auto const&im = *m_types[static_cast<std::size_t>(m_selectedType)];
|
||||||
if (sctx.project->exists(typeMaker.itemPath(m_itemName))) {
|
if (sctx.project->exists(im.itemPath(m_itemName))) {
|
||||||
oxLogError(ox::Error(1, "New file error: file already exists"));
|
oxLogError(ox::Error{1, "New file error: file already exists"});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto const [path, err] = typeMaker.write(sctx, m_itemName);
|
auto const [path, err] =
|
||||||
|
im.write(sctx, m_itemName, m_selectedTemplate);
|
||||||
if (err) {
|
if (err) {
|
||||||
oxLogError(err);
|
oxLogError(err);
|
||||||
return;
|
return;
|
||||||
|
@ -13,13 +13,14 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
class NewMenu: public studio::Popup {
|
class NewMenu final: public Popup {
|
||||||
public:
|
public:
|
||||||
enum class Stage {
|
enum class Stage {
|
||||||
Closed,
|
Closed,
|
||||||
Opening,
|
Opening,
|
||||||
NewItemType,
|
NewItemType,
|
||||||
NewItemName,
|
NewItemName,
|
||||||
|
NewItemTemplate,
|
||||||
};
|
};
|
||||||
|
|
||||||
// emits path parameter
|
// emits path parameter
|
||||||
@ -29,8 +30,9 @@ class NewMenu: public studio::Popup {
|
|||||||
Stage m_stage = Stage::Closed;
|
Stage m_stage = Stage::Closed;
|
||||||
ox::String m_typeName;
|
ox::String m_typeName;
|
||||||
ox::IString<255> m_itemName;
|
ox::IString<255> m_itemName;
|
||||||
ox::Vector<ox::UniquePtr<studio::ItemMaker>> m_types;
|
ox::Vector<ox::UPtr<studio::ItemMaker>> m_types;
|
||||||
int m_selectedType = 0;
|
size_t m_selectedType = 0;
|
||||||
|
size_t m_selectedTemplate = 0;
|
||||||
bool m_open = false;
|
bool m_open = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -43,37 +45,70 @@ class NewMenu: public studio::Popup {
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool isOpen() const noexcept override;
|
bool isOpen() const noexcept override;
|
||||||
|
|
||||||
void draw(studio::StudioContext &sctx) noexcept override;
|
void draw(StudioContext &sctx) noexcept override;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void addItemType(ox::String name, ox::String parentDir, ox::String fileExt, T itemTempl, ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;
|
void addItemType(
|
||||||
|
ox::StringParam displayName,
|
||||||
|
ox::StringParam parentDir,
|
||||||
|
ox::StringParam fileExt,
|
||||||
|
T itemTempl,
|
||||||
|
ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void addItemType(ox::String name, ox::String parentDir, ox::String fileExt, ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;
|
void addItemType(
|
||||||
|
ox::StringParam displayName,
|
||||||
|
ox::StringParam parentDir,
|
||||||
|
ox::StringParam fileExt,
|
||||||
|
ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;
|
||||||
|
|
||||||
void addItemMaker(ox::UniquePtr<studio::ItemMaker> &&im) noexcept;
|
void addItemMaker(ox::UPtr<ItemMaker> &&im) noexcept;
|
||||||
|
|
||||||
|
void installItemTemplate(ox::UPtr<ItemTemplate> &tmplt) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void drawNewItemType(studio::StudioContext &sctx) noexcept;
|
void drawNewItemType(StudioContext const&sctx) noexcept;
|
||||||
|
|
||||||
void drawNewItemName(studio::StudioContext &sctx) noexcept;
|
void drawNewItemName(StudioContext &sctx) noexcept;
|
||||||
|
|
||||||
void drawFirstPageButtons() noexcept;
|
void drawNewItemTemplate(StudioContext &sctx) noexcept;
|
||||||
|
|
||||||
void drawLastPageButtons(studio::StudioContext &sctx) noexcept;
|
void drawButtons(Stage prev, Stage next) noexcept;
|
||||||
|
|
||||||
void finish(studio::StudioContext &sctx) noexcept;
|
void drawFirstPageButtons(Stage next) noexcept;
|
||||||
|
|
||||||
|
void drawLastPageButtons(StudioContext &sctx) noexcept;
|
||||||
|
|
||||||
|
void finish(StudioContext &sctx) noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void NewMenu::addItemType(ox::String displayName, ox::String parentDir, ox::String fileExt, T itemTempl, ox::ClawFormat pFmt) noexcept {
|
void NewMenu::addItemType(
|
||||||
m_types.emplace_back(ox::make<studio::ItemMakerT<T>>(std::move(displayName), std::move(parentDir), std::move(fileExt), std::move(itemTempl), pFmt));
|
ox::StringParam displayName,
|
||||||
|
ox::StringParam parentDir,
|
||||||
|
ox::StringParam fileExt,
|
||||||
|
T itemTempl,
|
||||||
|
ox::ClawFormat const pFmt) noexcept {
|
||||||
|
m_types.emplace_back(ox::make<ItemMakerT<T>>(
|
||||||
|
std::move(displayName),
|
||||||
|
std::move(parentDir),
|
||||||
|
std::move(fileExt),
|
||||||
|
std::move(itemTempl),
|
||||||
|
pFmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void NewMenu::addItemType(ox::String displayName, ox::String parentDir, ox::String fileExt, ox::ClawFormat pFmt) noexcept {
|
void NewMenu::addItemType(
|
||||||
m_types.emplace_back(ox::make<studio::ItemMakerT<T>>(std::move(displayName), std::move(parentDir), std::move(fileExt), pFmt));
|
ox::StringParam displayName,
|
||||||
|
ox::StringParam parentDir,
|
||||||
|
ox::StringParam fileExt,
|
||||||
|
ox::ClawFormat const pFmt) noexcept {
|
||||||
|
m_types.emplace_back(ox::make<ItemMakerT<T>>(
|
||||||
|
std::move(displayName),
|
||||||
|
std::move(parentDir),
|
||||||
|
std::move(fileExt),
|
||||||
|
pFmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ void NewProject::draw(studio::StudioContext &ctx) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NewProject::drawNewProjectName(studio::StudioContext &sctx) noexcept {
|
void NewProject::drawNewProjectName(studio::StudioContext &sctx) noexcept {
|
||||||
drawWindow(sctx.tctx, &m_open, [this, &sctx] {
|
drawWindow(sctx.tctx, m_open, [this, &sctx] {
|
||||||
ig::InputText("Name", m_projectName);
|
ig::InputText("Name", m_projectName);
|
||||||
ImGui::Text("Path: %s", m_projectPath.c_str());
|
ImGui::Text("Path: %s", m_projectPath.c_str());
|
||||||
if (ImGui::Button("Browse")) {
|
if (ImGui::Button("Browse")) {
|
||||||
|
@ -251,6 +251,10 @@ void StudioUI::loadModule(Module const&mod) noexcept {
|
|||||||
for (auto &im : mod.itemMakers(m_sctx)) {
|
for (auto &im : mod.itemMakers(m_sctx)) {
|
||||||
m_newMenu.addItemMaker(std::move(im));
|
m_newMenu.addItemMaker(std::move(im));
|
||||||
}
|
}
|
||||||
|
auto tmplts = mod.itemTemplates(m_sctx);
|
||||||
|
for (auto &t : tmplts) {
|
||||||
|
m_newMenu.installItemTemplate(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StudioUI::loadModules() noexcept {
|
void StudioUI::loadModules() noexcept {
|
||||||
|
@ -214,7 +214,8 @@ bool ListBox(
|
|||||||
ox::CStringViewCR name,
|
ox::CStringViewCR name,
|
||||||
std::function<ox::CStringView(size_t)> const&f,
|
std::function<ox::CStringView(size_t)> const&f,
|
||||||
size_t strCnt,
|
size_t strCnt,
|
||||||
size_t &selIdx) noexcept;
|
size_t &selIdx,
|
||||||
|
ImVec2 const&sz = {0, 0}) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/claw/claw.hpp>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <ox/model/typenamecatcher.hpp>
|
||||||
|
|
||||||
#include <keel/media.hpp>
|
#include <keel/media.hpp>
|
||||||
#include <turbine/context.hpp>
|
#include <turbine/context.hpp>
|
||||||
@ -13,75 +15,212 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
class ItemMaker {
|
class ItemTemplate {
|
||||||
|
private:
|
||||||
|
ox::String const m_name{"Default"};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ox::String const typeName;
|
explicit ItemTemplate() noexcept = default;
|
||||||
ox::String const parentDir;
|
|
||||||
ox::String const fileExt;
|
explicit ItemTemplate(ox::StringParam name) noexcept: m_name{std::move(name)} {}
|
||||||
constexpr explicit ItemMaker(
|
|
||||||
|
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 pName,
|
||||||
ox::StringParam pParentDir,
|
ox::StringParam pParentDir,
|
||||||
ox::StringParam pFileExt) noexcept:
|
ox::StringParam pFileExt) noexcept:
|
||||||
typeName{std::move(pName)},
|
m_parentDir{std::move(pParentDir)},
|
||||||
parentDir{std::move(pParentDir)},
|
m_fileExt{std::move(pFileExt)},
|
||||||
fileExt{std::move(pFileExt)} {
|
m_typeDisplayName{std::move(pName)} {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ItemMaker() noexcept = default;
|
virtual ~ItemMaker() noexcept = default;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
virtual ox::String itemPath(ox::StringView pName) const noexcept {
|
ox::String const&typeDisplayName() const noexcept {
|
||||||
return ox::sfmt("/{}/{}.{}", parentDir, pName, fileExt);
|
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.
|
* Returns path of the file created.
|
||||||
* @param ctx
|
* @param ctx
|
||||||
* @param pName
|
* @param pName
|
||||||
|
* @param pTemplateIdx
|
||||||
* @return path of file or error in Result
|
* @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>
|
template<typename T>
|
||||||
class ItemMakerT: public ItemMaker {
|
class ItemMakerT final: public ItemMaker {
|
||||||
private:
|
private:
|
||||||
T const m_item;
|
|
||||||
ox::ClawFormat const m_fmt;
|
ox::ClawFormat const m_fmt;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr ItemMakerT(
|
constexpr ItemMakerT(
|
||||||
ox::StringParam pDisplayName,
|
ox::StringParam pDisplayName,
|
||||||
ox::StringParam pParentDir,
|
ox::StringParam pParentDir,
|
||||||
ox::StringParam fileExt,
|
ox::StringParam fileExt,
|
||||||
ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept:
|
ox::ClawFormat const pFmt = ox::ClawFormat::Metal) noexcept:
|
||||||
ItemMaker(std::move(pDisplayName), std::move(pParentDir), std::move(fileExt)),
|
ItemMaker(
|
||||||
m_fmt(pFmt) {
|
std::move(pDisplayName),
|
||||||
|
std::move(pParentDir),
|
||||||
|
std::move(fileExt)),
|
||||||
|
m_fmt{pFmt} {
|
||||||
|
installTemplate(ox::make_unique<ItemTemplateT<T>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ItemMakerT(
|
constexpr ItemMakerT(
|
||||||
ox::StringParam pDisplayName,
|
ox::StringParam pDisplayName,
|
||||||
ox::StringParam pParentDir,
|
ox::StringParam pParentDir,
|
||||||
ox::StringParam fileExt,
|
ox::StringParam fileExt,
|
||||||
T pItem,
|
T const&pItem,
|
||||||
ox::ClawFormat pFmt) noexcept:
|
ox::ClawFormat const pFmt) noexcept:
|
||||||
ItemMaker(std::move(pDisplayName), std::move(pParentDir), std::move(fileExt)),
|
ItemMaker(
|
||||||
m_item(std::move(pItem)),
|
std::move(pDisplayName),
|
||||||
m_fmt(pFmt) {
|
std::move(pParentDir),
|
||||||
|
std::move(fileExt)),
|
||||||
|
m_fmt{pFmt} {
|
||||||
|
installTemplate(ox::make_unique<ItemTemplateT<T>>(std::move(pItem)));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ItemMakerT(
|
constexpr ItemMakerT(
|
||||||
ox::StringParam pDisplayName,
|
ox::StringParam pDisplayName,
|
||||||
ox::StringParam pParentDir,
|
ox::StringParam pParentDir,
|
||||||
ox::StringParam fileExt,
|
ox::StringParam fileExt,
|
||||||
T &&pItem,
|
T &&pItem,
|
||||||
ox::ClawFormat pFmt) noexcept:
|
ox::ClawFormat const pFmt) noexcept:
|
||||||
ItemMaker(std::move(pDisplayName), std::move(pParentDir), std::move(fileExt)),
|
ItemMaker(
|
||||||
m_item(std::move(pItem)),
|
std::move(pDisplayName),
|
||||||
m_fmt(pFmt) {
|
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);
|
auto const path = itemPath(pName);
|
||||||
createUuidMapping(keelCtx(sctx.tctx), path, ox::UUID::generate().unwrap());
|
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;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ class Module {
|
|||||||
|
|
||||||
virtual ox::Vector<ox::UPtr<ItemMaker>> itemMakers(studio::StudioContext&) const;
|
virtual ox::Vector<ox::UPtr<ItemMaker>> itemMakers(studio::StudioContext&) const;
|
||||||
|
|
||||||
|
virtual ox::Vector<ox::UPtr<ItemTemplate>> itemTemplates(studio::StudioContext&) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Editor>
|
template<typename Editor>
|
||||||
|
@ -47,7 +47,7 @@ class Popup {
|
|||||||
return m_title;
|
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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -136,11 +136,12 @@ bool FileComboBox(
|
|||||||
bool ListBox(
|
bool ListBox(
|
||||||
ox::CStringViewCR name,
|
ox::CStringViewCR name,
|
||||||
std::function<ox::CStringView(size_t)> const&f,
|
std::function<ox::CStringView(size_t)> const&f,
|
||||||
size_t strCnt,
|
size_t const strCnt,
|
||||||
size_t &selIdx) noexcept {
|
size_t &selIdx,
|
||||||
|
ImVec2 const&sz) noexcept {
|
||||||
auto out = false;
|
auto out = false;
|
||||||
if (ImGui::BeginListBox(name.c_str())) {
|
if (ImGui::BeginListBox(name.c_str(), sz)) {
|
||||||
for (auto i = 0u; i < strCnt; ++i) {
|
for (size_t i = 0; i < strCnt; ++i) {
|
||||||
auto str = f(i);
|
auto str = f(i);
|
||||||
ig::IDStackItem const idStackItem2(static_cast<int>(i));
|
ig::IDStackItem const idStackItem2(static_cast<int>(i));
|
||||||
if (ImGui::Selectable(str.c_str(), selIdx == i)) {
|
if (ImGui::Selectable(str.c_str(), selIdx == i)) {
|
||||||
@ -161,6 +162,12 @@ bool ListBox(ox::CStringViewCR name, ox::SpanView<ox::String> const&list, size_t
|
|||||||
}, list.size(), selIdx);
|
}, list.size(), selIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ListBox(ox::CStringViewCR name, ox::SpanView<ox::CStringView> const&list, size_t &selIdx) noexcept {
|
||||||
|
return ListBox(name, [list](size_t i) -> ox::CStringView {
|
||||||
|
return list[i];
|
||||||
|
}, list.size(), selIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FilePicker::FilePicker(
|
FilePicker::FilePicker(
|
||||||
StudioContext &sctx,
|
StudioContext &sctx,
|
||||||
|
@ -6,11 +6,15 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
ox::Vector<EditorMaker> Module::editors(studio::StudioContext&) const {
|
ox::Vector<EditorMaker> Module::editors(StudioContext&) const {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Vector<ox::UPtr<ItemMaker>> Module::itemMakers(studio::StudioContext&) const {
|
ox::Vector<ox::UPtr<ItemMaker>> Module::itemMakers(StudioContext&) const {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Vector<ox::UPtr<ItemTemplate>> Module::itemTemplates(StudioContext&) const {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,11 +7,11 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
void Popup::drawWindow(turbine::Context &ctx, bool *open, std::function<void()> const&drawContents) {
|
void Popup::drawWindow(turbine::Context &ctx, bool &open, std::function<void()> const&drawContents) {
|
||||||
studio::ig::centerNextWindow(ctx);
|
studio::ig::centerNextWindow(ctx);
|
||||||
ImGui::SetNextWindowSize(static_cast<ImVec2>(m_size));
|
ImGui::SetNextWindowSize(static_cast<ImVec2>(m_size));
|
||||||
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
||||||
if (ImGui::BeginPopupModal(m_title.c_str(), open, modalFlags)) {
|
if (ImGui::BeginPopupModal(m_title.c_str(), &open, modalFlags)) {
|
||||||
drawContents();
|
drawContents();
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user