yeah these too
This commit is contained in:
@@ -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
@@ -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
@@ -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));
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace anm2ed::imgui
|
||||
class Events
|
||||
{
|
||||
int newEventId{-1};
|
||||
int renameQueued{-1};
|
||||
RenameState renameState{RENAME_SELECTABLE};
|
||||
|
||||
public:
|
||||
|
||||
+80
-65
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user