Squashed 'deps/nostalgia/' changes from 89ae226b..9676ea59

9676ea59 [turbine/glfw] Fix programmatic shutdown to invoke shutdownHandler
de8ac106 [turbine/glfw] Fix closing when no shutdown handler is set
88a6cd59 [turbine/glfw] Treat close window event like other events with regard to a mandatory refresh period
cd43fb7f [turbine,studio] Fix confirm app close pop up to work with Ctrl-Q
136f4224 [nostalgia] Update release notes
e773d6f0 [studio] Rename StudioContext to Context
7da2f68d [nostalgia/sample_project] Add assets
d20889ae [nostalgia/gfx/studio] Update for Ox changes
50c8302f [ox] Rename itoa to intToStr
d8195d30 [olympic,nostalgia] Address unsafe buffer warnings
a8c1387d [ox] Address unsafe buffer warnings
ff1e8f26 [studio] Add popup to warn about UUID duplication
d4329981 [studio,nostalgia] Cleanup
00034543 [studio,nostalgia/gfx/studio] Cleanup
8c6b2234 [olympic/util] Make pkg-gba script check return code of subprocesses
aad4b8a4 [studio] Cleanup
7cab1331 [keel] Add ability to log UUID duplication
640ac85d [nostalgia/gfx/studio/palette] Make page rename dialog accept on enter if input focused
b8d76586 [nostalgia/studio] Update generated icondata.cpp with Clang fix
2503bb3b [nostalgia/sample_project] Update type descriptors
e5dd448f [turbine,studio] Make Studio confirm with user before closing app if any unsaved changes
4770bb6a [olympic/util] Cleanup
c0bac696 [nostalgia/gfx/studio/paletteeditor] Fix color number key range
95f7c334 [studio] Change Studio font
535d8876 [keel] Cleanup
845e4332 [turbine] Fix Mac build
5169a607 [turbine] Disable useless window icon on Mac, it causes GLFW warning
8f03af99 [keel] Style updates
ee63a4a1 [keel] Cleanup

git-subtree-dir: deps/nostalgia
git-subtree-split: 9676ea59787215b01498dfa82f88d426363b3cfd
This commit is contained in:
2025-05-07 00:11:20 -05:00
parent ec6cf92c47
commit ce53be9271
140 changed files with 22045 additions and 402 deletions

View File

