Squashed 'deps/nostalgia/' changes from 804d78e1..2a8e3c2d
2a8e3c2d [nostalgia/gfx] Remove unnecessary cast 998066d3 [ox/std] Add comparison functions fefb876f [nostalgia/gfx] Add checks for GCC version for warning suppression 5979e988 [jsoncpp] Up required CMake version a17abe46 [nfde] Up required CMake version d62f9138 [nostalgia/gfx] Suppress some superfluous warnings 12bb7475 [nostalgia/gfx/studio/tilesheet] Adjust pixel line size on Windows df2c7e2b [nostalgia] Update release notes 713aec88 [buildcore] Change mypy invokation 3089cd7a Change builder type to olympic 00638bc8 [nostalgia/gfx/studio/tilesheet] Mark DrawCommands as obsolete if no changes e0021098 [studio] Make undo/redo skip over obsolete commands b4798fd2 [nostalgia/gfx/studio/tilesheet] Make rotate only available for square subsheets or selections 3c804bf6 [studio] Give MakeCopy popup an error message for files that already exist d39d552b [nostalgia/studio] Update icon to higher resolution b7202a2b [nostalgia/player] Disable Keel mods on GBA 4e27a4c1 [nostalgia/core/studio/tilesheet] Fix palette path display update 4ef31762 [nostalgia/core/studio/tilesheet] Cleanup 8b22a8f3 [keel] Make buildUuidMap only read the first 40 bytes of each file d45ff05b [ox/fs] Add new partial file read functions 671dd862 [keel,studio] Add Make Copy option to ProjectExplorer 0abadc18 [studio] Fix QuestionPopup to only emit a response when there is a response 4e068d62 [studio] Fix misrender flash on tab close 4461f99f [studio] Add Ctrl-W shortcut for closing active tab cd1f4bda [studio] Add confirmation for closing file with unsaved changes 47286995 [studio] Add combobox that will take string views 105a1e55 [nostalgia/core/studio/tilesheet] Rework operation ctrls into a dropbox 1bc18e34 [nostalgia/core/studio/tilesheet] Add ability to rotate a selection fb8d295f [nostalgia/core/studio/tilesheet] Add rotate functionality git-subtree-dir: deps/nostalgia git-subtree-split: 2a8e3c2dc44642fd9fef6bc8b645ad966f0277da
This commit is contained in:
@@ -225,6 +225,18 @@ PopupResponse PopupControlsOkCancel(
|
||||
[[nodiscard]]
|
||||
bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show, ImVec2 const&sz = {285, 0});
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lbl
|
||||
* @param list
|
||||
* @param selectedIdx
|
||||
* @return true if new value selected, false otherwise
|
||||
*/
|
||||
bool ComboBox(
|
||||
ox::CStringView lbl,
|
||||
ox::SpanView<ox::CStringView> list,
|
||||
size_t &selectedIdx) noexcept;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lbl
|
||||
@@ -291,6 +303,34 @@ class FilePicker {
|
||||
|
||||
};
|
||||
|
||||
class QuestionPopup {
|
||||
private:
|
||||
enum class Stage {
|
||||
Closed,
|
||||
Opening,
|
||||
Open,
|
||||
};
|
||||
Stage m_stage = Stage::Closed;
|
||||
bool m_open{};
|
||||
ox::String m_title;
|
||||
ox::String m_question;
|
||||
|
||||
public:
|
||||
ox::Signal<ox::Error(ig::PopupResponse)> response;
|
||||
|
||||
QuestionPopup(ox::StringParam title, ox::StringParam question) noexcept;
|
||||
|
||||
void open() noexcept;
|
||||
|
||||
void close() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
bool isOpen() const noexcept;
|
||||
|
||||
void draw(StudioContext &ctx, ImVec2 const &sz = {}) noexcept;
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
bool mainWinHasFocus() noexcept;
|
||||
|
||||
|
@@ -92,6 +92,8 @@ class Project: public ox::SignalHandler {
|
||||
|
||||
ox::Result<ox::FileStat> stat(ox::StringViewCR path) const noexcept;
|
||||
|
||||
ox::Error copyItem(ox::StringViewCR src, ox::StringViewCR dest) noexcept;
|
||||
|
||||
ox::Error moveItem(ox::StringViewCR src, ox::StringViewCR dest) noexcept;
|
||||
|
||||
ox::Error moveDir(ox::StringViewCR src, ox::StringViewCR dest) noexcept;
|
||||
|
@@ -90,6 +90,25 @@ bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show,
|
||||
return ImGui::BeginPopupModal(popupName.c_str(), &show, modalFlags);
|
||||
}
|
||||
|
||||
bool ComboBox(
|
||||
ox::CStringView lbl,
|
||||
ox::SpanView<ox::CStringView> list,
|
||||
size_t &selectedIdx) noexcept {
|
||||
bool out{};
|
||||
auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : "";
|
||||
if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
|
||||
for (auto i = 0u; i < list.size(); ++i) {
|
||||
const auto selected = (selectedIdx == i);
|
||||
if (ImGui::Selectable(list[i].c_str(), selected) && selectedIdx != i) {
|
||||
selectedIdx = i;
|
||||
out = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool ComboBox(
|
||||
ox::CStringView lbl,
|
||||
ox::Span<const ox::String> list,
|
||||
@@ -206,6 +225,60 @@ void FilePicker::show() noexcept {
|
||||
m_show = true;
|
||||
}
|
||||
|
||||
|
||||
QuestionPopup::QuestionPopup(ox::StringParam title, ox::StringParam question) noexcept:
|
||||
m_title{std::move(title)},
|
||||
m_question{std::move(question)} {
|
||||
}
|
||||
|
||||
void QuestionPopup::open() noexcept {
|
||||
m_stage = Stage::Opening;
|
||||
}
|
||||
|
||||
void QuestionPopup::close() noexcept {
|
||||
m_stage = Stage::Closed;
|
||||
m_open = false;
|
||||
}
|
||||
|
||||
bool QuestionPopup::isOpen() const noexcept {
|
||||
return m_open;
|
||||
}
|
||||
|
||||
void QuestionPopup::draw(StudioContext &ctx, ImVec2 const &sz) 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(static_cast<ImVec2>(sz));
|
||||
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());
|
||||
auto const r = PopupControlsOkCancel(m_open, "Yes", "No");
|
||||
switch (r) {
|
||||
case PopupResponse::None:
|
||||
break;
|
||||
case PopupResponse::OK:
|
||||
response.emit(r);
|
||||
close();
|
||||
break;
|
||||
case PopupResponse::Cancel:
|
||||
response.emit(r);
|
||||
close();
|
||||
break;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool s_mainWinHasFocus{};
|
||||
bool mainWinHasFocus() noexcept {
|
||||
return s_mainWinHasFocus;
|
||||
|
@@ -97,6 +97,14 @@ ox::Result<ox::FileStat> Project::stat(ox::StringViewCR path) const noexcept {
|
||||
return m_fs.stat(path);
|
||||
}
|
||||
|
||||
ox::Error Project::copyItem(ox::StringViewCR src, ox::StringViewCR dest) noexcept {
|
||||
OX_REQUIRE_M(buff, loadBuff(src));
|
||||
OX_REQUIRE(id, keel::regenerateUuidHeader(buff));
|
||||
OX_RETURN_ERROR(writeBuff(dest, buff));
|
||||
createUuidMapping(m_kctx, dest, id);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error Project::moveItem(ox::StringViewCR src, ox::StringViewCR dest) noexcept {
|
||||
OX_RETURN_ERROR(m_fs.move(src, dest));
|
||||
OX_RETURN_ERROR(keel::updatePath(m_kctx, src, dest));
|
||||
|
@@ -7,9 +7,7 @@
|
||||
namespace studio {
|
||||
|
||||
ox::Error UndoStack::push(ox::UPtr<UndoCommand> &&cmd) noexcept {
|
||||
for (auto const i = m_stackIdx; i < m_stack.size();) {
|
||||
std::ignore = m_stack.erase(i);
|
||||
}
|
||||
m_stack.resize(m_stackIdx);
|
||||
OX_RETURN_ERROR(cmd->redo());
|
||||
redoTriggered.emit(cmd.get());
|
||||
changeTriggered.emit(cmd.get());
|
||||
@@ -25,22 +23,29 @@ ox::Error UndoStack::push(ox::UPtr<UndoCommand> &&cmd) noexcept {
|
||||
}
|
||||
|
||||
ox::Error UndoStack::redo() noexcept {
|
||||
if (m_stackIdx < m_stack.size()) {
|
||||
auto &c = m_stack[m_stackIdx];
|
||||
OX_RETURN_ERROR(c->redo());
|
||||
while (m_stackIdx < m_stack.size()) {
|
||||
auto const &c = m_stack[m_stackIdx];
|
||||
++m_stackIdx;
|
||||
redoTriggered.emit(c.get());
|
||||
changeTriggered.emit(c.get());
|
||||
if (!c->isObsolete()) {
|
||||
OX_RETURN_ERROR(c->redo());
|
||||
redoTriggered.emit(c.get());
|
||||
changeTriggered.emit(c.get());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error UndoStack::undo() noexcept {
|
||||
if (m_stackIdx) {
|
||||
auto &c = m_stack[--m_stackIdx];
|
||||
OX_RETURN_ERROR(c->undo());
|
||||
undoTriggered.emit(c.get());
|
||||
changeTriggered.emit(c.get());
|
||||
while (m_stackIdx) {
|
||||
--m_stackIdx;
|
||||
auto const &c = m_stack[m_stackIdx];
|
||||
if (!c->isObsolete()) {
|
||||
OX_RETURN_ERROR(c->undo());
|
||||
undoTriggered.emit(c.get());
|
||||
changeTriggered.emit(c.get());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
Reference in New Issue
Block a user