280 lines
9.9 KiB
C++
280 lines
9.9 KiB
C++
#include "documents.hpp"
|
|
|
|
#include <format>
|
|
#include <vector>
|
|
|
|
#include "path_.hpp"
|
|
#include "strings.hpp"
|
|
#include "time_.hpp"
|
|
#include "toast.hpp"
|
|
#include "log.hpp"
|
|
|
|
using namespace anm2ed::resource;
|
|
using namespace anm2ed::types;
|
|
using namespace anm2ed::util;
|
|
|
|
namespace anm2ed::imgui
|
|
{
|
|
void Documents::update(Taskbar& taskbar, Manager& manager, Settings& settings, Resources& resources, bool& isQuitting)
|
|
{
|
|
auto viewport = ImGui::GetMainViewport();
|
|
auto windowHeight = ImGui::GetFrameHeightWithSpacing();
|
|
bool isLightTheme = settings.theme == theme::LIGHT;
|
|
bool pushedStyle = false;
|
|
|
|
ImGui::SetNextWindowViewport(viewport->ID);
|
|
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height));
|
|
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight));
|
|
if (isLightTheme)
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImGui::GetStyleColorVec4(ImGuiCol_TitleBgActive));
|
|
pushedStyle = true;
|
|
}
|
|
|
|
for (auto& document : manager.documents)
|
|
{
|
|
auto isDirty = document.is_dirty() && document.is_autosave_dirty();
|
|
if (isDirty)
|
|
{
|
|
document.lastAutosaveTime += ImGui::GetIO().DeltaTime;
|
|
if (document.lastAutosaveTime > time::SECOND_M)
|
|
manager.autosave(document, (anm2::Compatibility)settings.fileCompatibility,
|
|
settings.fileBakeSpecialInterpolatedFramesOnSave, settings.bakeIsRoundScale,
|
|
settings.bakeIsRoundRotation);
|
|
}
|
|
}
|
|
|
|
if (ImGui::Begin("##Documents", nullptr,
|
|
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
|
|
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus |
|
|
ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoScrollbar |
|
|
ImGuiWindowFlags_NoScrollWithMouse))
|
|
{
|
|
height = ImGui::GetWindowSize().y;
|
|
|
|
if (ImGui::BeginTabBar("##Documents Bar", ImGuiTabBarFlags_Reorderable))
|
|
{
|
|
auto documentsCount = (int)manager.documents.size();
|
|
bool isCloseShortcut = shortcut(manager.chords[SHORTCUT_CLOSE], shortcut::GLOBAL) && !closePopup.is_open();
|
|
int closeShortcutIndex =
|
|
isCloseShortcut && manager.selected >= 0 && manager.selected < documentsCount ? manager.selected : -1;
|
|
|
|
std::vector<int> closeIndices{};
|
|
closeIndices.reserve(documentsCount);
|
|
|
|
for (int i = 0; i < documentsCount; ++i)
|
|
{
|
|
auto& document = manager.documents[i];
|
|
auto isDocumentDirty = document.is_dirty() || document.isForceDirty;
|
|
auto isSpritesheetDirty = document.spritesheet_any_dirty();
|
|
auto isDirty = isDocumentDirty || isSpritesheetDirty;
|
|
|
|
if (!closePopup.is_open())
|
|
{
|
|
if (isQuitting)
|
|
document.isOpen = false;
|
|
else if (i == closeShortcutIndex)
|
|
document.isOpen = false;
|
|
}
|
|
|
|
if (!closePopup.is_open() && !document.isOpen)
|
|
{
|
|
if (isDirty)
|
|
{
|
|
closePopup.open();
|
|
closeDocumentIndex = i;
|
|
document.isOpen = true;
|
|
}
|
|
else
|
|
{
|
|
closeIndices.push_back(i);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
auto isRequested = i == manager.pendingSelected;
|
|
auto font = isDocumentDirty ? font::ITALICS : font::REGULAR;
|
|
auto filename = path::to_utf8(document.filename_get());
|
|
auto string =
|
|
isDocumentDirty ? std::vformat(localize.get(FORMAT_NOT_SAVED), std::make_format_args(filename)) : filename;
|
|
auto label = std::format("{}###Document{}", string, i);
|
|
|
|
auto flags = isDocumentDirty ? ImGuiTabItemFlags_UnsavedDocument : 0;
|
|
if (isRequested) flags |= ImGuiTabItemFlags_SetSelected;
|
|
|
|
ImGui::PushFont(resources.fonts[font].get(), font::SIZE);
|
|
if (ImGui::BeginTabItem(label.c_str(), &document.isOpen, flags))
|
|
{
|
|
if (manager.selected != i) manager.set(i);
|
|
|
|
if (isRequested) manager.pendingSelected = -1;
|
|
|
|
ImGui::EndTabItem();
|
|
}
|
|
auto pathUtf8 = path::to_utf8(document.path);
|
|
ImGui::SetItemTooltip("%s", pathUtf8.c_str());
|
|
|
|
ImGui::PopFont();
|
|
}
|
|
|
|
for (auto it = closeIndices.rbegin(); it != closeIndices.rend(); ++it)
|
|
{
|
|
if (closePopup.is_open() && closeDocumentIndex > *it) --closeDocumentIndex;
|
|
manager.close(*it);
|
|
}
|
|
|
|
ImGui::EndTabBar();
|
|
}
|
|
|
|
closePopup.trigger();
|
|
|
|
if (ImGui::BeginPopupModal(closePopup.label(), &closePopup.isOpen, ImGuiWindowFlags_NoResize))
|
|
{
|
|
if (closeDocumentIndex >= 0 && closeDocumentIndex < (int)manager.documents.size())
|
|
{
|
|
auto& closeDocument = manager.documents[closeDocumentIndex];
|
|
|
|
auto filename = path::to_utf8(closeDocument.filename_get());
|
|
auto isDocumentDirty = closeDocument.is_dirty() || closeDocument.isForceDirty;
|
|
auto isSpritesheetDirty = closeDocument.spritesheet_any_dirty();
|
|
auto promptLabel = isDocumentDirty && isSpritesheetDirty
|
|
? LABEL_DOCUMENT_AND_SPRITESHEETS_MODIFIED_PROMPT
|
|
: (isDocumentDirty ? LABEL_DOCUMENT_MODIFIED_PROMPT
|
|
: LABEL_SPRITESHEETS_MODIFIED_PROMPT);
|
|
auto prompt = std::vformat(localize.get(promptLabel), std::make_format_args(filename));
|
|
ImGui::TextUnformatted(prompt.c_str());
|
|
|
|
auto widgetSize = imgui::widget_size_with_row_get(3);
|
|
|
|
auto close = [&]()
|
|
{
|
|
closeDocumentIndex = -1;
|
|
closePopup.close();
|
|
};
|
|
|
|
shortcut(manager.chords[SHORTCUT_CONFIRM]);
|
|
if (ImGui::Button(localize.get(BASIC_YES), widgetSize))
|
|
{
|
|
if (isDocumentDirty)
|
|
manager.save(closeDocumentIndex, {}, (anm2::Compatibility)settings.fileCompatibility,
|
|
settings.fileBakeSpecialInterpolatedFramesOnSave, settings.bakeIsRoundScale,
|
|
settings.bakeIsRoundRotation);
|
|
|
|
if (isSpritesheetDirty)
|
|
{
|
|
for (auto& [id, spritesheet] : closeDocument.anm2.content.spritesheets)
|
|
{
|
|
if (!closeDocument.spritesheet_is_dirty(id)) continue;
|
|
auto pathString = path::to_utf8(spritesheet.path);
|
|
if (spritesheet.save(closeDocument.directory_get()))
|
|
{
|
|
closeDocument.spritesheet_hash_set_saved(id);
|
|
toasts.push(std::vformat(localize.get(TOAST_SAVE_SPRITESHEET), std::make_format_args(id, pathString)));
|
|
logger.info(std::vformat(localize.get(TOAST_SAVE_SPRITESHEET, anm2ed::ENGLISH),
|
|
std::make_format_args(id, pathString)));
|
|
}
|
|
else
|
|
{
|
|
toasts.push(
|
|
std::vformat(localize.get(TOAST_SAVE_SPRITESHEET_FAILED), std::make_format_args(id, pathString)));
|
|
logger.error(std::vformat(localize.get(TOAST_SAVE_SPRITESHEET_FAILED, anm2ed::ENGLISH),
|
|
std::make_format_args(id, pathString)));
|
|
}
|
|
}
|
|
}
|
|
manager.close(closeDocumentIndex);
|
|
close();
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if (ImGui::Button(localize.get(BASIC_NO), widgetSize))
|
|
{
|
|
manager.close(closeDocumentIndex);
|
|
close();
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
shortcut(manager.chords[SHORTCUT_CANCEL]);
|
|
if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize))
|
|
{
|
|
isQuitting = false;
|
|
close();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
closeDocumentIndex = -1;
|
|
closePopup.close();
|
|
}
|
|
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
|
|
ImGui::End();
|
|
if (pushedStyle) ImGui::PopStyleColor();
|
|
|
|
if (manager.isAnm2DragDrop)
|
|
{
|
|
auto drag_drop_reset = [&]()
|
|
{
|
|
manager.isAnm2DragDrop = false;
|
|
manager.anm2DragDropPaths.clear();
|
|
manager.anm2DragDropPopup.close();
|
|
};
|
|
|
|
if (manager.anm2DragDropPaths.empty())
|
|
drag_drop_reset();
|
|
else
|
|
{
|
|
if (!manager.anm2DragDropPopup.is_open()) manager.anm2DragDropPopup.open();
|
|
|
|
manager.anm2DragDropPopup.trigger();
|
|
|
|
if (ImGui::BeginPopupContextWindow(manager.anm2DragDropPopup.label(), ImGuiPopupFlags_None))
|
|
{
|
|
auto document = manager.get();
|
|
if (ImGui::MenuItem(manager.anm2DragDropPaths.size() > 1 ? localize.get(LABEL_DOCUMENTS_OPEN_MANY)
|
|
: localize.get(LABEL_DOCUMENTS_OPEN_NEW)))
|
|
{
|
|
for (auto& path : manager.anm2DragDropPaths)
|
|
manager.open(path);
|
|
drag_drop_reset();
|
|
}
|
|
|
|
if (ImGui::MenuItem(localize.get(LABEL_DOCUMENTS_MERGE_INTO_CURRENT), nullptr, false,
|
|
document && !manager.anm2DragDropPaths.empty()))
|
|
{
|
|
if (document)
|
|
{
|
|
auto merge_anm2s = [&]()
|
|
{
|
|
for (auto& path : manager.anm2DragDropPaths)
|
|
{
|
|
anm2::Anm2 source(path);
|
|
document->anm2.merge(source, document->directory_get(), path.parent_path());
|
|
}
|
|
};
|
|
|
|
DOCUMENT_EDIT_PTR(document, localize.get(EDIT_MERGE_ANM2), Document::ALL, merge_anm2s());
|
|
drag_drop_reset();
|
|
}
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::MenuItem(localize.get(BASIC_CANCEL))) drag_drop_reset();
|
|
|
|
manager.anm2DragDropPopup.end();
|
|
ImGui::EndPopup();
|
|
}
|
|
else if (!ImGui::IsPopupOpen(manager.anm2DragDropPopup.label()))
|
|
drag_drop_reset();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|