Merge commit 'c0baf7efca0e4c3a86a018ad2564d9df7b07c133'
All checks were successful
Build / build (push) Successful in 2m22s

This commit is contained in:
2024-04-21 13:13:26 -05:00
76 changed files with 527 additions and 437 deletions

View File

@ -134,12 +134,12 @@ ox::Result<char*> loadRom(ox::CRStringView) noexcept {
// media section
constexpr auto headerP2 = "R_______________";
constexpr auto headerP1 = "KEEL_MEDIA_HEADE";
constexpr auto headerP1Len = ox_strlen(headerP2);
constexpr auto headerP2Len = ox_strlen(headerP1);
constexpr auto headerP1Len = ox::strlen(headerP2);
constexpr auto headerP2Len = ox::strlen(headerP1);
constexpr auto headerLen = headerP1Len + headerP2Len;
for (auto current = MEM_ROM; current < reinterpret_cast<char*>(0x0a000000); current += headerLen) {
if (ox_memcmp(current, headerP1, headerP1Len) == 0 &&
ox_memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) {
if (ox::memcmp(current, headerP1, headerP1Len) == 0 &&
ox::memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) {
return current + headerLen;
}
}

View File

@ -29,7 +29,7 @@ bool AboutPopup::isOpen() const noexcept {
return m_stage == Stage::Open;
}
void AboutPopup::draw(turbine::Context &ctx) noexcept {
void AboutPopup::draw(studio::StudioContext &sctx) noexcept {
switch (m_stage) {
case Stage::Closed:
break;
@ -41,7 +41,7 @@ void AboutPopup::draw(turbine::Context &ctx) noexcept {
constexpr auto modalFlags =
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
ImGui::SetNextWindowSize(ImVec2(215, 90));
studio::ig::centerNextWindow(ctx);
studio::ig::centerNextWindow(sctx.tctx);
auto open = true;
if (ImGui::BeginPopupModal("About", &open, modalFlags)) {
ImGui::Text("%s", m_text.c_str());

View File

@ -35,7 +35,7 @@ class AboutPopup: public studio::Popup {
[[nodiscard]]
bool isOpen() const noexcept override;
void draw(turbine::Context &ctx) noexcept override;
void draw(studio::StudioContext &sctx) noexcept override;
};

View File

@ -13,7 +13,7 @@ ClawEditor::ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept:
m_obj(std::move(obj)) {
}
void ClawEditor::draw(turbine::Context&) noexcept {
void ClawEditor::draw(studio::StudioContext&) noexcept {
ImGui::BeginChild("PaletteEditor");
static constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
if (ImGui::BeginTable("ObjTree", 3, flags)) {

View File

@ -18,7 +18,7 @@ class ClawEditor: public studio::Editor {
public:
ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept;
void draw(turbine::Context&) noexcept final;
void draw(studio::StudioContext&) noexcept final;
private:
static void drawRow(ox::ModelValue const&value) noexcept;

View File

@ -33,7 +33,7 @@ bool NewMenu::isOpen() const noexcept {
return m_open;
}
void NewMenu::draw(turbine::Context &ctx) noexcept {
void NewMenu::draw(studio::StudioContext &sctx) noexcept {
switch (m_stage) {
case Stage::Opening:
ImGui::OpenPopup(title().c_str());
@ -41,10 +41,10 @@ void NewMenu::draw(turbine::Context &ctx) noexcept {
m_open = true;
[[fallthrough]];
case Stage::NewItemType:
drawNewItemType(ctx);
drawNewItemType(sctx);
break;
case Stage::NewItemName:
drawNewItemName(ctx);
drawNewItemName(sctx);
break;
case Stage::Closed:
m_open = false;
@ -61,8 +61,8 @@ void NewMenu::addItemMaker(ox::UniquePtr<studio::ItemMaker> &&im) noexcept {
});
}
void NewMenu::drawNewItemType(turbine::Context &ctx) noexcept {
drawWindow(ctx, &m_open, [this] {
void NewMenu::drawNewItemType(studio::StudioContext &sctx) noexcept {
drawWindow(sctx.tctx, &m_open, [this] {
auto items = ox_malloca(m_types.size() * sizeof(char const*), char const*, nullptr);
for (auto i = 0u; auto const&im : m_types) {
items.get()[i] = im->typeName.c_str();
@ -73,13 +73,13 @@ void NewMenu::drawNewItemType(turbine::Context &ctx) noexcept {
});
}
void NewMenu::drawNewItemName(turbine::Context &ctx) noexcept {
drawWindow(ctx, &m_open, [this, &ctx] {
void NewMenu::drawNewItemName(studio::StudioContext &sctx) noexcept {
drawWindow(sctx.tctx, &m_open, [this, &sctx] {
auto const typeIdx = static_cast<std::size_t>(m_selectedType);
if (typeIdx < m_types.size()) {
ImGui::InputText("Name", m_itemName.data(), m_itemName.cap());
}
drawLastPageButtons(ctx);
drawLastPageButtons(sctx);
});
}
@ -97,7 +97,7 @@ void NewMenu::drawFirstPageButtons() noexcept {
}
}
void NewMenu::drawLastPageButtons(turbine::Context &ctx) noexcept {
void NewMenu::drawLastPageButtons(studio::StudioContext &sctx) noexcept {
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 138);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
if (ImGui::Button("Back")) {
@ -105,7 +105,7 @@ void NewMenu::drawLastPageButtons(turbine::Context &ctx) noexcept {
}
ImGui::SameLine();
if (ImGui::Button("Finish")) {
finish(ctx);
finish(sctx);
}
ImGui::SameLine();
if (ImGui::Button("Quit")) {
@ -114,17 +114,16 @@ void NewMenu::drawLastPageButtons(turbine::Context &ctx) noexcept {
}
}
void NewMenu::finish(turbine::Context &ctx) noexcept {
void NewMenu::finish(studio::StudioContext &sctx) noexcept {
if (m_itemName.len() == 0) {
return;
}
auto const sctx = turbine::applicationData<studio::StudioContext>(ctx);
auto const&typeMaker = *m_types[static_cast<std::size_t>(m_selectedType)];
if (sctx->project->exists(typeMaker.itemPath(m_itemName))) {
if (sctx.project->exists(typeMaker.itemPath(m_itemName))) {
oxLogError(OxError(1, "New file error: File already exists"));
return;
}
auto const [path, err] = typeMaker.write(ctx, m_itemName);
auto const [path, err] = typeMaker.write(sctx, m_itemName);
if (err) {
oxLogError(err);
return;

View File

@ -43,7 +43,7 @@ class NewMenu: public studio::Popup {
[[nodiscard]]
bool isOpen() const noexcept override;
void draw(turbine::Context &ctx) noexcept override;
void draw(studio::StudioContext &sctx) noexcept override;
template<typename T>
void addItemType(ox::String name, ox::String parentDir, ox::String fileExt, T itemTempl, ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;
@ -54,15 +54,15 @@ class NewMenu: public studio::Popup {
void addItemMaker(ox::UniquePtr<studio::ItemMaker> &&im) noexcept;
private:
void drawNewItemType(turbine::Context &ctx) noexcept;
void drawNewItemType(studio::StudioContext &sctx) noexcept;
void drawNewItemName(turbine::Context &ctx) noexcept;
void drawNewItemName(studio::StudioContext &sctx) noexcept;
void drawFirstPageButtons() noexcept;
void drawLastPageButtons(turbine::Context &ctx) noexcept;
void drawLastPageButtons(studio::StudioContext &sctx) noexcept;
void finish(turbine::Context &ctx) noexcept;
void finish(studio::StudioContext &sctx) noexcept;
};

View File

@ -32,7 +32,7 @@ bool NewProject::isOpen() const noexcept {
return m_open;
}
void NewProject::draw(turbine::Context &ctx) noexcept {
void NewProject::draw(studio::StudioContext &ctx) noexcept {
switch (m_stage) {
case Stage::Opening:
ImGui::OpenPopup(title().c_str());
@ -48,14 +48,14 @@ void NewProject::draw(turbine::Context &ctx) noexcept {
}
}
void NewProject::drawNewProjectName(turbine::Context &ctx) noexcept {
drawWindow(ctx, &m_open, [this, &ctx] {
void NewProject::drawNewProjectName(studio::StudioContext &sctx) noexcept {
drawWindow(sctx.tctx, &m_open, [this, &sctx] {
ImGui::InputText("Name", m_projectName.data(), m_projectName.cap());
ImGui::Text("Path: %s", m_projectPath.c_str());
if (ImGui::Button("Browse")) {
oxLogError(studio::chooseDirectory().moveTo(m_projectPath));
}
drawLastPageButtons(ctx);
drawLastPageButtons(sctx);
});
}
@ -73,7 +73,7 @@ void NewProject::drawFirstPageButtons() noexcept {
}
}
void NewProject::drawLastPageButtons(turbine::Context&) noexcept {
void NewProject::drawLastPageButtons(studio::StudioContext&) noexcept {
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 95);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
if (ImGui::Button("Finish")) {

View File

@ -42,14 +42,14 @@ class NewProject: public studio::Popup {
[[nodiscard]]
bool isOpen() const noexcept override;
void draw(turbine::Context &ctx) noexcept override;
void draw(studio::StudioContext &ctx) noexcept override;
private:
void drawNewProjectName(turbine::Context &ctx) noexcept;
void drawNewProjectName(studio::StudioContext &ctx) noexcept;
void drawFirstPageButtons() noexcept;
void drawLastPageButtons(turbine::Context &ctx) noexcept;
void drawLastPageButtons(studio::StudioContext &ctx) noexcept;
void finish() noexcept;

View File

@ -37,12 +37,12 @@ static ox::Result<ox::UniquePtr<ProjectTreeModel>> buildProjectTreeModel(
ProjectExplorer::ProjectExplorer(turbine::Context &ctx) noexcept: m_ctx(ctx) {
}
void ProjectExplorer::draw(turbine::Context &ctx) noexcept {
void ProjectExplorer::draw(studio::StudioContext &ctx) noexcept {
auto const viewport = ImGui::GetContentRegionAvail();
ImGui::BeginChild("ProjectExplorer", ImVec2(300, viewport.y), true);
ImGui::SetNextItemOpen(true);
if (m_treeModel) {
m_treeModel->draw(ctx);
m_treeModel->draw(ctx.tctx);
}
ImGui::EndChild();
}

View File

@ -19,7 +19,7 @@ class ProjectExplorer: public studio::Widget {
public:
explicit ProjectExplorer(turbine::Context &ctx) noexcept;
void draw(turbine::Context &ctx) noexcept override;
void draw(studio::StudioContext &ctx) noexcept override;
void setModel(ox::UPtr<ProjectTreeModel> &&model) noexcept;

View File

@ -159,15 +159,15 @@ void StudioUI::draw() noexcept {
ImGui::Begin("MainWindow##Studio", nullptr, windowFlags);
{
if (m_showProjectExplorer) {
m_projectExplorer.draw(m_ctx);
m_projectExplorer.draw(m_sctx);
ImGui::SameLine();
}
drawTabBar();
for (auto &w: m_widgets) {
w->draw(m_ctx);
w->draw(m_sctx);
}
for (auto p: m_popups) {
p->draw(m_ctx);
p->draw(m_sctx);
}
}
ImGui::End();
@ -261,7 +261,7 @@ void StudioUI::drawTabs() noexcept {
m_activeEditor->onActivated();
turbine::setConstantRefresh(m_ctx, m_activeEditor->requiresConstantRefresh());
}
e->draw(m_ctx);
e->draw(m_sctx);
m_activeEditorOnLastDraw = e.get();
ImGui::EndTabItem();
}

View File

@ -18,7 +18,10 @@ class ItemMaker {
ox::String const typeName;
ox::String const parentDir;
ox::String const fileExt;
constexpr explicit ItemMaker(ox::StringView pName, ox::StringView pParentDir, ox::CRStringView pFileExt) noexcept:
constexpr explicit ItemMaker(
ox::StringView pName,
ox::StringView pParentDir,
ox::StringView pFileExt) noexcept:
typeName(pName),
parentDir(pParentDir),
fileExt(pFileExt) {
@ -36,7 +39,8 @@ class ItemMaker {
* @param pName
* @return path of file or error in Result
*/
virtual ox::Result<ox::String> write(turbine::Context &ctx, ox::CRStringView pName) const noexcept = 0;
virtual ox::Result<ox::String> write(
studio::StudioContext &ctx, ox::CRStringView pName) const noexcept = 0;
};
template<typename T>
@ -60,7 +64,7 @@ class ItemMakerT: public ItemMaker {
T pItem,
ox::ClawFormat pFmt) noexcept:
ItemMaker(pDisplayName, pParentDir, fileExt),
m_item(pItem),
m_item(std::move(pItem)),
m_fmt(pFmt) {
}
constexpr ItemMakerT(
@ -73,11 +77,10 @@ class ItemMakerT: public ItemMaker {
m_item(std::move(pItem)),
m_fmt(pFmt) {
}
ox::Result<ox::String> write(turbine::Context &ctx, ox::CRStringView pName) const noexcept override {
ox::Result<ox::String> write(studio::StudioContext &sctx, ox::CRStringView pName) const noexcept override {
auto const path = itemPath(pName);
auto const sctx = turbine::applicationData<studio::StudioContext>(ctx);
keel::createUuidMapping(keelCtx(ctx), path, ox::UUID::generate().unwrap());
oxReturnError(sctx->project->writeObj(path, m_item, m_fmt));
keel::createUuidMapping(keelCtx(sctx.tctx), path, ox::UUID::generate().unwrap());
oxReturnError(sctx.project->writeObj(path, m_item, m_fmt));
return path;
}
};

View File

@ -32,7 +32,7 @@ class Popup {
[[nodiscard]]
virtual bool isOpen() const noexcept = 0;
virtual void draw(turbine::Context &ctx) noexcept = 0;
virtual void draw(studio::StudioContext &ctx) noexcept = 0;
protected:
constexpr void setSize(ox::Size sz) noexcept {

View File

@ -8,12 +8,14 @@
#include <turbine/context.hpp>
#include "context.hpp"
namespace studio {
class Widget: public ox::SignalHandler {
public:
~Widget() noexcept override = default;
virtual void draw(turbine::Context&) noexcept = 0;
virtual void draw(studio::StudioContext&) noexcept = 0;
};
}

View File

@ -13,9 +13,9 @@ namespace studio {
FDFilterItem::FDFilterItem(ox::CRStringView pName, ox::CRStringView pSpec) noexcept {
name.resize(pName.len() + 1);
ox_strncpy(name.data(), pName.data(), pName.len());
ox::strncpy(name.data(), pName.data(), pName.len());
spec.resize(pSpec.len() + 1);
ox_strncpy(spec.data(), pSpec.data(), pSpec.len());
ox::strncpy(spec.data(), pSpec.data(), pSpec.len());
}
static ox::Result<ox::String> toResult(nfdresult_t r, NFD::UniquePathN const&path) noexcept {

View File

@ -37,82 +37,25 @@ inline ox::FileSystem *rom(Context &ctx) noexcept {
return keelCtx(ctx).rom.get();
}
struct WrapBase {
virtual ~WrapBase() = default;
virtual WrapBase *copyTo(ox::Span<char> s) noexcept = 0;
virtual operator bool() const noexcept = 0;
};
template<typename T>
struct Wrap: public WrapBase {
T *data{};
Wrap(T *pData) noexcept: data(pData) {
}
WrapBase *copyTo(ox::Span<char> s) noexcept override {
oxAssert(s.size() >= sizeof(Wrap), "too small buffer");
return new(s.data()) Wrap{data};
}
operator bool() const noexcept override {
return data != nullptr;
}
};
class WrapPtr {
private:
WrapBase *m_wrapPtr{};
ox::Array<char, sizeof(Wrap<void*>)> m_wrapData;
public:
template<typename T>
inline WrapPtr &operator=(T *ptr) noexcept {
m_wrapPtr = new(m_wrapData.data()) Wrap(ptr);
return *this;
}
inline WrapPtr &operator=(WrapBase &ptr) noexcept {
if (ptr) {
m_wrapPtr = ptr.copyTo(m_wrapData);
} else {
m_wrapPtr = nullptr;
}
return *this;
}
inline operator bool() const noexcept {
return m_wrapPtr && *m_wrapPtr;
}
[[nodiscard]]
inline WrapBase *getWrapBase() const noexcept {
return m_wrapPtr;
}
};
void setApplicationDataRaw(Context &ctx, WrapBase &applicationData) noexcept;
void setApplicationDataRaw(Context &ctx, ox::AnyPtr const&applicationData) noexcept;
template<typename T>
void setApplicationData(Context &ctx, T *applicationData) noexcept {
Wrap w(applicationData);
setApplicationDataRaw(ctx, w);
setApplicationDataRaw(ctx, applicationData);
}
[[nodiscard]]
WrapBase *applicationDataRaw(Context &ctx) noexcept;
ox::AnyPtr const&applicationDataRaw(Context &ctx) noexcept;
template<typename T>
[[nodiscard]]
T *applicationData(Context &ctx) noexcept {
auto const raw = applicationDataRaw(ctx);
if (!raw) [[unlikely]] {
return nullptr;
}
#ifdef OX_BARE_METAL
auto const out = static_cast<Wrap<T>*>(raw);
#else
auto const out = dynamic_cast<Wrap<T>*>(raw);
#endif
oxAssert(out, "Cast failed - wrong type");
return out->data;
return applicationDataRaw(ctx).get<T>();
}
void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept;
[[nodiscard]]
KeyEventHandler keyEventHandler(Context &ctx) noexcept;
}

View File

@ -18,12 +18,12 @@ keel::Context &keelCtx(Context &ctx) noexcept {
return ctx.keelCtx;
}
void setApplicationDataRaw(Context &ctx, WrapBase &applicationData) noexcept {
void setApplicationDataRaw(Context &ctx, ox::AnyPtr const&applicationData) noexcept {
ctx.applicationData = applicationData;
}
WrapBase *applicationDataRaw(Context &ctx) noexcept {
return ctx.applicationData.getWrapBase();
ox::AnyPtr const&applicationDataRaw(Context &ctx) noexcept {
return ctx.applicationData;
}
}

View File

@ -17,7 +17,7 @@ class Context {
UpdateHandler updateHandler = [](Context&) -> int {return 0;};
keel::Context keelCtx;
KeyEventHandler keyEventHandler = nullptr;
WrapPtr applicationData;
ox::AnyPtr applicationData;
// GBA impl data /////////////////////////////////////////////////////////
bool running = true;

View File

@ -43,8 +43,8 @@ static ox::Result<std::size_t> findPreloadSection() noexcept {
// media section
constexpr auto headerP2 = "DER_____________";
constexpr auto headerP1 = "KEEL_PRELOAD_HEA";
constexpr auto headerP1Len = ox_strlen(headerP2);
constexpr auto headerP2Len = ox_strlen(headerP1);
constexpr auto headerP1Len = ox::strlen(headerP2);
constexpr auto headerP2Len = ox::strlen(headerP1);
constexpr auto headerLen = headerP1Len + headerP2Len;
for (auto current = MEM_ROM; current < reinterpret_cast<char*>(0x0a000000); current += headerLen) {
if (memcmp(current, headerP1, headerP1Len) == 0 &&

View File

@ -18,7 +18,7 @@ ox::String getClipboardText(Context &ctx) noexcept {
void setClipboardText(Context &ctx, ox::CRStringView text) noexcept {
auto cstr = ox_malloca(text.bytes() + 1, char);
ox_strncpy(cstr.get(), text.data(), text.bytes());
ox::strncpy(cstr.get(), text.data(), text.bytes());
glfwSetClipboardString(ctx.window, cstr.get());
}

View File

@ -20,12 +20,12 @@ keel::Context &keelCtx(Context &ctx) noexcept {
return ctx.keelCtx;
}
void setApplicationDataRaw(Context &ctx, WrapBase &applicationData) noexcept {
void setApplicationDataRaw(Context &ctx, ox::AnyPtr const&applicationData) noexcept {
ctx.applicationData = applicationData;
}
WrapBase *applicationDataRaw(Context &ctx) noexcept {
return ctx.applicationData.getWrapBase();
ox::AnyPtr const&applicationDataRaw(Context &ctx) noexcept {
return ctx.applicationData;
}
}

View File

@ -16,7 +16,7 @@ class Context {
UpdateHandler updateHandler = [](Context&) -> int {return 0;};
keel::Context keelCtx;
KeyEventHandler keyEventHandler = nullptr;
WrapPtr applicationData;
ox::AnyPtr applicationData;
// GLFW impl data ////////////////////////////////////////////////////////
int uninterruptedRefreshes = 3;

View File

@ -221,7 +221,7 @@ ox::Error initGfx(Context &ctx) noexcept {
void setWindowTitle(Context &ctx, ox::CRStringView title) noexcept {
auto cstr = ox_malloca(title.bytes() + 1, char);
ox_strncpy(cstr.get(), title.data(), title.bytes());
ox::strncpy(cstr.get(), title.data(), title.bytes());
glfwSetWindowTitle(ctx.window, cstr.get());
}