Squashed 'deps/nostalgia/' changes from f847289b..671b8eda

671b8eda [ox/std] Make StringLiteral constructors consteval
952637a1 Merge commit 'cbf4414fcaf00c00a2abf73b5c04a055180ad980'
7569698e [nostalgia,studio] Add FileExts_TileSheet const, and corresponding FilePickerPopup constructor
21713ba9 [ox/std] Fix StringLiteral::operator= to work with DevkitARM
73273b6f [nostalgia/gfx] Add isTileSheet function for checking paths against both file extensions
9f040392 [olympic,nostalgia] Cleanup style
f4f7e5d0 Merge commit '9b5f7886cadc5c3dc826d00fa5b2e71696151dfd'
c27726a4 Merge commit '6bbcae10cc7b21b73171ec0ff196f4baf6304404'
bd24a775 Merge commit '7371df429534f264c179684412f6197f7968ebfa'
4419dff2 Merge commit '7688c05bac8c20bc267cae62ec78d55e5d0c493b'
536999c0 Merge commit '47eee1d56d591e3631d16e95a78ea3629ee312ee'
a5535ef5 Merge commit '08236fc790e711afe886b6ef545511d35e4e5c6c'
a90380f3 Merge commit 'e90dd887477452922f783535edb3d4c55e9a0d2c'
2000b2de [nostalgia/gfx/studio] Cleanup
7d92400f [nostalgia/gfx/studio] Add type specific navigateTo functions

git-subtree-dir: deps/nostalgia
git-subtree-split: 671b8edaadefe1872fb8954ad13d221b24f676c0
This commit is contained in:
2025-06-29 17:33:27 -05:00
parent 9b5f7886ca
commit b0726568df
36 changed files with 159 additions and 114 deletions

View File

