diff --git a/CMakeLists.txt b/CMakeLists.txt index 121cf19..ce375e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,6 +96,8 @@ file(GLOB PROJECT_SRC CONFIGURE_DEPENDS src/imgui/*.hpp src/imgui/window/*.cpp src/imgui/window/*.hpp + src/imgui/popup/*.cpp + src/imgui/popup/*.hpp src/imgui/wizard/*.cpp src/imgui/wizard/*.hpp src/util/*.cpp diff --git a/src/imgui/autosave_restore.cpp b/src/imgui/autosave_restore.cpp index 0d6af65..972da3e 100644 --- a/src/imgui/autosave_restore.cpp +++ b/src/imgui/autosave_restore.cpp @@ -11,11 +11,16 @@ namespace anm2ed::imgui { void AutosaveRestore::update(Manager& manager) { - if (!manager.autosaveFiles.empty() && !popup.is_open()) popup.open(); + if (!isInitialized) + { + isInitialized = true; + isRestoreAvailable = !manager.autosaveFiles.empty(); + if (isRestoreAvailable) popup.open(); + } popup.trigger(); - if (ImGui::BeginPopupModal(popup.label(), &popup.isOpen, ImGuiWindowFlags_NoResize)) + if (isRestoreAvailable && ImGui::BeginPopupModal(popup.label(), &popup.isOpen, ImGuiWindowFlags_NoResize)) { ImGui::TextUnformatted(localize.get(LABEL_RESTORE_AUTOSAVES_PROMPT)); @@ -37,6 +42,7 @@ namespace anm2ed::imgui if (ImGui::Button(localize.get(BASIC_YES), widgetSize)) { manager.autosave_files_open(); + isRestoreAvailable = false; popup.close(); } @@ -45,6 +51,7 @@ namespace anm2ed::imgui if (ImGui::Button(localize.get(BASIC_NO), widgetSize)) { manager.autosave_files_clear(); + isRestoreAvailable = false; popup.close(); } diff --git a/src/imgui/autosave_restore.hpp b/src/imgui/autosave_restore.hpp index 9eda88f..2a36185 100644 --- a/src/imgui/autosave_restore.hpp +++ b/src/imgui/autosave_restore.hpp @@ -8,6 +8,8 @@ namespace anm2ed::imgui class AutosaveRestore { PopupHelper popup{PopupHelper(LABEL_WELCOME_RESTORE_POPUP, imgui::POPUP_SMALL_NO_HEIGHT)}; + bool isInitialized{}; + bool isRestoreAvailable{}; public: void update(Manager&); diff --git a/src/imgui/popup/item_properties.cpp b/src/imgui/popup/item_properties.cpp new file mode 100644 index 0000000..6b7b74a --- /dev/null +++ b/src/imgui/popup/item_properties.cpp @@ -0,0 +1,218 @@ +#include "item_properties.hpp" + +#include + +#include "imgui_.hpp" + +using namespace anm2ed::resource; +using namespace anm2ed::types; + +namespace anm2ed::imgui::popup +{ + void ItemProperties::reset() + { + addItemName.clear(); + addItemID = -1; + addItemSpritesheetID = {}; + } + + std::set ItemProperties::unused_items_get(anm2::Anm2& anm2, anm2::Animation* animation, anm2::Type type) + { + if (!animation) return {}; + if (type == anm2::LAYER) return anm2.layers_unused(*animation); + if (type == anm2::NULL_) return anm2.nulls_unused(*animation); + return {}; + } + + void ItemProperties::open() + { + reset(); + popup.open(); + } + + void ItemProperties::update(Manager& manager, Settings& settings, Document& document, anm2::Animation* animation, + anm2::Reference& reference, + const std::function& referenceSetItem) + { + auto& anm2 = document.anm2; + + popup.trigger(); + + if (ImGui::BeginPopupModal(popup.label(), &popup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto close = [&]() + { + reset(); + popup.close(); + }; + + auto& type = settings.timelineAddItemType; + auto& destination = settings.timelineAddItemDestination; + auto& source = settings.timelineAddItemSource; + + auto contentHeight = ImGui::GetContentRegionAvail().y - ImGui::GetFrameHeightWithSpacing(); + if (contentHeight < 1.0f) contentHeight = 1.0f; + + if (ImGui::BeginChild("##Content", ImVec2(0, contentHeight), ImGuiChildFlags_Borders)) + { + auto spaced_pair = [](const std::function& left, const std::function& right) + { + auto startX = ImGui::GetCursorPosX(); + auto secondX = startX + ImGui::GetContentRegionAvail().x * 0.5f; + left(); + ImGui::SameLine(); + ImGui::SetCursorPosX(secondX); + right(); + }; + + ImGui::SeparatorText(localize.get(LABEL_TYPE)); + + spaced_pair( + [&]() + { + ImGui::RadioButton(localize.get(LABEL_LAYER), &type, anm2::LAYER); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LAYER_TYPE)); + }, + [&]() + { + ImGui::RadioButton(localize.get(LABEL_NULL), &type, anm2::NULL_); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_NULL_TYPE)); + }); + + ImGui::SeparatorText(localize.get(LABEL_SOURCE)); + + auto isUnusedItems = animation && !unused_items_get(anm2, animation, (anm2::Type)type).empty(); + spaced_pair( + [&]() + { + ImGui::RadioButton(localize.get(LABEL_NEW), &source, source::NEW); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_NEW_ITEM)); + }, + [&]() + { + ImGui::BeginDisabled(!isUnusedItems); + ImGui::RadioButton(localize.get(LABEL_EXISTING), &source, source::EXISTING); + ImGui::EndDisabled(); + ImGui::SetItemTooltip("%s", isUnusedItems ? localize.get(TOOLTIP_USE_EXISTING_ITEM) + : localize.get(TOOLTIP_NO_UNUSED_ITEMS)); + }); + + ImGui::SeparatorText(localize.get(LABEL_DESTINATION)); + + spaced_pair( + [&]() + { + ImGui::RadioButton(localize.get(LABEL_ALL_ANIMATIONS), &destination, destination::ALL); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ITEM_ALL_ANIMATIONS)); + }, + [&]() + { + ImGui::RadioButton(localize.get(LABEL_THIS_ANIMATION), &destination, destination::THIS); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ITEM_THIS_ANIMATION)); + }); + + if (source == source::NEW) + { + ImGui::SeparatorText(localize.get(LABEL_OPTIONS)); + + input_text_string(localize.get(BASIC_NAME), &addItemName); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ITEM_NAME)); + if (type == anm2::LAYER) + { + combo_id_mapped(localize.get(LABEL_SPRITESHEET), &addItemSpritesheetID, document.spritesheet.ids, + document.spritesheet.labels); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LAYER_SPRITESHEET)); + } + else if (type == anm2::NULL_) + { + ImGui::Checkbox(localize.get(LABEL_RECT), &addItemIsShowRect); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_NULL_RECT)); + } + } + else if (animation) + { + ImGui::SeparatorText(localize.get(type == anm2::LAYER ? LABEL_LAYER : LABEL_NULL)); + + if (ImGui::BeginChild("##Existing Items", ImVec2(0, 0))) + { + auto unusedItems = unused_items_get(anm2, animation, (anm2::Type)type); + if (addItemID != -1 && !unusedItems.contains(addItemID)) addItemID = -1; + + for (auto id : unusedItems) + { + auto isSelected = addItemID == id; + + ImGui::PushID(id); + + if (type == anm2::LAYER) + { + if (auto it = anm2.content.layers.find(id); it != anm2.content.layers.end()) + { + auto& layer = it->second; + auto label = std::vformat(localize.get(FORMAT_LAYER), + std::make_format_args(id, layer.name, layer.spritesheetID)); + if (ImGui::Selectable(label.c_str(), isSelected)) + { + addItemID = id; + addItemSpritesheetID = layer.spritesheetID; + } + } + } + else if (type == anm2::NULL_) + { + if (auto it = anm2.content.nulls.find(id); it != anm2.content.nulls.end()) + { + auto& null = it->second; + auto label = std::vformat(localize.get(FORMAT_NULL), std::make_format_args(id, null.name)); + if (ImGui::Selectable(label.c_str(), isSelected)) + { + addItemID = id; + addItemIsShowRect = null.isShowRect; + } + } + } + + ImGui::PopID(); + } + } + ImGui::EndChild(); + } + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + ImGui::BeginDisabled(source == source::EXISTING && addItemID == -1); + shortcut(manager.chords[SHORTCUT_CONFIRM]); + if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) + { + anm2::Reference addReference{}; + int insertBeforeID = reference.itemType == anm2::LAYER ? reference.itemID : -1; + + document.snapshot(localize.get(EDIT_ADD_ITEM)); + if (type == anm2::LAYER) + addReference = anm2.layer_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, insertBeforeID, + addItemName, addItemSpritesheetID, (destination::Type)destination); + else if (type == anm2::NULL_) + addReference = anm2.null_animation_add({reference.animationIndex, anm2::NULL_, addItemID}, addItemName, + addItemIsShowRect, (destination::Type)destination); + + document.change(Document::ITEMS); + + referenceSetItem(addReference.itemType, addReference.itemID); + + close(); + } + ImGui::EndDisabled(); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ADD_ITEM)); + + ImGui::SameLine(); + + shortcut(manager.chords[SHORTCUT_CANCEL]); + if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize)) close(); + ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CANCEL_ADD_ITEM)); + + ImGui::EndPopup(); + } + } +} diff --git a/src/imgui/popup/item_properties.hpp b/src/imgui/popup/item_properties.hpp new file mode 100644 index 0000000..4391e4a --- /dev/null +++ b/src/imgui/popup/item_properties.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#include "document.hpp" +#include "manager.hpp" +#include "settings.hpp" +#include "strings.hpp" + +namespace anm2ed::imgui::popup +{ + class ItemProperties + { + PopupHelper popup{PopupHelper(LABEL_TIMELINE_PROPERTIES_POPUP, POPUP_NORMAL)}; + std::string addItemName{"New Item"}; + bool addItemIsShowRect{}; + int addItemID{-1}; + int addItemSpritesheetID{-1}; + + void reset(); + std::set unused_items_get(anm2::Anm2&, anm2::Animation*, anm2::Type); + + public: + void open(); + void update(Manager&, Settings&, Document&, anm2::Animation*, anm2::Reference&, + const std::function&); + }; +} diff --git a/src/imgui/window/animation_preview.cpp b/src/imgui/window/animation_preview.cpp index 33a2719..cf896fb 100644 --- a/src/imgui/window/animation_preview.cpp +++ b/src/imgui/window/animation_preview.cpp @@ -1009,6 +1009,10 @@ namespace anm2ed::imgui auto useTool = tool; auto step = isMod ? STEP_FAST : STEP; mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); + auto selectedNullIt = reference.itemType == anm2::NULL_ ? anm2.content.nulls.find(reference.itemID) + : anm2.content.nulls.end(); + bool isSelectedNullRect = selectedNullIt != anm2.content.nulls.end() && selectedNullIt->second.isShowRect; + auto null_rect_top_left = [](const anm2::Frame& frame) { return frame.position - (frame.scale * 0.5f); }; if (isMouseMiddleDown) useTool = tool::PAN; if (tool == tool::MOVE && isMouseRightDown) useTool = tool::SCALE; @@ -1031,6 +1035,15 @@ namespace anm2ed::imgui auto frame_change_apply = [&](anm2::FrameChange frameChange, anm2::ChangeType changeType = anm2::ADJUST) { item->frames_change(frameChange, reference.itemType, changeType, frames); }; + auto null_rect_change = [&](vec2 topLeft, vec2 rectSize) + { + topLeft = vec2(ivec2(topLeft)); + rectSize = vec2(ivec2(rectSize)); + frame_change_apply({.positionX = topLeft.x + rectSize.x * 0.5f, + .positionY = topLeft.y + rectSize.y * 0.5f, + .scaleX = rectSize.x, + .scaleY = rectSize.y}); + }; auto& toolInfo = tool::INFO[useTool]; auto& areaType = toolInfo.areaType; @@ -1054,13 +1067,20 @@ namespace anm2ed::imgui document.snapshot(localize.get(EDIT_FRAME_POSITION)); if (isToolMouseClicked) { - moveOffset = settings.inputIsMoveToolSnapToMouse ? vec2() : mousePos - frame->position; + auto origin = isSelectedNullRect ? null_rect_top_left(*frame) : frame->position; + moveOffset = settings.inputIsMoveToolSnapToMouse ? vec2() : mousePos - origin; isMoveDragging = true; } } if (isToolMouseDown && isMoveDragging) - frame_change_apply( - {.positionX = (int)(mousePos.x - moveOffset.x), .positionY = (int)(mousePos.y - moveOffset.y)}); + { + auto position = mousePos - moveOffset; + if (isSelectedNullRect) + frame_change_apply({.positionX = (int)(position.x + frame->scale.x * 0.5f), + .positionY = (int)(position.y + frame->scale.y * 0.5f)}); + else + frame_change_apply({.positionX = (int)position.x, .positionY = (int)position.y}); + } if (isLeftPressed) frame_change_apply({.positionX = step}, anm2::SUBTRACT); if (isRightPressed) frame_change_apply({.positionX = step}, anm2::ADD); @@ -1082,12 +1102,34 @@ namespace anm2ed::imgui break; case tool::SCALE: if (!item || !frame || frames.empty()) break; - if (isToolBegin) document.snapshot(localize.get(EDIT_FRAME_SCALE)); + if (isToolBegin) + { + document.snapshot(localize.get(EDIT_FRAME_SCALE)); + if (isToolMouseClicked && isSelectedNullRect) nullRectScaleAnchor = null_rect_top_left(*frame); + } if (isToolMouseDown) { - auto scale = frame->scale + vec2(mouseDelta.x, mouseDelta.y); - if (isMod) scale = {scale.x, scale.x}; - frame_change_apply({.scaleX = scale.x, .scaleY = scale.y}); + if (isSelectedNullRect) + { + auto size = mousePos - nullRectScaleAnchor; + if (isMod) + { + auto squareSize = std::max(std::abs(size.x), std::abs(size.y)); + size = {std::copysign(squareSize, size.x), std::copysign(squareSize, size.y)}; + } + + auto minPoint = glm::min(nullRectScaleAnchor, nullRectScaleAnchor + size); + auto maxPoint = glm::max(nullRectScaleAnchor, nullRectScaleAnchor + size); + minPoint = vec2(ivec2(minPoint)); + maxPoint = vec2(ivec2(maxPoint)); + null_rect_change(minPoint, maxPoint - minPoint); + } + else + { + auto scale = frame->scale + vec2(mouseDelta.x, mouseDelta.y); + if (isMod) scale = {scale.x, scale.x}; + frame_change_apply({.scaleX = scale.x, .scaleY = scale.y}); + } } if (isLeftPressed) frame_change_apply({.scaleX = step}, anm2::SUBTRACT); @@ -1106,7 +1148,19 @@ namespace anm2ed::imgui } } - if (isToolEnd) document.change(Document::FRAMES); + if (isToolEnd) + { + if (isSelectedNullRect) + { + auto topLeft = null_rect_top_left(*frame); + auto minPoint = glm::min(topLeft, topLeft + frame->scale); + auto maxPoint = glm::max(topLeft, topLeft + frame->scale); + minPoint = vec2(ivec2(minPoint)); + maxPoint = vec2(ivec2(maxPoint)); + null_rect_change(minPoint, maxPoint - minPoint); + } + document.change(Document::FRAMES); + } break; case tool::ROTATE: if (!item || !frame || frames.empty()) break; diff --git a/src/imgui/window/animation_preview.hpp b/src/imgui/window/animation_preview.hpp index 3b591e2..1ed137b 100644 --- a/src/imgui/window/animation_preview.hpp +++ b/src/imgui/window/animation_preview.hpp @@ -29,6 +29,7 @@ namespace anm2ed::imgui bool hasPendingZoomPanAdjust{}; bool isMoveDragging{}; glm::vec2 moveOffset{}; + glm::vec2 nullRectScaleAnchor{}; std::filesystem::path renderTempDirectory{}; std::vector renderTempFrames{}; std::vector renderTempFrameDurations{}; diff --git a/src/imgui/window/timeline.cpp b/src/imgui/window/timeline.cpp index cce6f33..71e55a6 100644 --- a/src/imgui/window/timeline.cpp +++ b/src/imgui/window/timeline.cpp @@ -643,21 +643,6 @@ namespace anm2ed::imgui }; }; - auto item_properties_reset = [&]() - { - addItemName.clear(); - addItemSpritesheetID = {}; - addItemID = -1; - }; - - auto unused_items_get = [&](anm2::Type type) - { - if (!animation) return std::set{}; - if (type == anm2::LAYER) return anm2.layers_unused(*animation); - if (type == anm2::NULL_) return anm2.nulls_unused(*animation); - return std::set{}; - }; - auto item_context_menu = [&]() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); @@ -688,10 +673,7 @@ namespace anm2ed::imgui item_base_properties_open(type, id); if (ImGui::MenuItem(localize.get(BASIC_ADD), settings.shortcutAdd.c_str(), false, animation)) - { - item_properties_reset(); - propertiesPopup.open(); - } + itemProperties.open(); if (ImGui::MenuItem(localize.get(BASIC_REMOVE), settings.shortcutRemove.c_str(), false, item)) item_remove(); @@ -1086,10 +1068,7 @@ namespace anm2ed::imgui { shortcut(manager.chords[SHORTCUT_ADD]); if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) - { - item_properties_reset(); - propertiesPopup.open(); - } + itemProperties.open(); set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_ITEM), settings.shortcutAdd); ImGui::SameLine(); @@ -1922,189 +1901,7 @@ namespace anm2ed::imgui ImGui::PopStyleVar(); ImGui::End(); - propertiesPopup.trigger(); - - if (ImGui::BeginPopupModal(propertiesPopup.label(), &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) - { - auto item_properties_close = [&]() - { - item_properties_reset(); - propertiesPopup.close(); - }; - - auto& type = settings.timelineAddItemType; - auto& destination = settings.timelineAddItemDestination; - auto& source = settings.timelineAddItemSource; - - auto footerSize = footer_size_get(); - auto optionsSize = child_size_get(11); - auto itemsSize = ImVec2(0, ImGui::GetContentRegionAvail().y - - (optionsSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 4)); - if (ImGui::BeginChild("##Options", optionsSize, ImGuiChildFlags_Borders)) - { - ImGui::SeparatorText(localize.get(LABEL_TYPE)); - - auto size = ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, ImGui::GetFrameHeightWithSpacing()); - - if (ImGui::BeginChild("##Type 1", size)) - { - ImGui::RadioButton(localize.get(LABEL_LAYER), &type, anm2::LAYER); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LAYER_TYPE)); - } - ImGui::EndChild(); - - ImGui::SameLine(); - - if (ImGui::BeginChild("##Type 2", size)) - { - ImGui::RadioButton(localize.get(LABEL_NULL), &type, anm2::NULL_); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_NULL_TYPE)); - } - ImGui::EndChild(); - - ImGui::SeparatorText(localize.get(LABEL_SOURCE)); - - if (ImGui::BeginChild("##Source 1", size)) - { - ImGui::RadioButton(localize.get(LABEL_NEW), &source, source::NEW); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_NEW_ITEM)); - } - ImGui::EndChild(); - - ImGui::SameLine(); - - if (ImGui::BeginChild("##Source 2", size)) - { - auto isUnusedItems = animation && !unused_items_get((anm2::Type)type).empty(); - ImGui::BeginDisabled(!isUnusedItems); - ImGui::RadioButton(localize.get(LABEL_EXISTING), &source, source::EXISTING); - ImGui::EndDisabled(); - ImGui::SetItemTooltip("%s", isUnusedItems ? localize.get(TOOLTIP_USE_EXISTING_ITEM) - : localize.get(TOOLTIP_NO_UNUSED_ITEMS)); - } - ImGui::EndChild(); - - ImGui::SeparatorText(localize.get(LABEL_DESTINATION)); - - if (ImGui::BeginChild("##Destination 1", size)) - { - ImGui::RadioButton(localize.get(LABEL_ALL_ANIMATIONS), &destination, destination::ALL); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ITEM_ALL_ANIMATIONS)); - } - ImGui::EndChild(); - - ImGui::SameLine(); - - if (ImGui::BeginChild("##Destination 2", size)) - { - ImGui::RadioButton(localize.get(LABEL_THIS_ANIMATION), &destination, destination::THIS); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ITEM_THIS_ANIMATION)); - } - ImGui::EndChild(); - - ImGui::SeparatorText(localize.get(LABEL_OPTIONS)); - - ImGui::BeginDisabled(source == source::EXISTING); - { - input_text_string(localize.get(BASIC_NAME), &addItemName); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ITEM_NAME)); - if (type == anm2::LAYER) - { - combo_id_mapped(localize.get(LABEL_SPRITESHEET), &addItemSpritesheetID, document.spritesheet.ids, - document.spritesheet.labels); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LAYER_SPRITESHEET)); - } - else if (type == anm2::NULL_) - { - ImGui::Checkbox(localize.get(LABEL_RECT), &addItemIsShowRect); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_NULL_RECT)); - } - } - ImGui::EndDisabled(); - } - ImGui::EndChild(); - - if (ImGui::BeginChild("##Items", itemsSize, ImGuiChildFlags_Borders)) - { - if (animation && source == source::EXISTING) - { - auto unusedItems = unused_items_get((anm2::Type)type); - if (addItemID != -1 && !unusedItems.contains(addItemID)) addItemID = -1; - - for (auto id : unusedItems) - { - auto isSelected = addItemID == id; - - ImGui::PushID(id); - - if (type == anm2::LAYER) - { - if (auto it = anm2.content.layers.find(id); it != anm2.content.layers.end()) - { - auto& layer = it->second; - auto label = std::vformat(localize.get(FORMAT_LAYER), - std::make_format_args(id, layer.name, layer.spritesheetID)); - if (ImGui::Selectable(label.c_str(), isSelected)) - { - addItemID = id; - addItemSpritesheetID = layer.spritesheetID; - } - } - } - else if (type == anm2::NULL_) - { - if (auto it = anm2.content.nulls.find(id); it != anm2.content.nulls.end()) - { - auto& null = it->second; - auto label = std::vformat(localize.get(FORMAT_NULL), std::make_format_args(id, null.name)); - if (ImGui::Selectable(label.c_str(), isSelected)) - { - addItemID = id; - addItemIsShowRect = null.isShowRect; - } - } - } - - ImGui::PopID(); - } - } - } - ImGui::EndChild(); - - auto widgetSize = widget_size_with_row_get(2); - - ImGui::BeginDisabled(source == source::EXISTING && addItemID == -1); - shortcut(manager.chords[SHORTCUT_CONFIRM]); - if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) - { - anm2::Reference addReference{}; - int insertBeforeID = reference.itemType == anm2::LAYER ? reference.itemID : -1; - - document.snapshot(localize.get(EDIT_ADD_ITEM)); - if (type == anm2::LAYER) - addReference = anm2.layer_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, insertBeforeID, - addItemName, addItemSpritesheetID, (destination::Type)destination); - else if (type == anm2::NULL_) - addReference = anm2.null_animation_add({reference.animationIndex, anm2::NULL_, addItemID}, addItemName, - addItemIsShowRect, (destination::Type)destination); - - document.change(Document::ITEMS); - - reference_set_item(addReference.itemType, addReference.itemID); - - item_properties_close(); - } - ImGui::EndDisabled(); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ADD_ITEM)); - - ImGui::SameLine(); - - shortcut(manager.chords[SHORTCUT_CANCEL]); - if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize)) item_properties_close(); - ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CANCEL_ADD_ITEM)); - - ImGui::EndPopup(); - } + itemProperties.update(manager, settings, document, animation, reference, reference_set_item); bakePopup.trigger(); diff --git a/src/imgui/window/timeline.hpp b/src/imgui/window/timeline.hpp index b97c57a..2ba736b 100644 --- a/src/imgui/window/timeline.hpp +++ b/src/imgui/window/timeline.hpp @@ -4,6 +4,7 @@ #include "clipboard.hpp" #include "manager.hpp" +#include "popup/item_properties.hpp" #include "resources.hpp" #include "settings.hpp" #include "strings.hpp" @@ -26,12 +27,8 @@ namespace anm2ed::imgui bool isDragging{}; bool isWindowHovered{}; bool isHorizontalScroll{}; - PopupHelper propertiesPopup{PopupHelper(LABEL_TIMELINE_PROPERTIES_POPUP, POPUP_NORMAL)}; + popup::ItemProperties itemProperties{}; PopupHelper bakePopup{PopupHelper(LABEL_TIMELINE_BAKE_POPUP, POPUP_SMALL_NO_HEIGHT)}; - std::string addItemName{"New Item"}; - bool addItemIsShowRect{}; - int addItemID{-1}; - int addItemSpritesheetID{-1}; int hoveredTime{}; anm2::Frame* draggedFrame{}; anm2::Type draggedFrameType{};