Squashed 'deps/nostalgia/' changes from 66cd5c4a..3c7652ef

3c7652ef [nostalgia/core/studio] Fix PaletteEditor to handle Palettes with 0 pages
941bc713 [studio] Fix NewMenu name input
e4ae23e1 [olympic/developer-handbook] Remove Ox submodules from project structure
67187d5e [olympic/developer-handbook] Elaborate more on exception usage
3271a371 [ox] Add Project Structure section to docs
ea9f50de [olympic] Add error handling back to developer-handbook.md
ea3c5e03 [olympic] Remove Ox from developer-handbook.md
c8c4177d [ox] Add ox-docs.md
76b540e3 [nostalgia/core] Cleanup, add missing FileAddress wrapper function
20627486 [keel] Cleanup
135f0e4c [nostalgia/core/studio/paletteeditor] Fix Alt shortcuts to respect keyboard focus
cb166876 [studio] Add variant of InputText that returns an IString
cb3ef0e7 [keel] Cleanup
0a62d900 [studio] Remove Editor::setRequiresConstantRefresh
ba7e3929 [nostalgia/core/studio] Make TileSheetEditor palette keys behave like PaletteEditor
36c4022b [nostalgia/core/studio] Fix PaletteEditor shortcuts to differentiate based on Alt key
e22b25e5 [studio] Remove Editor::requiresConstantRefresh
c6efabaa [studio,nostalgia] Fix PaletteEditor color update command merging, add setObsolete
1f6fefdb [nostalgia/core/studio] Disable PaletteEditor num key shorts when page rename is open
1e34f91e Merge commit '34b7779397bd4712603b4c5a39ffc57b74da0abd'
35cb2ece [nostalgia/core/studio] Fix PaletteEditor color name edit

git-subtree-dir: deps/nostalgia
git-subtree-split: 3c7652efc205cb3acdb993d7eeb1e2c2d894c2cb
This commit is contained in:
2024-11-01 22:21:09 -05:00
parent 34b7779397
commit 9e11019b87
21 changed files with 679 additions and 640 deletions

View File

@ -143,6 +143,14 @@ ox::Error loadBgTileSheet(
size_t srcTileIdx,
size_t tileCnt) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tsAddr,
size_t dstTileIdx,
size_t srcTileIdx,
size_t tileCnt) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,

View File

