managed autosave deletion

This commit is contained in:
2026-05-20 11:41:40 -04:00
parent b7b49eb81e
commit 7db835e6d4
5 changed files with 139 additions and 85 deletions
+46 -17
View File
@@ -271,6 +271,8 @@ namespace anm2ed::imgui
bool isValid = spritesheet->is_valid();
auto& texture = isValid ? spritesheet->texture : resources.icons[icon::NONE];
auto tintColor = !isValid ? ImVec4(1.0f, 0.25f, 0.25f, 1.0f) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
static std::vector<int> dragDropSelection{};
bool isRegionDragDropSourceSubmitted = false;
for (int i = 0; i < (int)spritesheet->regionOrder.size(); i++)
{
@@ -324,17 +326,19 @@ namespace anm2ed::imgui
auto tooltipPadding = style.WindowPadding.x * 4.0f;
auto minWidth = previewSize.x + style.ItemSpacing.x + textWidth + tooltipPadding;
ImGui::SetNextWindowSize(ImVec2(minWidth, 0), ImGuiCond_Appearing);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
{
ImGui::SetNextWindowSize(ImVec2(minWidth, 0), ImGuiCond_Appearing);
if (ImGui::BeginItemTooltip())
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2());
auto childFlags = ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY;
auto noScrollFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
if (ImGui::BeginChild("##Region Tooltip Image Child", to_imvec2(previewSize), childFlags, noScrollFlags))
if (ImGui::BeginChild("##Region Tooltip Image Child", to_imvec2(previewSize), childFlags,
noScrollFlags))
ImGui::ImageWithBg(texture.id, to_imvec2(previewSize), to_imvec2(uvMin), to_imvec2(uvMax), ImVec4(),
tintColor);
ImGui::EndChild();
@@ -365,7 +369,8 @@ namespace anm2ed::imgui
else
{
StringType originString = LABEL_REGION_ORIGIN_CENTER;
if (region.origin == anm2::Spritesheet::Region::TOP_LEFT) originString = LABEL_REGION_ORIGIN_TOP_LEFT;
if (region.origin == anm2::Spritesheet::Region::TOP_LEFT)
originString = LABEL_REGION_ORIGIN_TOP_LEFT;
auto originLabel = localize.get(originString);
ImGui::TextUnformatted(
std::vformat(localize.get(FORMAT_ORIGIN), std::make_format_args(originLabel)).c_str());
@@ -374,28 +379,22 @@ namespace anm2ed::imgui
ImGui::EndChild();
ImGui::EndTooltip();
}
}
ImGui::PopStyleVar(2);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing);
if (ImGui::BeginDragDropSource())
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip))
{
static std::vector<int> dragDropSelection{};
isRegionDragDropSourceSubmitted = true;
if (selection.contains(id))
dragDropSelection.assign(selection.begin(), selection.end());
else
dragDropSelection = {id};
ImGui::SetDragDropPayload("Region Drag Drop", dragDropSelection.data(),
dragDropSelection.size() * sizeof(int));
for (auto regionId : dragDropSelection)
{
auto dragIt = spritesheet->regions.find(regionId);
if (dragIt == spritesheet->regions.end()) continue;
ImGui::TextUnformatted(dragIt->second.name.c_str());
}
ImGui::EndDragDropSource();
}
ImGui::PopStyleVar(2);
if (ImGui::BeginDragDropTarget())
{
if (auto payload = ImGui::AcceptDragDropPayload("Region Drag Drop"))
@@ -450,6 +449,36 @@ namespace anm2ed::imgui
ImGui::PopID();
}
auto regionDragPayload = ImGui::GetDragDropPayload();
bool isRegionDragActive = regionDragPayload && regionDragPayload->IsDataType("Region Drag Drop");
if (isRegionDragActive && !isRegionDragDropSourceSubmitted && !dragDropSelection.empty() &&
ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceExtern | ImGuiDragDropFlags_SourceNoPreviewTooltip))
{
ImGui::SetDragDropPayload("Region Drag Drop", dragDropSelection.data(),
dragDropSelection.size() * sizeof(int));
ImGui::EndDragDropSource();
}
if (isRegionDragActive && !dragDropSelection.empty())
{
auto mousePos = ImGui::GetIO().MousePos;
auto tooltipOffset = ImVec2(16.0f, 16.0f);
ImGui::SetNextWindowPos(ImVec2(mousePos.x + tooltipOffset.x, mousePos.y + tooltipOffset.y));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing);
if (ImGui::BeginTooltip())
{
for (auto regionId : dragDropSelection)
{
auto dragIt = spritesheet->regions.find(regionId);
if (dragIt == spritesheet->regions.end()) continue;
ImGui::TextUnformatted(dragIt->second.name.c_str());
}
ImGui::EndTooltip();
}
ImGui::PopStyleVar(2);
}
ImGui::PopStyleVar();
selection.finish();
+19 -11
View File
@@ -1174,6 +1174,10 @@ namespace anm2ed::imgui
}
};
float playheadLineCenterX{};
float playheadLineTopY{};
bool isPlayheadLineSet{};
auto frame_child = [&](anm2::Type type, int id, int& index, float width)
{
auto item = animation ? animation->item_get(type, id) : nullptr;
@@ -1307,6 +1311,11 @@ namespace anm2ed::imgui
{
ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * floorf(playback.time), cursorPos.y));
ImGui::Image(resources.icons[icon::PLAYHEAD].id, frameSize);
auto playheadMin = ImGui::GetItemRectMin();
auto playheadMax = ImGui::GetItemRectMax();
playheadLineCenterX = (playheadMin.x + playheadMax.x) * 0.5f;
playheadLineTopY = playheadMax.y;
isPlayheadLineSet = true;
overlay_icon(resources.icons[icon::PLAYHEAD].id, playheadIconTint, true);
}
}
@@ -1686,7 +1695,9 @@ namespace anm2ed::imgui
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2());
if (ImGui::BeginChild("##Frames List Child", viewListChildSize, true, ImGuiWindowFlags_HorizontalScrollbar))
{
auto cursorScreenPos = ImGui::GetCursorScreenPos();
playheadLineCenterX = 0.0f;
playheadLineTopY = 0.0f;
isPlayheadLineSet = false;
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2());
if (ImGui::BeginTable("##Frames List Table", 1,
@@ -1757,20 +1768,17 @@ namespace anm2ed::imgui
ImDrawList* windowDrawList = ImGui::GetWindowDrawList();
auto frameSize = ImVec2(ImGui::GetTextLineHeight(),
ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2));
auto playheadIndex = std::floor(playback.time);
auto lineCenterX = cursorScreenPos.x + frameSize.x * (playheadIndex + 0.6f) - scroll.x;
auto linePos =
ImVec2(lineCenterX - (PLAYHEAD_LINE_THICKNESS * 0.5f), cursorScreenPos.y + (frameSize.y * 2.0f));
auto lineSize = ImVec2((PLAYHEAD_LINE_THICKNESS / 2.0f),
viewListChildSize.y - frameSize.y -
(isHorizontalScroll ? ImGui::GetStyle().ScrollbarSize * 2.0f : 0.0f));
auto lineBottomY = ImGui::GetWindowPos().y + ImGui::GetWindowSize().y;
if (isHorizontalScroll) lineBottomY -= ImGui::GetStyle().ScrollbarSize;
auto rectMin = windowDrawList->GetClipRectMin();
auto rectMax = windowDrawList->GetClipRectMax();
if (pickerLineDrawList)
if (pickerLineDrawList && isPlayheadLineSet && lineBottomY > playheadLineTopY)
{
auto linePos =
ImVec2(playheadLineCenterX - (PLAYHEAD_LINE_THICKNESS * 0.5f), playheadLineTopY);
auto lineSize =
ImVec2((PLAYHEAD_LINE_THICKNESS / 2.0f), std::max(0.0f, lineBottomY - playheadLineTopY));
pickerLineDrawList->PushClipRect(rectMin, rectMax);
pickerLineDrawList->AddRectFilled(linePos, ImVec2(linePos.x + lineSize.x, linePos.y + lineSize.y),
ImGui::GetColorU32(playheadLineColor));
+1 -1
View File
@@ -181,7 +181,7 @@ namespace anm2ed::imgui::wizard
ImGui::BeginDisabled(!isRaw);
{
input_float_range(localize.get(BASIC_SCALE), scale, 0.1f, 100.0f, 0.1f, STEP_FAST, "%.1fx");
input_float_range(localize.get(BASIC_SCALE), scale, 0.1f, 100.0f, 1.0f, STEP_FAST, "%.1fx");
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SCALE_OUTPUT));
}
ImGui::EndDisabled();
+36 -19
View File
@@ -30,6 +30,15 @@ namespace anm2ed
std::filesystem::create_directories(parent, ec);
if (ec) logger.warning(std::format("Could not create directory for {}: {}", path::to_utf8(path), ec.message()));
}
void autosave_file_remove(const std::filesystem::path& path)
{
if (path.empty()) return;
std::error_code ec{};
std::filesystem::remove(path, ec);
if (ec) logger.warning(std::format("Could not remove autosave file {}: {}", path::to_utf8(path), ec.message()));
}
}
void Manager::selection_history_push(int index)
@@ -107,10 +116,22 @@ namespace anm2ed
{
std::string errorString{};
ensure_parent_directory_exists(path);
const auto previousAutosavePath = document->autosave_path_get();
document->path = !path.empty() ? path : document->path;
document->path.replace_extension(".anm2");
document->save(document->path, &errorString, compatibility, isBakeSpecialInterpolatedFramesOnSave, isRoundScale,
isRoundRotation);
const auto autosavePath = document->autosave_path_get();
if (document->save(document->path, &errorString, compatibility, isBakeSpecialInterpolatedFramesOnSave,
isRoundScale, isRoundRotation))
{
autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), previousAutosavePath),
autosaveFiles.end());
if (autosavePath != previousAutosavePath)
autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), autosavePath),
autosaveFiles.end());
autosave_file_remove(previousAutosavePath);
autosave_file_remove(autosavePath);
autosave_files_write();
}
recent_file_add(document->path);
}
}
@@ -142,15 +163,6 @@ namespace anm2ed
const auto autosavePath = documents[index].autosave_path_get();
autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), autosavePath), autosaveFiles.end());
if (!autosavePath.empty())
{
std::error_code ec{};
std::filesystem::remove(autosavePath, ec);
if (ec)
logger.warning(std::format("Could not remove autosave file {}: {}", path::to_utf8(autosavePath), ec.message()));
}
autosave_files_write();
documents.erase(documents.begin() + index);
@@ -351,6 +363,8 @@ namespace anm2ed
void Manager::autosave_files_open()
{
std::vector<std::filesystem::path> restoredFiles{};
for (auto& path : autosaveFiles)
{
if (auto document = open(path, false, false))
@@ -358,10 +372,16 @@ namespace anm2ed
document->isForceDirty = true;
document->path = document->path_from_autosave_get(path);
document->change(Document::ALL);
restoredFiles.emplace_back(path);
}
}
autosave_files_clear();
for (auto& path : restoredFiles)
{
autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), path), autosaveFiles.end());
autosave_file_remove(path);
}
autosave_files_write();
}
void Manager::autosave_files_load()
@@ -401,14 +421,11 @@ namespace anm2ed
std::format("Could not write autosave files to: {}. Skipping...", path::to_utf8(autosave_path_get())));
}
void Manager::autosave_files_clear()
void Manager::autosave_files_clear(bool removeFiles)
{
if (removeFiles)
for (auto& path : autosaveFiles)
{
std::error_code ec{};
std::filesystem::remove(path, ec);
if (ec) logger.warning(std::format("Could not remove autosave file {}: {}", path::to_utf8(path), ec.message()));
}
autosave_file_remove(path);
autosaveFiles.clear();
autosave_files_write();
@@ -420,5 +437,5 @@ namespace anm2ed
chords[i] = imgui::string_to_chord(settings.*SHORTCUT_MEMBERS[i]);
}
Manager::~Manager() { autosave_files_clear(); }
Manager::~Manager() = default;
}
+1 -1
View File
@@ -95,7 +95,7 @@ namespace anm2ed
void autosave_files_load();
void autosave_files_open();
void autosave_files_write();
void autosave_files_clear();
void autosave_files_clear(bool removeFiles = false);
void chords_set(Settings&);
};