@@ -14,19 +14,19 @@ namespace studio {
class StudioUI;
struct StudioContext {
struct Context {
StudioUI &ui;
Project *project = nullptr;
turbine::Context &tctx;
StudioContext(StudioUI &pUi, turbine::Context &pTctx) noexcept:
Context(StudioUI &pUi, turbine::Context &pTctx) noexcept:
ui(pUi), tctx(pTctx) {}
};
[[nodiscard]]
inline keel::Context &keelCtx(StudioContext &ctx) noexcept {
inline keel::Context &keelCtx(Context &ctx) noexcept {
return keelCtx(ctx.tctx);
}
void navigateTo(StudioContext &ctx, ox::StringParam filePath, ox::StringParam navArgs) noexcept;
void navigateTo(Context &ctx, ox::StringParam filePath, ox::StringParam navArgs) noexcept;
}

View File

@@ -121,7 +121,7 @@ class Editor: public studio::BaseEditor {
ox::String m_itemName;
public:
Editor(StudioContext &ctx, ox::StringParam itemPath) noexcept;
Editor(Context &ctx, ox::StringParam itemPath) noexcept;
[[nodiscard]]
ox::CStringView itemPath() const noexcept final;

View File

@@ -31,7 +31,7 @@ class FilePickerPopup {
[[nodiscard]]
bool isOpen() const noexcept;
ox::Optional<ox::String> draw(StudioContext &ctx) noexcept;
ox::Optional<ox::String> draw(Context &ctx) noexcept;
};

View File

@@ -32,7 +32,7 @@ class FileExplorer: public ox::SignalHandler {
m_kctx{kctx},
m_fileDraggable{fileDraggable} {}
void draw(StudioContext &ctx, ImVec2 const &sz) const noexcept;
void draw(Context &ctx, ImVec2 const &sz) const noexcept;
void setModel(ox::UPtr<FileTreeModel> &&model, bool selectRoot = false) noexcept;

View File

@@ -12,6 +12,7 @@
#include <turbine/context.hpp>
#include <studio/context.hpp>
#include <studio/widget.hpp>
namespace studio::ig {
@@ -168,7 +169,9 @@ TextInput<ox::IString<MaxChars>> InputText(
out.changed = ImGui::InputText(
label.c_str(), out.text.data(), MaxChars + 1, flags, callback, user_data);
if (out.changed) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
std::ignore = out.text.unsafeResize(ox::strlen(out.text.c_str()));
OX_ALLOW_UNSAFE_BUFFERS_END
}
return out;
}
@@ -185,7 +188,9 @@ TextInput<ox::IString<MaxChars>> InputTextWithHint(
out.changed = ImGui::InputTextWithHint(
label.c_str(), hint.c_str(), out.text.data(), MaxChars + 1, flags, callback, user_data);
if (out.changed) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
std::ignore = out.text.unsafeResize(ox::strlen(out.text.c_str()));
OX_ALLOW_UNSAFE_BUFFERS_END
}
return out;
}
@@ -200,7 +205,9 @@ bool InputText(
auto const out = ImGui::InputText(
label.c_str(), text.data(), StrCap + 1, flags, callback, user_data);
if (out) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
std::ignore = text.unsafeResize(ox::strlen(text.c_str()));
OX_ALLOW_UNSAFE_BUFFERS_END
}
return out;
}
@@ -222,6 +229,10 @@ PopupResponse PopupControlsOkCancel(
ox::CStringViewCR ok = "OK",
ox::CStringViewCR cancel = "Cancel");
PopupResponse PopupControlsOk(
bool &popupOpen,
ox::CStringViewCR ok);
[[nodiscard]]
bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show, ImVec2 const&sz = {285, 0});
@@ -249,7 +260,7 @@ bool ComboBox(ox::CStringView lbl, ox::Span<const ox::String> list, size_t &sele
/**
*
* @param lbl
* @param callback
* @param f callback function
* @param selectedIdx
* @return true if new value selected, false otherwise
*/
@@ -261,7 +272,7 @@ bool ComboBox(
bool FileComboBox(
ox::CStringViewCR lbl,
StudioContext &sctx,
Context &sctx,
ox::StringViewCR fileExt,
size_t &selectedIdx) noexcept;
@@ -284,7 +295,7 @@ bool ListBox(ox::CStringViewCR name, ox::SpanView<ox::String> const&list, size_t
class FilePicker {
private:
bool m_show{};
studio::StudioContext &m_sctx;
Context &m_sctx;
ox::String const m_title;
ox::String const m_fileExt;
ImVec2 const m_size;
@@ -292,7 +303,7 @@ class FilePicker {
ox::Signal<ox::Error(ox::StringView)> filePicked;
FilePicker(
studio::StudioContext &sctx,
studio::Context &sctx,
ox::StringParam title,
ox::StringParam fileExt,
ImVec2 const&size = {}) noexcept;
@@ -303,8 +314,8 @@ class FilePicker {
};
class QuestionPopup {
private:
class Popup: public Widget {
protected:
enum class Stage {
Closed,
Opening,
@@ -313,12 +324,11 @@ class QuestionPopup {
Stage m_stage = Stage::Closed;
bool m_open{};
ox::String m_title;
ox::String m_question;
public:
ox::Signal<ox::Error(ig::PopupResponse)> response;
ox::Signal<ox::Error(PopupResponse)> response;
QuestionPopup(ox::StringParam title, ox::StringParam question) noexcept;
explicit Popup(ox::StringParam title) noexcept;
void open() noexcept;
@@ -327,7 +337,33 @@ class QuestionPopup {
[[nodiscard]]
bool isOpen() const noexcept;
void draw(StudioContext &ctx, ImVec2 const &sz = {}) noexcept;
};
class QuestionPopup: public Popup {
private:
ox::String m_question;
public:
ox::Signal<ox::Error(PopupResponse)> response;
QuestionPopup(ox::StringParam title, ox::StringParam question) noexcept;
void draw(Context &ctx) noexcept override;
};
class MessagePopup: public Popup {
private:
ox::String m_msg;
public:
ox::Signal<ox::Error(PopupResponse)> response;
MessagePopup(ox::StringParam title, ox::StringParam msg) noexcept;
void show(ox::StringParam msg) noexcept;
void draw(Context &ctx) noexcept override;
};

View File

@@ -162,7 +162,7 @@ class ItemMaker {
* @return path of file or error in Result
*/
ox::Error write(
StudioContext &ctx,
Context &ctx,
ox::StringViewCR pPath,
size_t pTemplateIdx) const noexcept {
return writeItem(ctx, pPath, pTemplateIdx);
@@ -177,7 +177,7 @@ class ItemMaker {
* @return path of file or error in Result
*/
ox::Error write(
StudioContext &ctx,
Context &ctx,
ox::StringViewCR pPath,
ox::StringViewCR pName,
size_t pTemplateIdx) const noexcept {
@@ -187,7 +187,7 @@ class ItemMaker {
protected:
virtual ox::Error writeItem(
StudioContext &ctx,
Context &ctx,
ox::StringViewCR pPath,
size_t pTemplateIdx) const noexcept = 0;
@@ -249,7 +249,7 @@ class ItemMakerT final: public ItemMaker {
}
ox::Error writeItem(
StudioContext &ctx,
Context &ctx,
ox::StringViewCR pPath,
size_t const pTemplateIdx) const noexcept override {
createUuidMapping(keelCtx(ctx.tctx), pPath, ox::UUID::generate().unwrap());

View File

@@ -27,17 +27,17 @@ class Module {
public:
virtual ~Module() noexcept = default;
virtual ox::Vector<EditorMaker> editors(studio::StudioContext &ctx) const;
virtual ox::Vector<EditorMaker> editors(studio::Context &ctx) const;
virtual ox::Vector<ox::UPtr<ItemMaker>> itemMakers(studio::StudioContext&) const;
virtual ox::Vector<ox::UPtr<ItemMaker>> itemMakers(studio::Context&) const;
virtual ox::Vector<ox::UPtr<ItemTemplate>> itemTemplates(studio::StudioContext&) const;
virtual ox::Vector<ox::UPtr<ItemTemplate>> itemTemplates(studio::Context&) const;
};
template<typename Editor>
[[nodiscard]]
EditorMaker editorMaker(StudioContext &ctx, ox::StringParam ext) noexcept {
EditorMaker editorMaker(Context &ctx, ox::StringParam ext) noexcept {
return {
{std::move(ext)},
[&ctx](ox::StringViewCR path) -> ox::Result<BaseEditor*> {
@@ -48,7 +48,7 @@ EditorMaker editorMaker(StudioContext &ctx, ox::StringParam ext) noexcept {
template<typename Editor>
[[nodiscard]]
EditorMaker editorMaker(StudioContext &ctx, std::initializer_list<ox::StringView> exts) noexcept {
EditorMaker editorMaker(Context &ctx, std::initializer_list<ox::StringView> exts) noexcept {
return {
[&exts] {
ox::Vector<ox::String> fileTypes;

View File

@@ -12,10 +12,12 @@
#include <turbine/context.hpp>
#include "widget.hpp"
namespace studio {
class Popup {
class Popup: public Widget {
private:
ox::Vec2 m_size;
ox::String m_title;
@@ -23,7 +25,7 @@ class Popup {
// emits path parameter
ox::Signal<ox::Error(ox::String const&)> finished;
virtual ~Popup() noexcept = default;
~Popup() noexcept override = default;
virtual void open() noexcept = 0;
@@ -32,8 +34,6 @@ class Popup {
[[nodiscard]]
virtual bool isOpen() const noexcept = 0;
virtual void draw(studio::StudioContext &ctx) noexcept = 0;
protected:
constexpr void setSize(ox::Size sz) noexcept {
m_size = {static_cast<float>(sz.width), static_cast<float>(sz.height)};

View File

@@ -24,7 +24,7 @@ class Task: public ox::SignalHandler {
class TaskRunner {
private:
ox::Vector<ox::UniquePtr<studio::Task>> m_tasks;
ox::Vector<ox::UPtr<studio::Task>> m_tasks;
public:
void update(turbine::Context &ctx) noexcept;
void add(Task &task) noexcept;

View File

@@ -15,7 +15,7 @@ namespace studio {
class Widget: public ox::SignalHandler {
public:
~Widget() noexcept override = default;
virtual void draw(studio::StudioContext&) noexcept = 0;
virtual void draw(Context&) noexcept = 0;
};
}

View File

@@ -109,7 +109,7 @@ UndoStack *BaseEditor::undoStack() noexcept {
void BaseEditor::navigateTo(ox::StringViewCR) noexcept {}
Editor::Editor(StudioContext &ctx, ox::StringParam itemPath) noexcept:
Editor::Editor(Context &ctx, ox::StringParam itemPath) noexcept:
m_itemPath(std::move(itemPath)),
m_itemName(m_itemPath.substr(std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset() + 1)) {
m_undoStack.changeTriggered.connect(this, &Editor::markUnsavedChanges);

View File

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

View File

@@ -52,7 +52,7 @@ bool FilePickerPopup::isOpen() const noexcept {
return m_open;
}
ox::Optional<ox::String> FilePickerPopup::draw(StudioContext &ctx) noexcept {
ox::Optional<ox::String> FilePickerPopup::draw(Context &ctx) noexcept {
ox::Optional<ox::String> out;
if (!m_open) {
return out;

View File

@@ -11,7 +11,7 @@
namespace studio {
void FileExplorer::draw(StudioContext &ctx, ImVec2 const &sz) const noexcept {
void FileExplorer::draw(Context &ctx, ImVec2 const &sz) const noexcept {
ImGui::BeginChild("ProjectExplorer", sz, true);
ImGui::SetNextItemOpen(true);
if (m_treeModel) {

View File

@@ -82,6 +82,25 @@ PopupResponse PopupControlsOkCancel(
return PopupControlsOkCancel(ImGui::GetContentRegionAvail().x + 17, popupOpen, ok, cancel);
}
PopupResponse PopupControlsOk(
bool &popupOpen,
ox::CStringViewCR ok) {
auto out = PopupResponse::None;
constexpr auto btnSz = ImVec2{50, BtnSz.y};
ImGui::Separator();
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 42);
if (ImGui::Button(ok.c_str(), btnSz)) {
popupOpen = false;
out = PopupResponse::OK;
}
ImGui::SameLine();
if (ImGui::IsKeyDown(ImGuiKey_Escape)) {
popupOpen = false;
out = PopupResponse::Cancel;
}
return out;
}
bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show, ImVec2 const&sz) {
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
centerNextWindow(ctx);
@@ -150,7 +169,7 @@ bool ComboBox(
bool FileComboBox(
ox::CStringViewCR lbl,
StudioContext &sctx,
Context &sctx,
ox::StringViewCR fileExt,
size_t &selectedIdx) noexcept {
auto const&list = sctx.project->fileList(fileExt);
@@ -194,7 +213,7 @@ bool ListBox(ox::CStringViewCR name, ox::SpanView<ox::CStringView> const&list, s
FilePicker::FilePicker(
StudioContext &sctx,
Context &sctx,
ox::StringParam title,
ox::StringParam fileExt,
ImVec2 const&size) noexcept:
@@ -226,25 +245,29 @@ void FilePicker::show() noexcept {
}
QuestionPopup::QuestionPopup(ox::StringParam title, ox::StringParam question) noexcept:
m_title{std::move(title)},
m_question{std::move(question)} {
Popup::Popup(ox::StringParam title) noexcept: m_title{std::move(title)} {
}
void QuestionPopup::open() noexcept {
void Popup::open() noexcept {
m_stage = Stage::Opening;
}
void QuestionPopup::close() noexcept {
void Popup::close() noexcept {
m_stage = Stage::Closed;
m_open = false;
}
bool QuestionPopup::isOpen() const noexcept {
bool Popup::isOpen() const noexcept {
return m_open;
}
void QuestionPopup::draw(StudioContext &ctx, ImVec2 const &sz) noexcept {
QuestionPopup::QuestionPopup(ox::StringParam title, ox::StringParam question) noexcept:
Popup{std::move(title)},
m_question{std::move(question)} {
}
void QuestionPopup::draw(Context &ctx) noexcept {
switch (m_stage) {
case Stage::Closed:
break;
@@ -255,7 +278,7 @@ void QuestionPopup::draw(StudioContext &ctx, ImVec2 const &sz) noexcept {
[[fallthrough]];
case Stage::Open:
centerNextWindow(ctx.tctx);
ImGui::SetNextWindowSize(static_cast<ImVec2>(sz));
ImGui::SetNextWindowSize({});
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
if (ImGui::BeginPopupModal(m_title.c_str(), &m_open, modalFlags)) {
ImGui::Text("%s", m_question.c_str());
@@ -279,6 +302,49 @@ void QuestionPopup::draw(StudioContext &ctx, ImVec2 const &sz) noexcept {
}
MessagePopup::MessagePopup(ox::StringParam title, ox::StringParam msg) noexcept:
Popup{std::move(title)},
m_msg{std::move(msg)} {
}
void MessagePopup::show(ox::StringParam msg) noexcept {
m_msg = std::move(msg);
open();
}
void MessagePopup::draw(Context &ctx) noexcept {
switch (m_stage) {
case Stage::Closed:
break;
case Stage::Opening:
ImGui::OpenPopup(m_title.c_str());
m_stage = Stage::Open;
m_open = true;
[[fallthrough]];
case Stage::Open:
centerNextWindow(ctx.tctx);
ImGui::SetNextWindowSize({});
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
if (ImGui::BeginPopupModal(m_title.c_str(), &m_open, modalFlags)) {
ImGui::Text("%s", m_msg.c_str());
auto const r = PopupControlsOk(m_open, "OK");
switch (r) {
case PopupResponse::None:
break;
case PopupResponse::OK:
response.emit(r);
close();
break;
case PopupResponse::Cancel:
break;
}
ImGui::EndPopup();
}
break;
}
}
bool s_mainWinHasFocus{};
bool mainWinHasFocus() noexcept {
return s_mainWinHasFocus;

View File

@@ -6,15 +6,15 @@
namespace studio {
ox::Vector<EditorMaker> Module::editors(StudioContext&) const {
ox::Vector<EditorMaker> Module::editors(Context&) const {
return {};
}
ox::Vector<ox::UPtr<ItemMaker>> Module::itemMakers(StudioContext&) const {
ox::Vector<ox::UPtr<ItemMaker>> Module::itemMakers(Context&) const {
return {};
}
ox::Vector<ox::UPtr<ItemTemplate>> Module::itemTemplates(StudioContext&) const {
ox::Vector<ox::UPtr<ItemTemplate>> Module::itemTemplates(Context&) const {
return {};
}