@ -16,35 +16,28 @@ namespace ox {
* StringLiteral is used for functions that want to ensure that they are taking * StringLiteral is used for functions that want to ensure that they are taking
* string literals, and not strings outside of the data section of the program * string literals, and not strings outside of the data section of the program
* that might get deleted. * that might get deleted.
* This type cannot force you to use it correctly, so don't give it something
* that is not a literal.
* If you do this:
* StringLiteral(str.c_str())
* the resulting segfault is on you.
*/ */
class StringLiteral: public detail::BaseStringView { class StringLiteral: public detail::BaseStringView {
public: public:
constexpr StringLiteral() noexcept = default; consteval StringLiteral() noexcept = default;
constexpr StringLiteral(StringLiteral const&sv) noexcept = default; constexpr StringLiteral(StringLiteral const &sv) noexcept = default;
constexpr explicit StringLiteral(std::nullptr_t) noexcept {} consteval explicit StringLiteral(std::nullptr_t) noexcept {}
constexpr explicit StringLiteral(const char *str, std::size_t len) noexcept: BaseStringView(str, len) {} consteval explicit StringLiteral(char const *str, std::size_t const len) noexcept: BaseStringView{str, len} {}
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
constexpr explicit StringLiteral(char const *str) noexcept: StringLiteral(str, ox::strlen(str)) {} consteval explicit StringLiteral(char const *str) noexcept: StringLiteral{str, ox::strlen(str)} {}
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
constexpr StringLiteral &operator=(StringLiteral const&other) noexcept { constexpr StringLiteral &operator=(StringLiteral const &other) noexcept {
if (&other != this) {
set(other.data(), other.len()); set(other.data(), other.len());
}
return *this; return *this;
} }
[[nodiscard]] [[nodiscard]]
constexpr const char *c_str() const noexcept { constexpr char const *c_str() const noexcept {
return data(); return data();
} }

View File

@ -12,8 +12,18 @@ constexpr auto TileWidth = 8;
constexpr auto TileHeight = 8; constexpr auto TileHeight = 8;
constexpr auto PixelsPerTile = TileWidth * TileHeight; constexpr auto PixelsPerTile = TileWidth * TileHeight;
constexpr ox::StringLiteral FileExt_ng("ng"); constexpr ox::StringLiteral FileExt_ng{"ng"};
constexpr ox::StringLiteral FileExt_nts("nts"); constexpr ox::StringLiteral FileExt_nts{"nts"};
constexpr ox::StringLiteral FileExt_npal("npal"); constexpr ox::StringLiteral FileExt_npal{"npal"};
constexpr ox::Array<ox::StringLiteral, 2> FileExts_TileSheet{
FileExt_nts,
FileExt_ng,
};
[[nodiscard]]
constexpr bool isTileSheet(ox::StringViewCR path) noexcept {
return endsWith(path, FileExt_nts) || endsWith(path, FileExt_ng);
}
} }

View File

@ -114,10 +114,10 @@ struct InitParams {
ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const &params = {}) noexcept; ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const &params = {}) noexcept;
[[nodiscard]] [[nodiscard]]
int tileColumns(Context&) noexcept; int tileColumns(Context const&) noexcept;
[[nodiscard]] [[nodiscard]]
int tileRows(Context&) noexcept; int tileRows(Context const&) noexcept;
ox::Error loadBgPalette( ox::Error loadBgPalette(
Context &ctx, Context &ctx,

View File

@ -6,6 +6,28 @@
#include <studio/studio.hpp> #include <studio/studio.hpp>
namespace nostalgia::core { #include "tilesheet.hpp"
namespace nostalgia::gfx {
inline void navigateToTileSheet(
studio::Context &ctx, ox::StringParam path, SubSheetId const subsheetId) noexcept {
studio::navigateTo(ctx, std::move(path), ox::intToStr(subsheetId));
}
inline void navigateToPalette(studio::Context &ctx, ox::StringParam path) noexcept {
studio::navigateTo(ctx, std::move(path));
}
inline void navigateToPalette(
studio::Context &ctx,
ox::StringParam path,
size_t const colorIdx,
size_t const palPage) noexcept {
studio::navigateTo(
ctx,
std::move(path),
ox::sfmt("{};{}", colorIdx, palPage));
}
} }

View File

@ -10,11 +10,11 @@ namespace nostalgia::gfx {
constexpr auto GbaTileColumns = 32; constexpr auto GbaTileColumns = 32;
constexpr auto GbaTileRows = 32; constexpr auto GbaTileRows = 32;
int tileColumns(Context&) noexcept { int tileColumns(Context const&) noexcept {
return GbaTileColumns; return GbaTileColumns;
} }
int tileRows(Context&) noexcept { int tileRows(Context const&) noexcept {
return GbaTileRows; return GbaTileRows;
} }

View File

@ -9,6 +9,8 @@
#include <keel/media.hpp> #include <keel/media.hpp>
#include <studio/studio.hpp> #include <studio/studio.hpp>
#include <nostalgia/gfx/studio.hpp>
#include "tilesheeteditor-imgui.hpp" #include "tilesheeteditor-imgui.hpp"
namespace nostalgia::gfx { namespace nostalgia::gfx {
@ -576,10 +578,10 @@ void TileSheetEditorImGui::drawPaletteMenu() noexcept {
m_view.setPalIdx(i); m_view.setPalIdx(i);
} }
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) { if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
studio::navigateTo( navigateToPalette(
m_sctx, m_sctx,
m_model.palPath(), m_model.palPath(),
ox::sfmt("{};{}", i, m_model.palettePage())); i, m_model.palettePage());
} }
// Column: color RGB // Column: color RGB
ImGui::TableNextColumn(); ImGui::TableNextColumn();

View File

@ -28,7 +28,7 @@ void ClawEditor::draw(Context&) noexcept {
ImGui::EndChild(); ImGui::EndChild();
} }
void ClawEditor::drawRow(ox::ModelValue const&value) noexcept { void ClawEditor::drawRow(ox::ModelValue const &value) noexcept {
using Str = ox::BasicString<100>; using Str = ox::BasicString<100>;
Str val, type; Str val, type;
switch (value.type()) { switch (value.type()) {
@ -93,13 +93,13 @@ void ClawEditor::drawRow(ox::ModelValue const&value) noexcept {
ImGui::Text("%s", val.c_str()); ImGui::Text("%s", val.c_str());
} }
void ClawEditor::drawVar(ObjPath &path, ox::StringViewCR name, ox::ModelValue const&value) noexcept { void ClawEditor::drawVar(ObjPath &path, ox::StringViewCR name, ox::ModelValue const &value) noexcept {
using Str = ox::BasicString<100>; using Str = ox::BasicString<100>;
path.push_back(name); path.push_back(name);
if (value.type() == ox::ModelValue::Type::Object) { if (value.type() == ox::ModelValue::Type::Object) {
drawTree(path, value.get<ox::ModelObject>()); drawTree(path, value.get<ox::ModelObject>());
} else if (value.type() == ox::ModelValue::Type::Vector) { } else if (value.type() == ox::ModelValue::Type::Vector) {
auto const&vec = value.get<ox::ModelValueVector>(); auto const &vec = value.get<ox::ModelValueVector>();
auto const pathStr = ox::join<Str>("##", path).unwrap(); auto const pathStr = ox::join<Str>("##", path).unwrap();
auto const lbl = ox::sfmt<Str>("{}##{}", name, pathStr); auto const lbl = ox::sfmt<Str>("{}##{}", name, pathStr);
auto const flags = ImGuiTreeNodeFlags_SpanFullWidth auto const flags = ImGuiTreeNodeFlags_SpanFullWidth
@ -110,7 +110,7 @@ void ClawEditor::drawVar(ObjPath &path, ox::StringViewCR name, ox::ModelValue co
ImGui::SameLine(); ImGui::SameLine();
drawRow(value); drawRow(value);
if (open) { if (open) {
for (auto i = 0lu; auto const&e: vec) { for (auto i = 0lu; auto const &e: vec) {
auto const iStr = ox::sfmt<Str>("{}", i); auto const iStr = ox::sfmt<Str>("{}", i);
path.push_back(iStr); path.push_back(iStr);
ImGui::TableNextRow(0, 5); ImGui::TableNextRow(0, 5);
@ -138,7 +138,7 @@ void ClawEditor::drawVar(ObjPath &path, ox::StringViewCR name, ox::ModelValue co
path.pop_back(); path.pop_back();
} }
void ClawEditor::drawTree(ObjPath &path, ox::ModelObject const&obj) noexcept { void ClawEditor::drawTree(ObjPath &path, ox::ModelObject const &obj) noexcept {
using Str = ox::BasicString<100>; using Str = ox::BasicString<100>;
for (auto const &c : obj) { for (auto const &c : obj) {
ImGui::TableNextRow(0, 5); ImGui::TableNextRow(0, 5);

View File

@ -21,11 +21,11 @@ class ClawEditor: public Editor {
void draw(Context&) noexcept final; void draw(Context&) noexcept final;
private: private:
static void drawRow(ox::ModelValue const&value) noexcept; static void drawRow(ox::ModelValue const &value) noexcept;
void drawVar(ObjPath &path, ox::StringViewCR name, ox::ModelValue const&value) noexcept; void drawVar(ObjPath &path, ox::StringViewCR name, ox::ModelValue const &value) noexcept;
void drawTree(ObjPath &path, ox::ModelObject const&obj) noexcept; void drawTree(ObjPath &path, ox::ModelObject const &obj) noexcept;
}; };
} }

View File

@ -24,7 +24,7 @@ void NewMenu::open() noexcept {
m_useDefaultPath = true; m_useDefaultPath = true;
m_explorer.setModel(buildFileTreeModel( m_explorer.setModel(buildFileTreeModel(
m_explorer, m_explorer,
[](ox::StringViewCR, ox::FileStat const&s) { [](ox::StringViewCR, ox::FileStat const &s) {
return s.fileType == ox::FileType::Directory; return s.fileType == ox::FileType::Directory;
}).or_value(ox::UPtr<FileTreeModel>{})); }).or_value(ox::UPtr<FileTreeModel>{}));
} }
@ -75,26 +75,26 @@ 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->typeDisplayName() < im2->typeDisplayName(); return im1->typeDisplayName() < im2->typeDisplayName();
}); });
} }
void NewMenu::installItemTemplate(ox::UPtr<ItemTemplate> &&tmplt) noexcept { void NewMenu::installItemTemplate(ox::UPtr<ItemTemplate> &&tmplt) noexcept {
for (auto const&im : m_types) { for (auto const &im : m_types) {
if (im->installTemplate(std::move(tmplt))) { if (im->installTemplate(std::move(tmplt))) {
break; break;
} }
} }
} }
void NewMenu::drawNewItemType(Context const&sctx) noexcept { void NewMenu::drawNewItemType(Context const &sctx) noexcept {
setSize({280, 180}); setSize({280, 180});
drawWindow(sctx.tctx, m_open, [this] { drawWindow(sctx.tctx, m_open, [this] {
ig::ListBox("Item Type", [&](size_t const i) -> ox::CStringView { ig::ListBox("Item Type", [&](size_t const i) -> ox::CStringView {
return m_types[i]->typeDisplayName(); return m_types[i]->typeDisplayName();
}, m_types.size(), m_selectedType, {200, 100}); }, m_types.size(), m_selectedType, {200, 100});
auto const&im = *m_types[m_selectedType]; auto const &im = *m_types[m_selectedType];
drawFirstPageButtons(im.itemTemplates().size() == 1 ? drawFirstPageButtons(im.itemTemplates().size() == 1 ?
Stage::NewItemTransitioningToPath : Stage::NewItemTemplate); Stage::NewItemTransitioningToPath : Stage::NewItemTemplate);
if (m_stage == Stage::NewItemTransitioningToPath || m_stage == Stage::NewItemTemplate) { if (m_stage == Stage::NewItemTransitioningToPath || m_stage == Stage::NewItemTemplate) {
@ -105,10 +105,10 @@ void NewMenu::drawNewItemType(Context const&sctx) noexcept {
}); });
} }
void NewMenu::drawNewItemTemplate(Context const&sctx) noexcept { void NewMenu::drawNewItemTemplate(Context const &sctx) noexcept {
setSize({280, 180}); setSize({280, 180});
drawWindow(sctx.tctx, m_open, [this] { drawWindow(sctx.tctx, m_open, [this] {
auto const&templates = auto const &templates =
m_types[m_selectedType]->itemTemplates(); m_types[m_selectedType]->itemTemplates();
ig::ListBox("Template", [&](size_t const i) -> ox::CStringView { ig::ListBox("Template", [&](size_t const i) -> ox::CStringView {
return templates[i]->name(); return templates[i]->name();

View File

@ -75,7 +75,7 @@ class NewMenu final: public Popup {
void installItemTemplate(ox::UPtr<ItemTemplate> &&tmplt) noexcept; void installItemTemplate(ox::UPtr<ItemTemplate> &&tmplt) noexcept;
private: private:
void drawNewItemType(Context const&sctx) noexcept; void drawNewItemType(Context const &sctx) noexcept;
void drawNewItemPath(Context &sctx) noexcept; void drawNewItemPath(Context &sctx) noexcept;

View File

@ -13,7 +13,7 @@
namespace studio { namespace studio {
class NewProject: public studio::Popup { class NewProject: public Popup {
public: public:
enum class Stage { enum class Stage {
Closed, Closed,

View File

@ -140,7 +140,7 @@ class Editor: public studio::BaseEditor {
ox::Error pushCommand(Args&&... args) noexcept { ox::Error pushCommand(Args&&... args) noexcept {
try { try {
return m_undoStack.push(ox::make_unique<UC>(ox::forward<Args>(args)...)); return m_undoStack.push(ox::make_unique<UC>(ox::forward<Args>(args)...));
} catch (ox::Exception const&ex) { } catch (ox::Exception const &ex) {
return ex.toError(); return ex.toError();
} }
} }
@ -148,7 +148,7 @@ class Editor: public studio::BaseEditor {
private: private:
ox::Error markUnsavedChanges(UndoCommand const*) noexcept; ox::Error markUnsavedChanges(UndoCommand const*) noexcept;
ox::Error handleRename(ox::StringViewCR oldPath, ox::StringViewCR newPath, ox::UUID const&id) noexcept; ox::Error handleRename(ox::StringViewCR oldPath, ox::StringViewCR newPath, ox::UUID const &id) noexcept;
}; };

View File

@ -21,7 +21,7 @@ struct FDFilterItem {
FDFilterItem(ox::StringViewCR pName, ox::StringViewCR pSpec) noexcept; FDFilterItem(ox::StringViewCR pName, ox::StringViewCR pSpec) noexcept;
}; };
ox::Result<ox::String> saveFile(ox::Vector<FDFilterItem> const&exts) noexcept; ox::Result<ox::String> saveFile(ox::Vector<FDFilterItem> const &exts) noexcept;
ox::Result<ox::String> chooseDirectory() noexcept; ox::Result<ox::String> chooseDirectory() noexcept;

View File

@ -24,6 +24,8 @@ class FilePickerPopup {
public: public:
explicit FilePickerPopup(ox::StringParam name, keel::Context &kctx, ox::StringParam fileExt) noexcept; explicit FilePickerPopup(ox::StringParam name, keel::Context &kctx, ox::StringParam fileExt) noexcept;
explicit FilePickerPopup(ox::StringParam name, keel::Context &kctx, ox::SpanView<ox::StringLiteral> fileExts) noexcept;
explicit FilePickerPopup(ox::StringParam name, keel::Context &kctx, ox::Vector<ox::String> fileExts) noexcept; explicit FilePickerPopup(ox::StringParam name, keel::Context &kctx, ox::Vector<ox::String> fileExts) noexcept;
void refresh() noexcept; void refresh() noexcept;

View File

@ -78,7 +78,7 @@ class FileExplorer: public ox::SignalHandler {
} }
private: private:
ox::Result<bool> setSelectedPath(ox::StringViewCR path, FileTreeModel const&node) noexcept; ox::Result<bool> setSelectedPath(ox::StringViewCR path, FileTreeModel const &node) noexcept;
}; };
@ -106,7 +106,7 @@ class FileTreeModel {
void setChildren(ox::Vector<ox::UPtr<FileTreeModel>> children) noexcept; void setChildren(ox::Vector<ox::UPtr<FileTreeModel>> children) noexcept;
[[nodiscard]] [[nodiscard]]
ox::Vector<ox::UPtr<FileTreeModel>> const&children() const noexcept { ox::Vector<ox::UPtr<FileTreeModel>> const &children() const noexcept {
return m_children; return m_children;
} }
@ -129,13 +129,13 @@ ox::Result<ox::UPtr<FileTreeModel>> buildFileTreeModel(
ox::StringParam name, ox::StringParam name,
ox::StringViewCR path, ox::StringViewCR path,
FileTreeModel *parent = nullptr, FileTreeModel *parent = nullptr,
std::function<bool(ox::StringViewCR, ox::FileStat const&)> const&filter = std::function<bool(ox::StringViewCR, ox::FileStat const&)> const &filter =
[](ox::StringViewCR, ox::FileStat const&) {return true;}, [](ox::StringViewCR, ox::FileStat const&) {return true;},
bool showEmptyDirs = true) noexcept; bool showEmptyDirs = true) noexcept;
ox::Result<ox::UPtr<FileTreeModel>> buildFileTreeModel( ox::Result<ox::UPtr<FileTreeModel>> buildFileTreeModel(
FileExplorer &explorer, FileExplorer &explorer,
std::function<bool(ox::StringViewCR, ox::FileStat const&)> const&filter = std::function<bool(ox::StringViewCR, ox::FileStat const&)> const &filter =
[](ox::StringViewCR, ox::FileStat const&) {return true;}, [](ox::StringViewCR, ox::FileStat const&) {return true;},
bool showEmptyDirs = true) noexcept; bool showEmptyDirs = true) noexcept;

View File

@ -27,11 +27,11 @@ class ItemTemplate {
virtual ~ItemTemplate() = default; virtual ~ItemTemplate() = default;
[[nodiscard]] [[nodiscard]]
constexpr ox::String const&name() const noexcept { constexpr ox::String const &name() const noexcept {
return m_name; return m_name;
} }
constexpr bool operator<=>(ItemTemplate const&other) const noexcept { constexpr bool operator<=>(ItemTemplate const &other) const noexcept {
return m_name != other.name() ? (m_name < other.name() ? -1 : 1) : 0; return m_name != other.name() ? (m_name < other.name() ? -1 : 1) : 0;
} }
@ -105,7 +105,7 @@ class ItemMaker {
virtual ~ItemMaker() noexcept = default; virtual ~ItemMaker() noexcept = default;
[[nodiscard]] [[nodiscard]]
ox::String const&typeDisplayName() const noexcept { ox::String const &typeDisplayName() const noexcept {
return m_typeDisplayName; return m_typeDisplayName;
} }
@ -120,17 +120,17 @@ class ItemMaker {
return false; return false;
} }
constexpr ox::Vector<ox::UPtr<ItemTemplate>> const&itemTemplates() const noexcept { constexpr ox::Vector<ox::UPtr<ItemTemplate>> const &itemTemplates() const noexcept {
return m_templates; return m_templates;
} }
[[nodiscard]] [[nodiscard]]
ox::String const&fileExt() const noexcept { ox::String const &fileExt() const noexcept {
return m_fileExt; return m_fileExt;
} }
[[nodiscard]] [[nodiscard]]
ox::String const&defaultPath() const noexcept { ox::String const &defaultPath() const noexcept {
return m_parentDir; return m_parentDir;
} }
@ -212,7 +212,7 @@ class ItemMakerT final: public ItemMaker {
ox::StringParam pDisplayName, ox::StringParam pDisplayName,
ox::StringViewCR pParentDir, ox::StringViewCR pParentDir,
ox::StringParam fileExt, ox::StringParam fileExt,
T const&pItem, T const &pItem,
ox::ClawFormat const pFmt) noexcept: ox::ClawFormat const pFmt) noexcept:
ItemMaker( ItemMaker(
std::move(pDisplayName), std::move(pDisplayName),
@ -249,7 +249,7 @@ class ItemMakerT final: public ItemMaker {
ox::StringViewCR pPath, ox::StringViewCR pPath,
size_t const pTemplateIdx) const noexcept override { size_t const pTemplateIdx) const noexcept override {
createUuidMapping(keelCtx(ctx.tctx), pPath, ox::UUID::generate().unwrap()); createUuidMapping(keelCtx(ctx.tctx), pPath, ox::UUID::generate().unwrap());
auto const&templates = itemTemplates(); auto const &templates = itemTemplates();
auto const tmplIdx = pTemplateIdx < templates.size() ? pTemplateIdx : 0; auto const tmplIdx = pTemplateIdx < templates.size() ? pTemplateIdx : 0;
OX_REQUIRE_M(tmpl, templates[tmplIdx]->getItem( OX_REQUIRE_M(tmpl, templates[tmplIdx]->getItem(
keelCtx(ctx), typeName(), typeVersion())); keelCtx(ctx), typeName(), typeVersion()));

View File

@ -43,11 +43,11 @@ class Popup: public Widget {
m_title = std::move(title); m_title = std::move(title);
} }
constexpr ox::String const&title() const noexcept { constexpr ox::String const &title() const noexcept {
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);
}; };

View File

@ -64,7 +64,7 @@ class Project: public ox::SignalHandler {
ox::Error create() noexcept; ox::Error create() noexcept;
[[nodiscard]] [[nodiscard]]
ox::String const&projectPath() const noexcept; ox::String const &projectPath() const noexcept;
[[nodiscard]] [[nodiscard]]
ox::FileSystem &romFs() noexcept; ox::FileSystem &romFs() noexcept;
@ -77,7 +77,7 @@ class Project: public ox::SignalHandler {
template<typename T> template<typename T>
ox::Error writeObj( ox::Error writeObj(
ox::StringViewCR path, ox::StringViewCR path,
T const&obj, T const &obj,
ox::ClawFormat fmt) noexcept; ox::ClawFormat fmt) noexcept;
/** /**
@ -86,7 +86,7 @@ class Project: public ox::SignalHandler {
template<typename T> template<typename T>
ox::Error writeObj( ox::Error writeObj(
ox::StringViewCR path, ox::StringViewCR path,
T const&obj) noexcept; T const &obj) noexcept;
template<typename T> template<typename T>
ox::Result<T> loadObj(ox::StringViewCR path) const noexcept; ox::Result<T> loadObj(ox::StringViewCR path) const noexcept;
@ -108,7 +108,7 @@ class Project: public ox::SignalHandler {
ox::Error subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&slot) const noexcept; ox::Error subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&slot) const noexcept;
[[nodiscard]] [[nodiscard]]
ox::Vector<ox::String> const&fileList(ox::StringViewCR ext) noexcept; ox::Vector<ox::String> const &fileList(ox::StringViewCR ext) noexcept;
ox::Error writeTypeStore() noexcept; ox::Error writeTypeStore() noexcept;
@ -117,7 +117,7 @@ class Project: public ox::SignalHandler {
void indexFile(ox::StringViewCR path) noexcept; void indexFile(ox::StringViewCR path) noexcept;
ox::Error writeBuff(ox::StringViewCR path, ox::BufferView const&buff) noexcept; ox::Error writeBuff(ox::StringViewCR path, ox::BufferView const &buff) noexcept;
ox::Result<ox::Buffer> loadBuff(ox::StringViewCR path) const noexcept; ox::Result<ox::Buffer> loadBuff(ox::StringViewCR path) const noexcept;
@ -136,13 +136,13 @@ class Project: public ox::SignalHandler {
ox::Signal<ox::Error(ox::StringViewCR)> fileRecognized; ox::Signal<ox::Error(ox::StringViewCR)> fileRecognized;
ox::Signal<ox::Error(ox::StringViewCR)> fileDeleted; ox::Signal<ox::Error(ox::StringViewCR)> fileDeleted;
ox::Signal<ox::Error(ox::StringViewCR)> dirDeleted; ox::Signal<ox::Error(ox::StringViewCR)> dirDeleted;
ox::Signal<ox::Error(ox::StringViewCR path, ox::UUID const&id)> fileUpdated; ox::Signal<ox::Error(ox::StringViewCR path, ox::UUID const &id)> fileUpdated;
ox::Signal<ox::Error(ox::StringViewCR oldPath, ox::StringViewCR newPath, ox::UUID const&id)> fileMoved; ox::Signal<ox::Error(ox::StringViewCR oldPath, ox::StringViewCR newPath, ox::UUID const &id)> fileMoved;
}; };
template<typename T> template<typename T>
ox::Error Project::writeObj(ox::StringViewCR path, T const&obj, ox::ClawFormat fmt) noexcept { ox::Error Project::writeObj(ox::StringViewCR path, T const &obj, ox::ClawFormat fmt) noexcept {
OX_REQUIRE_M(buff, ox::writeClaw(obj, fmt)); OX_REQUIRE_M(buff, ox::writeClaw(obj, fmt));
if (fmt == ox::ClawFormat::Organic) { if (fmt == ox::ClawFormat::Organic) {
buff.pop_back(); buff.pop_back();
@ -167,7 +167,7 @@ ox::Error Project::writeObj(ox::StringViewCR path, T const&obj, ox::ClawFormat f
} }
template<typename T> template<typename T>
ox::Error Project::writeObj(ox::StringViewCR path, T const&obj) noexcept { ox::Error Project::writeObj(ox::StringViewCR path, T const &obj) noexcept {
OX_REQUIRE(ext, fileExt(path)); OX_REQUIRE(ext, fileExt(path));
auto const fmt = m_typeFmt[ext].or_value(ox::ClawFormat::Metal); auto const fmt = m_typeFmt[ext].or_value(ox::ClawFormat::Metal);
return writeObj(path, obj, fmt); return writeObj(path, obj, fmt);
@ -197,7 +197,7 @@ ox::Error Project::subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&s
case ProjectEvent::FileRecognized: case ProjectEvent::FileRecognized:
{ {
OX_REQUIRE(files, listFiles()); OX_REQUIRE(files, listFiles());
for (auto const&f : files) { for (auto const &f : files) {
slot(f); slot(f);
} }
connect(this, &Project::fileRecognized, tgt, slot); connect(this, &Project::fileRecognized, tgt, slot);

View File

@ -16,19 +16,19 @@ namespace studio {
struct Selection { struct Selection {
ox::Point a, b; ox::Point a, b;
constexpr Selection() noexcept = default; constexpr Selection() noexcept = default;
constexpr Selection(ox::Point const&pA, ox::Point const&pB) noexcept: a(pA), b(pB) {} constexpr Selection(ox::Point const &pA, ox::Point const &pB) noexcept: a(pA), b(pB) {}
[[nodiscard]] [[nodiscard]]
constexpr ox::Size size() const noexcept { constexpr ox::Size size() const noexcept {
return {b.x - a.x, b.y - a.y}; return {b.x - a.x, b.y - a.y};
} }
[[nodiscard]] [[nodiscard]]
constexpr bool contains(ox::Point const&pt) const noexcept { constexpr bool contains(ox::Point const &pt) const noexcept {
return a.x <= pt.x && a.y <= pt.y return a.x <= pt.x && a.y <= pt.y
&& b.x >= pt.x && b.y >= pt.y; && b.x >= pt.x && b.y >= pt.y;
} }
}; };
constexpr auto iterateSelection(studio::Selection const&sel, auto const&cb) { constexpr auto iterateSelection(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>;
for (auto x = sel.a.x; x <= sel.b.x; ++x) { for (auto x = sel.a.x; x <= sel.b.x; ++x) {
for (auto y = sel.a.y; y <= sel.b.y; ++y) { for (auto y = sel.a.y; y <= sel.b.y; ++y) {
@ -44,7 +44,7 @@ constexpr auto iterateSelection(studio::Selection const&sel, auto const&cb) {
} }
}; };
constexpr auto iterateSelectionRows(studio::Selection const&sel, auto const&cb) { constexpr auto iterateSelectionRows(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>;
for (auto y = sel.a.y; y <= sel.b.y; ++y) { for (auto y = sel.a.y; y <= sel.b.y; ++y) {
for (auto x = sel.a.x; x <= sel.b.x; ++x) { for (auto x = sel.a.x; x <= sel.b.x; ++x) {

View File

@ -12,7 +12,7 @@ namespace studio {
class NoChangesException: public ox::Exception { class NoChangesException: public ox::Exception {
public: public:
inline NoChangesException(std::source_location sloc = std::source_location::current()): explicit NoChangesException(std::source_location sloc = std::source_location::current()):
ox::Exception(1, "Command makes no changes.", sloc) {} ox::Exception(1, "Command makes no changes.", sloc) {}
}; };

View File

@ -20,7 +20,7 @@ FDFilterItem::FDFilterItem(ox::StringViewCR pName, ox::StringViewCR pSpec) noexc
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
} }
static ox::Result<ox::String> toResult(nfdresult_t r, NFD::UniquePathN const&path) noexcept { static ox::Result<ox::String> toResult(nfdresult_t r, NFD::UniquePathN const &path) noexcept {
switch (r) { switch (r) {
case NFD_OKAY: { case NFD_OKAY: {
ox::String out; ox::String out;
@ -39,11 +39,11 @@ OX_ALLOW_UNSAFE_BUFFERS_END
} }
} }
ox::Result<ox::String> saveFile(ox::Vector<FDFilterItem> const&exts) noexcept { ox::Result<ox::String> saveFile(ox::Vector<FDFilterItem> const &exts) noexcept {
NFD::Guard const guard; NFD::Guard const guard;
NFD::UniquePathN path; NFD::UniquePathN path;
ox::Vector<nfdnfilteritem_t, 5> filterItems(exts.size()); ox::Vector<nfdnfilteritem_t, 5> filterItems(exts.size());
for (auto i = 0u; auto const&f : exts) { for (auto i = 0u; auto const &f : exts) {
filterItems[i].name = f.name.data(); filterItems[i].name = f.name.data();
filterItems[i].spec = f.spec.data(); filterItems[i].spec = f.spec.data();
++i; ++i;

View File

@ -26,6 +26,22 @@ FilePickerPopup::FilePickerPopup(
m_fileExts{std::move(fileExt)} { m_fileExts{std::move(fileExt)} {
} }
FilePickerPopup::FilePickerPopup(
ox::StringParam name,
keel::Context &kctx,
ox::SpanView<ox::StringLiteral> fileExts) noexcept:
m_name{std::move(name)},
m_explorer{kctx},
m_fileExts{[fileExts] {
ox::Vector<ox::String> out;
out.reserve(fileExts.size());
for (auto &s : fileExts) {
out.emplace_back(s);
}
return out;
}()} {
}
FilePickerPopup::FilePickerPopup( FilePickerPopup::FilePickerPopup(
ox::StringParam name, ox::StringParam name,
keel::Context &kctx, keel::Context &kctx,

View File

@ -60,7 +60,7 @@ void FileExplorer::fileContextMenu(ox::StringViewCR) const noexcept {}
void FileExplorer::dirContextMenu(ox::StringViewCR) const noexcept {} void FileExplorer::dirContextMenu(ox::StringViewCR) const noexcept {}
ox::Result<bool> FileExplorer::setSelectedPath( ox::Result<bool> FileExplorer::setSelectedPath(
ox::StringViewCR path, FileTreeModel const&node) noexcept { ox::StringViewCR path, FileTreeModel const &node) noexcept {
if (path == node.path()) { if (path == node.path()) {
m_selected = &node; m_selected = &node;
return {}; return {};
@ -117,7 +117,7 @@ void FileTreeModel::draw(turbine::Context &tctx) const noexcept {
} }
} }
if (nodeOpen) { if (nodeOpen) {
for (auto const&child : m_children) { for (auto const &child : m_children) {
child->draw(tctx); child->draw(tctx);
} }
ImGui::TreePop(); ImGui::TreePop();
@ -160,16 +160,16 @@ ox::Result<ox::UPtr<FileTreeModel>> buildFileTreeModel(
ox::StringParam name, ox::StringParam name,
ox::StringViewCR path, ox::StringViewCR path,
FileTreeModel *parent, FileTreeModel *parent,
std::function<bool(ox::StringViewCR, ox::FileStat const&)> const &filter, std::function<bool(ox::StringViewCR, ox::FileStat const &)> const &filter,
bool const showEmptyDirs) noexcept { bool const showEmptyDirs) noexcept {
auto const&fs = explorer.romFs(); auto const &fs = explorer.romFs();
OX_REQUIRE(stat, fs.stat(path)); OX_REQUIRE(stat, fs.stat(path));
auto out = ox::make_unique<FileTreeModel>(explorer, std::move(name), stat.fileType, parent); auto out = ox::make_unique<FileTreeModel>(explorer, std::move(name), stat.fileType, parent);
if (stat.fileType == ox::FileType::Directory) { if (stat.fileType == ox::FileType::Directory) {
OX_REQUIRE_M(children, fs.ls(path)); OX_REQUIRE_M(children, fs.ls(path));
std::sort(children.begin(), children.end()); std::sort(children.begin(), children.end());
ox::Vector<ox::UPtr<FileTreeModel>> outChildren; ox::Vector<ox::UPtr<FileTreeModel>> outChildren;
for (auto const&childName : children) { for (auto const &childName : children) {
if (childName[0] != '.') { if (childName[0] != '.') {
auto const childPath = ox::sfmt("{}/{}", path, childName); auto const childPath = ox::sfmt("{}/{}", path, childName);
OX_REQUIRE(childStat, fs.stat(childPath)); OX_REQUIRE(childStat, fs.stat(childPath));
@ -195,7 +195,7 @@ ox::Result<ox::UPtr<FileTreeModel>> buildFileTreeModel(
ox::Result<ox::UPtr<FileTreeModel>> buildFileTreeModel( ox::Result<ox::UPtr<FileTreeModel>> buildFileTreeModel(
FileExplorer &explorer, FileExplorer &explorer,
std::function<bool(ox::StringViewCR, ox::FileStat const&)> const&filter, std::function<bool(ox::StringViewCR, ox::FileStat const&)> const &filter,
bool const showEmptyDirs) noexcept { bool const showEmptyDirs) noexcept {
return buildFileTreeModel(explorer, "Project", "/", nullptr, filter, showEmptyDirs); return buildFileTreeModel(explorer, "Project", "/", nullptr, filter, showEmptyDirs);
} }

View File

@ -7,8 +7,8 @@
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); 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)) {

View File

@ -75,7 +75,7 @@ ox::Error Project::create() noexcept {
return ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed"); return ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed");
} }
ox::String const&Project::projectPath() const noexcept { ox::String const &Project::projectPath() const noexcept {
return m_path; return m_path;
} }
@ -137,7 +137,7 @@ ox::Error Project::deleteItem(ox::StringViewCR path) noexcept {
if (stat.fileType == ox::FileType::Directory) { if (stat.fileType == ox::FileType::Directory) {
bool partialRemoval{}; bool partialRemoval{};
OX_REQUIRE(members, m_fs.ls(path)); OX_REQUIRE(members, m_fs.ls(path));
for (auto const&p : members) { for (auto const &p : members) {
partialRemoval = m_fs.remove(ox::sfmt("{}/{}", path, p)) || partialRemoval; partialRemoval = m_fs.remove(ox::sfmt("{}/{}", path, p)) || partialRemoval;
} }
if (partialRemoval) { if (partialRemoval) {
@ -161,7 +161,7 @@ bool Project::exists(ox::StringViewCR path) const noexcept {
return m_fs.stat(path).error == 0; return m_fs.stat(path).error == 0;
} }
ox::Vector<ox::String> const&Project::fileList(ox::StringViewCR ext) noexcept { ox::Vector<ox::String> const &Project::fileList(ox::StringViewCR ext) noexcept {
return m_fileExtFileMap[ext]; return m_fileExtFileMap[ext];
} }
@ -185,7 +185,7 @@ void Project::buildFileIndex() noexcept {
} }
m_fileExtFileMap.clear(); m_fileExtFileMap.clear();
std::sort(files.begin(), files.end()); std::sort(files.begin(), files.end());
for (auto const&file : files) { for (auto const &file : files) {
if (!beginsWith(file, ox::sfmt("/.{}/", m_projectDataDir))) { if (!beginsWith(file, ox::sfmt("/.{}/", m_projectDataDir))) {
indexFile(file); indexFile(file);
} }
@ -200,7 +200,7 @@ void Project::indexFile(ox::StringViewCR path) noexcept {
m_fileExtFileMap[ext].emplace_back(path); m_fileExtFileMap[ext].emplace_back(path);
} }
ox::Error Project::writeBuff(ox::StringViewCR path, ox::BufferView const&buff) noexcept { ox::Error Project::writeBuff(ox::StringViewCR path, ox::BufferView const &buff) noexcept {
constexpr auto HdrSz = 40; constexpr auto HdrSz = 40;
ox::Buffer outBuff; ox::Buffer outBuff;
outBuff.reserve(buff.size() + HdrSz); outBuff.reserve(buff.size() + HdrSz);
@ -227,7 +227,7 @@ ox::Result<ox::Buffer> Project::loadBuff(ox::StringViewCR path) const noexcept {
ox::Error Project::lsProcDir(ox::Vector<ox::String> &paths, ox::StringViewCR path) const noexcept { ox::Error Project::lsProcDir(ox::Vector<ox::String> &paths, ox::StringViewCR path) const noexcept {
OX_REQUIRE(files, m_fs.ls(path)); OX_REQUIRE(files, m_fs.ls(path));
for (auto const&name : files) { for (auto const &name : files) {
auto fullPath = ox::sfmt("{}/{}", path, name); auto fullPath = ox::sfmt("{}/{}", path, name);
OX_REQUIRE(stat, m_fs.stat(ox::StringView(fullPath))); OX_REQUIRE(stat, m_fs.stat(ox::StringView(fullPath)));
switch (stat.fileType) { switch (stat.fileType) {

View File

@ -28,7 +28,7 @@ class ClipboardObject: public BaseClipboardObject {
} }
}; };
ox::String getClipboardText(Context &ctx) noexcept; ox::String getClipboardText(Context const &ctx) noexcept;
void setClipboardText(Context &ctx, ox::StringViewCR text) noexcept; void setClipboardText(Context &ctx, ox::StringViewCR text) noexcept;

View File

@ -15,11 +15,11 @@ class Context;
void safeDelete(Context *p); void safeDelete(Context *p);
keel::Context const&keelCtx(Context const&ctx) noexcept; keel::Context const &keelCtx(Context const &ctx) noexcept;
keel::Context &keelCtx(Context &ctx) noexcept; keel::Context &keelCtx(Context &ctx) noexcept;
inline ox::FileSystem const*rom(Context const&ctx) noexcept { inline ox::FileSystem const*rom(Context const &ctx) noexcept {
return keelCtx(ctx).rom.get(); return keelCtx(ctx).rom.get();
} }
@ -27,7 +27,7 @@ inline ox::FileSystem *rom(Context &ctx) noexcept {
return keelCtx(ctx).rom.get(); return keelCtx(ctx).rom.get();
} }
void setApplicationDataRaw(Context &ctx, ox::AnyPtr const&applicationData) noexcept; void setApplicationDataRaw(Context &ctx, ox::AnyPtr const &applicationData) noexcept;
template<typename T> template<typename T>
void setApplicationData(Context &ctx, T *applicationData) noexcept { void setApplicationData(Context &ctx, T *applicationData) noexcept {
@ -35,7 +35,7 @@ void setApplicationData(Context &ctx, T *applicationData) noexcept {
} }
[[nodiscard]] [[nodiscard]]
ox::AnyPtr const&applicationDataRaw(Context &ctx) noexcept; ox::AnyPtr const &applicationDataRaw(Context &ctx) noexcept;
template<typename T> template<typename T>
[[nodiscard]] [[nodiscard]]

View File

@ -41,7 +41,7 @@ ox::Size getScreenSize(Context const &ctx) noexcept;
ox::Bounds getWindowBounds(Context const &ctx) noexcept; ox::Bounds getWindowBounds(Context const &ctx) noexcept;
ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept; ox::Error setWindowBounds(Context &ctx, ox::Bounds const &bnds) noexcept;
/** /**
* Tells Turbine to refresh the screen within the specified period of time. * Tells Turbine to refresh the screen within the specified period of time.

View File

@ -89,7 +89,7 @@ void setMouseButtonEventHandler(Context &ctx, MouseButtonEventHandler h) noexcep
KeyEventHandler keyEventHandler(Context const &ctx) noexcept; KeyEventHandler keyEventHandler(Context const &ctx) noexcept;
[[nodiscard]] [[nodiscard]]
bool buttonDown(Context const&ctx, Key) noexcept; bool buttonDown(Context const &ctx, Key) noexcept;
ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept; ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept;
@ -100,7 +100,7 @@ ox::Error run(Context &ctx) noexcept;
// Returns the number of milliseconds that have passed since the start of the // Returns the number of milliseconds that have passed since the start of the
// program. // program.
[[nodiscard]] [[nodiscard]]
TimeMs ticksMs(Context const&ctx) noexcept; TimeMs ticksMs(Context const &ctx) noexcept;
void requestShutdown(Context &ctx, bool force = false) noexcept; void requestShutdown(Context &ctx, bool force = false) noexcept;

View File

@ -9,7 +9,7 @@
namespace turbine { namespace turbine {
ox::String getClipboardText(Context&) noexcept { ox::String getClipboardText(Context const &) noexcept {
return {}; return {};
} }

View File

@ -10,7 +10,7 @@ void safeDelete(Context *p) {
delete p; delete p;
} }
keel::Context const&keelCtx(Context const&ctx) noexcept { keel::Context const &keelCtx(Context const &ctx) noexcept {
return ctx.keelCtx; return ctx.keelCtx;
} }
@ -18,11 +18,11 @@ keel::Context &keelCtx(Context &ctx) noexcept {
return ctx.keelCtx; return ctx.keelCtx;
} }
void setApplicationDataRaw(Context &ctx, ox::AnyPtr const&applicationData) noexcept { void setApplicationDataRaw(Context &ctx, ox::AnyPtr const &applicationData) noexcept {
ctx.applicationData = applicationData; ctx.applicationData = applicationData;
} }
ox::AnyPtr const&applicationDataRaw(Context &ctx) noexcept { ox::AnyPtr const &applicationDataRaw(Context &ctx) noexcept {
return ctx.applicationData; return ctx.applicationData;
} }

View File

@ -23,8 +23,8 @@ class Context final {
Context() noexcept = default; Context() noexcept = default;
Context(Context &other) noexcept = delete; Context(Context &other) noexcept = delete;
Context(Context const&other) noexcept = delete; Context(Context const &other) noexcept = delete;
Context(Context const&&other) noexcept = delete; Context(Context const &&other) noexcept = delete;
}; };

View File

@ -12,7 +12,7 @@
namespace turbine { namespace turbine {
ox::String getClipboardText(Context &ctx) noexcept { ox::String getClipboardText(Context const &ctx) noexcept {
return ox::String(glfwGetClipboardString(ctx.window)); return ox::String(glfwGetClipboardString(ctx.window));
} }

View File

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

View File

@ -35,8 +35,8 @@ class Context {
Context() noexcept = default; Context() noexcept = default;
Context(Context const&other) noexcept = delete; Context(Context const &other) noexcept = delete;
Context(Context const&&other) noexcept = delete; Context(Context const &&other) noexcept = delete;
}; };

View File

@ -214,7 +214,7 @@ ox::Bounds getWindowBounds(Context const &ctx) noexcept {
return bnds; return bnds;
} }
ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept { ox::Error setWindowBounds(Context &ctx, ox::Bounds const &bnds) noexcept {
glfwSetWindowPos(ctx.window, bnds.x, bnds.y); glfwSetWindowPos(ctx.window, bnds.x, bnds.y);
glfwSetWindowSize(ctx.window, bnds.width, bnds.height); glfwSetWindowSize(ctx.window, bnds.width, bnds.height);
return {}; return {};
@ -430,13 +430,13 @@ ox::Error run(Context &ctx) noexcept {
return {}; return {};
} }
TimeMs ticksMs(Context const&ctx) noexcept { TimeMs ticksMs(Context const &ctx) noexcept {
using namespace std::chrono; using namespace std::chrono;
auto const now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); auto const now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
return static_cast<TimeMs>(now) - ctx.startTime; return static_cast<TimeMs>(now) - ctx.startTime;
} }
bool buttonDown(Context const&ctx, Key const key) noexcept { bool buttonDown(Context const &ctx, Key const key) noexcept {
return (ctx.keysDown >> static_cast<int>(key)) & 1; return (ctx.keysDown >> static_cast<int>(key)) & 1;
} }