Update for selecting frames. No more flashing, etc. Not perfect but it'll do

This commit is contained in:
2025-11-17 00:58:22 -05:00
parent d414375d82
commit 25e902f4ea
5 changed files with 83 additions and 31 deletions

View File

@@ -337,14 +337,16 @@ namespace anm2ed::imgui
{ {
internal.UserData = this; internal.UserData = this;
auto io = ImGui::BeginMultiSelect(flags, this->size(), size); io = ImGui::BeginMultiSelect(flags, this->size(), size);
internal.ApplyRequests(io); apply();
} }
void MultiSelectStorage::apply() { internal.ApplyRequests(io); }
void MultiSelectStorage::finish() void MultiSelectStorage::finish()
{ {
auto io = ImGui::EndMultiSelect(); io = ImGui::EndMultiSelect();
internal.ApplyRequests(io); apply();
} }
PopupHelper::PopupHelper(const char* label, PopupType type, PopupPosition position) PopupHelper::PopupHelper(const char* label, PopupType type, PopupPosition position)

View File

@@ -193,6 +193,8 @@ namespace anm2ed::imgui
{ {
public: public:
ImGuiSelectionExternalStorage internal{}; ImGuiSelectionExternalStorage internal{};
ImGuiMultiSelectIO* io{};
using std::set<int>::set; using std::set<int>::set;
using std::set<int>::operator=; using std::set<int>::operator=;
using std::set<int>::begin; using std::set<int>::begin;
@@ -206,6 +208,7 @@ namespace anm2ed::imgui
void start(size_t, ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_BoxSelect2d | void start(size_t, ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_BoxSelect2d |
ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_ClearOnEscape |
ImGuiMultiSelectFlags_ScopeWindow); ImGuiMultiSelectFlags_ScopeWindow);
void apply();
void finish(); void finish();
}; };

View File

