expanded change all frame properties
This commit is contained in:
@@ -153,8 +153,11 @@ namespace anm2ed::imgui
|
||||
generatePopup.open();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_WIZARD_GENERATE_ANIMATION_FROM_GRID));
|
||||
|
||||
bool isChangeAllFramesAvailable =
|
||||
frames && !frames->selection.empty() && document->reference.itemType != anm2::TRIGGER;
|
||||
bool isChangeAllAnimationsAvailable = document && !document->animation.selection.empty();
|
||||
if (ImGui::MenuItem(localize.get(LABEL_CHANGE_ALL_FRAME_PROPERTIES), nullptr, false,
|
||||
frames && !frames->selection.empty() && document->reference.itemType != anm2::TRIGGER))
|
||||
isChangeAllFramesAvailable || isChangeAllAnimationsAvailable))
|
||||
changePopup.open();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_WIZARD_CHANGE_ALL_FRAME_PROPERTIES));
|
||||
|
||||
@@ -232,7 +235,7 @@ namespace anm2ed::imgui
|
||||
{
|
||||
if (document)
|
||||
{
|
||||
changeAllFrameProperties.update(*document, settings);
|
||||
changeAllFrameProperties.update(*document, settings, true);
|
||||
if (changeAllFrameProperties.isChanged) changePopup.close();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "change_all_frame_properties.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -11,11 +12,21 @@ using namespace glm;
|
||||
|
||||
namespace anm2ed::imgui::wizard
|
||||
{
|
||||
void ChangeAllFrameProperties::update(Document& document, Settings& settings)
|
||||
namespace
|
||||
{
|
||||
enum ChangeDestination
|
||||
{
|
||||
CHANGE_DESTINATION_FRAMES,
|
||||
CHANGE_DESTINATION_ANIMATIONS,
|
||||
};
|
||||
}
|
||||
|
||||
void ChangeAllFrameProperties::update(Document& document, Settings& settings, bool isFromWizard)
|
||||
{
|
||||
isChanged = false;
|
||||
|
||||
auto& frames = document.frames.selection;
|
||||
auto& animations = document.animation.selection;
|
||||
auto& isCropX = settings.changeIsCropX;
|
||||
auto& isCropY = settings.changeIsCropY;
|
||||
auto& isSizeX = settings.changeIsSizeX;
|
||||
@@ -54,8 +65,26 @@ namespace anm2ed::imgui::wizard
|
||||
auto& interpolation = settings.changeInterpolation;
|
||||
auto& isFlipX = settings.changeIsFlipX;
|
||||
auto& isFlipY = settings.changeIsFlipY;
|
||||
auto& destination = settings.changeDestination;
|
||||
auto& isRoot = settings.changeIsRoot;
|
||||
auto& isLayers = settings.changeIsLayers;
|
||||
auto& isNulls = settings.changeIsNulls;
|
||||
auto& itemType = document.reference.itemType;
|
||||
|
||||
bool isFramesDestination = !isFromWizard || destination == CHANGE_DESTINATION_FRAMES;
|
||||
bool isSelectedFramesAvailable = !frames.empty() && itemType != anm2::TRIGGER;
|
||||
bool isSelectedAnimationsAvailable = !animations.empty();
|
||||
if (isFromWizard)
|
||||
{
|
||||
if (destination == CHANGE_DESTINATION_FRAMES && !isSelectedFramesAvailable && isSelectedAnimationsAvailable)
|
||||
destination = CHANGE_DESTINATION_ANIMATIONS;
|
||||
if (destination == CHANGE_DESTINATION_ANIMATIONS && !isSelectedAnimationsAvailable && isSelectedFramesAvailable)
|
||||
destination = CHANGE_DESTINATION_FRAMES;
|
||||
isFramesDestination = destination == CHANGE_DESTINATION_FRAMES;
|
||||
}
|
||||
|
||||
bool isLayerPropertyAvailable = isFramesDestination ? itemType == anm2::LAYER : isLayers;
|
||||
|
||||
#define PROPERTIES_WIDGET(body, checkboxLabel, isEnabled) \
|
||||
ImGui::Checkbox(checkboxLabel, &isEnabled); \
|
||||
ImGui::SameLine(); \
|
||||
@@ -190,7 +219,7 @@ namespace anm2ed::imgui::wizard
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImGui::GetStyle().ItemInnerSpacing);
|
||||
|
||||
ImGui::BeginDisabled(itemType != anm2::LAYER);
|
||||
ImGui::BeginDisabled(!isLayerPropertyAvailable);
|
||||
float2_value("##Is Crop X", "##Is Crop Y", "##Crop X", localize.get(BASIC_CROP), isCropX, isCropY, crop);
|
||||
float2_value("##Is Size X", "##Is Size Y", "##Size X", localize.get(BASIC_SIZE), isSizeX, isSizeY, size);
|
||||
ImGui::EndDisabled();
|
||||
@@ -198,7 +227,7 @@ namespace anm2ed::imgui::wizard
|
||||
float2_value("##Is Position X", "##Is Position Y", "##Position X", localize.get(BASIC_POSITION), isPositionX,
|
||||
isPositionY, position);
|
||||
|
||||
ImGui::BeginDisabled(itemType != anm2::LAYER);
|
||||
ImGui::BeginDisabled(!isLayerPropertyAvailable);
|
||||
float2_value("##Is Pivot X", "##Is Pivot Y", "##Pivot X", localize.get(BASIC_PIVOT), isPivotX, isPivotY, pivot);
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -215,7 +244,7 @@ namespace anm2ed::imgui::wizard
|
||||
"##Color Offset B", "##Color Offset G", localize.get(BASIC_COLOR_OFFSET), isColorOffsetR,
|
||||
isColorOffsetG, isColorOffsetB, colorOffset);
|
||||
|
||||
ImGui::BeginDisabled(itemType != anm2::LAYER);
|
||||
ImGui::BeginDisabled(!isLayerPropertyAvailable);
|
||||
std::vector<int> fallbackIds{-1};
|
||||
std::vector<std::string> fallbackLabelsString{localize.get(BASIC_NONE)};
|
||||
std::vector<const char*> fallbackLabels{fallbackLabelsString[0].c_str()};
|
||||
@@ -244,7 +273,8 @@ namespace anm2ed::imgui::wizard
|
||||
}
|
||||
auto regionIds = regionStorage && !regionStorage->ids.empty() ? regionStorage->ids : fallbackIds;
|
||||
auto regionLabels = regionStorage && !regionStorage->labels.empty() ? regionStorage->labels : fallbackLabels;
|
||||
if (itemType != anm2::LAYER || std::find(regionIds.begin(), regionIds.end(), regionId) == regionIds.end()) regionId = -1;
|
||||
if (!isLayerPropertyAvailable || std::find(regionIds.begin(), regionIds.end(), regionId) == regionIds.end())
|
||||
regionId = -1;
|
||||
PROPERTIES_WIDGET(combo_id_mapped(localize.get(BASIC_REGION), ®ionId, regionIds, regionLabels), "##Is Region",
|
||||
isRegion);
|
||||
ImGui::EndDisabled();
|
||||
@@ -293,25 +323,106 @@ namespace anm2ed::imgui::wizard
|
||||
if (isFlipXSet) frameChange.isFlipX = std::make_optional(isFlipX);
|
||||
if (isFlipYSet) frameChange.isFlipY = std::make_optional(isFlipY);
|
||||
|
||||
if (auto item = document.item_get())
|
||||
auto all_frames_selection = [](anm2::Item& item)
|
||||
{
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_CHANGE_FRAME_PROPERTIES), Document::FRAMES,
|
||||
item->frames_change(frameChange, itemType, changeType, frames));
|
||||
std::set<int> selection{};
|
||||
for (int i = 0; i < (int)item.frames.size(); ++i)
|
||||
selection.insert(i);
|
||||
return selection;
|
||||
};
|
||||
|
||||
if (isFramesDestination)
|
||||
{
|
||||
if (auto item = document.item_get())
|
||||
{
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_CHANGE_FRAME_PROPERTIES), Document::FRAMES,
|
||||
item->frames_change(frameChange, itemType, changeType, frames));
|
||||
|
||||
isChanged = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto behavior = [&]()
|
||||
{
|
||||
for (auto animationIndex : animations)
|
||||
{
|
||||
if (animationIndex < 0 || animationIndex >= (int)document.anm2.animations.items.size()) continue;
|
||||
auto& animation = document.anm2.animations.items[animationIndex];
|
||||
|
||||
if (isRoot)
|
||||
{
|
||||
auto selection = all_frames_selection(animation.rootAnimation);
|
||||
animation.rootAnimation.frames_change(frameChange, anm2::ROOT, changeType, selection);
|
||||
}
|
||||
|
||||
if (isLayers)
|
||||
{
|
||||
for (auto& [_, item] : animation.layerAnimations)
|
||||
{
|
||||
auto selection = all_frames_selection(item);
|
||||
item.frames_change(frameChange, anm2::LAYER, changeType, selection);
|
||||
}
|
||||
}
|
||||
|
||||
if (isNulls)
|
||||
{
|
||||
for (auto& [_, item] : animation.nullAnimations)
|
||||
{
|
||||
auto selection = all_frames_selection(item);
|
||||
item.frames_change(frameChange, anm2::NULL_, changeType, selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_CHANGE_FRAME_PROPERTIES), Document::FRAMES, behavior());
|
||||
isChanged = true;
|
||||
}
|
||||
};
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (isFromWizard)
|
||||
{
|
||||
ImGui::SeparatorText(localize.get(LABEL_DESTINATION));
|
||||
|
||||
ImGui::BeginDisabled(!isSelectedFramesAvailable);
|
||||
ImGui::RadioButton(localize.get(BASIC_FRAMES), &destination, CHANGE_DESTINATION_FRAMES);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CHANGE_ALL_DESTINATION_FRAMES));
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(!isSelectedAnimationsAvailable);
|
||||
ImGui::RadioButton(localize.get(LABEL_ANIMATIONS_CHILD), &destination, CHANGE_DESTINATION_ANIMATIONS);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CHANGE_ALL_DESTINATION_ANIMATIONS));
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::BeginDisabled(isFramesDestination);
|
||||
ImGui::Checkbox(localize.get(LABEL_ROOT), &isRoot);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CHANGE_ALL_ROOT));
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox(localize.get(LABEL_LAYERS), &isLayers);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CHANGE_ALL_LAYERS));
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox(localize.get(LABEL_NULLS), &isNulls);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CHANGE_ALL_NULLS));
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
bool isAnyProperty = isCropX || isCropY || isSizeX || isSizeY || isPositionX || isPositionY || isPivotX ||
|
||||
isPivotY || isScaleX || isScaleY || isRotation || isDuration || isTintR || isTintG ||
|
||||
isTintB || isTintA || isColorOffsetR || isColorOffsetG || isColorOffsetB || isRegion ||
|
||||
isVisibleSet || isInterpolationSet || isFlipXSet || isFlipYSet;
|
||||
bool isDestinationValid = isFramesDestination ? isSelectedFramesAvailable
|
||||
: isSelectedAnimationsAvailable && (isRoot || isLayers || isNulls);
|
||||
|
||||
auto rowWidgetSize = widget_size_with_row_get(5);
|
||||
|
||||
ImGui::BeginDisabled(!isAnyProperty);
|
||||
ImGui::BeginDisabled(!isAnyProperty || !isDestinationValid);
|
||||
|
||||
if (ImGui::Button(localize.get(LABEL_ADJUST), rowWidgetSize)) frame_change(anm2::ADJUST);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ADJUST));
|
||||
|
||||
@@ -10,6 +10,6 @@ namespace anm2ed::imgui::wizard
|
||||
public:
|
||||
bool isChanged{};
|
||||
|
||||
void update(Document&, Settings&);
|
||||
void update(Document&, Settings&, bool = false);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -311,6 +311,9 @@ namespace anm2ed
|
||||
X(LABEL_REGION_ORIGIN_TOP_LEFT, "Top Left", "Superior izquierda", "Верхний левый", "左上", "왼쪽 위") \
|
||||
X(LABEL_REGION_ORIGIN_CENTER, "Center", "Centro", "Центр", "中心", "중앙") \
|
||||
X(LABEL_REGION_ORIGIN_CUSTOM, "Custom", "Personalizado", "Пользовательский", "自定义", "사용자 지정") \
|
||||
X(LABEL_ROOT, "Root", "Root", "Корень", "根", "Root") \
|
||||
X(LABEL_LAYERS, "Layers", "Capas", "Слои", "动画层", "레이어") \
|
||||
X(LABEL_NULLS, "Nulls", "Nulls", "Нули", "Nulls", "Null") \
|
||||
X(LABEL_MANAGER_LAYER_PROPERTIES, "Layer Properties", "Propiedades de Capa", "Свойства слоя", "动画层属性", "레이어 속성") \
|
||||
X(LABEL_MANAGER_NULL_PROPERTIES, "Null Properties", "Propiedades Null", "Свойства нуля", "Null属性", "Null 속성") \
|
||||
X(LABEL_MANAGER_RENDERING_PROGRESS, "Rendering...", "Renderizando...", "Рендеринг...", "渲染中...", "렌더링 중...") \
|
||||
@@ -531,6 +534,11 @@ namespace anm2ed
|
||||
X(TOOLTIP_BORDER, "Toggle the visibility of borders around layers.", "Alterna la visibilidad de los bordes alrededor de las capas.", "Переключить видимость границ около слоев.", "切换动画层边框是否可见.", "레이어 주변 경계선을 표시하거나 숨깁니다.") \
|
||||
X(TOOLTIP_CANCEL_ADD_ITEM, "Cancel adding an item.", "Cancelar añadir un item.", "Отменить добавление предмета.", "取消添加物品.", "항목 추가를 취소합니다.") \
|
||||
X(TOOLTIP_CANCEL_BAKE_FRAMES, "Cancel baking frames.", "Cancelar hacer bake de Frames.", "Отменить запечку кадров.", "取消提前渲染.", "프레임 베이킹을 취소합니다.") \
|
||||
X(TOOLTIP_CHANGE_ALL_DESTINATION_FRAMES, "Apply specified frame properties to selected frames.", "Aplica las propiedades de frame especificadas a los frames seleccionados.", "Применить указанные свойства кадра к выбранным кадрам.", "将指定的帧属性应用到所选帧。", "지정한 프레임 속성을 선택한 프레임에 적용합니다.") \
|
||||
X(TOOLTIP_CHANGE_ALL_DESTINATION_ANIMATIONS, "Apply specified frame properties to the specified items in the selected animations.", "Aplica las propiedades de frame especificadas a los items indicados en las animaciones seleccionadas.", "Применить указанные свойства кадра к указанным элементам в выбранных анимациях.", "将指定的帧属性应用到所选动画中的指定项目。", "지정한 프레임 속성을 선택한 애니메이션의 지정 항목에 적용합니다.") \
|
||||
X(TOOLTIP_CHANGE_ALL_ROOT, "The frame property changes will apply to root frames.", "Los cambios de propiedades de frame se aplicaran a los frames root.", "Изменения свойств кадра будут применены к корневым кадрам.", "帧属性更改将应用于根帧。", "프레임 속성 변경 사항을 Root 프레임에 적용합니다.") \
|
||||
X(TOOLTIP_CHANGE_ALL_LAYERS, "The frame property changes will apply to layer frames.", "Los cambios de propiedades de frame se aplicaran a los frames de capa.", "Изменения свойств кадра будут применены к кадрам слоев.", "帧属性更改将应用于图层帧。", "프레임 속성 변경 사항을 레이어 프레임에 적용합니다.") \
|
||||
X(TOOLTIP_CHANGE_ALL_NULLS, "The frame property changes will apply to null frames.", "Los cambios de propiedades de frame se aplicaran a los frames null.", "Изменения свойств кадра будут применены к нулевым кадрам.", "帧属性更改将应用于 Null 帧。", "프레임 속성 변경 사항을 Null 프레임에 적용합니다.") \
|
||||
X(TOOLTIP_CENTER_VIEW, "Centers the view.", "Centra la vista.", "Центрирует вид.", "居中视角.", "미리보기 화면을 가운데에 맞춥니다.") \
|
||||
X(TOOLTIP_CLOSE_SETTINGS, "Close without updating settings.", "Cerrar sin actualizar las configuraciones.", "Закрыть без обновления настройки.", "关闭但不保存设置.", "설정을 갱신하지 않고 닫습니다.") \
|
||||
X(TOOLTIP_COMPATIBILITY_ISAAC, "Sets the output file format to that of The Binding of Isaac: Rebirth's.\nThis removes the following:\n- Sounds\n- Regions\n- Special interpolation modes\nNOTE: This will not serialize this data and it won't be able to be recovered.", "Establece el formato del archivo de salida al de The Binding of Isaac: Rebirth.\nEsto elimina lo siguiente:\n- Sonidos\n- Regiones\n- Modos especiales de interpolación\nNOTA: Estos datos no se serializaran y no podran recuperarse.", "Устанавливает формат выходного файла как у The Binding of Isaac: Rebirth.\nЭто удаляет следующее:\n- Звуки\n- Регионы\n- Специальные режимы интерполяции\nПРИМЕЧАНИЕ: Эти данные не будут сериализованы, и их нельзя будет восстановить.", "将输出文件格式设置为 The Binding of Isaac: Rebirth 的格式。\n这会移除以下内容:\n- 声音\n- 区域\n- 特殊插值模式\n注意:这些数据不会被序列化,且无法恢复。", "출력 파일 형식을 The Binding of Isaac: Rebirth의 형식으로 설정합니다.\n다음 항목이 제거됩니다:\n- 사운드\n- 영역\n- 특수 보간 모드\n참고: 이 데이터는 직렬화되지 않으며 복구할 수 없습니다.") \
|
||||
|
||||
@@ -115,6 +115,10 @@ namespace anm2ed
|
||||
X(CHANGE_INTERPOLATION, changeInterpolation, STRING_UNDEFINED, INT, 0) \
|
||||
X(CHANGE_IS_FLIP_X, changeIsFlipX, STRING_UNDEFINED, BOOL, false) \
|
||||
X(CHANGE_IS_FLIP_Y, changeIsFlipY, STRING_UNDEFINED, BOOL, false) \
|
||||
X(CHANGE_DESTINATION, changeDestination, STRING_UNDEFINED, INT, 0) \
|
||||
X(CHANGE_IS_ROOT, changeIsRoot, STRING_UNDEFINED, BOOL, true) \
|
||||
X(CHANGE_IS_LAYERS, changeIsLayers, STRING_UNDEFINED, BOOL, true) \
|
||||
X(CHANGE_IS_NULLS, changeIsNulls, STRING_UNDEFINED, BOOL, true) \
|
||||
\
|
||||
X(SCALE_VALUE, scaleValue, STRING_UNDEFINED, FLOAT, 1.0f) \
|
||||
\
|
||||
|
||||
Reference in New Issue
Block a user