yeah these too

This commit is contained in:
2025-12-13 01:21:57 -05:00
parent 3be9f0746f
commit c77701fe72
41 changed files with 1391 additions and 872 deletions
+1 -2
View File
@@ -154,8 +154,7 @@ namespace anm2ed::imgui
{
if (ImGui::Selectable(label.c_str(), isSelected, flags)) isActivated = true;
if (state == RENAME_FORCE_EDIT || (ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGuiKey_F2)) ||
(ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)))
if (state == RENAME_FORCE_EDIT || (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)))
{
state = RENAME_BEGIN;
editID = id;
+2 -3
View File
@@ -206,9 +206,8 @@ namespace anm2ed::imgui
using std::set<int>::erase;
MultiSelectStorage();
void start(size_t, ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_BoxSelect2d |
ImGuiMultiSelectFlags_ClearOnEscape |
ImGuiMultiSelectFlags_ScopeWindow);
void start(size_t,
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_ScopeWindow);
void apply();
void finish();
void set_index_map(std::vector<int>*);
+12 -2
View File
@@ -742,7 +742,12 @@ namespace anm2ed::imgui
ImGui::SameLine();
input_text_string(localize.get(LABEL_FFMPEG_PATH), &ffmpegPath);
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_FFMPEG_PATH));
dialog.set_string_to_selected_path(ffmpegPath, dialog::FFMPEG_PATH_SET);
if (dialog.is_selected(dialog::FFMPEG_PATH_SET))
{
ffmpegPath = dialog.path;
dialog.reset();
}
if (ImGui::ImageButton("##Path Set", resources.icons[icon::FOLDER].id, icon_size_get()))
{
@@ -755,7 +760,12 @@ namespace anm2ed::imgui
auto pathLabel = type == render::PNGS ? LABEL_OUTPUT_DIRECTORY : LABEL_OUTPUT_PATH;
input_text_string(localize.get(pathLabel), &path);
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_OUTPUT_PATH));
dialog.set_string_to_selected_path(path, dialogType);
if (dialog.is_selected(dialogType))
{
path = dialog.path;
dialog.reset();
}
if (ImGui::Combo(localize.get(LABEL_TYPE), &type, render::STRINGS, render::COUNT)) render_set();
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_RENDER_TYPE));
+41 -3
View File
@@ -275,6 +275,22 @@ namespace anm2ed::imgui
auto center_view = [&]() { pan = vec2(); };
auto fit_view = [&]()
{
if (animation) set_to_rect(zoom, pan, animation->rect(isRootTransform));
};
auto zoom_adjust = [&](float delta)
{
auto focus = position_translate(zoom, pan, size * 0.5f);
auto previousZoom = zoom;
zoom_set(zoom, pan, focus, delta);
if (zoom != previousZoom) hasPendingZoomPanAdjust = true;
};
auto zoom_in = [&]() { zoom_adjust(zoomStep); };
auto zoom_out = [&]() { zoom_adjust(-zoomStep); };
if (ImGui::Begin(localize.get(LABEL_ANIMATION_PREVIEW_WINDOW), &settings.windowIsAnimationPreview))
{
auto childSize = ImVec2(row_widget_width_get(4),
@@ -306,14 +322,13 @@ namespace anm2ed::imgui
auto widgetSize = widget_size_with_row_get(2);
shortcut(manager.chords[SHORTCUT_CENTER_VIEW]);
if (ImGui::Button(localize.get(LABEL_CENTER_VIEW), widgetSize)) pan = vec2();
if (ImGui::Button(localize.get(LABEL_CENTER_VIEW), widgetSize)) center_view();
set_item_tooltip_shortcut(localize.get(TOOLTIP_CENTER_VIEW), settings.shortcutCenterView);
ImGui::SameLine();
shortcut(manager.chords[SHORTCUT_FIT]);
if (ImGui::Button(localize.get(LABEL_FIT), widgetSize))
if (animation) set_to_rect(zoom, pan, animation->rect(isRootTransform));
if (ImGui::Button(localize.get(LABEL_FIT), widgetSize)) fit_view();
set_item_tooltip_shortcut(localize.get(TOOLTIP_FIT), settings.shortcutFit);
auto mousePosInt = ivec2(mousePos);
@@ -813,6 +828,29 @@ namespace anm2ed::imgui
}
}
}
if (ImGui::BeginPopupContextWindow("##Animation Preview Context Menu", ImGuiMouseButton_Right))
{
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_UNDO), settings.shortcutUndo.c_str(), false,
document.is_able_to_undo()))
document.undo();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REDO), settings.shortcutRedo.c_str(), false,
document.is_able_to_redo()))
document.redo();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(LABEL_CENTER_VIEW), settings.shortcutCenterView.c_str())) center_view();
if (ImGui::MenuItem(localize.get(LABEL_FIT), settings.shortcutFit.c_str(), false, animation)) fit_view();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_ZOOM_IN), settings.shortcutZoomIn.c_str())) zoom_in();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_ZOOM_OUT), settings.shortcutZoomOut.c_str())) zoom_out();
ImGui::EndPopup();
}
ImGui::End();
manager.progressPopup.trigger();
+244 -209
View File
@@ -1,6 +1,5 @@
#include "animations.h"
#include <cstddef>
#include <format>
#include <ranges>
@@ -20,27 +19,185 @@ namespace anm2ed::imgui
auto& document = *manager.get();
auto& anm2 = document.anm2;
auto& reference = document.reference;
auto& hovered = document.animation.hovered;
auto& selection = document.animation.selection;
auto& mergeSelection = document.merge.selection;
auto& mergeReference = document.merge.reference;
auto& overlayIndex = document.overlayIndex;
hovered = -1;
auto rename_format_get = [&](int index)
{ return std::format("###Document #{} Animation #{}", manager.selected, index); };
auto animations_remove = [&]()
auto rename = [&]()
{
if (!selection.empty())
if (!selection.empty()) renameQueued = *selection.begin();
};
auto add = [&]()
{
auto behavior = [&]()
{
for (auto it = selection.rbegin(); it != selection.rend(); ++it)
anm2::Animation animation;
animation.name = localize.get(TEXT_NEW_ANIMATION);
if (anm2::Animation* referenceAnimation = document.animation_get())
{
auto i = *it;
if (overlayIndex == i) overlayIndex = -1;
if (reference.animationIndex == i) reference.animationIndex = -1;
anm2.animations.items.erase(anm2.animations.items.begin() + i);
for (auto [id, layerAnimation] : referenceAnimation->layerAnimations)
animation.layerAnimations[id] = anm2::Item();
animation.layerOrder = referenceAnimation->layerOrder;
for (auto [id, nullAnimation] : referenceAnimation->nullAnimations)
animation.nullAnimations[id] = anm2::Item();
}
selection.clear();
}
animation.rootAnimation.frames.emplace_back(anm2::Frame());
auto index = (int)anm2.animations.items.size();
if (!selection.empty())
{
index = *selection.rbegin() + 1;
index = std::min(index, (int)anm2.animations.items.size());
}
if (anm2.animations.items.empty()) anm2.animations.defaultAnimation = animation.name;
anm2.animations.items.insert(anm2.animations.items.begin() + index, animation);
selection = {index};
reference = {index};
newAnimationSelectedIndex = index;
};
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_ANIMATION), Document::ANIMATIONS, behavior());
};
auto remove = [&]()
{
auto behavior = [&]()
{
if (!selection.empty())
{
for (auto it = selection.rbegin(); it != selection.rend(); ++it)
{
auto i = *it;
if (overlayIndex == i) overlayIndex = -1;
if (reference.animationIndex == i) reference.animationIndex = -1;
anm2.animations.items.erase(anm2.animations.items.begin() + i);
}
selection.clear();
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_ANIMATIONS), Document::ANIMATIONS, behavior());
};
auto duplicate = [&]()
{
auto behavior = [&]()
{
auto duplicated = selection;
auto end = std::ranges::max(duplicated);
for (auto& id : duplicated)
{
anm2.animations.items.insert(anm2.animations.items.begin() + end, anm2.animations.items[id]);
selection.insert(++end);
selection.erase(id);
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_ANIMATIONS), Document::ANIMATIONS, behavior());
};
auto merge = [&]()
{
auto behavior = [&]()
{
if (mergeSelection.contains(overlayIndex)) overlayIndex = -1;
auto merged = anm2.animations_merge(mergeReference, mergeSelection, (merge::Type)settings.mergeType,
settings.mergeIsDeleteAnimationsAfter);
selection = {merged};
reference = {merged};
};
DOCUMENT_EDIT(document, localize.get(EDIT_MERGE_ANIMATIONS), Document::ANIMATIONS, behavior());
};
auto merge_popup_open = [&]()
{
mergePopup.open();
mergeSelection.clear();
mergeReference = *selection.begin();
};
auto merge_quick = [&]()
{
auto behavior = [&]()
{
int merged{};
if (selection.contains(overlayIndex)) overlayIndex = -1;
if (selection.size() > 1)
merged = anm2.animations_merge(*selection.begin(), selection);
else if (selection.size() == 1 && *selection.begin() != (int)anm2.animations.items.size() - 1)
{
auto start = *selection.begin();
auto next = *selection.begin() + 1;
std::set<int> animationSet{};
animationSet.insert(start);
animationSet.insert(next);
merged = anm2.animations_merge(start, animationSet);
}
else
return;
selection = {merged};
reference = {merged};
};
DOCUMENT_EDIT(document, localize.get(EDIT_MERGE_ANIMATIONS), Document::ANIMATIONS, behavior());
};
auto default_set = [&]()
{
DOCUMENT_EDIT(document, localize.get(EDIT_DEFAULT_ANIMATION), Document::ANIMATIONS,
anm2.animations.defaultAnimation = anm2.animations.items[*selection.begin()].name);
};
auto copy = [&]()
{
if (selection.empty()) return;
std::string clipboardText{};
for (auto& i : selection)
clipboardText += anm2.animations.items[i].to_string();
clipboard.set(clipboardText);
};
auto cut = [&]()
{
copy();
DOCUMENT_EDIT(document, localize.get(EDIT_CUT_ANIMATIONS), Document::ANIMATIONS, remove());
};
auto paste = [&]()
{
if (clipboard.is_empty()) return;
auto behavior = [&]()
{
auto clipboardText = clipboard.get();
auto start = selection.empty() ? anm2.animations.items.size() : *selection.rbegin() + 1;
std::set<int> indices{};
std::string errorString{};
if (anm2.animations_deserialize(clipboardText, start, indices, &errorString))
selection = indices;
else
{
toasts.push(
std::vformat(localize.get(TOAST_DESERIALIZE_ANIMATIONS_FAILED), std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_ANIMATIONS_FAILED, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_PASTE_ANIMATIONS), Document::ANIMATIONS, behavior());
};
if (ImGui::Begin(localize.get(LABEL_ANIMATIONS_WINDOW), &settings.windowIsAnimations))
@@ -70,9 +227,13 @@ namespace anm2ed::imgui
ImGui::PushFont(resources.fonts[font].get(), font::SIZE);
ImGui::SetNextItemSelectionUserData((int)i);
if (isNewAnimation) renameState = RENAME_FORCE_EDIT;
if (selectable_input_text(animation.name, std::format("###Document #{} Animation #{}", manager.selected, i),
animation.name, selection.contains((int)i), ImGuiSelectableFlags_None, renameState))
if (isNewAnimation || renameQueued == i)
{
renameState = RENAME_FORCE_EDIT;
renameQueued = -1;
}
if (selectable_input_text(animation.name, rename_format_get(i), animation.name, selection.contains((int)i),
ImGuiSelectableFlags_None, renameState))
{
reference = {(int)i};
document.frames.clear();
@@ -85,7 +246,6 @@ namespace anm2ed::imgui
document.change(Document::ANIMATIONS);
}
}
if (ImGui::IsItemHovered()) hovered = (int)i;
if (isNewAnimation)
{
@@ -145,68 +305,42 @@ namespace anm2ed::imgui
selection.finish();
auto copy = [&]()
{
if (!selection.empty())
{
std::string clipboardText{};
for (auto& i : selection)
clipboardText += anm2.animations.items[i].to_string();
clipboard.set(clipboardText);
}
else if (hovered > -1)
clipboard.set(anm2.animations.items[hovered].to_string());
};
auto cut = [&]()
{
copy();
DOCUMENT_EDIT(document, localize.get(EDIT_CUT_ANIMATIONS), Document::ANIMATIONS, animations_remove());
};
auto paste = [&]()
{
auto clipboardText = clipboard.get();
auto deserialize = [&]()
{
auto start = selection.empty() ? anm2.animations.items.size() : *selection.rbegin() + 1;
std::set<int> indices{};
std::string errorString{};
if (anm2.animations_deserialize(clipboardText, start, indices, &errorString))
selection = indices;
else
{
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_ANIMATIONS_FAILED),
std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_ANIMATIONS_FAILED, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_PASTE_ANIMATIONS), Document::ANIMATIONS, deserialize());
};
if (shortcut(manager.chords[SHORTCUT_RENAME], shortcut::FOCUSED)) rename();
if (shortcut(manager.chords[SHORTCUT_MERGE], shortcut::FOCUSED)) merge_quick();
if (shortcut(manager.chords[SHORTCUT_CUT], shortcut::FOCUSED)) cut();
if (shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
if (shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste();
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
{
if (ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false,
!selection.empty() || hovered > -1))
{
cut();
}
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
!selection.empty() || hovered > -1))
{
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_UNDO), settings.shortcutUndo.c_str(), false,
document.is_able_to_undo()))
document.undo();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REDO), settings.shortcutRedo.c_str(), false,
document.is_able_to_redo()))
document.redo();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_RENAME), settings.shortcutRename.c_str(), false,
selection.size() == 1))
rename();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_ADD), settings.shortcutAdd.c_str())) add();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_DUPLICATE), settings.shortcutDuplicate.c_str())) duplicate();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_MERGE), settings.shortcutMerge.c_str())) merge_quick();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REMOVE), settings.shortcutRemove.c_str())) remove();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_DEFAULT), settings.shortcutDefault.c_str(), false,
selection.size() == 1))
default_set();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, !selection.empty())) cut();
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false, !selection.empty()))
copy();
}
if (ImGui::MenuItem(localize.get(BASIC_PASTE), settings.shortcutPaste.c_str(), false, !clipboard.is_empty()))
{
paste();
}
ImGui::EndPopup();
}
}
@@ -215,133 +349,45 @@ namespace anm2ed::imgui
auto widgetSize = widget_size_with_row_get(5);
shortcut(manager.chords[SHORTCUT_ADD]);
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize))
{
auto add = [&]()
{
anm2::Animation animation;
animation.name = localize.get(TEXT_NEW_ANIMATION);
if (anm2::Animation* referenceAnimation = document.animation_get())
{
for (auto [id, layerAnimation] : referenceAnimation->layerAnimations)
animation.layerAnimations[id] = anm2::Item();
animation.layerOrder = referenceAnimation->layerOrder;
for (auto [id, nullAnimation] : referenceAnimation->nullAnimations)
animation.nullAnimations[id] = anm2::Item();
}
animation.rootAnimation.frames.emplace_back(anm2::Frame());
auto index = (int)anm2.animations.items.size();
if (!selection.empty())
{
index = *selection.rbegin() + 1;
index = std::min(index, (int)anm2.animations.items.size());
}
if (anm2.animations.items.empty()) anm2.animations.defaultAnimation = animation.name;
anm2.animations.items.insert(anm2.animations.items.begin() + index, animation);
selection = {index};
reference = {index};
newAnimationSelectedIndex = index;
};
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_ANIMATION), Document::ANIMATIONS, add());
}
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) add();
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_ANIMATION), settings.shortcutAdd);
ImGui::SameLine();
ImGui::BeginDisabled(selection.empty());
{
shortcut(manager.chords[SHORTCUT_DUPLICATE]);
if (ImGui::Button(localize.get(BASIC_DUPLICATE), widgetSize))
{
auto duplicate = [&]()
{
auto duplicated = selection;
auto end = std::ranges::max(duplicated);
for (auto& id : duplicated)
{
anm2.animations.items.insert(anm2.animations.items.begin() + end, anm2.animations.items[id]);
selection.insert(++end);
selection.erase(id);
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_DUPLICATE_ANIMATIONS), Document::ANIMATIONS, duplicate());
}
set_item_tooltip_shortcut(localize.get(TOOLTIP_DUPLICATE_ANIMATION), settings.shortcutDuplicate);
ImGui::SameLine();
if (shortcut(manager.chords[SHORTCUT_MERGE], shortcut::FOCUSED) && !selection.empty())
{
auto merge_quick = [&]()
{
int merged{};
if (selection.contains(overlayIndex)) overlayIndex = -1;
if (selection.size() > 1)
merged = anm2.animations_merge(*selection.begin(), selection);
else if (selection.size() == 1 && *selection.begin() != (int)anm2.animations.items.size() - 1)
{
auto start = *selection.begin();
auto next = *selection.begin() + 1;
std::set<int> animationSet{};
animationSet.insert(start);
animationSet.insert(next);
merged = anm2.animations_merge(start, animationSet);
}
else
return;
selection = {merged};
reference = {merged};
};
DOCUMENT_EDIT(document, localize.get(EDIT_MERGE_ANIMATIONS), Document::ANIMATIONS, merge_quick())
}
ImGui::BeginDisabled(selection.size() != 1);
{
if (ImGui::Button(localize.get(LABEL_MERGE), widgetSize))
{
mergePopup.open();
mergeSelection.clear();
mergeReference = *selection.begin();
}
}
ImGui::EndDisabled();
set_item_tooltip_shortcut(localize.get(TOOLTIP_OPEN_MERGE_POPUP), settings.shortcutMerge);
ImGui::SameLine();
shortcut(manager.chords[SHORTCUT_REMOVE]);
if (ImGui::Button(localize.get(BASIC_REMOVE), widgetSize))
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_ANIMATIONS), Document::ANIMATIONS, animations_remove());
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_ANIMATION), settings.shortcutRemove);
ImGui::SameLine();
shortcut(manager.chords[SHORTCUT_DEFAULT]);
ImGui::BeginDisabled(selection.size() != 1);
if (ImGui::Button(localize.get(BASIC_DEFAULT), widgetSize))
{
DOCUMENT_EDIT(document, localize.get(EDIT_DEFAULT_ANIMATION), Document::ANIMATIONS,
anm2.animations.defaultAnimation = anm2.animations.items[*selection.begin()].name);
}
ImGui::EndDisabled();
set_item_tooltip_shortcut(localize.get(TOOLTIP_SET_DEFAULT_ANIMATION), settings.shortcutDefault);
}
shortcut(manager.chords[SHORTCUT_DUPLICATE]);
if (ImGui::Button(localize.get(BASIC_DUPLICATE), widgetSize)) duplicate();
ImGui::EndDisabled();
set_item_tooltip_shortcut(localize.get(TOOLTIP_DUPLICATE_ANIMATION), settings.shortcutDuplicate);
ImGui::SameLine();
ImGui::BeginDisabled(selection.size() != 1);
if (ImGui::Button(localize.get(LABEL_MERGE), widgetSize)) merge_popup_open();
ImGui::EndDisabled();
set_item_tooltip_shortcut(localize.get(TOOLTIP_OPEN_MERGE_POPUP), settings.shortcutMerge);
ImGui::SameLine();
ImGui::BeginDisabled(selection.empty());
shortcut(manager.chords[SHORTCUT_REMOVE]);
if (ImGui::Button(localize.get(BASIC_REMOVE), widgetSize)) remove();
ImGui::EndDisabled();
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_ANIMATION), settings.shortcutRemove);
ImGui::SameLine();
ImGui::BeginDisabled(selection.size() != 1);
shortcut(manager.chords[SHORTCUT_DEFAULT]);
if (ImGui::Button(localize.get(BASIC_DEFAULT), widgetSize)) default_set();
ImGui::EndDisabled();
set_item_tooltip_shortcut(localize.get(TOOLTIP_SET_DEFAULT_ANIMATION), settings.shortcutDefault);
mergePopup.trigger();
if (ImGui::BeginPopupModal(mergePopup.label(), &mergePopup.isOpen, ImGuiWindowFlags_NoResize))
{
auto merge_close = [&]()
auto close = [&]()
{
mergeSelection.clear();
mergePopup.close();
@@ -361,16 +407,16 @@ namespace anm2ed::imgui
{
mergeSelection.start(anm2.animations.items.size());
for (std::size_t index = 0; index < anm2.animations.items.size(); ++index)
for (int i = 0; i < (int)anm2.animations.items.size(); i++)
{
if ((int)index == mergeReference) continue;
if (i == mergeReference) continue;
auto& animation = anm2.animations.items[index];
auto& animation = anm2.animations.items[i];
ImGui::PushID((int)index);
ImGui::PushID(i);
ImGui::SetNextItemSelectionUserData((int)index);
ImGui::Selectable(animation.name.c_str(), mergeSelection.contains((int)index));
ImGui::SetNextItemSelectionUserData(i);
ImGui::Selectable(animation.name.c_str(), mergeSelection.contains(i));
ImGui::PopID();
}
@@ -408,30 +454,19 @@ namespace anm2ed::imgui
auto widgetSize = widget_size_with_row_get(2);
ImGui::BeginDisabled(mergeSelection.empty());
if (ImGui::Button(localize.get(LABEL_MERGE), widgetSize))
{
if (ImGui::Button(localize.get(LABEL_MERGE), widgetSize))
{
auto merge = [&]()
{
if (mergeSelection.contains(overlayIndex)) overlayIndex = -1;
auto merged =
anm2.animations_merge(mergeReference, mergeSelection, (merge::Type)type, isDeleteAnimationsAfter);
selection = {merged};
reference = {merged};
};
DOCUMENT_EDIT(document, localize.get(EDIT_MERGE_ANIMATIONS), Document::ANIMATIONS, merge());
merge_close();
}
merge();
close();
}
ImGui::EndDisabled();
ImGui::SameLine();
if (ImGui::Button(localize.get(LABEL_CLOSE), widgetSize)) merge_close();
if (ImGui::Button(localize.get(LABEL_CLOSE), widgetSize)) close();
ImGui::EndPopup();
}
ImGui::End();
}
ImGui::End();
}
}
}
+2
View File
@@ -12,6 +12,8 @@ namespace anm2ed::imgui
{
PopupHelper mergePopup{PopupHelper(LABEL_ANIMATIONS_MERGE_POPUP)};
int newAnimationSelectedIndex{-1};
int renameQueued{-1};
bool isInContextMenu{};
RenameState renameState{RENAME_SELECTABLE};
public:
+103 -72
View File
@@ -18,11 +18,75 @@ namespace anm2ed::imgui
auto& document = *manager.get();
auto& anm2 = document.anm2;
auto& unused = document.event.unused;
auto& hovered = document.event.hovered;
auto& reference = document.event.reference;
auto& selection = document.event.selection;
hovered = -1;
auto rename_format_get = [&](int id) { return std::format("###Document #{} Event #{}", manager.selected, id); };
auto rename = [&]()
{
if (!selection.empty()) renameQueued = *selection.begin();
};
auto add = [&]()
{
auto behavior = [&]()
{
auto id = map::next_id_get(anm2.content.events);
anm2::Event event{};
event.name = localize.get(TEXT_NEW_EVENT);
anm2.content.events[id] = event;
selection = {id};
reference = {id};
newEventId = id;
};
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_EVENT), Document::EVENTS, behavior());
};
auto remove_unused = [&]()
{
if (unused.empty()) return;
auto behavior = [&]()
{
for (auto& id : unused)
anm2.content.events.erase(id);
unused.clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_EVENTS), Document::EVENTS, behavior());
};
auto copy = [&]()
{
if (selection.empty()) return;
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.events[id].to_string(id);
clipboard.set(clipboardText);
};
auto paste = [&]()
{
if (clipboard.is_empty()) return;
auto behavior = [&]()
{
std::string errorString{};
document.snapshot(localize.get(EDIT_PASTE_EVENTS));
if (anm2.events_deserialize(clipboard.get(), merge::APPEND, &errorString))
document.change(Document::EVENTS);
else
{
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_EVENTS_FAILED), std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_EVENTS_FAILED, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_PASTE_EVENTS), Document::EVENTS, behavior());
};
if (ImGui::Begin(localize.get(LABEL_EVENTS_WINDOW), &settings.windowIsEvents))
{
@@ -38,16 +102,19 @@ namespace anm2ed::imgui
ImGui::PushID(id);
ImGui::SetNextItemSelectionUserData(id);
if (isNewEvent) renameState = RENAME_FORCE_EDIT;
if (selectable_input_text(event.name, std::format("###Document #{} Event #{}", manager.selected, id),
event.name, selection.contains(id), ImGuiSelectableFlags_None, renameState))
if (isNewEvent || renameQueued == id)
{
renameState = RENAME_FORCE_EDIT;
renameQueued = -1;
}
if (selectable_input_text(event.name, rename_format_get(id), event.name, selection.contains(id),
ImGuiSelectableFlags_None, renameState))
{
if (renameState == RENAME_BEGIN)
document.snapshot(localize.get(EDIT_RENAME_EVENT));
else if (renameState == RENAME_FINISHED)
document.change(Document::EVENTS);
}
if (ImGui::IsItemHovered()) hovered = id;
if (isNewEvent)
{
@@ -68,51 +135,39 @@ namespace anm2ed::imgui
selection.finish();
auto copy = [&]()
{
if (!selection.empty())
{
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.events[id].to_string(id);
clipboard.set(clipboardText);
}
else if (hovered > -1)
clipboard.set(anm2.content.events[hovered].to_string(hovered));
};
auto paste = [&](merge::Type type)
{
std::string errorString{};
document.snapshot(localize.get(EDIT_PASTE_EVENTS));
if (anm2.events_deserialize(clipboard.get(), type, &errorString))
document.change(Document::EVENTS);
else
{
toasts.push(
std::vformat(localize.get(TOAST_DESERIALIZE_EVENTS_FAILED), std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_EVENTS_FAILED, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
if (shortcut(manager.chords[SHORTCUT_RENAME], shortcut::FOCUSED)) rename();
if (shortcut(manager.chords[SHORTCUT_ADD], shortcut::FOCUSED)) add();
if (shortcut(manager.chords[SHORTCUT_REMOVE], shortcut::FOCUSED)) remove_unused();
if (shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
if (shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste(merge::APPEND);
if (shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste();
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
{
ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, false);
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
!selection.empty() || hovered > -1))
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_UNDO), settings.shortcutUndo.c_str(), false,
document.is_able_to_undo()))
document.undo();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REDO), settings.shortcutRedo.c_str(), false,
document.is_able_to_redo()))
document.redo();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_RENAME), settings.shortcutRename.c_str(), false,
selection.size() == 1))
rename();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_ADD), settings.shortcutAdd.c_str())) add();
if (ImGui::MenuItem(localize.get(BASIC_REMOVE_UNUSED), settings.shortcutRemove.c_str(), false,
!unused.empty()))
remove_unused();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false, !selection.empty()))
copy();
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
{
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
ImGui::EndMenu();
}
if (ImGui::MenuItem(localize.get(BASIC_PASTE), settings.shortcutPaste.c_str(), false, !clipboard.is_empty()))
paste();
ImGui::EndPopup();
}
@@ -122,37 +177,13 @@ namespace anm2ed::imgui
auto widgetSize = widget_size_with_row_get(2);
shortcut(manager.chords[SHORTCUT_ADD]);
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize))
{
auto add = [&]()
{
auto id = map::next_id_get(anm2.content.events);
anm2::Event event{};
event.name = localize.get(TEXT_NEW_EVENT);
anm2.content.events[id] = event;
selection = {id};
reference = {id};
newEventId = id;
};
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_EVENT), Document::EVENTS, add());
}
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) add();
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_EVENT), settings.shortcutAdd);
ImGui::SameLine();
shortcut(manager.chords[SHORTCUT_REMOVE]);
ImGui::BeginDisabled(unused.empty());
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize))
{
auto remove_unused = [&]()
{
for (auto& id : unused)
anm2.content.events.erase(id);
unused.clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_EVENTS), Document::EVENTS, remove_unused());
}
shortcut(manager.chords[SHORTCUT_REMOVE]);
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize)) remove_unused();
ImGui::EndDisabled();
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_EVENTS), settings.shortcutRemove);
}
+1
View File
@@ -10,6 +10,7 @@ namespace anm2ed::imgui
class Events
{
int newEventId{-1};
int renameQueued{-1};
RenameState renameState{RENAME_SELECTABLE};
public:
+80 -65
View File
@@ -19,11 +19,56 @@ namespace anm2ed::imgui
auto& anm2 = document.anm2;
auto& reference = document.layer.reference;
auto& unused = document.layer.unused;
auto& hovered = document.layer.hovered;
auto& selection = document.layer.selection;
auto& propertiesPopup = manager.layerPropertiesPopup;
hovered = -1;
auto add = [&]() { manager.layer_properties_open(); };
auto remove_unused = [&]()
{
if (unused.empty()) return;
auto behavior = [&]()
{
for (auto& id : unused)
anm2.content.layers.erase(id);
unused.clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_LAYERS), Document::LAYERS, behavior());
};
auto copy = [&]()
{
if (selection.empty()) return;
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.layers[id].to_string(id);
clipboard.set(clipboardText);
};
auto paste = [&]()
{
if (clipboard.is_empty()) return;
auto behavior = [&]()
{
std::string errorString{};
document.snapshot(localize.get(EDIT_PASTE_LAYERS));
if (anm2.layers_deserialize(clipboard.get(), merge::APPEND, &errorString))
document.change(Document::NULLS);
else
{
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_LAYERS_FAILED), std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_LAYERS_FAILED, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_PASTE_LAYERS), Document::LAYERS, behavior());
};
auto properties = [&](int id) { manager.layer_properties_open(id); };
if (ImGui::Begin(localize.get(LABEL_LAYERS_WINDOW), &settings.windowIsLayers))
{
@@ -49,13 +94,7 @@ namespace anm2ed::imgui
ImGui::SetScrollHereY(0.5f);
newLayerId = -1;
}
if (ImGui::IsItemHovered())
{
hovered = id;
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) manager.layer_properties_open(id);
}
else
hovered = -1;
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) properties(id);
if (ImGui::BeginItemTooltip())
{
@@ -72,51 +111,37 @@ namespace anm2ed::imgui
selection.finish();
auto copy = [&]()
{
if (!selection.empty())
{
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.layers[id].to_string(id);
clipboard.set(clipboardText);
}
else if (hovered > -1)
clipboard.set(anm2.content.layers[hovered].to_string(hovered));
};
auto paste = [&](merge::Type type)
{
std::string errorString{};
document.snapshot(localize.get(EDIT_PASTE_LAYERS));
if (anm2.layers_deserialize(clipboard.get(), type, &errorString))
document.change(Document::NULLS);
else
{
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_LAYERS_FAILED),
std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_LAYERS_FAILED, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
if (shortcut(manager.chords[SHORTCUT_ADD], shortcut::FOCUSED)) add();
if (shortcut(manager.chords[SHORTCUT_REMOVE], shortcut::FOCUSED)) remove_unused();
if (shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
if (shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste(merge::APPEND);
if (shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste();
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
{
ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, false);
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
!selection.empty() || hovered > -1))
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_UNDO), settings.shortcutUndo.c_str(), false,
document.is_able_to_undo()))
document.undo();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REDO), settings.shortcutRedo.c_str(), false,
document.is_able_to_redo()))
document.redo();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_PROPERTIES), nullptr, false, selection.size() == 1))
properties(*selection.begin());
if (ImGui::MenuItem(localize.get(BASIC_ADD), settings.shortcutAdd.c_str())) add();
if (ImGui::MenuItem(localize.get(BASIC_REMOVE_UNUSED), settings.shortcutRemove.c_str(), false,
!unused.empty()))
remove_unused();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false, !selection.empty()))
copy();
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
{
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
ImGui::EndMenu();
}
if (ImGui::MenuItem(localize.get(BASIC_PASTE), settings.shortcutPaste.c_str(), false, !clipboard.is_empty()))
paste();
ImGui::EndPopup();
}
@@ -126,23 +151,13 @@ namespace anm2ed::imgui
auto widgetSize = widget_size_with_row_get(2);
shortcut(manager.chords[SHORTCUT_ADD]);
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) manager.layer_properties_open();
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) add();
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_LAYER), settings.shortcutAdd);
ImGui::SameLine();
shortcut(manager.chords[SHORTCUT_REMOVE]);
ImGui::BeginDisabled(unused.empty());
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize))
{
auto remove_unused = [&]()
{
for (auto& id : unused)
anm2.content.layers.erase(id);
unused.clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_LAYERS), Document::LAYERS, remove_unused());
}
shortcut(manager.chords[SHORTCUT_REMOVE]);
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize)) remove_unused();
ImGui::EndDisabled();
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_LAYERS), settings.shortcutRemove);
}
@@ -171,7 +186,7 @@ namespace anm2ed::imgui
{
if (reference == -1)
{
auto add = [&]()
auto layer_add = [&]()
{
auto id = map::next_id_get(anm2.content.layers);
anm2.content.layers[id] = layer;
@@ -179,17 +194,17 @@ namespace anm2ed::imgui
newLayerId = id;
};
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_LAYER), Document::LAYERS, add());
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_LAYER), Document::LAYERS, layer_add());
}
else
{
auto set = [&]()
auto layer_set = [&]()
{
anm2.content.layers[reference] = layer;
selection = {reference};
};
DOCUMENT_EDIT(document, localize.get(EDIT_SET_LAYER_PROPERTIES), Document::LAYERS, set());
DOCUMENT_EDIT(document, localize.get(EDIT_SET_LAYER_PROPERTIES), Document::LAYERS, layer_set());
}
manager.layer_properties_close();
+80 -62
View File
@@ -19,11 +19,56 @@ namespace anm2ed::imgui
auto& anm2 = document.anm2;
auto& reference = document.null.reference;
auto& unused = document.null.unused;
auto& hovered = document.null.hovered;
auto& selection = document.null.selection;
auto& propertiesPopup = manager.nullPropertiesPopup;
hovered = -1;
auto add = [&]() { manager.null_properties_open(); };
auto remove_unused = [&]()
{
if (unused.empty()) return;
auto behavior = [&]()
{
for (auto& id : unused)
anm2.content.nulls.erase(id);
unused.clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_NULLS), Document::NULLS, behavior());
};
auto copy = [&]()
{
if (selection.empty()) return;
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.nulls[id].to_string(id);
clipboard.set(clipboardText);
};
auto paste = [&]()
{
if (clipboard.is_empty()) return;
auto behavior = [&]()
{
std::string errorString{};
document.snapshot(localize.get(EDIT_PASTE_NULLS));
if (anm2.nulls_deserialize(clipboard.get(), merge::APPEND, &errorString))
document.change(Document::NULLS);
else
{
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_NULLS_FAILED), std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_NULLS_FAILED, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_PASTE_NULLS), Document::NULLS, behavior());
};
auto properties = [&](int id) { manager.null_properties_open(id); };
if (ImGui::Begin(localize.get(LABEL_NULLS_WINDOW), &settings.windowIsNulls))
{
@@ -48,11 +93,7 @@ namespace anm2ed::imgui
ImGui::SetScrollHereY(0.5f);
newNullId = -1;
}
if (ImGui::IsItemHovered())
{
hovered = id;
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) manager.null_properties_open(id);
}
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) properties(id);
if (isReferenced) ImGui::PopFont();
@@ -69,50 +110,37 @@ namespace anm2ed::imgui
selection.finish();
auto copy = [&]()
{
if (!selection.empty())
{
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.nulls[id].to_string(id);
clipboard.set(clipboardText);
}
else if (hovered > -1)
clipboard.set(anm2.content.nulls[hovered].to_string(hovered));
};
auto paste = [&](merge::Type type)
{
std::string errorString{};
document.snapshot(localize.get(EDIT_PASTE_NULLS));
if (anm2.nulls_deserialize(clipboard.get(), type, &errorString))
document.change(Document::NULLS);
else
{
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_NULLS_FAILED), std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_NULLS_FAILED, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
if (shortcut(manager.chords[SHORTCUT_ADD], shortcut::FOCUSED)) add();
if (shortcut(manager.chords[SHORTCUT_REMOVE], shortcut::FOCUSED)) remove_unused();
if (shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
if (shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste(merge::APPEND);
if (shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste();
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
{
ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, false);
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
selection.empty() || hovered > -1))
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_UNDO), settings.shortcutUndo.c_str(), false,
document.is_able_to_undo()))
document.undo();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REDO), settings.shortcutRedo.c_str(), false,
document.is_able_to_redo()))
document.redo();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_PROPERTIES), nullptr, false, selection.size() == 1))
properties(*selection.begin());
if (ImGui::MenuItem(localize.get(BASIC_ADD), settings.shortcutAdd.c_str())) add();
if (ImGui::MenuItem(localize.get(BASIC_REMOVE_UNUSED), settings.shortcutRemove.c_str(), false,
!unused.empty()))
remove_unused();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false, !selection.empty()))
copy();
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
{
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
ImGui::EndMenu();
}
if (ImGui::MenuItem(localize.get(BASIC_PASTE), settings.shortcutPaste.c_str(), false, !clipboard.is_empty()))
paste();
ImGui::EndPopup();
}
@@ -122,23 +150,13 @@ namespace anm2ed::imgui
auto widgetSize = widget_size_with_row_get(2);
shortcut(manager.chords[SHORTCUT_ADD]);
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) manager.null_properties_open();
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) add();
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_NULL), settings.shortcutAdd);
ImGui::SameLine();
shortcut(manager.chords[SHORTCUT_REMOVE]);
ImGui::BeginDisabled(unused.empty());
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize))
{
auto remove_unused = [&]()
{
for (auto& id : unused)
anm2.content.nulls.erase(id);
unused.clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_NULLS), Document::EVENTS, remove_unused());
}
shortcut(manager.chords[SHORTCUT_REMOVE]);
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize)) remove_unused();
ImGui::EndDisabled();
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_NULLS), settings.shortcutRemove);
}
@@ -168,7 +186,7 @@ namespace anm2ed::imgui
{
if (reference == -1)
{
auto add = [&]()
auto null_add = [&]()
{
auto id = map::next_id_get(anm2.content.nulls);
anm2.content.nulls[id] = null;
@@ -176,17 +194,17 @@ namespace anm2ed::imgui
newNullId = id;
};
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_NULL), Document::NULLS, add());
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_NULL), Document::NULLS, null_add());
}
else
{
auto set = [&]()
auto null_set = [&]()
{
anm2.content.nulls[reference] = null;
selection = {reference};
};
DOCUMENT_EDIT(document, localize.get(EDIT_SET_NULL_PROPERTIES), Document::NULLS, set());
DOCUMENT_EDIT(document, localize.get(EDIT_SET_NULL_PROPERTIES), Document::NULLS, null_set());
}
manager.null_properties_close();
+271 -118
View File
@@ -2,13 +2,16 @@
#include <ranges>
#include "filesystem_.h"
#include "log.h"
#include "strings.h"
#include "toast.h"
using namespace anm2ed::dialog;
using namespace anm2ed::util;
using namespace anm2ed::types;
using namespace anm2ed::resource;
using namespace glm;
namespace anm2ed::imgui
{
@@ -18,157 +21,307 @@ namespace anm2ed::imgui
auto& anm2 = document.anm2;
auto& reference = document.sound.reference;
auto& unused = document.sound.unused;
auto& hovered = document.null.hovered;
auto& selection = document.sound.selection;
auto style = ImGui::GetStyle();
hovered = -1;
auto add_open = [&]() { dialog.file_open(dialog::SOUND_OPEN); };
auto replace_open = [&]() { dialog.file_open(dialog::SOUND_REPLACE); };
auto play = [&](anm2::Sound& sound) { sound.play(); };
auto add = [&](const std::filesystem::path& path)
{
auto behavior = [&]()
{
int id{};
auto pathString = path.string();
if (anm2.sound_add(document.directory_get(), path, id))
{
selection = {id};
newSoundId = id;
toasts.push(std::vformat(localize.get(TOAST_SOUND_INITIALIZED), std::make_format_args(id, pathString)));
logger.info(std::vformat(localize.get(TOAST_SOUND_INITIALIZED, anm2ed::ENGLISH),
std::make_format_args(id, pathString)));
}
else
{
toasts.push(std::vformat(localize.get(TOAST_SOUND_INITIALIZE_FAILED), std::make_format_args(pathString)));
logger.error(std::vformat(localize.get(TOAST_SOUND_INITIALIZE_FAILED, anm2ed::ENGLISH),
std::make_format_args(pathString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_SOUND), Document::SOUNDS, behavior());
};
auto remove_unused = [&]()
{
if (unused.empty()) return;
auto behavior = [&]()
{
for (auto& id : unused)
anm2.content.sounds.erase(id);
unused.clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_SOUNDS), Document::SOUNDS, behavior());
};
auto reload = [&]()
{
auto behavior = [&]()
{
for (auto& id : selection)
{
anm2::Sound& sound = anm2.content.sounds[id];
sound.reload(document.directory_get());
auto pathString = sound.path.string();
toasts.push(std::vformat(localize.get(TOAST_RELOAD_SOUND), std::make_format_args(id, pathString)));
logger.info(
std::vformat(localize.get(TOAST_RELOAD_SOUND, anm2ed::ENGLISH), std::make_format_args(id, pathString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_RELOAD_SOUNDS), Document::SOUNDS, behavior());
};
auto replace = [&](const std::filesystem::path& path)
{
if (selection.size() != 1 || path.empty()) return;
auto behavior = [&]()
{
auto& id = *selection.begin();
anm2::Sound& sound = anm2.content.sounds[id];
sound = anm2::Sound(document.directory_get().string(), path);
auto pathString = sound.path.string();
toasts.push(std::vformat(localize.get(TOAST_REPLACE_SOUND), std::make_format_args(id, pathString)));
logger.info(
std::vformat(localize.get(TOAST_REPLACE_SOUND, anm2ed::ENGLISH), std::make_format_args(id, pathString)));
};
DOCUMENT_EDIT(document, localize.get(EDIT_REPLACE_SOUND), Document::SOUNDS, behavior());
};
auto open_directory = [&](anm2::Sound& sound)
{
if (sound.path.empty()) return;
filesystem::WorkingDirectory workingDirectory(document.directory_get());
dialog.file_explorer_open(sound.path.parent_path());
};
auto copy = [&]()
{
if (selection.empty()) return;
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.sounds[id].to_string(id);
clipboard.set(clipboardText);
};
auto paste = [&]()
{
if (clipboard.is_empty()) return;
auto behavior = [&]()
{
std::string errorString{};
document.snapshot(localize.get(TOAST_SOUNDS_PASTE));
if (anm2.sounds_deserialize(clipboard.get(), document.directory_get().string(), merge::APPEND, &errorString))
document.change(Document::SOUNDS);
else
{
toasts.push(std::vformat(localize.get(TOAST_SOUNDS_DESERIALIZE_ERROR), std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_SOUNDS_DESERIALIZE_ERROR, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_PASTE_SOUNDS), Document::SOUNDS, behavior());
};
auto context_menu = [&]()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByWindow) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Right))
ImGui::OpenPopup("##Sound Context Menu");
if (ImGui::BeginPopup("##Sound Context Menu"))
{
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_UNDO), settings.shortcutUndo.c_str(), false,
document.is_able_to_undo()))
document.undo();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REDO), settings.shortcutRedo.c_str(), false,
document.is_able_to_redo()))
document.redo();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(LABEL_PLAY), nullptr, false, selection.size() == 1))
play(anm2.content.sounds[*selection.begin()]);
if (ImGui::MenuItem(localize.get(BASIC_OPEN_DIRECTORY), nullptr, false, selection.size() == 1))
open_directory(anm2.content.sounds[*selection.begin()]);
if (ImGui::MenuItem(localize.get(BASIC_ADD), settings.shortcutAdd.c_str())) add_open();
if (ImGui::MenuItem(localize.get(BASIC_REMOVE_UNUSED), settings.shortcutRemove.c_str(), false, !unused.empty()))
remove_unused();
if (ImGui::MenuItem(localize.get(BASIC_RELOAD), nullptr, false, !selection.empty())) reload();
if (ImGui::MenuItem(localize.get(BASIC_REPLACE), nullptr, false, selection.size() == 1)) replace_open();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false, !selection.empty())) copy();
if (ImGui::MenuItem(localize.get(BASIC_PASTE), settings.shortcutPaste.c_str(), false, !clipboard.is_empty()))
paste();
ImGui::EndPopup();
}
ImGui::PopStyleVar(2);
};
if (ImGui::Begin(localize.get(LABEL_SOUNDS_WINDOW), &settings.windowIsSounds))
{
auto childSize = imgui::size_without_footer_get();
if (ImGui::BeginChild("##Sounds Child", childSize, true))
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2());
if (ImGui::BeginChild("##Sounds Child", childSize, ImGuiChildFlags_Borders))
{
auto soundChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() * 2);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2());
selection.start(anm2.content.sounds.size());
for (auto& [id, sound] : anm2.content.sounds)
{
auto isSelected = selection.contains(id);
auto isReferenced = reference == id;
const std::string pathString = sound.path.empty() ? std::string{anm2::NO_PATH} : sound.path.string();
const char* pathLabel = pathString.c_str();
ImGui::PushID(id);
ImGui::SetNextItemSelectionUserData(id);
if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE);
if (ImGui::Selectable(pathLabel, isSelected)) sound.play();
if (ImGui::IsItemHovered()) hovered = id;
if (newSoundId == id)
{
ImGui::SetScrollHereY(0.5f);
newSoundId = -1;
}
if (isReferenced) ImGui::PopFont();
if (ImGui::BeginItemTooltip())
if (ImGui::BeginChild("##Sound Child", soundChildSize, ImGuiChildFlags_Borders))
{
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
ImGui::TextUnformatted(pathLabel);
ImGui::PopFont();
ImGui::Text("%s: %d", localize.get(BASIC_ID), id);
ImGui::Text("%s", localize.get(TOOLTIP_SOUNDS_PLAY));
if (!sound.is_valid())
auto isSelected = selection.contains(id);
auto cursorPos = ImGui::GetCursorPos();
bool isValid = sound.is_valid();
auto& soundIcon = isValid ? resources.icons[icon::SOUND] : 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);
auto pathCStr = sound.path.c_str();
ImGui::SetNextItemSelectionUserData(id);
ImGui::SetNextItemStorageID(id);
if (ImGui::Selectable("##Sound Selectable", isSelected, 0, soundChildSize))
{
ImGui::Spacing();
ImGui::TextWrapped("%s", localize.get(TOOLTIP_SOUND_INVALID));
reference = id;
play(sound);
}
ImGui::EndTooltip();
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) open_directory(sound);
if (newSoundId == id)
{
ImGui::SetScrollHereY(0.5f);
newSoundId = -1;
}
auto textWidth = ImGui::CalcTextSize(pathCStr).x;
auto tooltipPadding = style.WindowPadding.x * 4.0f;
auto minWidth = textWidth + style.ItemSpacing.x + tooltipPadding;
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
ImGui::SetNextWindowSize(ImVec2(minWidth, 0), ImGuiCond_Appearing);
if (ImGui::BeginItemTooltip())
{
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
ImGui::TextUnformatted(sound.path.c_str());
ImGui::PopFont();
ImGui::Text("%s: %d", localize.get(BASIC_ID), id);
if (!isValid)
{
ImGui::Spacing();
ImGui::TextWrapped("%s", localize.get(TOOLTIP_SOUND_INVALID));
}
else
{
ImGui::Text("%s", localize.get(TEXT_SOUND_PLAY));
ImGui::Text("%s", localize.get(TEXT_OPEN_DIRECTORY));
}
ImGui::EndTooltip();
}
ImGui::PopStyleVar(2);
ImGui::SetCursorPos(cursorPos);
auto imageSize = to_imvec2(vec2(soundChildSize.y));
ImGui::ImageWithBg(soundIcon.id, imageSize, ImVec2(), ImVec2(1, 1), ImVec4(), tintColor);
ImGui::SetCursorPos(ImVec2(soundChildSize.y + style.ItemSpacing.x,
soundChildSize.y - soundChildSize.y / 2 - ImGui::GetTextLineHeight() / 2));
ImGui::TextUnformatted(
std::vformat(localize.get(FORMAT_SOUND), std::make_format_args(id, pathCStr)).c_str());
}
ImGui::EndChild();
ImGui::PopID();
}
context_menu();
ImGui::PopStyleVar();
selection.finish();
auto copy = [&]()
{
if (!selection.empty())
{
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.sounds[id].to_string(id);
clipboard.set(clipboardText);
}
else if (hovered > -1)
clipboard.set(anm2.content.sounds[hovered].to_string(hovered));
};
auto paste = [&](merge::Type type)
{
std::string errorString{};
document.snapshot(localize.get(TOAST_SOUNDS_PASTE));
if (anm2.sounds_deserialize(clipboard.get(), document.directory_get().string(), type, &errorString))
document.change(Document::SOUNDS);
else
{
toasts.push(std::vformat(localize.get(TOAST_SOUNDS_DESERIALIZE_ERROR), std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_SOUNDS_DESERIALIZE_ERROR, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
if (imgui::shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
if (imgui::shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste(merge::APPEND);
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
{
ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, false);
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(),
!selection.empty() && hovered > -1))
copy();
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
{
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
ImGui::EndMenu();
}
ImGui::EndPopup();
}
}
ImGui::EndChild();
auto widgetSize = imgui::widget_size_with_row_get(2);
ImGui::EndChild();
ImGui::PopStyleVar();
auto widgetSize = imgui::widget_size_with_row_get(4);
imgui::shortcut(manager.chords[SHORTCUT_ADD]);
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) dialog.file_open(dialog::SOUND_OPEN);
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) add_open();
imgui::set_item_tooltip_shortcut(localize.get(TOOLTIP_SOUND_ADD), settings.shortcutAdd);
if (dialog.is_selected(dialog::SOUND_OPEN))
{
add(dialog.path);
dialog.reset();
}
ImGui::SameLine();
imgui::shortcut(manager.chords[SHORTCUT_REMOVE]);
ImGui::BeginDisabled(unused.empty());
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize))
{
auto remove_unused = [&]()
{
for (auto& id : unused)
anm2.content.sounds.erase(id);
unused.clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_SOUNDS), Document::SOUNDS, remove_unused());
};
ImGui::EndDisabled();
imgui::shortcut(manager.chords[SHORTCUT_REMOVE]);
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize)) remove_unused();
imgui::set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_SOUNDS), settings.shortcutRemove);
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::BeginDisabled(selection.empty());
if (ImGui::Button(localize.get(BASIC_RELOAD), widgetSize)) reload();
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_RELOAD_SOUNDS));
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::BeginDisabled(selection.size() != 1);
if (ImGui::Button(localize.get(BASIC_REPLACE), widgetSize)) replace_open();
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_REPLACE_SOUND));
ImGui::EndDisabled();
if (dialog.is_selected(dialog::SOUND_REPLACE))
{
replace(dialog.path);
dialog.reset();
}
}
ImGui::End();
if (dialog.is_selected(dialog::SOUND_OPEN))
{
auto add = [&]()
{
int id{};
if (anm2.sound_add(document.directory_get().string(), dialog.path, id))
{
selection = {id};
newSoundId = id;
toasts.push(std::vformat(localize.get(TOAST_SOUND_INITIALIZED), std::make_format_args(id, dialog.path)));
logger.info(std::vformat(localize.get(TOAST_SOUND_INITIALIZED, anm2ed::ENGLISH),
std::make_format_args(id, dialog.path)));
}
else
{
toasts.push(std::vformat(localize.get(TOAST_SOUND_INITIALIZE_FAILED), std::make_format_args(dialog.path)));
logger.error(std::vformat(localize.get(TOAST_SOUND_INITIALIZE_FAILED, anm2ed::ENGLISH),
std::make_format_args(dialog.path)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_SOUND), Document::SOUNDS, add());
dialog.reset();
}
if (imgui::shortcut(manager.chords[SHORTCUT_ADD], shortcut::FOCUSED)) add_open();
if (imgui::shortcut(manager.chords[SHORTCUT_REMOVE], shortcut::FOCUSED)) remove_unused();
if (imgui::shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
if (imgui::shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste();
}
}
+44 -2
View File
@@ -80,6 +80,23 @@ namespace anm2ed::imgui
auto center_view = [&]() { pan = -size * 0.5f; };
auto fit_view = [&]()
{
if (spritesheet && spritesheet->texture.is_valid())
set_to_rect(zoom, pan, {0, 0, (float)spritesheet->texture.size.x, (float)spritesheet->texture.size.y});
};
auto zoom_adjust = [&](float delta)
{
auto focus = position_translate(zoom, pan, size * 0.5f);
auto previousZoom = zoom;
zoom_set(zoom, pan, focus, delta);
if (zoom != previousZoom) hasPendingZoomPanAdjust = true;
};
auto zoom_in = [&]() { zoom_adjust(zoomStep); };
auto zoom_out = [&]() { zoom_adjust(-zoomStep); };
if (ImGui::Begin(localize.get(LABEL_SPRITESHEET_EDITOR_WINDOW), &settings.windowIsSpritesheetEditor))
{
@@ -121,8 +138,7 @@ namespace anm2ed::imgui
ImGui::SameLine();
imgui::shortcut(manager.chords[SHORTCUT_FIT]);
if (ImGui::Button(localize.get(LABEL_FIT), widgetSize))
if (spritesheet) set_to_rect(zoom, pan, {0, 0, spritesheet->texture.size.x, spritesheet->texture.size.y});
if (ImGui::Button(localize.get(LABEL_FIT), widgetSize)) fit_view();
imgui::set_item_tooltip_shortcut(localize.get(TOOLTIP_FIT), settings.shortcutFit);
auto mousePosInt = ivec2(mousePos);
@@ -425,6 +441,32 @@ namespace anm2ed::imgui
}
}
}
if (ImGui::BeginPopupContextWindow("##Spritesheet Editor Context Menu", ImGuiMouseButton_Right))
{
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_UNDO), settings.shortcutUndo.c_str(), false,
document.is_able_to_undo()))
document.undo();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REDO), settings.shortcutRedo.c_str(), false,
document.is_able_to_redo()))
document.redo();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(LABEL_CENTER_VIEW), settings.shortcutCenterView.c_str())) center_view();
if (ImGui::MenuItem(localize.get(LABEL_FIT), settings.shortcutFit.c_str(), false,
spritesheet && spritesheet->texture.is_valid()))
fit_view();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_ZOOM_IN), settings.shortcutZoomIn.c_str())) zoom_in();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_ZOOM_OUT), settings.shortcutZoomOut.c_str())) zoom_out();
ImGui::EndPopup();
}
ImGui::End();
if (!document.isSpritesheetEditorSet)
+184 -155
View File
@@ -2,11 +2,12 @@
#include <ranges>
#include <filesystem>
#include <format>
#include "log.h"
#include "document.h"
#include "filesystem_.h"
#include "log.h"
#include "strings.h"
#include "toast.h"
@@ -24,70 +25,185 @@ namespace anm2ed::imgui
auto& anm2 = document.anm2;
auto& selection = document.spritesheet.selection;
auto& unused = document.spritesheet.unused;
auto& hovered = document.spritesheet.hovered;
auto& reference = document.spritesheet.reference;
auto style = ImGui::GetStyle();
hovered = -1;
auto add_open = [&]() { dialog.file_open(dialog::SPRITESHEET_OPEN); };
auto replace_open = [&]() { dialog.file_open(dialog::SPRITESHEET_REPLACE); };
if (ImGui::Begin(localize.get(LABEL_SPRITESHEETS_WINDOW), &settings.windowIsSpritesheets))
auto add = [&](const std::filesystem::path& path)
{
auto style = ImGui::GetStyle();
if (path.empty()) return;
document.spritesheet_add(path.string());
newSpritesheetId = document.spritesheet.reference;
};
auto context_menu = [&]()
auto remove_unused = [&]()
{
if (unused.empty()) return;
auto behavior = [&]()
{
auto copy = [&]()
for (auto& id : unused)
{
if (!selection.empty())
{
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.spritesheets[id].to_string(id);
clipboard.set(clipboardText);
}
else if (hovered > -1)
clipboard.set(anm2.content.spritesheets[hovered].to_string(hovered));
};
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
auto pathString = spritesheet.path.string();
toasts.push(std::vformat(localize.get(TOAST_REMOVE_SPRITESHEET), std::make_format_args(id, pathString)));
logger.info(std::vformat(localize.get(TOAST_REMOVE_SPRITESHEET, anm2ed::ENGLISH),
std::make_format_args(id, pathString)));
anm2.content.spritesheets.erase(id);
}
unused.clear();
};
auto paste = [&](merge::Type type)
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_SPRITESHEETS), Document::SPRITESHEETS, behavior());
};
auto reload = [&]()
{
if (selection.empty()) return;
auto behavior = [&]()
{
for (auto& id : selection)
{
std::string errorString{};
document.snapshot(localize.get(EDIT_PASTE_SPRITESHEETS));
if (anm2.spritesheets_deserialize(clipboard.get(), document.directory_get().string(), type, &errorString))
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
spritesheet.reload(document.directory_get());
auto pathString = spritesheet.path.string();
toasts.push(std::vformat(localize.get(TOAST_RELOAD_SPRITESHEET), std::make_format_args(id, pathString)));
logger.info(std::vformat(localize.get(TOAST_RELOAD_SPRITESHEET, anm2ed::ENGLISH),
std::make_format_args(id, pathString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_RELOAD_SPRITESHEETS), Document::SPRITESHEETS, behavior());
};
auto replace = [&](const std::filesystem::path& path)
{
if (selection.size() != 1 || path.empty()) return;
auto behavior = [&]()
{
auto& id = *selection.begin();
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
spritesheet = anm2::Spritesheet(document.directory_get().string(), path);
auto pathString = spritesheet.path.string();
toasts.push(std::vformat(localize.get(TOAST_REPLACE_SPRITESHEET), std::make_format_args(id, pathString)));
logger.info(std::vformat(localize.get(TOAST_REPLACE_SPRITESHEET, anm2ed::ENGLISH),
std::make_format_args(id, pathString)));
};
DOCUMENT_EDIT(document, localize.get(EDIT_REPLACE_SPRITESHEET), Document::SPRITESHEETS, behavior());
};
auto save = [&]()
{
if (selection.empty()) return;
for (auto& id : selection)
{
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
auto pathString = spritesheet.path.string();
if (spritesheet.save(document.directory_get().string()))
{
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)));
}
}
};
auto open_directory = [&](anm2::Spritesheet& spritesheet)
{
if (spritesheet.path.empty()) return;
filesystem::WorkingDirectory workingDirectory(document.directory_get());
dialog.file_explorer_open(spritesheet.path.parent_path());
};
auto copy = [&]()
{
if (selection.empty()) return;
std::string clipboardText{};
for (auto& id : selection)
clipboardText += anm2.content.spritesheets[id].to_string(id);
clipboard.set(clipboardText);
};
auto paste = [&]()
{
if (clipboard.is_empty()) return;
auto behavior = [&]()
{
std::string errorString{};
document.snapshot(localize.get(EDIT_PASTE_SPRITESHEETS));
if (anm2.spritesheets_deserialize(clipboard.get(), document.directory_get().string(), merge::APPEND,
&errorString))
document.change(Document::SPRITESHEETS);
else
{
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_SPRITESHEETS_FAILED),
std::make_format_args(errorString)));
toasts.push(
std::vformat(localize.get(TOAST_DESERIALIZE_SPRITESHEETS_FAILED), std::make_format_args(errorString)));
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_SPRITESHEETS_FAILED, anm2ed::ENGLISH),
std::make_format_args(errorString)));
}
};
if (shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
if (shortcut(manager.chords[SHORTCUT_PASTE], shortcut::FOCUSED)) paste(merge::APPEND);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing);
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
{
ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, true);
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
!selection.empty() || hovered > -1))
copy();
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
{
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
ImGui::EndMenu();
}
ImGui::EndPopup();
}
ImGui::PopStyleVar(2);
};
DOCUMENT_EDIT(document, localize.get(EDIT_PASTE_SPRITESHEETS), Document::SPRITESHEETS, behavior());
};
auto context_menu = [&]()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByWindow) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Right))
ImGui::OpenPopup("##Spritesheet Context Menu");
if (ImGui::BeginPopup("##Spritesheet Context Menu"))
{
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_UNDO), settings.shortcutUndo.c_str(), false,
document.is_able_to_undo()))
document.undo();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REDO), settings.shortcutRedo.c_str(), false,
document.is_able_to_redo()))
document.redo();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_OPEN_DIRECTORY), nullptr, false, selection.size() == 1))
open_directory(anm2.content.spritesheets[*selection.begin()]);
if (ImGui::MenuItem(localize.get(BASIC_ADD), settings.shortcutAdd.c_str())) add_open();
if (ImGui::MenuItem(localize.get(BASIC_REMOVE_UNUSED), settings.shortcutRemove.c_str(), false, !unused.empty()))
remove_unused();
if (ImGui::MenuItem(localize.get(BASIC_RELOAD), nullptr, false, !selection.empty())) reload();
if (ImGui::MenuItem(localize.get(BASIC_REPLACE), nullptr, false, selection.size() == 1)) replace_open();
if (ImGui::MenuItem(localize.get(BASIC_SAVE), nullptr, false, !selection.empty())) save();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false, !selection.empty())) copy();
if (ImGui::MenuItem(localize.get(BASIC_PASTE), settings.shortcutPaste.c_str(), false, !clipboard.is_empty()))
paste();
ImGui::EndPopup();
}
ImGui::PopStyleVar(2);
};
if (ImGui::Begin(localize.get(LABEL_SPRITESHEETS_WINDOW), &settings.windowIsSpritesheets))
{
auto childSize = size_without_footer_get(2);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2());
@@ -97,7 +213,7 @@ namespace anm2ed::imgui
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2());
selection.start(anm2.content.spritesheets.size(), ImGuiMultiSelectFlags_ClearOnEscape);
selection.start(anm2.content.spritesheets.size());
for (auto& [id, spritesheet] : anm2.content.spritesheets)
{
@@ -108,25 +224,17 @@ namespace anm2ed::imgui
auto isSelected = selection.contains(id);
auto isReferenced = id == reference;
auto cursorPos = ImGui::GetCursorPos();
bool isTextureValid = spritesheet.texture.is_valid();
auto& texture = isTextureValid ? spritesheet.texture : resources.icons[icon::NONE];
auto textureRef = ImTextureRef(texture.id);
auto tintColor = !isTextureValid ? ImVec4(1.0f, 0.25f, 0.25f, 1.0f) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
bool isValid = spritesheet.texture.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);
auto pathString = spritesheet.path.empty() ? std::string{anm2::NO_PATH} : spritesheet.path.string();
auto pathCStr = pathString.c_str();
ImGui::SetNextItemSelectionUserData(id);
ImGui::SetNextItemStorageID(id);
if (ImGui::Selectable("##Spritesheet Selectable", isSelected, 0, spritesheetChildSize)) reference = id;
if (ImGui::IsItemHovered())
{
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
filesystem::WorkingDirectory workingDirectory(document.directory_get().string());
dialog.file_explorer_open(spritesheet.path.parent_path().string());
}
hovered = id;
}
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
open_directory(spritesheet);
if (newSpritesheetId == id)
{
ImGui::SetScrollHereY(0.5f);
@@ -157,7 +265,7 @@ namespace anm2ed::imgui
auto noScrollFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
if (ImGui::BeginChild("##Spritesheet Tooltip Image Child", to_imvec2(textureSize), childFlags,
noScrollFlags))
ImGui::ImageWithBg(textureRef, to_imvec2(textureSize), ImVec2(), ImVec2(1, 1), ImVec4(), tintColor);
ImGui::ImageWithBg(texture.id, to_imvec2(textureSize), ImVec2(), ImVec2(1, 1), ImVec4(), tintColor);
ImGui::EndChild();
ImGui::PopStyleVar();
@@ -172,7 +280,7 @@ namespace anm2ed::imgui
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_ID), std::make_format_args(id)).c_str());
if (!isTextureValid)
if (!isValid)
ImGui::TextUnformatted(localize.get(TOOLTIP_SPRITESHEET_INVALID));
else
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_TEXTURE_SIZE),
@@ -196,7 +304,7 @@ namespace anm2ed::imgui
imageSize.y = imageSize.x / aspectRatio;
ImGui::SetCursorPos(cursorPos);
ImGui::ImageWithBg(textureRef, imageSize, ImVec2(), ImVec2(1, 1), ImVec4(), tintColor);
ImGui::ImageWithBg(texture.id, imageSize, ImVec2(), ImVec2(1, 1), ImVec4(), tintColor);
ImGui::SetCursorPos(
ImVec2(spritesheetChildSize.y + style.ItemSpacing.x,
@@ -206,8 +314,6 @@ namespace anm2ed::imgui
ImGui::TextUnformatted(
std::vformat(localize.get(FORMAT_SPRITESHEET), std::make_format_args(id, pathCStr)).c_str());
if (isReferenced) ImGui::PopFont();
context_menu();
}
ImGui::EndChild();
@@ -225,124 +331,47 @@ namespace anm2ed::imgui
auto rowOneWidgetSize = widget_size_with_row_get(3);
shortcut(manager.chords[SHORTCUT_ADD]);
if (ImGui::Button(localize.get(BASIC_ADD), rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_OPEN);
if (ImGui::Button(localize.get(BASIC_ADD), rowOneWidgetSize)) add_open();
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_SPRITESHEET), settings.shortcutAdd);
if (dialog.is_selected(dialog::SPRITESHEET_OPEN))
{
document.spritesheet_add(dialog.path);
newSpritesheetId = document.spritesheet.reference;
add(dialog.path);
dialog.reset();
}
ImGui::SameLine();
ImGui::BeginDisabled(selection.empty());
{
if (ImGui::Button(localize.get(BASIC_RELOAD), rowOneWidgetSize))
{
auto reload = [&]()
{
for (auto& id : selection)
{
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
spritesheet.reload(document.directory_get());
auto pathString = spritesheet.path.string();
toasts.push(std::vformat(localize.get(TOAST_RELOAD_SPRITESHEET),
std::make_format_args(id, pathString)));
logger.info(std::vformat(localize.get(TOAST_RELOAD_SPRITESHEET, anm2ed::ENGLISH),
std::make_format_args(id, pathString)));
}
};
DOCUMENT_EDIT(document, localize.get(EDIT_RELOAD_SPRITESHEETS), Document::SPRITESHEETS, reload());
}
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_RELOAD_SPRITESHEETS));
}
if (ImGui::Button(localize.get(BASIC_RELOAD), rowOneWidgetSize)) reload();
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_RELOAD_SPRITESHEETS));
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::BeginDisabled(selection.size() != 1);
{
if (ImGui::Button(localize.get(BASIC_REPLACE), rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_REPLACE);
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_REPLACE_SPRITESHEET));
}
if (ImGui::Button(localize.get(BASIC_REPLACE), rowOneWidgetSize)) replace_open();
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_REPLACE_SPRITESHEET));
ImGui::EndDisabled();
if (dialog.is_selected(dialog::SPRITESHEET_REPLACE))
{
auto replace = [&]()
{
auto& id = *selection.begin();
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
spritesheet = anm2::Spritesheet(document.directory_get().string(), dialog.path);
auto pathString = spritesheet.path.string();
toasts.push(std::vformat(localize.get(TOAST_REPLACE_SPRITESHEET), std::make_format_args(id, pathString)));
logger.info(std::vformat(localize.get(TOAST_REPLACE_SPRITESHEET, anm2ed::ENGLISH),
std::make_format_args(id, pathString)));
};
DOCUMENT_EDIT(document, localize.get(EDIT_REPLACE_SPRITESHEET), Document::SPRITESHEETS, replace());
replace(dialog.path);
dialog.reset();
}
auto rowTwoWidgetSize = widget_size_with_row_get(2);
ImGui::BeginDisabled(unused.empty());
{
shortcut(manager.chords[SHORTCUT_REMOVE]);
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), rowTwoWidgetSize))
{
auto remove_unused = [&]()
{
for (auto& id : unused)
{
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
auto pathString = spritesheet.path.string();
toasts.push(std::vformat(localize.get(TOAST_REMOVE_SPRITESHEET),
std::make_format_args(id, pathString)));
logger.info(std::vformat(localize.get(TOAST_REMOVE_SPRITESHEET, anm2ed::ENGLISH),
std::make_format_args(id, pathString)));
anm2.content.spritesheets.erase(id);
}
unused.clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_SPRITESHEETS), Document::SPRITESHEETS,
remove_unused());
}
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_SPRITESHEETS), settings.shortcutRemove);
}
shortcut(manager.chords[SHORTCUT_REMOVE]);
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), rowTwoWidgetSize)) remove_unused();
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_SPRITESHEETS), settings.shortcutRemove);
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::BeginDisabled(selection.empty());
{
if (ImGui::Button(localize.get(BASIC_SAVE), rowTwoWidgetSize))
{
for (auto& id : selection)
{
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
auto pathString = spritesheet.path.string();
if (spritesheet.save(document.directory_get().string()))
{
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)));
}
}
}
}
if (ImGui::Button(localize.get(BASIC_SAVE), rowTwoWidgetSize)) save();
ImGui::EndDisabled();
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SAVE_SPRITESHEETS));
}
+106 -38
View File
@@ -457,6 +457,7 @@ namespace anm2ed::imgui
reference = {reference.animationIndex, type, id};
frames_selection_reset();
if (type == anm2::LAYER || type == anm2::NULL_) items.reference = (int)type;
items.selection = {(int)id};
};
auto fit_animation_length = [&]()
@@ -689,6 +690,67 @@ namespace anm2ed::imgui
item_selection_sync();
};
auto item_context_menu = [&]()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing);
auto selectionType = item_selection_type_get();
bool hasSelection = !itemSelection.empty() && (selectionType == anm2::LAYER || selectionType == anm2::NULL_);
auto currentItem = document.item_get();
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByWindow) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Right))
ImGui::OpenPopup("##Items Context Menu");
if (ImGui::BeginPopup("##Items Context Menu"))
{
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_UNDO), settings.shortcutUndo.c_str(), false,
document.is_able_to_undo()))
document.undo();
if (ImGui::MenuItem(localize.get(SHORTCUT_STRING_REDO), settings.shortcutRedo.c_str(), false,
document.is_able_to_redo()))
document.redo();
ImGui::Separator();
if (ImGui::MenuItem(localize.get(BASIC_ADD), settings.shortcutAdd.c_str(), false, animation))
{
item_properties_reset();
propertiesPopup.open();
}
if (ImGui::MenuItem(localize.get(BASIC_REMOVE), settings.shortcutRemove.c_str(), false,
hasSelection || currentItem))
{
auto remove = [&]()
{
if (hasSelection)
{
std::vector<int> ids{};
ids.reserve(itemSelection.size());
for (auto value : itemSelection)
ids.push_back(item_selection_decode(value));
std::sort(ids.begin(), ids.end());
for (auto id : ids)
animation->item_remove(selectionType, id);
item_selection_clear();
}
else if (reference.itemType == anm2::LAYER || reference.itemType == anm2::NULL_)
animation->item_remove(reference.itemType, reference.itemID);
reference_clear();
};
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_ITEMS), Document::ITEMS, remove());
}
ImGui::EndPopup();
}
ImGui::PopStyleVar(2);
};
auto item_child = [&](anm2::Type type, int id, int& index)
{
ImGui::PushID(index);
@@ -1118,6 +1180,8 @@ namespace anm2ed::imgui
ImGui::EndTable();
}
ImGui::PopStyleVar(2);
item_context_menu();
}
ImGui::PopStyleVar(2);
ImGui::EndChild();
@@ -1310,7 +1374,9 @@ namespace anm2ed::imgui
{
float frameTime{};
if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left) && !ImGui::IsAnyItemHovered())
if (ImGui::IsWindowHovered() &&
(ImGui::IsMouseReleased(ImGuiMouseButton_Left) || ImGui::IsMouseReleased(ImGuiMouseButton_Right)) &&
!ImGui::IsAnyItemHovered())
reference_set_item(type, id);
for (int i = frameMin; i < frameMax; i++)
@@ -1503,6 +1569,7 @@ namespace anm2ed::imgui
if (type == anm2::TRIGGER || ImGui::IsKeyDown(ImGuiMod_Ctrl))
{
draggedFrame = &frame;
draggedFrameType = type;
draggedFrameIndex = (int)i;
draggedFrameStart = hoveredTime;
if (type != anm2::TRIGGER) draggedFrameStartDuration = draggedFrame->duration;
@@ -1674,47 +1741,48 @@ namespace anm2ed::imgui
frameSelectionSnapshot.assign(frames.selection.begin(), frames.selection.end());
frameSelectionSnapshotReference = reference;
}
}
}
if (draggedFrame)
if (draggedFrame)
{
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
if (!isDraggedFrameSnapshot && hoveredTime != draggedFrameStart)
{
isDraggedFrameSnapshot = true;
document.snapshot(draggedFrameType == anm2::TRIGGER ? localize.get(EDIT_TRIGGER_AT_FRAME)
: localize.get(EDIT_FRAME_DURATION));
}
if (draggedFrameType == anm2::TRIGGER)
{
draggedFrame->atFrame =
glm::clamp(hoveredTime, 0, settings.playbackIsClamp ? animation->frameNum - 1 : anm2::FRAME_NUM_MAX - 1);
for (auto [i, trigger] : std::views::enumerate(animation->triggers.frames))
{
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
if (!isDraggedFrameSnapshot && hoveredTime != draggedFrameStart)
{
isDraggedFrameSnapshot = true;
document.snapshot(type == anm2::TRIGGER ? localize.get(EDIT_TRIGGER_AT_FRAME)
: localize.get(EDIT_FRAME_DURATION));
}
if (type == anm2::TRIGGER)
{
draggedFrame->atFrame = glm::clamp(
hoveredTime, 0, settings.playbackIsClamp ? animation->frameNum - 1 : anm2::FRAME_NUM_MAX - 1);
for (auto [i, trigger] : std::views::enumerate(animation->triggers.frames))
{
if ((int)i == draggedFrameIndex) continue;
if (trigger.atFrame == draggedFrame->atFrame) draggedFrame->atFrame--;
}
}
else
{
draggedFrame->duration = glm::clamp(draggedFrameStartDuration + (hoveredTime - draggedFrameStart),
anm2::FRAME_DURATION_MIN, anm2::FRAME_DURATION_MAX);
}
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
document.change(Document::FRAMES);
draggedFrame = nullptr;
draggedFrameIndex = -1;
draggedFrameStart = -1;
draggedFrameStartDuration = -1;
isDraggedFrameSnapshot = false;
if (type == anm2::TRIGGER) item->frames_sort_by_at_frame();
}
if ((int)i == draggedFrameIndex) continue;
if (trigger.atFrame == draggedFrame->atFrame) draggedFrame->atFrame--;
}
}
else
{
draggedFrame->duration = glm::clamp(draggedFrameStartDuration + (hoveredTime - draggedFrameStart),
anm2::FRAME_DURATION_MIN, anm2::FRAME_DURATION_MAX);
}
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
document.change(Document::FRAMES);
draggedFrame = nullptr;
draggedFrameType = anm2::NONE;
draggedFrameIndex = -1;
draggedFrameStart = -1;
draggedFrameStartDuration = -1;
isDraggedFrameSnapshot = false;
if (type == anm2::TRIGGER) item->frames_sort_by_at_frame();
}
}
context_menu();
+1
View File
@@ -31,6 +31,7 @@ namespace anm2ed::imgui
int addItemSpritesheetID{-1};
int hoveredTime{};
anm2::Frame* draggedFrame{};
anm2::Type draggedFrameType{};
int draggedFrameIndex{-1};
int draggedFrameStart{-1};
int draggedFrameStartDuration{-1};