@ -61,21 +61,6 @@ ox::Error loadSpritePalette(
return {};
}
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
ox::FileAddress const&paletteAddr) noexcept {
oxRequire(pal, keel::readObj<CompactPalette>(keelCtx(ctx), paletteAddr));
return loadBgPalette(ctx, palBank, *pal, 0);
}
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept {
oxRequire(pal, keel::readObj<CompactPalette>(keelCtx(ctx), paletteAddr));
return loadSpritePalette(ctx, *pal, 0);
}
static ox::Error loadTileSheetSet(
Context &ctx,
ox::Span<uint16_t> tileMapTargetMem,
@ -156,15 +141,6 @@ ox::Error loadBgTileSheet(
return {};
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tilesheetAddr,
ox::Optional<unsigned> const&paletteBank) noexcept {
oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned const cbb,
@ -206,14 +182,6 @@ ox::Error loadSpriteTileSheet(
return {};
}
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
bool loadDefaultPalette) noexcept {
oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
}
ox::Error loadSpriteTileSheet(
Context &ctx,
TileSheetSet const&set) noexcept {

View File

@ -2,6 +2,7 @@
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <keel/media.hpp>
#include <nostalgia/core/gfx.hpp>
namespace nostalgia::core {
@ -17,6 +18,49 @@ int tileRows(Context&) noexcept {
return GbaTileRows;
}
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
ox::FileAddress const&paletteAddr) noexcept {
oxRequire(pal, keel::readObj<CompactPalette>(keelCtx(ctx), paletteAddr));
return loadBgPalette(ctx, palBank, *pal, 0);
}
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept {
oxRequire(pal, keel::readObj<CompactPalette>(keelCtx(ctx), paletteAddr));
return loadSpritePalette(ctx, *pal, 0);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tsAddr,
size_t dstTileIdx,
size_t srcTileIdx,
size_t tileCnt) noexcept {
oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tsAddr));
return loadBgTileSheet(ctx, cbb, *ts, dstTileIdx, srcTileIdx, tileCnt);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tilesheetAddr,
ox::Optional<unsigned> const&paletteBank) noexcept {
oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
}
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
bool loadDefaultPalette) noexcept {
oxRequire(ts, readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
}
// map ASCII values to the nostalgia charset
constexpr ox::Array<char, 128> charMap = {
0,

View File

@ -531,26 +531,6 @@ ox::Error loadSpritePalette(
return {};
}
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
ox::FileAddress const&paletteAddr) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx);
oxRequire(palette, readObj<CompactPalette>(kctx, paletteAddr));
renderer::loadPalette(ctx.bgPalette, palBank * 16 * 4, ctx.bgShader, *palette);
return {};
}
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx);
oxRequire(palette, readObj<CompactPalette>(kctx, paletteAddr));
ox::Array<GLfloat, 1024> pal;
renderer::loadPalette(pal, 0, ctx.spriteShader, *palette);
return {};
}
static ox::Result<TileSheetData> buildSetTsd(
Context &ctx,
TileSheetSet const&set) noexcept {
@ -630,16 +610,6 @@ ox::Error loadBgTileSheet(
return {};
}
ox::Error loadBgTileSheet(
Context &ctx,
uint_t cbb,
ox::FileAddress const&tilesheetAddr,
ox::Optional<unsigned> const&paletteBank) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx);
oxRequire(ts, readObj<CompactTileSheet>(kctx, tilesheetAddr));
return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
@ -662,15 +632,6 @@ ox::Error loadSpriteTileSheet(
return {};
}
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
bool loadDefaultPalette) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx);
oxRequire(ts, readObj<CompactTileSheet>(kctx, tilesheetAddr));
return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
}
ox::Error loadSpriteTileSheet(
Context &ctx,
TileSheetSet const&set) noexcept {

View File

@ -41,31 +41,10 @@ PaletteEditorImGui::PaletteEditorImGui(studio::StudioContext &sctx, ox::StringPa
m_sctx(sctx),
m_tctx(sctx.tctx),
m_pal(*keel::readObj<Palette>(keelCtx(m_tctx), itemPath()).unwrapThrow()) {
if (keel::ensureValid(m_pal).errCode) {
throw OxException(1, "PaletteEditorImGui: invalid Palette object");
}
undoStack()->changeTriggered.connect(this, &PaletteEditorImGui::handleCommand);
m_pageRename.inputSubmitted.connect(this, &PaletteEditorImGui::renamePage);
}
void PaletteEditorImGui::keyStateChanged(turbine::Key key, bool down) {
if (!down || m_pageRename.isOpen()) {
return;
}
if (key >= turbine::Key::Num_1 && key <= turbine::Key::Num_9) {
if (turbine::buttonDown(m_tctx, turbine::Key::Mod_Alt)) {
m_page = ox::min<std::size_t>(
static_cast<uint32_t>(key - turbine::Key::Num_1), m_pal.pages.size() - 1);
}
} else if (key == turbine::Key::Num_0) {
if (turbine::buttonDown(m_tctx, turbine::Key::Mod_Alt)) {
m_selectedColorRow =
ox::min<std::size_t>(
static_cast<uint32_t>(key - turbine::Key::Num_1 + 9), m_pal.pages.size() - 1);
}
}
}
void PaletteEditorImGui::draw(studio::StudioContext&) noexcept {
auto const paneSize = ImGui::GetContentRegionAvail();
{
@ -98,6 +77,19 @@ void PaletteEditorImGui::drawColumn(ox::CStringView txt) noexcept {
ImGui::Text("%s", txt.c_str());
}
void PaletteEditorImGui::numShortcuts(size_t &val, size_t const sizeRange) noexcept {
auto const lastElem = sizeRange - 1;
if (ImGui::IsKeyPressed(ImGuiKey_0)) {
val = ox::min<size_t>(9, lastElem);
} else for (auto i = 9u; i < 10; --i) {
auto const key = static_cast<ImGuiKey>(ImGuiKey_1 + i);
if (ImGui::IsKeyPressed(key)) {
val = ox::min<size_t>(i, lastElem);
break;
}
}
}
void PaletteEditorImGui::colorInput(ox::CStringView label, int &v, bool &inputFocused) noexcept {
ImGui::InputInt(label.c_str(), &v, 1, 5);
inputFocused = inputFocused || ImGui::IsItemFocused();
@ -162,22 +154,24 @@ void PaletteEditorImGui::drawColorsEditor() noexcept {
ImGui::TableSetupColumn("Blue", ImGuiTableColumnFlags_WidthFixed, 40);
ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_NoHide);
ImGui::TableHeadersRow();
for (auto i = 0u; auto const&c : m_pal.pages[m_page].colors) {
ig::IDStackItem const idStackItem(static_cast<int>(i));
ImGui::TableNextRow();
drawColumn(i + 1);
drawColumnLeftAlign(m_pal.colorNames[i]);
drawColumn(red16(c));
drawColumn(green16(c));
drawColumn(blue16(c));
ImGui::TableNextColumn();
auto const ic = ImGui::GetColorU32({redf(c), greenf(c), bluef(c), 1});
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic);
if (ImGui::Selectable(
"##ColorRow", i == m_selectedColorRow, ImGuiSelectableFlags_SpanAllColumns)) {
m_selectedColorRow = i;
if (m_page < m_pal.pages.size()) {
for (auto i = 0u; auto const &c: m_pal.pages[m_page].colors) {
ig::IDStackItem const idStackItem(static_cast<int>(i));
ImGui::TableNextRow();
drawColumn(i + 1);
drawColumnLeftAlign(m_pal.colorNames[i]);
drawColumn(red16(c));
drawColumn(green16(c));
drawColumn(blue16(c));
ImGui::TableNextColumn();
auto const ic = ImGui::GetColorU32({redf(c), greenf(c), bluef(c), 1});
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic);
if (ImGui::Selectable(
"##ColorRow", i == m_selectedColorRow, ImGuiSelectableFlags_SpanAllColumns)) {
m_selectedColorRow = i;
}
++i;
}
++i;
}
}
ImGui::EndTable();
@ -240,10 +234,8 @@ void PaletteEditorImGui::drawColorEditor() noexcept {
int g = green16(c);
int b = blue16(c);
int const a = alpha16(c);
auto const&currentName = m_pal.colorNames[m_selectedColorRow];
ox::IString<50> name;
name = currentName;
ImGui::InputText("Name", name.data(), name.cap() + 1);
auto const newName = ig::InputText<50>(
"Name", m_pal.colorNames[m_selectedColorRow]);
bool inputFocused = ImGui::IsItemFocused();
ImGui::Separator();
colorInput("Red", r, inputFocused);
@ -253,25 +245,20 @@ void PaletteEditorImGui::drawColorEditor() noexcept {
std::ignore = pushCommand<ApplyColorAllPagesCommand>(
m_pal, m_page, m_selectedColorRow);
}
if (!inputFocused) {
auto const lastColor = largestPage(m_pal) - 1;
if (ImGui::IsKeyPressed(ImGuiKey_0, false)) {
m_selectedColorRow = ox::min<size_t>(9, lastColor);
} else for (auto i = 9u; i < 10; --i) {
auto const key = static_cast<ImGuiKey>(ImGuiKey_1 + i);
if (ImGui::IsKeyPressed(key, false)) {
m_selectedColorRow = ox::min<size_t>(i, lastColor);
break;
}
if (!inputFocused && !m_pageRename.isOpen()) {
if (!ImGui::IsKeyDown(ImGuiKey_ModAlt)) {
numShortcuts(m_selectedColorRow, largestPage(m_pal));
} else {
numShortcuts(m_page, m_pal.pages.size());
}
}
auto const newColor = color16(r, g, b, a);
if (c != newColor) {
std::ignore = pushCommand<UpdateColorCommand>(m_pal, m_page, m_selectedColorRow, newColor);
}
if (currentName != name) {
if (newName) {
std::ignore = pushCommand<UpdateColorInfoCommand>(
m_pal, m_selectedColorRow, ox::String{name});
m_pal, m_selectedColorRow, ox::String{newName});
}
}

View File

@ -40,8 +40,6 @@ class PaletteEditorImGui: public studio::Editor {
public:
PaletteEditorImGui(studio::StudioContext &sctx, ox::StringParam path);
void keyStateChanged(turbine::Key key, bool down) override;
void draw(studio::StudioContext&) noexcept final;
protected:
@ -56,6 +54,8 @@ class PaletteEditorImGui: public studio::Editor {
drawColumn(ox::itoa(i));
}
static void numShortcuts(size_t &val, size_t sizeRange) noexcept;
static void colorInput(ox::CStringView label, int &v, bool &inputFocused) noexcept;
void drawColorsEditor() noexcept;

View File

@ -188,19 +188,21 @@ UpdateColorInfoCommand::UpdateColorInfoCommand(
}
}
bool UpdateColorInfoCommand::mergeWith(UndoCommand const&cmd) noexcept {
if (cmd.commandId() != static_cast<int>(PaletteEditorCommandId::UpdateColor)) {
bool UpdateColorInfoCommand::mergeWith(UndoCommand &cmd) noexcept {
if (cmd.commandId() != static_cast<int>(PaletteEditorCommandId::UpdateColorInfo)) {
return false;
}
auto ucCmd = static_cast<UpdateColorInfoCommand const*>(&cmd);
auto ucCmd = dynamic_cast<UpdateColorInfoCommand const*>(&cmd);
if (m_idx != ucCmd->m_idx) {
return false;
}
m_pal.colorNames[m_idx] = std::move(ucCmd->m_pal.colorNames[m_idx]);
setObsolete(m_altColorInfo == m_pal.colorNames[m_idx]);
return true;
}
int UpdateColorInfoCommand::commandId() const noexcept {
return static_cast<int>(PaletteEditorCommandId::UpdateColor);
return static_cast<int>(PaletteEditorCommandId::UpdateColorInfo);
}
ox::Error UpdateColorInfoCommand::redo() noexcept {
@ -232,11 +234,11 @@ UpdateColorCommand::UpdateColorCommand(
}
}
bool UpdateColorCommand::mergeWith(UndoCommand const&cmd) noexcept {
bool UpdateColorCommand::mergeWith(UndoCommand &cmd) noexcept {
if (cmd.commandId() != static_cast<int>(PaletteEditorCommandId::UpdateColor)) {
return false;
}
auto ucCmd = static_cast<UpdateColorCommand const*>(&cmd);
auto ucCmd = dynamic_cast<UpdateColorCommand const*>(&cmd);
if (m_idx != ucCmd->m_idx) {
return false;
}

View File

@ -163,7 +163,7 @@ class UpdateColorInfoCommand: public studio::UndoCommand {
~UpdateColorInfoCommand() noexcept override = default;
[[nodiscard]]
bool mergeWith(const UndoCommand &cmd) noexcept final;
bool mergeWith(UndoCommand &cmd) noexcept final;
[[nodiscard]]
int commandId() const noexcept final;
@ -194,7 +194,7 @@ class UpdateColorCommand: public studio::UndoCommand {
~UpdateColorCommand() noexcept override = default;
[[nodiscard]]
bool mergeWith(const UndoCommand &cmd) noexcept final;
bool mergeWith(UndoCommand &cmd) noexcept final;
[[nodiscard]]
int commandId() const noexcept final;

View File

@ -158,21 +158,25 @@ void TileSheetEditorImGui::keyStateChanged(turbine::Key key, bool down) {
} else if (key >= turbine::Key::Num_1 && key <= turbine::Key::Num_9) {
if (turbine::buttonDown(m_tctx, turbine::Key::Mod_Alt)) {
auto const idx = ox::min<std::size_t>(
static_cast<uint32_t>(key - turbine::Key::Num_1), m_model.pal().pages.size() - 1);
static_cast<uint32_t>(key - turbine::Key::Num_1),
m_model.pal().pages.size() - 1);
m_model.setPalettePage(idx);
} else if (key <= turbine::Key::Num_0 + colorCnt) {
} else if (key <= turbine::Key::Num_9) {
auto const idx = ox::min<std::size_t>(
static_cast<uint32_t>(key - turbine::Key::Num_1), colorCnt - 1);
static_cast<uint32_t>(key - turbine::Key::Num_1),
colorCnt - 1);
m_view.setPalIdx(idx);
}
} else if (key == turbine::Key::Num_0) {
if (turbine::buttonDown(m_tctx, turbine::Key::Mod_Alt)) {
auto const idx = ox::min<std::size_t>(
static_cast<uint32_t>(key - turbine::Key::Num_1 + 9), m_model.pal().pages.size() - 1);
static_cast<uint32_t>(key - turbine::Key::Num_1 + 9),
m_model.pal().pages.size() - 1);
m_model.setPalettePage(idx);
} else if (colorCnt >= 10) {
} else {
auto const idx = ox::min<std::size_t>(
static_cast<uint32_t>(key - turbine::Key::Num_1 + 9), colorCnt - 1);
static_cast<uint32_t>(key - turbine::Key::Num_1 + 9),
colorCnt - 1);
m_view.setPalIdx(idx);
}
}

View File

@ -15,7 +15,6 @@ SceneEditorImGui::SceneEditorImGui(studio::StudioContext &ctx, ox::StringView pa
m_ctx(ctx.tctx),
m_editor(m_ctx, path),
m_view(m_ctx, m_editor.scene()) {
setRequiresConstantRefresh(false);
}
void SceneEditorImGui::draw(studio::StudioContext&) noexcept {

View File

@ -29,8 +29,8 @@ oxModelBegin(PreloadPtr)
oxModelField(preloadAddr)
oxModelEnd()
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&file) noexcept;
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::StringViewCR file) noexcept;
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&addr) noexcept;
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::StringViewCR path) noexcept;
void createUuidMapping(Context &ctx, ox::StringView filePath, ox::UUID const&uuid) noexcept;
@ -89,7 +89,7 @@ ox::Result<keel::AssetRef<T>> readObjFile(
assetId = substr(assetId, 7);
oxRequire(p, keel::uuidToPath(ctx, assetId));
} else {
auto const [uuid, uuidErr] = getUuid(ctx, assetId);
auto const [uuid, uuidErr] = getUuid(ctx, assetId);
if (!uuidErr) {
uuidStr = uuid.toString();
assetId = uuidStr;

View File

@ -208,15 +208,15 @@ void unloadRom(char*) noexcept {
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::StringViewCR path) noexcept {
oxRequire(stat, ctx.rom->stat(path));
oxRequire(buff, static_cast<ox::MemFS*>(ctx.rom.get())->directAccess(path));
oxRequire(buff, static_cast<ox::MemFS&>(*ctx.rom).directAccess(path));
PreloadPtr p;
oxReturnError(ox::readMC({buff, static_cast<std::size_t>(stat.size)}, p));
return static_cast<std::size_t>(p.preloadAddr) + ctx.preloadSectionOffset;
}
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&file) noexcept {
oxRequire(stat, ctx.rom->stat(file));
oxRequire(buff, static_cast<ox::MemFS*>(ctx.rom.get())->directAccess(file));
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&addr) noexcept {
oxRequire(stat, ctx.rom->stat(addr));
oxRequire(buff, static_cast<ox::MemFS&>(*ctx.rom).directAccess(addr));
PreloadPtr p;
oxReturnError(ox::readMC({buff, static_cast<std::size_t>(stat.size)}, p));
return static_cast<std::size_t>(p.preloadAddr) + ctx.preloadSectionOffset;

View File

@ -77,7 +77,7 @@ 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());
ig::InputText("Name", m_itemName);
}
drawLastPageButtons(sctx);
});

View File

@ -23,7 +23,6 @@ class BaseEditor: public Widget {
bool m_cutEnabled = false;
bool m_copyEnabled = false;
bool m_pasteEnabled = false;
bool m_requiresConstantRefresh = false;
public:
~BaseEditor() override = default;
@ -52,9 +51,6 @@ class BaseEditor: public Widget {
virtual void onActivated() noexcept;
[[nodiscard]]
bool requiresConstantRefresh() const noexcept;
void close() const;
/**
@ -71,10 +67,10 @@ class BaseEditor: public Widget {
[[nodiscard]]
bool unsavedChanges() const noexcept;
void setExportable(bool);
void setExportable(bool) noexcept;
[[nodiscard]]
bool exportable() const;
bool exportable() const noexcept;
void setCutEnabled(bool);

View File

@ -128,9 +128,35 @@ void centerNextWindow(turbine::Context &ctx) noexcept;
bool PushButton(ox::CStringView lbl, ImVec2 const&btnSz = BtnSz) noexcept;
template<typename Str>
struct TextInput {
bool changed{};
Str text;
explicit constexpr operator ox::String() const noexcept { return ox::String{text}; }
constexpr operator ox::CStringView() const noexcept { return text; }
constexpr operator ox::StringView() const noexcept { return text; }
constexpr operator bool() const noexcept { return changed; }
};
template<size_t MaxChars = 50>
TextInput<ox::IString<MaxChars>> InputText(
ox::CStringViewCR label,
ox::StringViewCR currentText,
ImGuiInputTextFlags const flags = 0,
ImGuiInputTextCallback const callback = nullptr,
void *user_data = nullptr) noexcept {
TextInput<ox::IString<MaxChars>> out = {.text = currentText};
out.changed = ImGui::InputText(
label.c_str(), out.text.data(), MaxChars + 1, flags, callback, user_data);
if (out.changed) {
std::ignore = out.text.unsafeResize(ox::strlen(out.text.c_str()));
}
return out;
}
template<size_t StrCap>
bool InputText(
ox::CStringView label,
ox::CStringViewCR label,
ox::IString<StrCap> &text,
ImGuiInputTextFlags const flags = 0,
ImGuiInputTextCallback const callback = nullptr,

View File

@ -17,13 +17,22 @@ class NoChangesException: public ox::Exception {
};
class UndoCommand {
private:
bool m_obsolete{};
public:
virtual ~UndoCommand() noexcept = default;
virtual ox::Error redo() noexcept = 0;
virtual ox::Error undo() noexcept = 0;
[[nodiscard]]
virtual int commandId() const noexcept = 0;
virtual bool mergeWith(UndoCommand const&cmd) noexcept;
virtual bool mergeWith(UndoCommand &cmd) noexcept;
constexpr void setObsolete(bool obsolete) noexcept {
m_obsolete = obsolete;
}
[[nodiscard]]
constexpr bool isObsolete() const noexcept {
return m_obsolete;
}
};
}

View File

@ -36,10 +36,6 @@ void BaseEditor::keyStateChanged(turbine::Key, bool) {
void BaseEditor::onActivated() noexcept {
}
bool BaseEditor::requiresConstantRefresh() const noexcept {
return m_requiresConstantRefresh;
}
void BaseEditor::close() const {
this->closed.emit(itemPath());
}
@ -66,12 +62,12 @@ bool BaseEditor::unsavedChanges() const noexcept {
return m_unsavedChanges;
}
void BaseEditor::setExportable(bool exportable) {
void BaseEditor::setExportable(bool exportable) noexcept {
m_exportable = exportable;
exportableChanged.emit(exportable);
}
bool BaseEditor::exportable() const {
bool BaseEditor::exportable() const noexcept {
return m_exportable;
}
@ -110,10 +106,6 @@ UndoStack *BaseEditor::undoStack() noexcept {
return nullptr;
}
void BaseEditor::setRequiresConstantRefresh(bool value) noexcept {
m_requiresConstantRefresh = value;
}
Editor::Editor(ox::StringParam itemPath) noexcept:
m_itemPath(std::move(itemPath)),

View File

@ -3,7 +3,7 @@
namespace studio {
bool UndoCommand::mergeWith(UndoCommand const&) noexcept {
bool UndoCommand::mergeWith(UndoCommand&) noexcept {
return false;
}

View File

@ -17,6 +17,10 @@ ox::Error UndoStack::push(ox::UPtr<UndoCommand> &&cmd) noexcept {
m_stack.emplace_back(std::move(cmd));
++m_stackIdx;
}
if ((*m_stack.back().unwrap())->isObsolete()) {
m_stack.pop_back();
--m_stackIdx;
}
return {};
}