autosave fix + item properties change
This commit is contained in:
@@ -96,6 +96,8 @@ file(GLOB PROJECT_SRC CONFIGURE_DEPENDS
|
|||||||
src/imgui/*.hpp
|
src/imgui/*.hpp
|
||||||
src/imgui/window/*.cpp
|
src/imgui/window/*.cpp
|
||||||
src/imgui/window/*.hpp
|
src/imgui/window/*.hpp
|
||||||
|
src/imgui/popup/*.cpp
|
||||||
|
src/imgui/popup/*.hpp
|
||||||
src/imgui/wizard/*.cpp
|
src/imgui/wizard/*.cpp
|
||||||
src/imgui/wizard/*.hpp
|
src/imgui/wizard/*.hpp
|
||||||
src/util/*.cpp
|
src/util/*.cpp
|
||||||
|
|||||||
@@ -11,11 +11,16 @@ namespace anm2ed::imgui
|
|||||||
{
|
{
|
||||||
void AutosaveRestore::update(Manager& manager)
|
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();
|
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));
|
ImGui::TextUnformatted(localize.get(LABEL_RESTORE_AUTOSAVES_PROMPT));
|
||||||
|
|
||||||
@@ -37,6 +42,7 @@ namespace anm2ed::imgui
|
|||||||
if (ImGui::Button(localize.get(BASIC_YES), widgetSize))
|
if (ImGui::Button(localize.get(BASIC_YES), widgetSize))
|
||||||
{
|
{
|
||||||
manager.autosave_files_open();
|
manager.autosave_files_open();
|
||||||
|
isRestoreAvailable = false;
|
||||||
popup.close();
|
popup.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +51,7 @@ namespace anm2ed::imgui
|
|||||||
if (ImGui::Button(localize.get(BASIC_NO), widgetSize))
|
if (ImGui::Button(localize.get(BASIC_NO), widgetSize))
|
||||||
{
|
{
|
||||||
manager.autosave_files_clear();
|
manager.autosave_files_clear();
|
||||||
|
isRestoreAvailable = false;
|
||||||
popup.close();
|
popup.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace anm2ed::imgui
|
|||||||
class AutosaveRestore
|
class AutosaveRestore
|
||||||
{
|
{
|
||||||
PopupHelper popup{PopupHelper(LABEL_WELCOME_RESTORE_POPUP, imgui::POPUP_SMALL_NO_HEIGHT)};
|
PopupHelper popup{PopupHelper(LABEL_WELCOME_RESTORE_POPUP, imgui::POPUP_SMALL_NO_HEIGHT)};
|
||||||
|
bool isInitialized{};
|
||||||
|
bool isRestoreAvailable{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void update(Manager&);
|
void update(Manager&);
|
||||||
|
|||||||
@@ -0,0 +1,218 @@
|
|||||||
|
#include "item_properties.hpp"
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
#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<int> 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<void(anm2::Type, int)>& 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<void()>& left, const std::function<void()>& 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#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<int> unused_items_get(anm2::Anm2&, anm2::Animation*, anm2::Type);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void open();
|
||||||
|
void update(Manager&, Settings&, Document&, anm2::Animation*, anm2::Reference&,
|
||||||
|
const std::function<void(anm2::Type, int)>&);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1009,6 +1009,10 @@ namespace anm2ed::imgui
|
|||||||
auto useTool = tool;
|
auto useTool = tool;
|
||||||
auto step = isMod ? STEP_FAST : STEP;
|
auto step = isMod ? STEP_FAST : STEP;
|
||||||
mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos));
|
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 (isMouseMiddleDown) useTool = tool::PAN;
|
||||||
if (tool == tool::MOVE && isMouseRightDown) useTool = tool::SCALE;
|
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)
|
auto frame_change_apply = [&](anm2::FrameChange frameChange, anm2::ChangeType changeType = anm2::ADJUST)
|
||||||
{ item->frames_change(frameChange, reference.itemType, changeType, frames); };
|
{ 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& toolInfo = tool::INFO[useTool];
|
||||||
auto& areaType = toolInfo.areaType;
|
auto& areaType = toolInfo.areaType;
|
||||||
@@ -1054,13 +1067,20 @@ namespace anm2ed::imgui
|
|||||||
document.snapshot(localize.get(EDIT_FRAME_POSITION));
|
document.snapshot(localize.get(EDIT_FRAME_POSITION));
|
||||||
if (isToolMouseClicked)
|
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;
|
isMoveDragging = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isToolMouseDown && isMoveDragging)
|
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 (isLeftPressed) frame_change_apply({.positionX = step}, anm2::SUBTRACT);
|
||||||
if (isRightPressed) frame_change_apply({.positionX = step}, anm2::ADD);
|
if (isRightPressed) frame_change_apply({.positionX = step}, anm2::ADD);
|
||||||
@@ -1082,13 +1102,35 @@ namespace anm2ed::imgui
|
|||||||
break;
|
break;
|
||||||
case tool::SCALE:
|
case tool::SCALE:
|
||||||
if (!item || !frame || frames.empty()) break;
|
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)
|
if (isToolMouseDown)
|
||||||
|
{
|
||||||
|
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);
|
auto scale = frame->scale + vec2(mouseDelta.x, mouseDelta.y);
|
||||||
if (isMod) scale = {scale.x, scale.x};
|
if (isMod) scale = {scale.x, scale.x};
|
||||||
frame_change_apply({.scaleX = scale.x, .scaleY = scale.y});
|
frame_change_apply({.scaleX = scale.x, .scaleY = scale.y});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isLeftPressed) frame_change_apply({.scaleX = step}, anm2::SUBTRACT);
|
if (isLeftPressed) frame_change_apply({.scaleX = step}, anm2::SUBTRACT);
|
||||||
if (isRightPressed) frame_change_apply({.scaleX = step}, anm2::ADD);
|
if (isRightPressed) frame_change_apply({.scaleX = step}, anm2::ADD);
|
||||||
@@ -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;
|
break;
|
||||||
case tool::ROTATE:
|
case tool::ROTATE:
|
||||||
if (!item || !frame || frames.empty()) break;
|
if (!item || !frame || frames.empty()) break;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace anm2ed::imgui
|
|||||||
bool hasPendingZoomPanAdjust{};
|
bool hasPendingZoomPanAdjust{};
|
||||||
bool isMoveDragging{};
|
bool isMoveDragging{};
|
||||||
glm::vec2 moveOffset{};
|
glm::vec2 moveOffset{};
|
||||||
|
glm::vec2 nullRectScaleAnchor{};
|
||||||
std::filesystem::path renderTempDirectory{};
|
std::filesystem::path renderTempDirectory{};
|
||||||
std::vector<std::filesystem::path> renderTempFrames{};
|
std::vector<std::filesystem::path> renderTempFrames{};
|
||||||
std::vector<double> renderTempFrameDurations{};
|
std::vector<double> renderTempFrameDurations{};
|
||||||
|
|||||||
@@ -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<int>{};
|
|
||||||
if (type == anm2::LAYER) return anm2.layers_unused(*animation);
|
|
||||||
if (type == anm2::NULL_) return anm2.nulls_unused(*animation);
|
|
||||||
return std::set<int>{};
|
|
||||||
};
|
|
||||||
|
|
||||||
auto item_context_menu = [&]()
|
auto item_context_menu = [&]()
|
||||||
{
|
{
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
|
||||||
@@ -688,10 +673,7 @@ namespace anm2ed::imgui
|
|||||||
item_base_properties_open(type, id);
|
item_base_properties_open(type, id);
|
||||||
|
|
||||||
if (ImGui::MenuItem(localize.get(BASIC_ADD), settings.shortcutAdd.c_str(), false, animation))
|
if (ImGui::MenuItem(localize.get(BASIC_ADD), settings.shortcutAdd.c_str(), false, animation))
|
||||||
{
|
itemProperties.open();
|
||||||
item_properties_reset();
|
|
||||||
propertiesPopup.open();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::MenuItem(localize.get(BASIC_REMOVE), settings.shortcutRemove.c_str(), false, item)) item_remove();
|
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]);
|
shortcut(manager.chords[SHORTCUT_ADD]);
|
||||||
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize))
|
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize))
|
||||||
{
|
itemProperties.open();
|
||||||
item_properties_reset();
|
|
||||||
propertiesPopup.open();
|
|
||||||
}
|
|
||||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_ITEM), settings.shortcutAdd);
|
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_ITEM), settings.shortcutAdd);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
@@ -1922,189 +1901,7 @@ namespace anm2ed::imgui
|
|||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
propertiesPopup.trigger();
|
itemProperties.update(manager, settings, document, animation, reference, reference_set_item);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
bakePopup.trigger();
|
bakePopup.trigger();
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "clipboard.hpp"
|
#include "clipboard.hpp"
|
||||||
#include "manager.hpp"
|
#include "manager.hpp"
|
||||||
|
#include "popup/item_properties.hpp"
|
||||||
#include "resources.hpp"
|
#include "resources.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "strings.hpp"
|
#include "strings.hpp"
|
||||||
@@ -26,12 +27,8 @@ namespace anm2ed::imgui
|
|||||||
bool isDragging{};
|
bool isDragging{};
|
||||||
bool isWindowHovered{};
|
bool isWindowHovered{};
|
||||||
bool isHorizontalScroll{};
|
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)};
|
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{};
|
int hoveredTime{};
|
||||||
anm2::Frame* draggedFrame{};
|
anm2::Frame* draggedFrame{};
|
||||||
anm2::Type draggedFrameType{};
|
anm2::Type draggedFrameType{};
|
||||||
|
|||||||
Reference in New Issue
Block a user