@@ -51,6 +51,18 @@ namespace anm2ed::imgui
style = ImGui::GetStyle(); style = ImGui::GetStyle();
auto frames_selection_set_reference = [&]()
{
frames.selection.clear();
if (reference.frameIndex >= 0) frames.selection.insert(reference.frameIndex);
frameSelectionSnapshot.assign(frames.selection.begin(), frames.selection.end());
frameSelectionSnapshotReference = reference;
frameSelectionLocked.clear();
isFrameSelectionLocked = false;
frameFocusIndex = reference.frameIndex;
frameFocusRequested = reference.frameIndex >= 0;
};
auto frames_delete = [&]() auto frames_delete = [&]()
{ {
if (auto item = animation->item_get(reference.itemType, reference.itemID); item) if (auto item = animation->item_get(reference.itemType, reference.itemID); item)
@@ -61,11 +73,34 @@ namespace anm2ed::imgui
item->frames.erase(item->frames.begin() + i); item->frames.erase(item->frames.begin() + i);
} }
reference.frameIndex = -1; reference.frameIndex = glm::clamp(--reference.frameIndex, -1, (int)item->frames.size() - 1);
frames.clear(); frames_selection_set_reference();
} }
}; };
auto frames_selection_reset = [&]()
{
frames.clear();
frameSelectionSnapshot.clear();
frameSelectionLocked.clear();
isFrameSelectionLocked = false;
frameFocusRequested = false;
frameFocusIndex = -1;
frameSelectionSnapshotReference = reference;
};
auto reference_clear = [&]()
{
reference = {reference.animationIndex};
frames_selection_reset();
};
auto reference_set_item = [&](anm2::Type type, int id)
{
reference = {reference.animationIndex, type, id};
frames_selection_reset();
};
auto context_menu = [&]() auto context_menu = [&]()
{ {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
@@ -185,7 +220,7 @@ namespace anm2ed::imgui
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4()); ImGui::PushStyleColor(ImGuiCol_Header, ImVec4());
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4()); ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4());
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4()); ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4());
if (ImGui::Selectable("##Item Button", false, ImGuiSelectableFlags_None, itemSize)) if (ImGui::Selectable("##Item Button", false, ImGuiSelectableFlags_SelectOnNav, itemSize))
{ {
if (type == anm2::LAYER) if (type == anm2::LAYER)
{ {
@@ -195,7 +230,7 @@ namespace anm2ed::imgui
else if (type == anm2::NULL_) else if (type == anm2::NULL_)
document.null.selection = {id}; document.null.selection = {id};
reference = {reference.animationIndex, type, id}; reference_set_item(type, id);
} }
ImGui::PopStyleColor(3); ImGui::PopStyleColor(3);
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
@@ -424,7 +459,7 @@ namespace anm2ed::imgui
auto remove = [&]() auto remove = [&]()
{ {
animation->item_remove(reference.itemType, reference.itemID); animation->item_remove(reference.itemType, reference.itemID);
reference = {reference.animationIndex}; reference_clear();
}; };
DOCUMENT_EDIT(document, "Remove Item", Document::ITEMS, remove()); DOCUMENT_EDIT(document, "Remove Item", Document::ITEMS, remove());
@@ -537,11 +572,9 @@ namespace anm2ed::imgui
{ {
float frameTime{}; float frameTime{};
if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left) && !ImGui::IsAnyItemHovered())
ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{ {
frames.clear(); reference_set_item(type, id);
reference = {reference.animationIndex, type, id};
} }
for (int i = frameMin; i < frameMax; i++) for (int i = frameMin; i < frameMax; i++)
@@ -565,8 +598,7 @@ namespace anm2ed::imgui
auto isFrameVisible = isVisible && frame.isVisible; auto isFrameVisible = isVisible && frame.isVisible;
auto isReferenced = reference == frameReference; auto isReferenced = reference == frameReference;
auto isSelected = auto isSelected =
(frames.selection.contains((int)i) && reference.itemType == type && reference.itemID == id) || (frames.selection.contains((int)i) && reference.itemType == type && reference.itemID == id);
isReferenced;
if (type == anm2::TRIGGER) frameTime = frame.atFrame; if (type == anm2::TRIGGER) frameTime = frame.atFrame;
@@ -574,17 +606,29 @@ namespace anm2ed::imgui
type == anm2::TRIGGER ? frameSize : to_imvec2(vec2(frameSize.x * frame.duration, frameSize.y)); type == anm2::TRIGGER ? frameSize : to_imvec2(vec2(frameSize.x * frame.duration, frameSize.y));
auto buttonPos = ImVec2(cursorPos.x + (frameTime * frameSize.x), cursorPos.y); auto buttonPos = ImVec2(cursorPos.x + (frameTime * frameSize.x), cursorPos.y);
if (frameFocusRequested && frameFocusIndex == (int)i && reference == frameReference)
{
ImGui::SetKeyboardFocusHere();
frameFocusRequested = false;
}
ImGui::SetCursorPos(buttonPos); ImGui::SetCursorPos(buttonPos);
ImGui::PushStyleColor(ImGuiCol_Header, isFrameVisible && isSelected ? colorActive
: isSelected ? colorActiveHidden auto buttonScreenPos = ImGui::GetCursorScreenPos();
: isFrameVisible ? color auto fillColor = isSelected ? (isFrameVisible ? colorActive : colorActiveHidden)
: colorHidden); : (isFrameVisible ? color : colorHidden);
drawList->AddRectFilled(buttonScreenPos,
ImVec2(buttonScreenPos.x + buttonSize.x, buttonScreenPos.y + buttonSize.y),
ImGui::GetColorU32(fillColor));
ImGui::PushStyleColor(ImGuiCol_Header, isFrameVisible ? colorActive : colorActiveHidden);
ImGui::PushStyleColor(ImGuiCol_HeaderActive, isFrameVisible ? colorActive : colorActiveHidden); ImGui::PushStyleColor(ImGuiCol_HeaderActive, isFrameVisible ? colorActive : colorActiveHidden);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, isFrameVisible ? colorHovered : colorHoveredHidden); ImGui::PushStyleColor(ImGuiCol_HeaderHovered, isFrameVisible ? colorHovered : colorHoveredHidden);
ImGui::PushStyleColor(ImGuiCol_NavCursor, isFrameVisible ? colorHovered : colorHoveredHidden);
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetNextItemSelectionUserData((int)i); ImGui::SetNextItemSelectionUserData((int)i);
if (ImGui::Selectable("##Frame Button", true, ImGuiSelectableFlags_None, buttonSize)) if (ImGui::Selectable("##Frame Button", isSelected, ImGuiSelectableFlags_None, buttonSize))
{ {
if (type == anm2::LAYER) if (type == anm2::LAYER)
{ {
@@ -604,7 +648,11 @@ namespace anm2ed::imgui
} }
reference = frameReference; reference = frameReference;
isReferenced = true;
} }
ImGui::PopStyleColor(4);
if (ImGui::IsItemHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Left)) if (ImGui::IsItemHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Left))
{ {
if (type == anm2::TRIGGER || ImGui::IsKeyDown(ImGuiMod_Ctrl)) if (type == anm2::TRIGGER || ImGui::IsKeyDown(ImGuiMod_Ctrl))
@@ -616,8 +664,6 @@ namespace anm2ed::imgui
} }
} }
ImGui::PopStyleColor(3);
if (type != anm2::TRIGGER) if (type != anm2::TRIGGER)
{ {
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip)) if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip))
@@ -1013,7 +1059,7 @@ namespace anm2ed::imgui
} }
} }
frames.selection = {reference.frameIndex}; frames_selection_set_reference();
}; };
DOCUMENT_EDIT(document, "Insert Frame", Document::FRAMES, insert_frame()); DOCUMENT_EDIT(document, "Insert Frame", Document::FRAMES, insert_frame());
@@ -1350,22 +1396,20 @@ namespace anm2ed::imgui
if (shortcut(manager.chords[SHORTCUT_PREVIOUS_FRAME], shortcut::GLOBAL, true)) if (shortcut(manager.chords[SHORTCUT_PREVIOUS_FRAME], shortcut::GLOBAL, true))
{ {
if (auto item = document.item_get()) if (auto item = document.item_get(); !item->frames.empty())
{ {
reference.frameIndex--; reference.frameIndex = glm::clamp(--reference.frameIndex, 0, (int)item->frames.size() - 1);
reference.frameIndex = glm::clamp(reference.frameIndex--, -1, (int)item->frames.size() - 1); frames_selection_set_reference();
frames.selection = {reference.frameIndex};
document.frameTime = item->frame_time_from_index_get(reference.frameIndex); document.frameTime = item->frame_time_from_index_get(reference.frameIndex);
} }
} }
if (shortcut(manager.chords[SHORTCUT_NEXT_FRAME], shortcut::GLOBAL, true)) if (shortcut(manager.chords[SHORTCUT_NEXT_FRAME], shortcut::GLOBAL, true))
{ {
if (auto item = document.item_get()) if (auto item = document.item_get(); !item->frames.empty())
{ {
reference.frameIndex++; reference.frameIndex = glm::clamp(++reference.frameIndex, 0, (int)item->frames.size() - 1);
reference.frameIndex = glm::clamp(reference.frameIndex, -1, (int)item->frames.size() - 1); frames_selection_set_reference();
frames.selection = {reference.frameIndex};
document.frameTime = item->frame_time_from_index_get(reference.frameIndex); document.frameTime = item->frame_time_from_index_get(reference.frameIndex);
} }
} }

View File

@@ -35,6 +35,8 @@ namespace anm2ed::imgui
int draggedFrameStart{-1}; int draggedFrameStart{-1};
int draggedFrameStartDuration{-1}; int draggedFrameStartDuration{-1};
bool isDraggedFrameSnapshot{}; bool isDraggedFrameSnapshot{};
bool frameFocusRequested{};
int frameFocusIndex{-1};
FrameDragDrop frameDragDrop{}; FrameDragDrop frameDragDrop{};
std::vector<int> frameSelectionSnapshot{}; std::vector<int> frameSelectionSnapshot{};
std::vector<int> frameSelectionLocked{}; std::vector<int> frameSelectionLocked{};

View File

@@ -195,6 +195,7 @@ namespace anm2ed
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.IniFilename = nullptr; io.IniFilename = nullptr;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigWindowsMoveFromTitleBarOnly = true; io.ConfigWindowsMoveFromTitleBarOnly = true;
ImGui::LoadIniSettingsFromDisk(settings_path().c_str()); ImGui::LoadIniSettingsFromDisk(settings_path().c_str());