Added previous/next item, default keybind is Shift+F7/Shift+F8

This commit is contained in:
2026-05-01 21:01:57 -04:00
parent e9cd4f1ec4
commit fba8edb569
3 changed files with 69 additions and 11 deletions
+62 -9
View File
@@ -381,6 +381,55 @@ namespace anm2ed::imgui
frames_selection_reset(); frames_selection_reset();
}; };
auto reference_set_timeline_item = [&](anm2::Type type, int id)
{
if (type == anm2::LAYER)
if (auto it = anm2.content.layers.find(id); it != anm2.content.layers.end())
document.spritesheet.reference = it->second.spritesheetID;
reference_set_item(type, id);
};
auto timeline_item_references_get = [&]()
{
std::vector<anm2::Reference> itemReferences;
if (!animation) return itemReferences;
itemReferences.push_back({reference.animationIndex, anm2::ROOT});
for (auto& id : animation->layerOrder | std::views::reverse)
{
auto item = animation->item_get(anm2::LAYER, id);
if (!item || (!settings.timelineIsShowUnused && item->frames.empty())) continue;
itemReferences.push_back({reference.animationIndex, anm2::LAYER, id});
}
for (auto& [id, item] : animation->nullAnimations)
{
if (!settings.timelineIsShowUnused && item.frames.empty()) continue;
itemReferences.push_back({reference.animationIndex, anm2::NULL_, id});
}
itemReferences.push_back({reference.animationIndex, anm2::TRIGGER});
return itemReferences;
};
auto reference_set_adjacent_item = [&](int direction)
{
auto itemReferences = timeline_item_references_get();
if (itemReferences.empty()) return;
auto it = std::find_if(itemReferences.begin(), itemReferences.end(), [&](const anm2::Reference& itemReference) {
return itemReference.itemType == reference.itemType && itemReference.itemID == reference.itemID;
});
int index = direction > 0 ? 0 : (int)itemReferences.size() - 1;
if (it != itemReferences.end()) index = (int)std::distance(itemReferences.begin(), it) + direction;
index = std::clamp(index, 0, (int)itemReferences.size() - 1);
auto& itemReference = itemReferences[index];
reference_set_timeline_item(itemReference.itemType, itemReference.itemID);
};
auto item_remove = [&]() auto item_remove = [&]()
{ {
auto behavior = [&]() auto behavior = [&]()
@@ -715,10 +764,7 @@ namespace anm2ed::imgui
ImGui::SetNextItemStorageID(id); ImGui::SetNextItemStorageID(id);
if (ImGui::Selectable("##Item Button", isReferenced, ImGuiSelectableFlags_SelectOnClick, itemSize)) if (ImGui::Selectable("##Item Button", isReferenced, ImGuiSelectableFlags_SelectOnClick, itemSize))
{ {
if (type == anm2::LAYER) reference_set_timeline_item(type, id);
if (auto it = anm2.content.layers.find(id); it != anm2.content.layers.end())
document.spritesheet.reference = it->second.spritesheetID;
reference_set_item(type, id);
} }
ImGui::PopStyleColor(3); ImGui::PopStyleColor(3);
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
@@ -934,11 +980,13 @@ namespace anm2ed::imgui
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::Text("(?)"); ImGui::Text("(?)");
ImGui::PopStyleColor(); ImGui::PopStyleColor();
auto tooltipShortcuts = std::vformat( auto tooltipShortcuts =
localize.get(TOOLTIP_TIMELINE_SHORTCUTS), std::vformat(localize.get(TOOLTIP_TIMELINE_SHORTCUTS),
std::make_format_args(settings.shortcutMovePlayheadBack, settings.shortcutMovePlayheadForward, std::make_format_args(settings.shortcutMovePlayheadBack,
settings.shortcutShortenFrame, settings.shortcutExtendFrame, settings.shortcutMovePlayheadForward, settings.shortcutShortenFrame,
settings.shortcutPreviousFrame, settings.shortcutNextFrame)); settings.shortcutExtendFrame, settings.shortcutPreviousFrame,
settings.shortcutNextFrame, settings.shortcutPreviousItem,
settings.shortcutNextItem));
ImGui::SetItemTooltip("%s", tooltipShortcuts.c_str()); ImGui::SetItemTooltip("%s", tooltipShortcuts.c_str());
ImGui::EndDisabled(); ImGui::EndDisabled();
} }
@@ -2042,6 +2090,8 @@ namespace anm2ed::imgui
auto isPreviousFrame = shortcut(manager.chords[SHORTCUT_PREVIOUS_FRAME], shortcut::GLOBAL); auto isPreviousFrame = shortcut(manager.chords[SHORTCUT_PREVIOUS_FRAME], shortcut::GLOBAL);
auto isNextFrame = shortcut(manager.chords[SHORTCUT_NEXT_FRAME], shortcut::GLOBAL); auto isNextFrame = shortcut(manager.chords[SHORTCUT_NEXT_FRAME], shortcut::GLOBAL);
auto isPreviousItem = shortcut(manager.chords[SHORTCUT_PREVIOUS_ITEM], shortcut::GLOBAL);
auto isNextItem = shortcut(manager.chords[SHORTCUT_NEXT_ITEM], shortcut::GLOBAL);
if (isPreviousFrame) if (isPreviousFrame)
if (auto item = document.item_get(); item && !item->frames.empty()) if (auto item = document.item_get(); item && !item->frames.empty())
@@ -2059,6 +2109,9 @@ namespace anm2ed::imgui
document.frameTime = item->frame_time_from_index_get(reference.frameIndex); document.frameTime = item->frame_time_from_index_get(reference.frameIndex);
} }
} }
if (isPreviousItem) reference_set_adjacent_item(-1);
if (isNextItem) reference_set_adjacent_item(1);
} }
if (isTextPushed) ImGui::PopStyleColor(); if (isTextPushed) ImGui::PopStyleColor();
+3 -1
View File
@@ -420,6 +420,7 @@ namespace anm2ed
X(SHORTCUT_STRING_NEW, "New", "Nuevo", "Новый", "新", "새 파일") \ X(SHORTCUT_STRING_NEW, "New", "Nuevo", "Новый", "新", "새 파일") \
X(SHORTCUT_STRING_NEXT_ANIMATION, "Next Animation", "Siguiente Animacion", "Следующая анимация", "下一动画", "다음 애니메이션") \ X(SHORTCUT_STRING_NEXT_ANIMATION, "Next Animation", "Siguiente Animacion", "Следующая анимация", "下一动画", "다음 애니메이션") \
X(SHORTCUT_STRING_NEXT_FRAME, "Next Frame", "Siguiente Frame", "Следующий кадр", "下一帧", "다음 프레임") \ X(SHORTCUT_STRING_NEXT_FRAME, "Next Frame", "Siguiente Frame", "Следующий кадр", "下一帧", "다음 프레임") \
X(SHORTCUT_STRING_NEXT_ITEM, "Next Item", "Siguiente Item", "Следующий предмет", "下一物品", "다음 항목") \
X(SHORTCUT_STRING_ONIONSKIN, "Onionskin", "Papel Cebolla", "Оньонскин", "洋葱皮预览", "전후 비교") \ X(SHORTCUT_STRING_ONIONSKIN, "Onionskin", "Papel Cebolla", "Оньонскин", "洋葱皮预览", "전후 비교") \
X(SHORTCUT_STRING_OPEN, "Open", "Abrir", "Открыть", "打开", "열기") \ X(SHORTCUT_STRING_OPEN, "Open", "Abrir", "Открыть", "打开", "열기") \
X(SHORTCUT_STRING_PAN, "Pan", "Panoramico", "Панорамирование", "平移", "시점 이동") \ X(SHORTCUT_STRING_PAN, "Pan", "Panoramico", "Панорамирование", "平移", "시점 이동") \
@@ -429,6 +430,7 @@ namespace anm2ed
X(SHORTCUT_STRING_PLAY_PAUSE, "Play/Pause", "Reproducir/Pausar", "Возпроизвести/Пауза", "播放/暂停", "재생/일시정지") \ X(SHORTCUT_STRING_PLAY_PAUSE, "Play/Pause", "Reproducir/Pausar", "Возпроизвести/Пауза", "播放/暂停", "재생/일시정지") \
X(SHORTCUT_STRING_PREVIOUS_ANIMATION, "Previous Animation", "Animacion Anterior", "Предыдущая анимация", "上一动画", "이전 애니메이션") \ X(SHORTCUT_STRING_PREVIOUS_ANIMATION, "Previous Animation", "Animacion Anterior", "Предыдущая анимация", "上一动画", "이전 애니메이션") \
X(SHORTCUT_STRING_PREVIOUS_FRAME, "Previous Frame", "Frame Anterior", "Предыдущий кадр", "前一帧", "이전 프레임") \ X(SHORTCUT_STRING_PREVIOUS_FRAME, "Previous Frame", "Frame Anterior", "Предыдущий кадр", "前一帧", "이전 프레임") \
X(SHORTCUT_STRING_PREVIOUS_ITEM, "Previous Item", "Item Anterior", "Предыдущий предмет", "上一物品", "이전 항목") \
X(SHORTCUT_STRING_REDO, "Redo", "Rehacer", "Повторить", "重做", "다시 실행") \ X(SHORTCUT_STRING_REDO, "Redo", "Rehacer", "Повторить", "重做", "다시 실행") \
X(SHORTCUT_STRING_RENAME, "Rename", "Renombrar", "Переименовать", "重命名", "이름 변경") \ X(SHORTCUT_STRING_RENAME, "Rename", "Renombrar", "Переименовать", "重命名", "이름 변경") \
X(SHORTCUT_STRING_REMOVE, "Remove", "Remover", "Удалить", "去除", "제거") \ X(SHORTCUT_STRING_REMOVE, "Remove", "Remover", "Удалить", "去除", "제거") \
@@ -645,7 +647,7 @@ namespace anm2ed
X(TOOLTIP_STACK_SIZE, "Set the maximum snapshot stack size of a document (i.e., how many undo/redos are preserved at a time).", "Ajusta el tamaño maximo del stack de snapshot de un documento (i. e., cuantos deshacer/rehacer se preservan a lo largo del tiempo.", "Установить максимальный размер стека снимков документа (т. е. количество отмен/повторов, сохраняемых одновременно).", "设置文件的快照栈的最大存储空间. (也就是最大可以存储多少撤销与重做)", "파일의 최대 스냅숏 스택 크기(즉 한 번에 보존되는 실행 취소/다시 실행 수)를 설정합니다.") \ X(TOOLTIP_STACK_SIZE, "Set the maximum snapshot stack size of a document (i.e., how many undo/redos are preserved at a time).", "Ajusta el tamaño maximo del stack de snapshot de un documento (i. e., cuantos deshacer/rehacer se preservan a lo largo del tiempo.", "Установить максимальный размер стека снимков документа (т. е. количество отмен/повторов, сохраняемых одновременно).", "设置文件的快照栈的最大存储空间. (也就是最大可以存储多少撤销与重做)", "파일의 최대 스냅숏 스택 크기(즉 한 번에 보존되는 실행 취소/다시 실행 수)를 설정합니다.") \
X(TOOLTIP_START, "Set the starting time of the animation.", "Ajusta el tiempo de inicio de la animacion.", "Установить начальное время анимации.", "设置动画的起始时间.", "애니메이션의 시작 시간을 설정합니다.") \ X(TOOLTIP_START, "Set the starting time of the animation.", "Ajusta el tiempo de inicio de la animacion.", "Установить начальное время анимации.", "设置动画的起始时间.", "애니메이션의 시작 시간을 설정합니다.") \
X(TOOLTIP_SUBTRACT_VALUES, "Subtract the specified values from each frame.\n(Boolean/mapped values will simply be set.)", "Subtrae los valores especificos de cada Frame.\n(Los valores booleanos/mapeados simplemente se estableceran.)", "Вычтить указанные значения из каждого кадра.\n(Булевы/сопоставленные значения будут просто установлены.)", "将每一帧的指定值进行相减操作. (布尔/映射值将直接被设置.)", "각 프레임의 속성에 지정한 값을 뺍니다.\n(불리언/매핑 값은 그대로 설정됩니다.)") \ X(TOOLTIP_SUBTRACT_VALUES, "Subtract the specified values from each frame.\n(Boolean/mapped values will simply be set.)", "Subtrae los valores especificos de cada Frame.\n(Los valores booleanos/mapeados simplemente se estableceran.)", "Вычтить указанные значения из каждого кадра.\n(Булевы/сопоставленные значения будут просто установлены.)", "将每一帧的指定值进行相减操作. (布尔/映射值将直接被设置.)", "각 프레임의 속성에 지정한 값을 뺍니다.\n(불리언/매핑 값은 그대로 설정됩니다.)") \
X(TOOLTIP_TIMELINE_SHORTCUTS, "- Press {0} to decrement time.\n- Press {1} to increment time.\n- Press {2} to shorten the selected frame, by one frame.\n- Press {3} to extend the selected frame, by one frame.\n- Press {4} to go to the previous frame.\n- Press {5} to go to the next frame.\n- Click and hold on a frame while holding CTRL to change its duration.\n- Click and hold on a trigger to change its At Frame.\n- Hold Alt while clicking a non-trigger frame to toggle interpolation.", "- Presiona{0} para reducir el tiempo.\n- Presiona {1} para incrementar el tiempo.\n- Presiona {2} para acortar el Frame selecionado, por uno.\n- Presiona {3} para extender el Frame seleccionado, por uno.\n- Presiona {4} para ir al Frame anterior.\n- Presiona {5} para ir al siguiente Frame.\n- Haz click y mantiene en un Frame mientras apretas CTRL para cambiar su duracion.\n- Haz click y mantiene en un trigger para cambiar su \"En Frame\".\n- Manten Alt mientras haces click en un frame sin trigger para alternar la interpolacion.", "- Нажмите {0}, чтобы уменьшить время.\n- Нажмите {1}, чтобы увеличить время.\n- Нажмите {2}, чтобы укоротить выбранный кадр одной мерной единицей.\n- Нажмите {3}, чтобы продлить выбранный кадр на одну мерную единицу.\n- Нажмите {4}, чтобы перейти к предыдущему кадру.\n- Нажмите {5}, чтобы перейти к следующему кадру.\n- Удерживайте нажатой кнопку мыши по кадру, удерживая CTRL, чтобы изменить его длительность.\n- Нажмите и удерживайте кнопку мыши по триггеру, чтобы изменить параметр «На кадре».\n- Удерживайте Alt и нажмите по кадру, который не является триггером, чтобы переключить интерполяцию.", "- 按下 {0} 减少时间.\n- 按下 {1} 增加时间.\n- 按下 {2} 将所选帧缩短一帧.\n- 按下 {3} 将所选帧延长一帧.\n- 按下 {4} 跳到上一帧.\n- 按下 {5} 跳到下一帧.\n- 在按住 CTRL 的同时点击并按住某一帧以更改其持续时间.\n- 点击并按住触发器即可更改其触发帧.\n- 按住 Alt 并点击任何无触发器的帧以切换线性插值的使用.", "- {0} 키: 플레이헤드를 뒤로 보냅니다.\n- {1} 키: 플레이헤드를 앞으로 보냅니다.\n- {2} 키: 선택한 프레임을 한 프레임 단축합니다.\n- {3} 키: 선택한 프레임을 한 프레임 연장합니다.\n- {4} 키: 이전 프레임을 선택합니다.\n- {5} 키: 다음 프레임을 선택합니다.\n- CTRL 키를 누른 채 프레임을 클릭하고 드래그하면 프레임의 유지 시간을 변경할 수 있습니다.\n- 트리거를 클릭하고 드래그하면 트리거의 시작 프레임을 변경할 수 있습니다.\n- Alt 키를 누른 채 트리거를 제외한 프레임을 클릭하면 매끄럽게 연결 설정을 켤 수 있습니다.") \ X(TOOLTIP_TIMELINE_SHORTCUTS, "- Press {0}/{1} to move the playhead backward/forward.\n- Press {2}/{3} to shorten/extend the selected frame by one frame.\n- Press {4}/{5} to select the previous/next frame.\n- Press {6}/{7} to select the previous/next item.\n- Click and hold on a frame while holding CTRL to change its duration.\n- Click and hold on a trigger to change its At Frame.\n- Hold Alt while clicking a non-trigger frame to toggle interpolation.", "- Presiona {0}/{1} para mover el cabezal hacia atras/adelante.\n- Presiona {2}/{3} para acortar/extender el Frame seleccionado por uno.\n- Presiona {4}/{5} para seleccionar el Frame anterior/siguiente.\n- Presiona {6}/{7} para seleccionar el Item anterior/siguiente.\n- Haz click y mantiene en un Frame mientras apretas CTRL para cambiar su duracion.\n- Haz click y mantiene en un trigger para cambiar su \"En Frame\".\n- Manten Alt mientras haces click en un frame sin trigger para alternar la interpolacion.", "- Нажмите {0}/{1}, чтобы переместить воспроизводящую головку назад/вперёд.\n- Нажмите {2}/{3}, чтобы укоротить/продлить выбранный кадр на одну мерную единицу.\n- Нажмите {4}/{5}, чтобы выбрать предыдущий/следующий кадр.\n- Нажмите {6}/{7}, чтобы выбрать предыдущий/следующий предмет.\n- Удерживайте нажатой кнопку мыши по кадру, удерживая CTRL, чтобы изменить его длительность.\n- Нажмите и удерживайте кнопку мыши по триггеру, чтобы изменить параметр «На кадре».\n- Удерживайте Alt и нажмите по кадру, который не является триггером, чтобы переключить интерполяцию.", "- 按下 {0}/{1} 可向后/向前移动播放指针.\n- 按下 {2}/{3} 将所选帧缩短/延长一帧.\n- 按下 {4}/{5} 可选择上一帧/下一帧.\n- 按下 {6}/{7} 可选择上一物品/下一物品.\n- 在按住 CTRL 的同时点击并按住某一帧以更改其持续时间.\n- 点击并按住触发器即可更改其触发帧.\n- 按住 Alt 并点击任何无触发器的帧以切换线性插值的使用.", "- {0}/{1} 키: 플레이헤드를 뒤로/앞으로 보냅니다.\n- {2}/{3} 키: 선택한 프레임을 한 프레임 단축/연장합니다.\n- {4}/{5} 키: 이전/다음 프레임을 선택합니다.\n- {6}/{7} 키: 이전/다음 항목을 선택합니다.\n- CTRL 키를 누른 채 프레임을 클릭하고 드래그하면 프레임의 유지 시간을 변경할 수 있습니다.\n- 트리거를 클릭하고 드래그하면 트리거의 시작 프레임을 변경할 수 있습니다.\n- Alt 키를 누른 채 트리거를 제외한 프레임을 클릭하면 매끄럽게 연결 설정을 켤 수 있습니다.") \
X(TOOLTIP_TINT, "Change the tint of the frame.", "Cambia el matiz del Frame", "Изменить оттенок кадра.", "更改此帧的色调.", "프레임의 색조를 변경합니다.") \ X(TOOLTIP_TINT, "Change the tint of the frame.", "Cambia el matiz del Frame", "Изменить оттенок кадра.", "更改此帧的色调.", "프레임의 색조를 변경합니다.") \
X(TOOLTIP_TOOL_COLOR, "Selects the color to be used for drawing.\n(Spritesheet Editor only.)", "Selecciona el color que se usara para dibujar.\n(Solo en el Editor de Spritesheet.)", "Выбирает цвет, который будет использоваться для рисования.\n(Только в редакторе спрайт-листов.)", "选择用于绘画的颜色.\n(仅应用于图集编辑器.)", "그리기용으로 사용할 색을 선택합니다.\n(스프라이트 시트 편집기 전용)") \ X(TOOLTIP_TOOL_COLOR, "Selects the color to be used for drawing.\n(Spritesheet Editor only.)", "Selecciona el color que se usara para dibujar.\n(Solo en el Editor de Spritesheet.)", "Выбирает цвет, который будет использоваться для рисования.\n(Только в редакторе спрайт-листов.)", "选择用于绘画的颜色.\n(仅应用于图集编辑器.)", "그리기용으로 사용할 색을 선택합니다.\n(스프라이트 시트 편집기 전용)") \
X(TOOLTIP_TOOL_COLOR_PICKER, "Selects a color from the canvas.\n(Spritesheet Editor only.)", "Selecciona un color del lienzo.\n(Solo en el Editor de Spritesheet.)", "Выбирает цвет из холста.\n(Только в редакторе спрайт-листов.)", "从画板上选择一个颜色.\n(仅应用于图集编辑器.)", "캔버스에서 색을 선택합니다.\n(스프라이트시트 편집기 전용)") \ X(TOOLTIP_TOOL_COLOR_PICKER, "Selects a color from the canvas.\n(Spritesheet Editor only.)", "Selecciona un color del lienzo.\n(Solo en el Editor de Spritesheet.)", "Выбирает цвет из холста.\n(Только в редакторе спрайт-листов.)", "从画板上选择一个颜色.\n(仅应用于图集编辑器.)", "캔버스에서 색을 선택합니다.\n(스프라이트시트 편집기 전용)") \
+4 -1
View File
@@ -240,7 +240,10 @@ namespace anm2ed
X(SHORTCUT_INSERT_FRAME, shortcutInsertFrame, SHORTCUT_STRING_INSERT_FRAME, STRING, "F6") \ X(SHORTCUT_INSERT_FRAME, shortcutInsertFrame, SHORTCUT_STRING_INSERT_FRAME, STRING, "F6") \
X(SHORTCUT_PREVIOUS_FRAME, shortcutPreviousFrame, SHORTCUT_STRING_PREVIOUS_FRAME, STRING, "F7") \ X(SHORTCUT_PREVIOUS_FRAME, shortcutPreviousFrame, SHORTCUT_STRING_PREVIOUS_FRAME, STRING, "F7") \
X(SHORTCUT_NEXT_FRAME, shortcutNextFrame, SHORTCUT_STRING_NEXT_FRAME, STRING, "F8") \ X(SHORTCUT_NEXT_FRAME, shortcutNextFrame, SHORTCUT_STRING_NEXT_FRAME, STRING, "F8") \
/* Animations */ \ /* Item */ \
X(SHORTCUT_PREVIOUS_ITEM, shortcutPreviousItem, SHORTCUT_STRING_PREVIOUS_ITEM, STRING, "Shift+F7") \
X(SHORTCUT_NEXT_ITEM, shortcutNextItem, SHORTCUT_STRING_NEXT_ITEM, STRING, "Shift+F8") \
/* Animation */ \
X(SHORTCUT_PREVIOUS_ANIMATION, shortcutPreviousAnimation, SHORTCUT_STRING_PREVIOUS_ANIMATION, STRING, "F9") \ X(SHORTCUT_PREVIOUS_ANIMATION, shortcutPreviousAnimation, SHORTCUT_STRING_PREVIOUS_ANIMATION, STRING, "F9") \
X(SHORTCUT_NEXT_ANIMATION, shortcutNextAnimation, SHORTCUT_STRING_NEXT_ANIMATION, STRING, "F10") \ X(SHORTCUT_NEXT_ANIMATION, shortcutNextAnimation, SHORTCUT_STRING_NEXT_ANIMATION, STRING, "F10") \
/* Toggles */ \ /* Toggles */ \