Sound drag/drop
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <format>
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
|
||||
@@ -10,6 +11,7 @@
|
||||
#include "imgui_.h"
|
||||
#include "log.h"
|
||||
#include "math_.h"
|
||||
#include "strings.h"
|
||||
#include "toast.h"
|
||||
#include "tool.h"
|
||||
#include "types.h"
|
||||
@@ -69,9 +71,18 @@ namespace anm2ed::imgui
|
||||
}
|
||||
|
||||
if (isSuccess)
|
||||
toasts.info(std::format("Exported rendered frames to: {}", path));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_EXPORT_RENDERED_FRAMES), std::make_format_args(path)));
|
||||
logger.info(std::vformat(localize.get(TOAST_EXPORT_RENDERED_FRAMES, anm2ed::ENGLISH),
|
||||
std::make_format_args(path)));
|
||||
}
|
||||
else
|
||||
toasts.warning(std::format("Could not export frames to: {}", path));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_EXPORT_RENDERED_FRAMES_FAILED),
|
||||
std::make_format_args(path)));
|
||||
logger.error(std::vformat(localize.get(TOAST_EXPORT_RENDERED_FRAMES_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(path)));
|
||||
}
|
||||
}
|
||||
else if (type == render::SPRITESHEET)
|
||||
{
|
||||
@@ -79,12 +90,18 @@ namespace anm2ed::imgui
|
||||
auto& columns = settings.renderColumns;
|
||||
|
||||
if (renderFrames.empty())
|
||||
toasts.warning("No frames captured for spritesheet export.");
|
||||
{
|
||||
toasts.push(localize.get(TOAST_SPRITESHEET_NO_FRAMES));
|
||||
logger.warning(localize.get(TOAST_SPRITESHEET_NO_FRAMES, anm2ed::ENGLISH));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& firstFrame = renderFrames.front();
|
||||
auto& firstFrame = renderFrames.front();
|
||||
if (firstFrame.size.x <= 0 || firstFrame.size.y <= 0 || firstFrame.pixels.empty())
|
||||
toasts.warning("Spritesheet export failed: captured frames are empty.");
|
||||
{
|
||||
toasts.push(localize.get(TOAST_SPRITESHEET_EMPTY));
|
||||
logger.error(localize.get(TOAST_SPRITESHEET_EMPTY, anm2ed::ENGLISH));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto frameWidth = firstFrame.size.x;
|
||||
@@ -113,18 +130,36 @@ namespace anm2ed::imgui
|
||||
|
||||
Texture spritesheetTexture(spritesheet.data(), spritesheetSize);
|
||||
if (spritesheetTexture.write_png(path))
|
||||
toasts.info(std::format("Exported spritesheet to: {}", path));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_EXPORT_SPRITESHEET), std::make_format_args(path)));
|
||||
logger.info(std::vformat(localize.get(TOAST_EXPORT_SPRITESHEET, anm2ed::ENGLISH),
|
||||
std::make_format_args(path)));
|
||||
}
|
||||
else
|
||||
toasts.warning(std::format("Could not export spritesheet to: {}", path));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_EXPORT_SPRITESHEET_FAILED),
|
||||
std::make_format_args(path)));
|
||||
logger.error(std::vformat(localize.get(TOAST_EXPORT_SPRITESHEET_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(path)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (animation_render(ffmpegPath, path, renderFrames, audioStream, (render::Type)type, size, anm2.info.fps))
|
||||
toasts.info(std::format("Exported rendered animation to: {}", path));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_EXPORT_RENDERED_ANIMATION), std::make_format_args(path)));
|
||||
logger.info(std::vformat(localize.get(TOAST_EXPORT_RENDERED_ANIMATION, anm2ed::ENGLISH),
|
||||
std::make_format_args(path)));
|
||||
}
|
||||
else
|
||||
toasts.warning(std::format("Could not output rendered animation: {}", path));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_EXPORT_RENDERED_ANIMATION_FAILED),
|
||||
std::make_format_args(path)));
|
||||
logger.error(std::vformat(localize.get(TOAST_EXPORT_RENDERED_ANIMATION_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(path)));
|
||||
}
|
||||
}
|
||||
|
||||
renderFrames.clear();
|
||||
@@ -242,24 +277,24 @@ namespace anm2ed::imgui
|
||||
|
||||
auto center_view = [&]() { pan = vec2(); };
|
||||
|
||||
if (ImGui::Begin("Animation Preview", &settings.windowIsAnimationPreview))
|
||||
if (ImGui::Begin(localize.get(LABEL_ANIMATION_PREVIEW_WINDOW), &settings.windowIsAnimationPreview))
|
||||
{
|
||||
auto childSize = ImVec2(row_widget_width_get(4),
|
||||
(ImGui::GetTextLineHeightWithSpacing() * 4) + (ImGui::GetStyle().WindowPadding.y * 2));
|
||||
|
||||
if (ImGui::BeginChild("##Grid Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
ImGui::Checkbox("Grid", &isGrid);
|
||||
ImGui::SetItemTooltip("Toggle the visibility of the grid.");
|
||||
ImGui::Checkbox(localize.get(BASIC_GRID), &isGrid);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GRID_VISIBILITY));
|
||||
ImGui::SameLine();
|
||||
ImGui::ColorEdit4("Color", value_ptr(gridColor), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("Change the grid's color.");
|
||||
ImGui::ColorEdit4(localize.get(BASIC_COLOR), value_ptr(gridColor), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GRID_COLOR));
|
||||
|
||||
input_int2_range("Size", gridSize, ivec2(GRID_SIZE_MIN), ivec2(GRID_SIZE_MAX));
|
||||
ImGui::SetItemTooltip("Change the size of all cells in the grid.");
|
||||
input_int2_range(localize.get(BASIC_SIZE), gridSize, ivec2(GRID_SIZE_MIN), ivec2(GRID_SIZE_MAX));
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GRID_SIZE));
|
||||
|
||||
input_int2_range("Offset", gridOffset, ivec2(GRID_OFFSET_MIN), ivec2(GRID_OFFSET_MAX));
|
||||
ImGui::SetItemTooltip("Change the offset of the grid.");
|
||||
input_int2_range(localize.get(BASIC_OFFSET), gridOffset, ivec2(GRID_OFFSET_MIN), ivec2(GRID_OFFSET_MAX));
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GRID_OFFSET));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -267,23 +302,26 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginChild("##View Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
ImGui::InputFloat("Zoom", &zoom, zoomStep, zoomStep, "%.0f%%");
|
||||
ImGui::SetItemTooltip("Change the zoom of the preview.");
|
||||
ImGui::InputFloat(localize.get(BASIC_ZOOM), &zoom, zoomStep, zoomStep, "%.0f%%");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_PREVIEW_ZOOM));
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_CENTER_VIEW]);
|
||||
if (ImGui::Button("Center View", widgetSize)) pan = vec2();
|
||||
set_item_tooltip_shortcut("Centers the view.", settings.shortcutCenterView);
|
||||
if (ImGui::Button(localize.get(LABEL_CENTER_VIEW), widgetSize)) pan = vec2();
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_CENTER_VIEW), settings.shortcutCenterView);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_FIT]);
|
||||
if (ImGui::Button("Fit", widgetSize))
|
||||
if (ImGui::Button(localize.get(LABEL_FIT), widgetSize))
|
||||
if (animation) set_to_rect(zoom, pan, animation->rect(isRootTransform));
|
||||
set_item_tooltip_shortcut("Set the view to match the extent of the animation.", settings.shortcutFit);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_FIT), settings.shortcutFit);
|
||||
|
||||
ImGui::TextUnformatted(std::format(POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y).c_str());
|
||||
auto mousePosInt = ivec2(mousePos);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_POSITION_SPACED), std::make_format_args(mousePosInt.x, mousePosInt.y))
|
||||
.c_str());
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -291,20 +329,21 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginChild("##Background Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
ImGui::ColorEdit3("Background", value_ptr(backgroundColor), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("Change the background color.");
|
||||
ImGui::ColorEdit3(localize.get(LABEL_BACKGROUND_COLOR), value_ptr(backgroundColor),
|
||||
ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_BACKGROUND_COLOR));
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Axes", &isAxes);
|
||||
ImGui::SetItemTooltip("Toggle the axes' visbility.");
|
||||
ImGui::Checkbox(localize.get(LABEL_AXES), &isAxes);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_AXES));
|
||||
ImGui::SameLine();
|
||||
ImGui::ColorEdit4("Color", value_ptr(axesColor), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("Set the color of the axes.");
|
||||
ImGui::ColorEdit4(localize.get(BASIC_COLOR), value_ptr(axesColor), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_AXES_COLOR));
|
||||
|
||||
combo_negative_one_indexed("Overlay", &overlayIndex, document.animation.labels);
|
||||
ImGui::SetItemTooltip("Set an animation to be drawn over the current animation.");
|
||||
combo_negative_one_indexed(localize.get(LABEL_OVERLAY), &overlayIndex, document.animation.labels);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_OVERLAY));
|
||||
|
||||
ImGui::InputFloat("Alpha", &overlayTransparency, 0, 0, "%.0f");
|
||||
ImGui::SetItemTooltip("Set the alpha of the overlayed animation.");
|
||||
ImGui::InputFloat(localize.get(BASIC_ALPHA), &overlayTransparency, 0, 0, "%.0f");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_OVERLAY_ALPHA));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -316,10 +355,10 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginChild("##Helpers Child 1", helpersChildSize))
|
||||
{
|
||||
ImGui::Checkbox("Root Transform", &isRootTransform);
|
||||
ImGui::SetItemTooltip("Root frames will transform the rest of the animation.");
|
||||
ImGui::Checkbox("Pivots", &isPivots);
|
||||
ImGui::SetItemTooltip("Toggle the visibility of the animation's pivots.");
|
||||
ImGui::Checkbox(localize.get(LABEL_ROOT_TRANSFORM), &isRootTransform);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ROOT_TRANSFORM));
|
||||
ImGui::Checkbox(localize.get(LABEL_PIVOTS), &isPivots);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_PIVOTS));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -327,10 +366,10 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginChild("##Helpers Child 2", helpersChildSize))
|
||||
{
|
||||
ImGui::Checkbox("Alt Icons", &isAltIcons);
|
||||
ImGui::SetItemTooltip("Toggle a different appearance of the target icons.");
|
||||
ImGui::Checkbox("Border", &isBorder);
|
||||
ImGui::SetItemTooltip("Toggle the visibility of borders around layers.");
|
||||
ImGui::Checkbox(localize.get(LABEL_ALT_ICONS), &isAltIcons);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ALT_ICONS));
|
||||
ImGui::Checkbox(localize.get(LABEL_BORDER), &isBorder);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_BORDER));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
@@ -592,12 +631,11 @@ namespace anm2ed::imgui
|
||||
{
|
||||
auto layeredOnions = settings.onionskinIsEnabled ? &onionskinSamples : nullptr;
|
||||
|
||||
render(animation, frameTime, {}, 0.0f, layeredOnions,
|
||||
settings.onionskinMode == static_cast<int>(OnionskinMode::INDEX));
|
||||
render(animation, frameTime, {}, 0.0f, layeredOnions, settings.onionskinMode == (int)OnionskinMode::INDEX);
|
||||
|
||||
if (auto overlayAnimation = anm2.animation_get(overlayIndex))
|
||||
render(overlayAnimation, frameTime, {}, 1.0f - math::uint8_to_float(overlayTransparency), layeredOnions,
|
||||
settings.onionskinMode == static_cast<int>(OnionskinMode::INDEX));
|
||||
settings.onionskinMode == (int)OnionskinMode::INDEX);
|
||||
}
|
||||
|
||||
unbind();
|
||||
@@ -692,7 +730,7 @@ namespace anm2ed::imgui
|
||||
if (!frame) break;
|
||||
if (isBegin)
|
||||
{
|
||||
document.snapshot("Frame Position");
|
||||
document.snapshot(localize.get(EDIT_FRAME_POSITION));
|
||||
if (isMouseClicked)
|
||||
{
|
||||
moveOffset = settings.inputIsMoveToolSnapToMouse ? vec2() : mousePos - frame->position;
|
||||
@@ -710,16 +748,16 @@ namespace anm2ed::imgui
|
||||
{
|
||||
if (ImGui::BeginTooltip())
|
||||
{
|
||||
auto positionFormat = math::vec2_format_get(frame->position);
|
||||
auto positionString = std::format("Position: ({}, {})", positionFormat, positionFormat);
|
||||
ImGui::Text(positionString.c_str(), frame->position.x, frame->position.y);
|
||||
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_POSITION),
|
||||
std::make_format_args(frame->position.x, frame->position.y))
|
||||
.c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case tool::SCALE:
|
||||
if (!frame) break;
|
||||
if (isBegin) document.snapshot("Frame Scale");
|
||||
if (isBegin) document.snapshot(localize.get(EDIT_FRAME_SCALE));
|
||||
if (isMouseDown)
|
||||
{
|
||||
frame->scale += vec2(mouseDelta.x, mouseDelta.y);
|
||||
@@ -734,9 +772,9 @@ namespace anm2ed::imgui
|
||||
{
|
||||
if (ImGui::BeginTooltip())
|
||||
{
|
||||
auto scaleFormat = math::vec2_format_get(frame->scale);
|
||||
auto scaleString = std::format("Scale: ({}, {})", scaleFormat, scaleFormat);
|
||||
ImGui::Text(scaleString.c_str(), frame->scale.x, frame->scale.y);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_SCALE), std::make_format_args(frame->scale.x, frame->scale.y))
|
||||
.c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -745,7 +783,7 @@ namespace anm2ed::imgui
|
||||
break;
|
||||
case tool::ROTATE:
|
||||
if (!frame) break;
|
||||
if (isBegin) document.snapshot("Frame Rotation");
|
||||
if (isBegin) document.snapshot(localize.get(EDIT_FRAME_ROTATION));
|
||||
if (isMouseDown) frame->rotation += mouseDelta.y;
|
||||
if (isLeftPressed || isDownPressed) frame->rotation -= step;
|
||||
if (isUpPressed || isRightPressed) frame->rotation += step;
|
||||
@@ -754,9 +792,8 @@ namespace anm2ed::imgui
|
||||
{
|
||||
if (ImGui::BeginTooltip())
|
||||
{
|
||||
auto rotationFormat = math::float_format_get(frame->rotation);
|
||||
auto rotationString = std::format("Rotation: {}", rotationFormat);
|
||||
ImGui::Text(rotationString.c_str(), frame->rotation);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_ROTATION), std::make_format_args(frame->rotation)).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -779,7 +816,7 @@ namespace anm2ed::imgui
|
||||
|
||||
manager.progressPopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(manager.progressPopup.label, &manager.progressPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(manager.progressPopup.label(), &manager.progressPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
if (!animation) return;
|
||||
|
||||
@@ -789,9 +826,9 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::ProgressBar(progress);
|
||||
|
||||
ImGui::Text("Once recording is complete, rendering may take some time.\nPlease be patient...");
|
||||
ImGui::TextUnformatted(localize.get(TEXT_RECORDING_PROGRESS));
|
||||
|
||||
if (ImGui::Button("Cancel", ImVec2(ImGui::GetContentRegionAvail().x, 0)))
|
||||
if (ImGui::Button(localize.get(BASIC_CANCEL), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
|
||||
{
|
||||
renderFrames.clear();
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "animations.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <format>
|
||||
#include <ranges>
|
||||
|
||||
#include "log.h"
|
||||
#include "strings.h"
|
||||
#include "toast.h"
|
||||
#include "vector_.h"
|
||||
|
||||
@@ -40,7 +43,7 @@ namespace anm2ed::imgui
|
||||
}
|
||||
};
|
||||
|
||||
if (ImGui::Begin("Animations", &settings.windowIsAnimations))
|
||||
if (ImGui::Begin(localize.get(LABEL_ANIMATIONS_WINDOW), &settings.windowIsAnimations))
|
||||
{
|
||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||
reference = {};
|
||||
@@ -75,7 +78,7 @@ namespace anm2ed::imgui
|
||||
document.frames.clear();
|
||||
|
||||
if (renameState == RENAME_BEGIN)
|
||||
document.snapshot("Rename Animation");
|
||||
document.snapshot(localize.get(SNAPSHOT_RENAME_ANIMATION));
|
||||
else if (renameState == RENAME_FINISHED)
|
||||
{
|
||||
if (anm2.animations.items.size() == 1) anm2.animations.defaultAnimation = animation.name;
|
||||
@@ -97,10 +100,17 @@ namespace anm2ed::imgui
|
||||
ImGui::TextUnformatted(animation.name.c_str());
|
||||
ImGui::PopFont();
|
||||
|
||||
if (isDefault) ImGui::TextUnformatted("(Default Animation)");
|
||||
if (isDefault)
|
||||
{
|
||||
ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE);
|
||||
ImGui::TextUnformatted(localize.get(BASIC_DEFAULT));
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
ImGui::Text("Length: %d", animation.frameNum);
|
||||
ImGui::Text("Loop: %s", animation.isLoop ? "true" : "false");
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_LENGTH), std::make_format_args(animation.frameNum)).c_str());
|
||||
auto loopLabel = animation.isLoop ? localize.get(BASIC_YES) : localize.get(BASIC_NO);
|
||||
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_LOOP), std::make_format_args(loopLabel)).c_str());
|
||||
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
@@ -124,7 +134,7 @@ namespace anm2ed::imgui
|
||||
auto payloadCount = payload->DataSize / sizeof(int);
|
||||
std::vector<int> indices(payloadIndices, payloadIndices + payloadCount);
|
||||
std::sort(indices.begin(), indices.end());
|
||||
DOCUMENT_EDIT(document, "Move Animation(s)", Document::ANIMATIONS,
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_MOVE_ANIMATIONS), Document::ANIMATIONS,
|
||||
selection = vector::move_indices(anm2.animations.items, indices, i));
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
@@ -151,7 +161,7 @@ namespace anm2ed::imgui
|
||||
auto cut = [&]()
|
||||
{
|
||||
copy();
|
||||
DOCUMENT_EDIT(document, "Cut Animation(s)", Document::ANIMATIONS, animations_remove());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_CUT_ANIMATIONS), Document::ANIMATIONS, animations_remove());
|
||||
};
|
||||
|
||||
auto paste = [&]()
|
||||
@@ -163,13 +173,18 @@ namespace anm2ed::imgui
|
||||
auto start = selection.empty() ? anm2.animations.items.size() : *selection.rbegin() + 1;
|
||||
std::set<int> indices{};
|
||||
std::string errorString{};
|
||||
if (anm2.animations_deserialize(clipboardText, start, indices, &errorString))
|
||||
selection = indices;
|
||||
else
|
||||
toasts.error(std::format("Failed to deserialize animation(s): {}", errorString));
|
||||
if (anm2.animations_deserialize(clipboardText, start, indices, &errorString))
|
||||
selection = indices;
|
||||
else
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_ANIMATIONS_FAILED),
|
||||
std::make_format_args(errorString)));
|
||||
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_ANIMATIONS_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(errorString)));
|
||||
}
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Paste Animation(s)", Document::ANIMATIONS, deserialize());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_PASTE_ANIMATIONS), Document::ANIMATIONS, deserialize());
|
||||
};
|
||||
|
||||
if (shortcut(manager.chords[SHORTCUT_CUT], shortcut::FOCUSED)) cut();
|
||||
@@ -178,9 +193,20 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
|
||||
{
|
||||
if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, !selection.empty() || hovered > -1)) cut();
|
||||
if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy();
|
||||
if (ImGui::MenuItem("Paste", settings.shortcutPaste.c_str(), false, !clipboard.is_empty())) paste();
|
||||
if (ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false,
|
||||
!selection.empty() || hovered > -1))
|
||||
{
|
||||
cut();
|
||||
}
|
||||
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
|
||||
!selection.empty() || hovered > -1))
|
||||
{
|
||||
copy();
|
||||
}
|
||||
if (ImGui::MenuItem(localize.get(BASIC_PASTE), settings.shortcutPaste.c_str(), false, !clipboard.is_empty()))
|
||||
{
|
||||
paste();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
@@ -189,7 +215,7 @@ namespace anm2ed::imgui
|
||||
auto widgetSize = widget_size_with_row_get(5);
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_ADD]);
|
||||
if (ImGui::Button("Add", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize))
|
||||
{
|
||||
auto add = [&]()
|
||||
{
|
||||
@@ -219,16 +245,16 @@ namespace anm2ed::imgui
|
||||
newAnimationSelectedIndex = index;
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Add Animation", Document::ANIMATIONS, add());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_ANIMATION), Document::ANIMATIONS, add());
|
||||
}
|
||||
set_item_tooltip_shortcut("Add a new animation.", settings.shortcutAdd);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_ANIMATION), settings.shortcutAdd);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(selection.empty());
|
||||
{
|
||||
shortcut(manager.chords[SHORTCUT_DUPLICATE]);
|
||||
if (ImGui::Button("Duplicate", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_DUPLICATE), widgetSize))
|
||||
{
|
||||
auto duplicate = [&]()
|
||||
{
|
||||
@@ -242,9 +268,9 @@ namespace anm2ed::imgui
|
||||
}
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Duplicate Animation(s)", Document::ANIMATIONS, duplicate());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_DUPLICATE_ANIMATIONS), Document::ANIMATIONS, duplicate());
|
||||
}
|
||||
set_item_tooltip_shortcut("Duplicate the selected animation(s).", settings.shortcutDuplicate);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_DUPLICATE_ANIMATION), settings.shortcutDuplicate);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -274,12 +300,12 @@ namespace anm2ed::imgui
|
||||
reference = {merged};
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Merge Animations", Document::ANIMATIONS, merge_quick())
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_MERGE_ANIMATIONS), Document::ANIMATIONS, merge_quick())
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(selection.size() != 1);
|
||||
{
|
||||
if (ImGui::Button("Merge", widgetSize))
|
||||
if (ImGui::Button(localize.get(LABEL_MERGE), widgetSize))
|
||||
{
|
||||
mergePopup.open();
|
||||
mergeSelection.clear();
|
||||
@@ -287,34 +313,32 @@ namespace anm2ed::imgui
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
set_item_tooltip_shortcut("Open the merge popup.\nUsing the shortcut will merge the animations with\nthe last "
|
||||
"configured merge settings.",
|
||||
settings.shortcutMerge);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_OPEN_MERGE_POPUP), settings.shortcutMerge);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_REMOVE]);
|
||||
if (ImGui::Button("Remove", widgetSize))
|
||||
DOCUMENT_EDIT(document, "Remove Animation(s)", Document::ANIMATIONS, animations_remove());
|
||||
set_item_tooltip_shortcut("Remove the selected animation(s).", settings.shortcutRemove);
|
||||
if (ImGui::Button(localize.get(BASIC_REMOVE), widgetSize))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_ANIMATIONS), Document::ANIMATIONS, animations_remove());
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_ANIMATION), settings.shortcutRemove);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_DEFAULT]);
|
||||
ImGui::BeginDisabled(selection.size() != 1);
|
||||
if (ImGui::Button("Default", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_DEFAULT), widgetSize))
|
||||
{
|
||||
DOCUMENT_EDIT(document, "Default Animation", Document::ANIMATIONS,
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_DEFAULT_ANIMATION), Document::ANIMATIONS,
|
||||
anm2.animations.defaultAnimation = anm2.animations.items[*selection.begin()].name);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
set_item_tooltip_shortcut("Set the selected animation as the default.", settings.shortcutDefault);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_SET_DEFAULT_ANIMATION), settings.shortcutDefault);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
mergePopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(mergePopup.label, &mergePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(mergePopup.label(), &mergePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
auto merge_close = [&]()
|
||||
{
|
||||
@@ -332,7 +356,7 @@ namespace anm2ed::imgui
|
||||
ImVec2(0, ImGui::GetContentRegionAvail().y -
|
||||
(optionsSize.y + deleteAfterSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 3));
|
||||
|
||||
if (ImGui::BeginChild("Animations", animationsSize, ImGuiChildFlags_Borders))
|
||||
if (ImGui::BeginChild(localize.get(LABEL_ANIMATIONS_CHILD), animationsSize, ImGuiChildFlags_Borders))
|
||||
{
|
||||
mergeSelection.start(anm2.animations.items.size());
|
||||
|
||||
@@ -354,37 +378,37 @@ namespace anm2ed::imgui
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
if (ImGui::BeginChild("Merge Options", optionsSize, ImGuiChildFlags_Borders))
|
||||
if (ImGui::BeginChild("##Merge Options", optionsSize, ImGuiChildFlags_Borders))
|
||||
{
|
||||
auto size = ImVec2(optionsSize.x * 0.5f, optionsSize.y - ImGui::GetStyle().WindowPadding.y * 2);
|
||||
|
||||
if (ImGui::BeginChild("Merge Options 1", size))
|
||||
if (ImGui::BeginChild("##Merge Options 1", size))
|
||||
{
|
||||
ImGui::RadioButton("Append Frames", &type, merge::APPEND);
|
||||
ImGui::RadioButton("Prepend Frames", &type, merge::PREPEND);
|
||||
ImGui::RadioButton(localize.get(LABEL_APPEND_FRAMES), &type, merge::APPEND);
|
||||
ImGui::RadioButton(localize.get(LABEL_PREPEND_FRAMES), &type, merge::PREPEND);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::BeginChild("Merge Options 2", size))
|
||||
if (ImGui::BeginChild("##Merge Options 2", size))
|
||||
{
|
||||
ImGui::RadioButton("Replace Frames", &type, merge::REPLACE);
|
||||
ImGui::RadioButton("Ignore Frames", &type, merge::IGNORE);
|
||||
ImGui::RadioButton(localize.get(LABEL_REPLACE_FRAMES), &type, merge::REPLACE);
|
||||
ImGui::RadioButton(localize.get(LABEL_IGNORE_FRAMES), &type, merge::IGNORE);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
if (ImGui::BeginChild("Merge Delete After", deleteAfterSize, ImGuiChildFlags_Borders))
|
||||
ImGui::Checkbox("Delete Animations After", &isDeleteAnimationsAfter);
|
||||
if (ImGui::BeginChild("##Merge Delete After", deleteAfterSize, ImGuiChildFlags_Borders))
|
||||
ImGui::Checkbox(localize.get(LABEL_DELETE_ANIMATIONS_AFTER), &isDeleteAnimationsAfter);
|
||||
ImGui::EndChild();
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
ImGui::BeginDisabled(mergeSelection.empty());
|
||||
{
|
||||
if (ImGui::Button("Merge", widgetSize))
|
||||
if (ImGui::Button(localize.get(LABEL_MERGE), widgetSize))
|
||||
{
|
||||
auto merge = [&]()
|
||||
{
|
||||
@@ -396,13 +420,13 @@ namespace anm2ed::imgui
|
||||
reference = {merged};
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Merge Animations", Document::ANIMATIONS, merge());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_MERGE_ANIMATIONS), Document::ANIMATIONS, merge());
|
||||
merge_close();
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Close", widgetSize)) merge_close();
|
||||
if (ImGui::Button(localize.get(LABEL_CLOSE), widgetSize)) merge_close();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
#include "manager.h"
|
||||
#include "resources.h"
|
||||
#include "settings.h"
|
||||
#include "strings.h"
|
||||
|
||||
namespace anm2ed::imgui
|
||||
{
|
||||
class Animations
|
||||
{
|
||||
PopupHelper mergePopup{PopupHelper("Merge Animations")};
|
||||
PopupHelper mergePopup{PopupHelper(LABEL_ANIMATIONS_MERGE_POPUP)};
|
||||
int newAnimationSelectedIndex{-1};
|
||||
RenameState renameState{RENAME_SELECTABLE};
|
||||
|
||||
|
||||
+25
-16
@@ -2,7 +2,9 @@
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "log.h"
|
||||
#include "map_.h"
|
||||
#include "strings.h"
|
||||
#include "toast.h"
|
||||
|
||||
using namespace anm2ed::util;
|
||||
@@ -22,7 +24,7 @@ namespace anm2ed::imgui
|
||||
|
||||
hovered = -1;
|
||||
|
||||
if (ImGui::Begin("Events", &settings.windowIsEvents))
|
||||
if (ImGui::Begin(localize.get(LABEL_EVENTS_WINDOW), &settings.windowIsEvents))
|
||||
{
|
||||
auto childSize = size_without_footer_get();
|
||||
|
||||
@@ -41,7 +43,7 @@ namespace anm2ed::imgui
|
||||
event.name, selection.contains(id), ImGuiSelectableFlags_None, renameState))
|
||||
{
|
||||
if (renameState == RENAME_BEGIN)
|
||||
document.snapshot("Rename Event");
|
||||
document.snapshot(localize.get(EDIT_RENAME_EVENT));
|
||||
else if (renameState == RENAME_FINISHED)
|
||||
document.change(Document::EVENTS);
|
||||
}
|
||||
@@ -58,6 +60,7 @@ namespace anm2ed::imgui
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
|
||||
ImGui::TextUnformatted(event.name.c_str());
|
||||
ImGui::PopFont();
|
||||
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_ID), std::make_format_args(id)).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopID();
|
||||
@@ -81,11 +84,16 @@ namespace anm2ed::imgui
|
||||
auto paste = [&](merge::Type type)
|
||||
{
|
||||
std::string errorString{};
|
||||
document.snapshot("Paste Event(s)");
|
||||
document.snapshot(localize.get(EDIT_PASTE_EVENTS));
|
||||
if (anm2.events_deserialize(clipboard.get(), type, &errorString))
|
||||
document.change(Document::EVENTS);
|
||||
else
|
||||
toasts.error(std::format("Failed to deserialize event(s): {}", errorString));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_EVENTS_FAILED),
|
||||
std::make_format_args(errorString)));
|
||||
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_EVENTS_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(errorString)));
|
||||
}
|
||||
};
|
||||
|
||||
if (shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
|
||||
@@ -93,13 +101,15 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
|
||||
{
|
||||
ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false);
|
||||
if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy();
|
||||
ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, false);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
|
||||
!selection.empty() || hovered > -1))
|
||||
copy();
|
||||
|
||||
if (ImGui::BeginMenu("Paste", !clipboard.is_empty()))
|
||||
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
|
||||
{
|
||||
if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem("Replace")) paste(merge::REPLACE);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -112,7 +122,7 @@ namespace anm2ed::imgui
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_ADD]);
|
||||
if (ImGui::Button("Add", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize))
|
||||
{
|
||||
auto add = [&]()
|
||||
{
|
||||
@@ -123,14 +133,14 @@ namespace anm2ed::imgui
|
||||
newEventId = id;
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Add Event", Document::EVENTS, add());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_EVENT), Document::EVENTS, add());
|
||||
}
|
||||
set_item_tooltip_shortcut("Add an event.", settings.shortcutAdd);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_EVENT), settings.shortcutAdd);
|
||||
ImGui::SameLine();
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_REMOVE]);
|
||||
ImGui::BeginDisabled(unused.empty());
|
||||
if (ImGui::Button("Remove Unused", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize))
|
||||
{
|
||||
auto remove_unused = [&]()
|
||||
{
|
||||
@@ -139,11 +149,10 @@ namespace anm2ed::imgui
|
||||
unused.clear();
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Remove Unused Events", Document::EVENTS, remove_unused());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_EVENTS), Document::EVENTS, remove_unused());
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
set_item_tooltip_shortcut("Remove unused events (i.e., ones not used by any trigger in any animation.)",
|
||||
settings.shortcutRemove);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_EVENTS), settings.shortcutRemove);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "math_.h"
|
||||
#include "strings.h"
|
||||
#include "types.h"
|
||||
|
||||
using namespace anm2ed::util::math;
|
||||
@@ -13,7 +14,7 @@ namespace anm2ed::imgui
|
||||
{
|
||||
void FrameProperties::update(Manager& manager, Settings& settings)
|
||||
{
|
||||
if (ImGui::Begin("Frame Properties", &settings.windowIsFrameProperties))
|
||||
if (ImGui::Begin(localize.get(LABEL_FRAME_PROPERTIES_WINDOW), &settings.windowIsFrameProperties))
|
||||
{
|
||||
auto& document = *manager.get();
|
||||
auto& frames = document.frames.selection;
|
||||
@@ -28,103 +29,117 @@ namespace anm2ed::imgui
|
||||
{
|
||||
if (type == anm2::TRIGGER)
|
||||
{
|
||||
if (combo_negative_one_indexed("Event", frame ? &useFrame.eventID : &dummy_value_negative<int>(),
|
||||
if (combo_negative_one_indexed(localize.get(BASIC_EVENT),
|
||||
frame ? &useFrame.eventID : &dummy_value_negative<int>(),
|
||||
document.event.labels))
|
||||
DOCUMENT_EDIT(document, "Trigger Event", Document::FRAMES, frame->eventID = useFrame.eventID);
|
||||
ImGui::SetItemTooltip("Change the event this trigger uses.");
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_TRIGGER_EVENT), Document::FRAMES,
|
||||
frame->eventID = useFrame.eventID);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_TRIGGER_EVENT));
|
||||
|
||||
if (combo_negative_one_indexed("Sound", frame ? &useFrame.soundID : &dummy_value_negative<int>(),
|
||||
if (combo_negative_one_indexed(localize.get(BASIC_SOUND),
|
||||
frame ? &useFrame.soundID : &dummy_value_negative<int>(),
|
||||
document.sound.labels))
|
||||
DOCUMENT_EDIT(document, "Trigger Sound", Document::FRAMES, frame->soundID = useFrame.soundID);
|
||||
ImGui::SetItemTooltip("Change the sound this trigger uses.");
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_TRIGGER_SOUND), Document::FRAMES,
|
||||
frame->soundID = useFrame.soundID);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_TRIGGER_SOUND));
|
||||
|
||||
if (ImGui::InputInt("At Frame", frame ? &useFrame.atFrame : &dummy_value<int>(), STEP, STEP_FAST,
|
||||
!frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0))
|
||||
DOCUMENT_EDIT(document, "Trigger At Frame", Document::FRAMES, frame->atFrame = useFrame.atFrame);
|
||||
ImGui::SetItemTooltip("Change the frame the trigger will be activated at.");
|
||||
if (ImGui::InputInt(localize.get(BASIC_AT_FRAME), frame ? &useFrame.atFrame : &dummy_value<int>(), STEP,
|
||||
STEP_FAST, !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_TRIGGER_AT_FRAME), Document::FRAMES,
|
||||
frame->atFrame = useFrame.atFrame);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_TRIGGER_AT_FRAME));
|
||||
|
||||
if (ImGui::Checkbox("Visible", frame ? &useFrame.isVisible : &dummy_value<bool>()))
|
||||
DOCUMENT_EDIT(document, "Trigger Visibility", Document::FRAMES, frame->isVisible = useFrame.isVisible);
|
||||
ImGui::SetItemTooltip("Toggle the trigger's visibility.");
|
||||
if (ImGui::Checkbox(localize.get(BASIC_VISIBLE), frame ? &useFrame.isVisible : &dummy_value<bool>()))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_TRIGGER_VISIBILITY), Document::FRAMES,
|
||||
frame->isVisible = useFrame.isVisible);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_TRIGGER_VISIBILITY));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_);
|
||||
{
|
||||
if (ImGui::InputFloat2("Crop", frame ? value_ptr(useFrame.crop) : &dummy_value<float>(),
|
||||
if (ImGui::InputFloat2(localize.get(BASIC_CROP), frame ? value_ptr(useFrame.crop) : &dummy_value<float>(),
|
||||
frame ? vec2_format_get(useFrame.crop) : ""))
|
||||
DOCUMENT_EDIT(document, "Frame Crop", Document::FRAMES, frame->crop = useFrame.crop);
|
||||
ImGui::SetItemTooltip("Change the crop position the frame uses.");
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_CROP), Document::FRAMES, frame->crop = useFrame.crop);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CROP));
|
||||
|
||||
if (ImGui::InputFloat2("Size", frame ? value_ptr(useFrame.size) : &dummy_value<float>(),
|
||||
if (ImGui::InputFloat2(localize.get(BASIC_SIZE), frame ? value_ptr(useFrame.size) : &dummy_value<float>(),
|
||||
frame ? vec2_format_get(useFrame.size) : ""))
|
||||
DOCUMENT_EDIT(document, "Frame Size", Document::FRAMES, frame->size = useFrame.size);
|
||||
ImGui::SetItemTooltip("Change the size of the crop the frame uses.");
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_SIZE), Document::FRAMES, frame->size = useFrame.size);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SIZE));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::InputFloat2("Position", frame ? value_ptr(useFrame.position) : &dummy_value<float>(),
|
||||
if (ImGui::InputFloat2(localize.get(BASIC_POSITION),
|
||||
frame ? value_ptr(useFrame.position) : &dummy_value<float>(),
|
||||
frame ? vec2_format_get(useFrame.position) : ""))
|
||||
DOCUMENT_EDIT(document, "Frame Position", Document::FRAMES, frame->position = useFrame.position);
|
||||
ImGui::SetItemTooltip("Change the position of the frame.");
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_POSITION), Document::FRAMES,
|
||||
frame->position = useFrame.position);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_POSITION));
|
||||
|
||||
ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_);
|
||||
{
|
||||
if (ImGui::InputFloat2("Pivot", frame ? value_ptr(useFrame.pivot) : &dummy_value<float>(),
|
||||
if (ImGui::InputFloat2(localize.get(BASIC_PIVOT),
|
||||
frame ? value_ptr(useFrame.pivot) : &dummy_value<float>(),
|
||||
frame ? vec2_format_get(useFrame.pivot) : ""))
|
||||
DOCUMENT_EDIT(document, "Frame Pivot", Document::FRAMES, frame->pivot = useFrame.pivot);
|
||||
ImGui::SetItemTooltip("Change the pivot of the frame; i.e., where it is centered.");
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_PIVOT), Document::FRAMES,
|
||||
frame->pivot = useFrame.pivot);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_PIVOT));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::InputFloat2("Scale", frame ? value_ptr(useFrame.scale) : &dummy_value<float>(),
|
||||
if (ImGui::InputFloat2(localize.get(BASIC_SCALE), frame ? value_ptr(useFrame.scale) : &dummy_value<float>(),
|
||||
frame ? vec2_format_get(useFrame.scale) : ""))
|
||||
DOCUMENT_EDIT(document, "Frame Scale", Document::FRAMES, frame->scale = useFrame.scale);
|
||||
ImGui::SetItemTooltip("Change the scale of the frame, in percent.");
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_SCALE), Document::FRAMES, frame->scale = useFrame.scale);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SCALE));
|
||||
|
||||
if (ImGui::InputFloat("Rotation", frame ? &useFrame.rotation : &dummy_value<float>(), STEP, STEP_FAST,
|
||||
frame ? float_format_get(useFrame.rotation) : ""))
|
||||
DOCUMENT_EDIT(document, "Frame Rotation", Document::FRAMES, frame->rotation = useFrame.rotation);
|
||||
ImGui::SetItemTooltip("Change the rotation of the frame.");
|
||||
if (ImGui::InputFloat(localize.get(BASIC_ROTATION), frame ? &useFrame.rotation : &dummy_value<float>(),
|
||||
STEP, STEP_FAST, frame ? float_format_get(useFrame.rotation) : ""))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_ROTATION), Document::FRAMES,
|
||||
frame->rotation = useFrame.rotation);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ROTATION));
|
||||
|
||||
if (input_int_range("Duration", frame ? useFrame.duration : dummy_value<int>(),
|
||||
if (input_int_range(localize.get(BASIC_DURATION), frame ? useFrame.duration : dummy_value<int>(),
|
||||
frame ? anm2::FRAME_DURATION_MIN : 0, anm2::FRAME_DURATION_MAX, STEP, STEP_FAST,
|
||||
!frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0))
|
||||
DOCUMENT_EDIT(document, "Frame Duration", Document::FRAMES, frame->duration = useFrame.duration);
|
||||
ImGui::SetItemTooltip("Change how long the frame lasts.");
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_DURATION), Document::FRAMES,
|
||||
frame->duration = useFrame.duration);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_DURATION));
|
||||
|
||||
if (ImGui::ColorEdit4("Tint", frame ? value_ptr(useFrame.tint) : &dummy_value<float>()))
|
||||
DOCUMENT_EDIT(document, "Frame Tint", Document::FRAMES, frame->tint = useFrame.tint);
|
||||
ImGui::SetItemTooltip("Change the tint of the frame.");
|
||||
if (ImGui::ColorEdit4(localize.get(BASIC_TINT), frame ? value_ptr(useFrame.tint) : &dummy_value<float>()))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_TINT), Document::FRAMES, frame->tint = useFrame.tint);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_TINT));
|
||||
|
||||
if (ImGui::ColorEdit3("Color Offset", frame ? value_ptr(useFrame.colorOffset) : &dummy_value<float>()))
|
||||
DOCUMENT_EDIT(document, "Frame Color Offset", Document::FRAMES,
|
||||
if (ImGui::ColorEdit3(localize.get(BASIC_COLOR_OFFSET),
|
||||
frame ? value_ptr(useFrame.colorOffset) : &dummy_value<float>()))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_COLOR_OFFSET), Document::FRAMES,
|
||||
frame->colorOffset = useFrame.colorOffset);
|
||||
ImGui::SetItemTooltip("Change the color added onto the frame.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_COLOR_OFFSET));
|
||||
|
||||
if (ImGui::Checkbox("Visible", frame ? &useFrame.isVisible : &dummy_value<bool>()))
|
||||
DOCUMENT_EDIT(document, "Frame Visibility", Document::FRAMES, frame->isVisible = useFrame.isVisible);
|
||||
ImGui::SetItemTooltip("Toggle the frame's visibility.");
|
||||
if (ImGui::Checkbox(localize.get(BASIC_VISIBLE), frame ? &useFrame.isVisible : &dummy_value<bool>()))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_VISIBILITY), Document::FRAMES,
|
||||
frame->isVisible = useFrame.isVisible);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_FRAME_VISIBILITY));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Checkbox("Interpolated", frame ? &useFrame.isInterpolated : &dummy_value<bool>()))
|
||||
DOCUMENT_EDIT(document, "Frame Interpolation", Document::FRAMES,
|
||||
if (ImGui::Checkbox(localize.get(BASIC_INTERPOLATED),
|
||||
frame ? &useFrame.isInterpolated : &dummy_value<bool>()))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_INTERPOLATION), Document::FRAMES,
|
||||
frame->isInterpolated = useFrame.isInterpolated);
|
||||
ImGui::SetItemTooltip(
|
||||
"Toggle the frame interpolating; i.e., blending its values into the next frame based on the time.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_FRAME_INTERPOLATION));
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
if (ImGui::Button("Flip X", widgetSize))
|
||||
DOCUMENT_EDIT(document, "Frame Flip X", Document::FRAMES, frame->scale.x = -frame->scale.x);
|
||||
ImGui::SetItemTooltip("%s", "Flip the horizontal scale of the frame, to cheat mirroring the frame "
|
||||
"horizontally.\n(Note: the format does not support mirroring.)");
|
||||
if (ImGui::Button(localize.get(LABEL_FLIP_X), widgetSize))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_FLIP_X), Document::FRAMES,
|
||||
frame->scale.x = -frame->scale.x);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_FLIP_X));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Flip Y", widgetSize))
|
||||
DOCUMENT_EDIT(document, "Frame Flip Y", Document::FRAMES, frame->scale.y = -frame->scale.y);
|
||||
ImGui::SetItemTooltip("%s", "Flip the vertical scale of the frame, to cheat mirroring the frame "
|
||||
"vertically.\n(Note: the format does not support mirroring.)");
|
||||
if (ImGui::Button(localize.get(LABEL_FLIP_Y), widgetSize))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_FLIP_Y), Document::FRAMES,
|
||||
frame->scale.y = -frame->scale.y);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_FLIP_Y));
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
@@ -184,18 +199,18 @@ namespace anm2ed::imgui
|
||||
|
||||
#undef PROPERTIES_WIDGET
|
||||
|
||||
float2_value("##Is Crop", "Crop", isCrop, crop);
|
||||
float2_value("##Is Size", "Size", isSize, size);
|
||||
float2_value("##Is Position", "Position", isPosition, position);
|
||||
float2_value("##Is Pivot", "Pivot", isPivot, pivot);
|
||||
float2_value("##Is Scale", "Scale", isScale, scale);
|
||||
float_value("##Is Rotation", "Rotation", isRotation, rotation);
|
||||
duration_value("##Is Duration", "Duration", isDuration, duration);
|
||||
color4_value("##Is Tint", "Tint", isTint, tint);
|
||||
color3_value("##Is Color Offset", "Color Offset", isColorOffset, colorOffset);
|
||||
bool_value("##Is Visible", "Visible", isVisibleSet, isVisible);
|
||||
float2_value("##Is Crop", localize.get(BASIC_CROP), isCrop, crop);
|
||||
float2_value("##Is Size", localize.get(BASIC_SIZE), isSize, size);
|
||||
float2_value("##Is Position", localize.get(BASIC_POSITION), isPosition, position);
|
||||
float2_value("##Is Pivot", localize.get(BASIC_PIVOT), isPivot, pivot);
|
||||
float2_value("##Is Scale", localize.get(BASIC_SCALE), isScale, scale);
|
||||
float_value("##Is Rotation", localize.get(BASIC_ROTATION), isRotation, rotation);
|
||||
duration_value("##Is Duration", localize.get(BASIC_DURATION), isDuration, duration);
|
||||
color4_value("##Is Tint", localize.get(BASIC_TINT), isTint, tint);
|
||||
color3_value("##Is Color Offset", localize.get(BASIC_COLOR_OFFSET), isColorOffset, colorOffset);
|
||||
bool_value("##Is Visible", localize.get(BASIC_VISIBLE), isVisibleSet, isVisible);
|
||||
ImGui::SameLine();
|
||||
bool_value("##Is Interpolated", "Interpolated", isInterpolatedSet, isInterpolated);
|
||||
bool_value("##Is Interpolated", localize.get(BASIC_INTERPOLATED), isInterpolatedSet, isInterpolated);
|
||||
|
||||
auto frame_change = [&](anm2::ChangeType type)
|
||||
{
|
||||
@@ -212,30 +227,30 @@ namespace anm2ed::imgui
|
||||
if (isVisibleSet) frameChange.isVisible = std::make_optional(isVisible);
|
||||
if (isInterpolatedSet) frameChange.isInterpolated = std::make_optional(isInterpolated);
|
||||
|
||||
DOCUMENT_EDIT(document, "Change Frame Properties", Document::FRAMES,
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_CHANGE_FRAME_PROPERTIES), Document::FRAMES,
|
||||
document.item_get()->frames_change(frameChange, type, *frames.begin(), (int)frames.size()));
|
||||
};
|
||||
|
||||
auto rowOneWidgetSize = widget_size_with_row_get(1);
|
||||
|
||||
if (ImGui::Button("Adjust", rowOneWidgetSize)) frame_change(anm2::ADJUST);
|
||||
ImGui::SetItemTooltip("Set the value of each specified value onto the frame's equivalent.");
|
||||
if (ImGui::Button(localize.get(LABEL_ADJUST), rowOneWidgetSize)) frame_change(anm2::ADJUST);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ADJUST));
|
||||
|
||||
auto rowTwoWidgetSize = widget_size_with_row_get(4);
|
||||
|
||||
if (ImGui::Button("Add", rowTwoWidgetSize)) frame_change(anm2::ADD);
|
||||
ImGui::SetItemTooltip("Add the specified values onto each frame.\n(Boolean values will simply be set.)");
|
||||
if (ImGui::Button(localize.get(BASIC_ADD), rowTwoWidgetSize)) frame_change(anm2::ADD);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ADD_VALUES));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Subtract", rowTwoWidgetSize)) frame_change(anm2::SUBTRACT);
|
||||
ImGui::SetItemTooltip("Subtract the specified values from each frame.\n(Boolean values will simply be set.)");
|
||||
if (ImGui::Button(localize.get(LABEL_SUBTRACT), rowTwoWidgetSize)) frame_change(anm2::SUBTRACT);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SUBTRACT_VALUES));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Multiply", rowTwoWidgetSize)) frame_change(anm2::MULTIPLY);
|
||||
ImGui::SetItemTooltip("Multiply the specified values for each frame.\n(Boolean values will simply be set.)");
|
||||
if (ImGui::Button(localize.get(LABEL_MULTIPLY), rowTwoWidgetSize)) frame_change(anm2::MULTIPLY);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_MULTIPLY_VALUES));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Divide", rowTwoWidgetSize)) frame_change(anm2::DIVIDE);
|
||||
ImGui::SetItemTooltip("Divide the specified values for each frame.\n(Boolean values will simply be set.)");
|
||||
if (ImGui::Button(localize.get(LABEL_DIVIDE), rowTwoWidgetSize)) frame_change(anm2::DIVIDE);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_DIVIDE_VALUES));
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-27
@@ -2,7 +2,9 @@
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "log.h"
|
||||
#include "map_.h"
|
||||
#include "strings.h"
|
||||
#include "toast.h"
|
||||
|
||||
using namespace anm2ed::util;
|
||||
@@ -23,7 +25,7 @@ namespace anm2ed::imgui
|
||||
|
||||
hovered = -1;
|
||||
|
||||
if (ImGui::Begin("Layers", &settings.windowIsLayers))
|
||||
if (ImGui::Begin(localize.get(LABEL_LAYERS_WINDOW), &settings.windowIsLayers))
|
||||
{
|
||||
auto childSize = size_without_footer_get();
|
||||
|
||||
@@ -38,7 +40,10 @@ namespace anm2ed::imgui
|
||||
ImGui::PushID(id);
|
||||
|
||||
ImGui::SetNextItemSelectionUserData(id);
|
||||
ImGui::Selectable(std::format(anm2::LAYER_FORMAT, id, layer.name, layer.spritesheetID).c_str(), isSelected);
|
||||
ImGui::Selectable(
|
||||
std::vformat(localize.get(FORMAT_LAYER), std::make_format_args(id, layer.name, layer.spritesheetID))
|
||||
.c_str(),
|
||||
isSelected);
|
||||
if (newLayerId == id)
|
||||
{
|
||||
ImGui::SetScrollHereY(0.5f);
|
||||
@@ -57,8 +62,9 @@ namespace anm2ed::imgui
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
|
||||
ImGui::TextUnformatted(layer.name.c_str());
|
||||
ImGui::PopFont();
|
||||
ImGui::Text("ID: %d", id);
|
||||
ImGui::Text("Spritesheet ID: %d", layer.spritesheetID);
|
||||
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_ID), std::make_format_args(id)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_SPRITESHEET_ID), std::make_format_args(layer.spritesheetID)).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopID();
|
||||
@@ -82,11 +88,16 @@ namespace anm2ed::imgui
|
||||
auto paste = [&](merge::Type type)
|
||||
{
|
||||
std::string errorString{};
|
||||
document.snapshot("Paste Layer(s)");
|
||||
document.snapshot(localize.get(EDIT_PASTE_LAYERS));
|
||||
if (anm2.layers_deserialize(clipboard.get(), type, &errorString))
|
||||
document.change(Document::NULLS);
|
||||
else
|
||||
toasts.error(std::format("Failed to deserialize layer(s): {}", errorString));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_LAYERS_FAILED),
|
||||
std::make_format_args(errorString)));
|
||||
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_LAYERS_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(errorString)));
|
||||
}
|
||||
};
|
||||
|
||||
if (shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
|
||||
@@ -94,13 +105,15 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
|
||||
{
|
||||
ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false);
|
||||
if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy();
|
||||
ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, false);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
|
||||
!selection.empty() || hovered > -1))
|
||||
copy();
|
||||
|
||||
if (ImGui::BeginMenu("Paste", !clipboard.is_empty()))
|
||||
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
|
||||
{
|
||||
if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem("Replace")) paste(merge::REPLACE);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -113,13 +126,13 @@ namespace anm2ed::imgui
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_ADD]);
|
||||
if (ImGui::Button("Add", widgetSize)) manager.layer_properties_open();
|
||||
set_item_tooltip_shortcut("Add a layer.", settings.shortcutAdd);
|
||||
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) manager.layer_properties_open();
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_LAYER), settings.shortcutAdd);
|
||||
ImGui::SameLine();
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_REMOVE]);
|
||||
ImGui::BeginDisabled(unused.empty());
|
||||
if (ImGui::Button("Remove Unused", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize))
|
||||
{
|
||||
auto remove_unused = [&]()
|
||||
{
|
||||
@@ -128,34 +141,33 @@ namespace anm2ed::imgui
|
||||
unused.clear();
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Remove Unused Layers", Document::LAYERS, remove_unused());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_LAYERS), Document::LAYERS, remove_unused());
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
set_item_tooltip_shortcut("Remove unused layers (i.e., ones not used in any animation.)",
|
||||
settings.shortcutRemove);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_LAYERS), settings.shortcutRemove);
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
manager.layer_properties_trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(propertiesPopup.label(), &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
auto childSize = child_size_get(2);
|
||||
auto& layer = manager.editLayer;
|
||||
|
||||
if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders))
|
||||
if (ImGui::BeginChild("##Child", childSize, ImGuiChildFlags_Borders))
|
||||
{
|
||||
if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere();
|
||||
input_text_string("Name", &layer.name);
|
||||
ImGui::SetItemTooltip("Set the item's name.");
|
||||
combo_negative_one_indexed("Spritesheet", &layer.spritesheetID, document.spritesheet.labels);
|
||||
ImGui::SetItemTooltip("Set the layer item's spritesheet.");
|
||||
input_text_string(localize.get(BASIC_NAME), &layer.name);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ITEM_NAME));
|
||||
combo_negative_one_indexed(localize.get(LABEL_SPRITESHEET), &layer.spritesheetID, document.spritesheet.labels);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LAYER_SPRITESHEET));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize))
|
||||
if (ImGui::Button(reference == -1 ? localize.get(BASIC_ADD) : localize.get(BASIC_CONFIRM), widgetSize))
|
||||
{
|
||||
if (reference == -1)
|
||||
{
|
||||
@@ -167,7 +179,7 @@ namespace anm2ed::imgui
|
||||
newLayerId = id;
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Add Layer", Document::LAYERS, add());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_LAYER), Document::LAYERS, add());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -177,7 +189,7 @@ namespace anm2ed::imgui
|
||||
selection = {reference};
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Set Layer Properties", Document::LAYERS, set());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_SET_LAYER_PROPERTIES), Document::LAYERS, set());
|
||||
}
|
||||
|
||||
manager.layer_properties_close();
|
||||
@@ -185,7 +197,7 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel", widgetSize)) manager.layer_properties_close();
|
||||
if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize)) manager.layer_properties_close();
|
||||
|
||||
manager.layer_properties_end();
|
||||
ImGui::EndPopup();
|
||||
|
||||
+35
-25
@@ -2,7 +2,9 @@
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "log.h"
|
||||
#include "map_.h"
|
||||
#include "strings.h"
|
||||
#include "toast.h"
|
||||
|
||||
using namespace anm2ed::resource;
|
||||
@@ -23,7 +25,7 @@ namespace anm2ed::imgui
|
||||
|
||||
hovered = -1;
|
||||
|
||||
if (ImGui::Begin("Nulls", &settings.windowIsNulls))
|
||||
if (ImGui::Begin(localize.get(LABEL_NULLS_WINDOW), &settings.windowIsNulls))
|
||||
{
|
||||
auto childSize = size_without_footer_get();
|
||||
|
||||
@@ -39,7 +41,8 @@ namespace anm2ed::imgui
|
||||
ImGui::PushID(id);
|
||||
ImGui::SetNextItemSelectionUserData(id);
|
||||
if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE);
|
||||
ImGui::Selectable(std::format(anm2::NULL_FORMAT, id, null.name).c_str(), isSelected);
|
||||
ImGui::Selectable(std::vformat(localize.get(FORMAT_NULL), std::make_format_args(id, null.name)).c_str(),
|
||||
isSelected);
|
||||
if (newNullId == id)
|
||||
{
|
||||
ImGui::SetScrollHereY(0.5f);
|
||||
@@ -58,7 +61,7 @@ namespace anm2ed::imgui
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
|
||||
ImGui::TextUnformatted(null.name.c_str());
|
||||
ImGui::PopFont();
|
||||
ImGui::Text("ID: %d", id);
|
||||
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_ID), std::make_format_args(id)).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopID();
|
||||
@@ -82,11 +85,16 @@ namespace anm2ed::imgui
|
||||
auto paste = [&](merge::Type type)
|
||||
{
|
||||
std::string errorString{};
|
||||
document.snapshot("Paste Null(s)");
|
||||
document.snapshot(localize.get(EDIT_PASTE_NULLS));
|
||||
if (anm2.nulls_deserialize(clipboard.get(), type, &errorString))
|
||||
document.change(Document::NULLS);
|
||||
else
|
||||
toasts.error(std::format("Failed to deserialize null(s): {}", errorString));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_NULLS_FAILED),
|
||||
std::make_format_args(errorString)));
|
||||
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_NULLS_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(errorString)));
|
||||
}
|
||||
};
|
||||
|
||||
if (shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
|
||||
@@ -94,13 +102,15 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
|
||||
{
|
||||
ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false);
|
||||
if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, selection.empty() || hovered > -1)) copy();
|
||||
ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, false);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
|
||||
selection.empty() || hovered > -1))
|
||||
copy();
|
||||
|
||||
if (ImGui::BeginMenu("Paste", !clipboard.is_empty()))
|
||||
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
|
||||
{
|
||||
if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem("Replace")) paste(merge::REPLACE);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -113,13 +123,13 @@ namespace anm2ed::imgui
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_ADD]);
|
||||
if (ImGui::Button("Add", widgetSize)) manager.null_properties_open();
|
||||
set_item_tooltip_shortcut("Add a null.", settings.shortcutAdd);
|
||||
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) manager.null_properties_open();
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_NULL), settings.shortcutAdd);
|
||||
ImGui::SameLine();
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_REMOVE]);
|
||||
ImGui::BeginDisabled(unused.empty());
|
||||
if (ImGui::Button("Remove Unused", widgetSize))
|
||||
if (ImGui::Button(localize.get(LABEL_REMOVE_UNUSED_NULLS), widgetSize))
|
||||
{
|
||||
auto remove_unused = [&]()
|
||||
{
|
||||
@@ -128,34 +138,34 @@ namespace anm2ed::imgui
|
||||
unused.clear();
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Remove Unused Events", Document::EVENTS, remove_unused());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_NULLS), Document::EVENTS, remove_unused());
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
set_item_tooltip_shortcut("Remove unused nulls (i.e., ones not used in any animation.)", settings.shortcutRemove);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_NULLS), settings.shortcutRemove);
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
manager.null_properties_trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(propertiesPopup.label(), &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
auto childSize = child_size_get(2);
|
||||
auto& null = manager.editNull;
|
||||
|
||||
if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders))
|
||||
if (ImGui::BeginChild("##Child", childSize, ImGuiChildFlags_Borders))
|
||||
{
|
||||
if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere();
|
||||
input_text_string("Name", &null.name);
|
||||
ImGui::SetItemTooltip("Set the null's name.");
|
||||
input_text_string(localize.get(BASIC_NAME), &null.name);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_NULL_NAME));
|
||||
|
||||
ImGui::Checkbox("Rect", &null.isShowRect);
|
||||
ImGui::SetItemTooltip("The null will have a rectangle show around it.");
|
||||
ImGui::Checkbox(localize.get(LABEL_RECT), &null.isShowRect);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_NULL_RECT));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize))
|
||||
if (ImGui::Button(reference == -1 ? localize.get(BASIC_ADD) : localize.get(BASIC_CONFIRM), widgetSize))
|
||||
{
|
||||
if (reference == -1)
|
||||
{
|
||||
@@ -167,7 +177,7 @@ namespace anm2ed::imgui
|
||||
newNullId = id;
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Add Null", Document::NULLS, add());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_NULL), Document::NULLS, add());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -177,7 +187,7 @@ namespace anm2ed::imgui
|
||||
selection = {reference};
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Set Null Properties", Document::NULLS, set());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_SET_NULL_PROPERTIES), Document::NULLS, set());
|
||||
}
|
||||
|
||||
manager.null_properties_close();
|
||||
@@ -185,7 +195,7 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel", widgetSize)) manager.null_properties_close();
|
||||
if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize)) manager.null_properties_close();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "imgui_.h"
|
||||
#include "strings.h"
|
||||
|
||||
using namespace anm2ed::types;
|
||||
using namespace glm;
|
||||
@@ -20,30 +21,30 @@ namespace anm2ed::imgui
|
||||
auto& afterColor = settings.onionskinAfterColor;
|
||||
auto& mode = settings.onionskinMode;
|
||||
|
||||
if (ImGui::Begin("Onionskin", &settings.windowIsOnionskin))
|
||||
if (ImGui::Begin(localize.get(LABEL_ONIONSKIN_WINDOW), &settings.windowIsOnionskin))
|
||||
{
|
||||
auto configure_widgets = [&](const char* separator, int& frames, vec3& color)
|
||||
{
|
||||
ImGui::PushID(separator);
|
||||
ImGui::SeparatorText(separator);
|
||||
input_int_range("Frames", frames, 0, FRAMES_MAX);
|
||||
ImGui::SetItemTooltip("Change the amount of frames this onionskin will use.");
|
||||
ImGui::ColorEdit3("Color", value_ptr(color));
|
||||
ImGui::SetItemTooltip("Change the color of the frames this onionskin will use.");
|
||||
input_int_range(localize.get(BASIC_FRAMES), frames, 0, FRAMES_MAX);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ONIONSKIN_FRAMES));
|
||||
ImGui::ColorEdit3(localize.get(BASIC_COLOR), value_ptr(color));
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ONIONSKIN_COLOR));
|
||||
ImGui::PopID();
|
||||
};
|
||||
|
||||
ImGui::Checkbox("Enabled", &isEnabled);
|
||||
set_item_tooltip_shortcut("Toggle onionskinning.", settings.shortcutOnionskin);
|
||||
ImGui::Checkbox(localize.get(BASIC_ENABLED), &isEnabled);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_ONIONSKIN_ENABLED), settings.shortcutOnionskin);
|
||||
|
||||
configure_widgets("Before", beforeCount, beforeColor);
|
||||
configure_widgets("After", afterCount, afterColor);
|
||||
ImGui::SeparatorText("Mode");
|
||||
ImGui::RadioButton("Time", &mode, (int)OnionskinMode::TIME);
|
||||
ImGui::SetItemTooltip("The onionskinned frames will be based on frame time.");
|
||||
configure_widgets(localize.get(BASIC_BEFORE), beforeCount, beforeColor);
|
||||
configure_widgets(localize.get(BASIC_AFTER), afterCount, afterColor);
|
||||
ImGui::SeparatorText(localize.get(BASIC_MODE));
|
||||
ImGui::RadioButton(localize.get(BASIC_TIME), &mode, (int)OnionskinMode::TIME);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ONIONSKIN_TIME));
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("Index", &mode, (int)OnionskinMode::INDEX);
|
||||
ImGui::SetItemTooltip("The onionskinned frames will be based on frame index.");
|
||||
ImGui::RadioButton(localize.get(BASIC_INDEX), &mode, (int)OnionskinMode::INDEX);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ONIONSKIN_INDEX));
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
|
||||
+28
-13
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "log.h"
|
||||
#include "strings.h"
|
||||
#include "toast.h"
|
||||
|
||||
@@ -22,7 +23,7 @@ namespace anm2ed::imgui
|
||||
|
||||
hovered = -1;
|
||||
|
||||
if (ImGui::Begin(localize.get(LABEL_SOUNDS), &settings.windowIsSounds))
|
||||
if (ImGui::Begin(localize.get(LABEL_SOUNDS_WINDOW), &settings.windowIsSounds))
|
||||
{
|
||||
auto childSize = imgui::size_without_footer_get();
|
||||
|
||||
@@ -57,6 +58,11 @@ namespace anm2ed::imgui
|
||||
ImGui::PopFont();
|
||||
ImGui::Text("%s: %d", localize.get(BASIC_ID), id);
|
||||
ImGui::Text("%s", localize.get(TOOLTIP_SOUNDS_PLAY));
|
||||
if (!sound.is_valid())
|
||||
{
|
||||
ImGui::Spacing();
|
||||
ImGui::TextWrapped("%s", localize.get(TOOLTIP_SOUND_INVALID));
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopID();
|
||||
@@ -84,7 +90,11 @@ namespace anm2ed::imgui
|
||||
if (anm2.sounds_deserialize(clipboard.get(), document.directory_get().string(), type, &errorString))
|
||||
document.change(Document::SOUNDS);
|
||||
else
|
||||
toasts.error(std::format("{}: {}", localize.get(TOAST_SOUNDS_PASTE_ERROR), errorString));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_SOUNDS_DESERIALIZE_ERROR), std::make_format_args(errorString)));
|
||||
logger.error(std::vformat(localize.get(TOAST_SOUNDS_DESERIALIZE_ERROR, anm2ed::ENGLISH),
|
||||
std::make_format_args(errorString)));
|
||||
}
|
||||
};
|
||||
|
||||
if (imgui::shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
|
||||
@@ -99,8 +109,8 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
|
||||
{
|
||||
if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem("Replace")) paste(merge::REPLACE);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -113,13 +123,13 @@ namespace anm2ed::imgui
|
||||
auto widgetSize = imgui::widget_size_with_row_get(2);
|
||||
|
||||
imgui::shortcut(manager.chords[SHORTCUT_ADD]);
|
||||
if (ImGui::Button("Add", widgetSize)) dialog.file_open(dialog::SOUND_OPEN);
|
||||
imgui::set_item_tooltip_shortcut("Add a sound.", settings.shortcutAdd);
|
||||
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize)) dialog.file_open(dialog::SOUND_OPEN);
|
||||
imgui::set_item_tooltip_shortcut(localize.get(TOOLTIP_SOUND_ADD), settings.shortcutAdd);
|
||||
ImGui::SameLine();
|
||||
|
||||
imgui::shortcut(manager.chords[SHORTCUT_REMOVE]);
|
||||
ImGui::BeginDisabled(unused.empty());
|
||||
if (ImGui::Button("Remove Unused", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), widgetSize))
|
||||
{
|
||||
auto remove_unused = [&]()
|
||||
{
|
||||
@@ -128,11 +138,10 @@ namespace anm2ed::imgui
|
||||
unused.clear();
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Remove Unused Sounds", Document::SOUNDS, remove_unused());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_SOUNDS), Document::SOUNDS, remove_unused());
|
||||
};
|
||||
ImGui::EndDisabled();
|
||||
imgui::set_item_tooltip_shortcut("Remove unused sounds (i.e., ones not used in any trigger.)",
|
||||
settings.shortcutRemove);
|
||||
imgui::set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_SOUNDS), settings.shortcutRemove);
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
@@ -145,13 +154,19 @@ namespace anm2ed::imgui
|
||||
{
|
||||
selection = {id};
|
||||
newSoundId = id;
|
||||
toasts.info(std::format("Initialized sound #{}: {}", id, dialog.path));
|
||||
toasts.push(std::vformat(localize.get(TOAST_SOUND_INITIALIZED), std::make_format_args(id, dialog.path)));
|
||||
logger.info(std::vformat(localize.get(TOAST_SOUND_INITIALIZED, anm2ed::ENGLISH),
|
||||
std::make_format_args(id, dialog.path)));
|
||||
}
|
||||
else
|
||||
toasts.error(std::format("Failed to initialize sound: {}", dialog.path));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_SOUND_INITIALIZE_FAILED), std::make_format_args(dialog.path)));
|
||||
logger.error(std::vformat(localize.get(TOAST_SOUND_INITIALIZE_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(dialog.path)));
|
||||
}
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Add Sound", Document::SOUNDS, add());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_ADD_SOUND), Document::SOUNDS, add());
|
||||
|
||||
dialog.reset();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "imgui_.h"
|
||||
#include "imgui_internal.h"
|
||||
#include "math_.h"
|
||||
#include "strings.h"
|
||||
#include "tool.h"
|
||||
#include "types.h"
|
||||
|
||||
@@ -79,7 +80,7 @@ namespace anm2ed::imgui
|
||||
|
||||
auto center_view = [&]() { pan = -size * 0.5f; };
|
||||
|
||||
if (ImGui::Begin("Spritesheet Editor", &settings.windowIsSpritesheetEditor))
|
||||
if (ImGui::Begin(localize.get(LABEL_SPRITESHEET_EDITOR_WINDOW), &settings.windowIsSpritesheetEditor))
|
||||
{
|
||||
|
||||
auto childSize = ImVec2(imgui::row_widget_width_get(3),
|
||||
@@ -87,20 +88,20 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginChild("##Grid Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
ImGui::Checkbox("Grid", &isGrid);
|
||||
ImGui::SetItemTooltip("Toggle the visibility of the grid.");
|
||||
ImGui::Checkbox(localize.get(BASIC_GRID), &isGrid);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GRID_VISIBILITY));
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Snap", &isGridSnap);
|
||||
ImGui::SetItemTooltip("Cropping will snap points to the grid.");
|
||||
ImGui::Checkbox(localize.get(LABEL_SNAP), &isGridSnap);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GRID_SNAP));
|
||||
ImGui::SameLine();
|
||||
ImGui::ColorEdit4("Color", value_ptr(gridColor), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("Change the grid's color.");
|
||||
ImGui::ColorEdit4(localize.get(BASIC_COLOR), value_ptr(gridColor), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GRID_COLOR));
|
||||
|
||||
input_int2_range("Size", gridSize, ivec2(GRID_SIZE_MIN), ivec2(GRID_SIZE_MAX));
|
||||
ImGui::SetItemTooltip("Change the size of all cells in the grid.");
|
||||
input_int2_range(localize.get(BASIC_SIZE), gridSize, ivec2(GRID_SIZE_MIN), ivec2(GRID_SIZE_MAX));
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GRID_SIZE));
|
||||
|
||||
input_int2_range("Offset", gridOffset, ivec2(GRID_OFFSET_MIN), ivec2(GRID_OFFSET_MAX));
|
||||
ImGui::SetItemTooltip("Change the offset of the grid.");
|
||||
input_int2_range(localize.get(BASIC_OFFSET), gridOffset, ivec2(GRID_OFFSET_MIN), ivec2(GRID_OFFSET_MAX));
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GRID_OFFSET));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -108,23 +109,26 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginChild("##View Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
ImGui::InputFloat("Zoom", &zoom, zoomStep, zoomStep, "%.0f%%");
|
||||
ImGui::SetItemTooltip("Change the zoom of the editor.");
|
||||
ImGui::InputFloat(localize.get(BASIC_ZOOM), &zoom, zoomStep, zoomStep, "%.0f%%");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_EDITOR_ZOOM));
|
||||
|
||||
auto widgetSize = ImVec2(imgui::row_widget_width_get(2), 0);
|
||||
|
||||
imgui::shortcut(manager.chords[SHORTCUT_CENTER_VIEW]);
|
||||
if (ImGui::Button("Center View", widgetSize)) center_view();
|
||||
imgui::set_item_tooltip_shortcut("Centers the view.", settings.shortcutCenterView);
|
||||
if (ImGui::Button(localize.get(LABEL_CENTER_VIEW), widgetSize)) center_view();
|
||||
imgui::set_item_tooltip_shortcut(localize.get(TOOLTIP_CENTER_VIEW), settings.shortcutCenterView);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
imgui::shortcut(manager.chords[SHORTCUT_FIT]);
|
||||
if (ImGui::Button("Fit", widgetSize))
|
||||
if (ImGui::Button(localize.get(LABEL_FIT), widgetSize))
|
||||
if (spritesheet) set_to_rect(zoom, pan, {0, 0, spritesheet->texture.size.x, spritesheet->texture.size.y});
|
||||
imgui::set_item_tooltip_shortcut("Set the view to match the extent of the spritesheet.", settings.shortcutFit);
|
||||
imgui::set_item_tooltip_shortcut(localize.get(TOOLTIP_FIT), settings.shortcutFit);
|
||||
|
||||
ImGui::TextUnformatted(std::format(POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y).c_str());
|
||||
auto mousePosInt = ivec2(mousePos);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_POSITION_SPACED), std::make_format_args(mousePosInt.x, mousePosInt.y))
|
||||
.c_str());
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -136,11 +140,16 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginChild("##Background Child 1", subChildSize))
|
||||
{
|
||||
ImGui::ColorEdit3("Background", value_ptr(backgroundColor), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("Change the background color.");
|
||||
ImGui::BeginDisabled(isTransparent);
|
||||
{
|
||||
ImGui::ColorEdit3(localize.get(LABEL_BACKGROUND_COLOR), value_ptr(backgroundColor),
|
||||
ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_BACKGROUND_COLOR));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::Checkbox("Border", &isBorder);
|
||||
ImGui::SetItemTooltip("Toggle a border appearing around the spritesheet.");
|
||||
ImGui::Checkbox(localize.get(LABEL_BORDER), &isBorder);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SPRITESHEET_BORDER));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -148,8 +157,8 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginChild("##Background Child 2", subChildSize))
|
||||
{
|
||||
ImGui::Checkbox("Transparent", &isTransparent);
|
||||
ImGui::SetItemTooltip("Toggle the spritesheet editor being transparent.");
|
||||
ImGui::Checkbox(localize.get(LABEL_TRANSPARENT), &isTransparent);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_TRANSPARENT));
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
@@ -201,10 +210,11 @@ namespace anm2ed::imgui
|
||||
unbind();
|
||||
|
||||
sync_checker_pan();
|
||||
render_checker_background(drawList, min, max, -size * 0.5f - checkerPan, CHECKER_SIZE);
|
||||
if (!isTransparent) drawList->AddRectFilled(min, max, ImGui::GetColorU32(to_imvec4(vec4(backgroundColor, 1.0f))));
|
||||
drawList->AddImage(texture, min, max);
|
||||
ImGui::InvisibleButton("##Spritesheet Editor", to_imvec2(size));
|
||||
if (isTransparent)
|
||||
render_checker_background(drawList, min, max, -size * 0.5f - checkerPan, CHECKER_SIZE);
|
||||
else
|
||||
drawList->AddRectFilled(min, max, ImGui::GetColorU32(to_imvec4(vec4(backgroundColor, 1.0f))));
|
||||
ImGui::Image(texture, to_imvec2(size));
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
@@ -299,7 +309,7 @@ namespace anm2ed::imgui
|
||||
break;
|
||||
case tool::MOVE:
|
||||
if (!frame) break;
|
||||
if (isBegin) document.snapshot("Frame Pivot");
|
||||
if (isBegin) document.snapshot(localize.get(EDIT_FRAME_PIVOT));
|
||||
if (isMouseDown) frame->pivot = vec2(ivec2(mousePos - frame->crop));
|
||||
if (isLeftPressed) frame->pivot.x -= step;
|
||||
if (isRightPressed) frame->pivot.x += step;
|
||||
@@ -310,9 +320,9 @@ namespace anm2ed::imgui
|
||||
{
|
||||
if (ImGui::BeginTooltip())
|
||||
{
|
||||
auto pivotFormat = math::vec2_format_get(frame->pivot);
|
||||
auto pivotString = std::format("Pivot: ({}, {})", pivotFormat, pivotFormat);
|
||||
ImGui::Text(pivotString.c_str(), frame->pivot.x, frame->pivot.y);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_PIVOT), std::make_format_args(frame->pivot.x, frame->pivot.y))
|
||||
.c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -321,7 +331,7 @@ namespace anm2ed::imgui
|
||||
break;
|
||||
case tool::CROP:
|
||||
if (!frame) break;
|
||||
if (isBegin) document.snapshot("Frame Crop");
|
||||
if (isBegin) document.snapshot(localize.get(EDIT_FRAME_CROP));
|
||||
|
||||
if (isMouseClicked)
|
||||
{
|
||||
@@ -358,12 +368,12 @@ namespace anm2ed::imgui
|
||||
}
|
||||
if (ImGui::BeginTooltip())
|
||||
{
|
||||
auto cropFormat = math::vec2_format_get(frame->crop);
|
||||
auto sizeFormat = math::vec2_format_get(frame->size);
|
||||
auto cropString = std::format("Crop: ({}, {})", cropFormat, cropFormat);
|
||||
auto sizeString = std::format("Size: ({}, {})", sizeFormat, sizeFormat);
|
||||
ImGui::Text(cropString.c_str(), frame->crop.x, frame->crop.y);
|
||||
ImGui::Text(sizeString.c_str(), frame->size.x, frame->size.y);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_CROP), std::make_format_args(frame->crop.x, frame->crop.y))
|
||||
.c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_SIZE), std::make_format_args(frame->size.x, frame->size.y))
|
||||
.c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -374,7 +384,8 @@ namespace anm2ed::imgui
|
||||
{
|
||||
if (!spritesheet) break;
|
||||
auto color = useTool == tool::DRAW ? toolColor : vec4();
|
||||
if (isMouseClicked) document.snapshot(useTool == tool::DRAW ? "Draw" : "Erase");
|
||||
if (isMouseClicked)
|
||||
document.snapshot(useTool == tool::DRAW ? localize.get(EDIT_DRAW) : localize.get(EDIT_ERASE));
|
||||
if (isMouseDown) spritesheet->texture.pixel_line(ivec2(previousMousePos), ivec2(mousePos), color);
|
||||
if (isMouseReleased) document.change(Document::SPRITESHEETS);
|
||||
break;
|
||||
|
||||
@@ -2,11 +2,17 @@
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <format>
|
||||
|
||||
#include "log.h"
|
||||
#include "document.h"
|
||||
#include "filesystem_.h"
|
||||
#include "strings.h"
|
||||
#include "toast.h"
|
||||
|
||||
using namespace anm2ed::types;
|
||||
using namespace anm2ed::resource;
|
||||
using namespace anm2ed::util;
|
||||
using namespace glm;
|
||||
|
||||
namespace anm2ed::imgui
|
||||
@@ -23,7 +29,7 @@ namespace anm2ed::imgui
|
||||
|
||||
hovered = -1;
|
||||
|
||||
if (ImGui::Begin("Spritesheets", &settings.windowIsSpritesheets))
|
||||
if (ImGui::Begin(localize.get(LABEL_SPRITESHEETS_WINDOW), &settings.windowIsSpritesheets))
|
||||
{
|
||||
auto style = ImGui::GetStyle();
|
||||
|
||||
@@ -45,11 +51,16 @@ namespace anm2ed::imgui
|
||||
auto paste = [&](merge::Type type)
|
||||
{
|
||||
std::string errorString{};
|
||||
document.snapshot("Paste Spritesheet(s)");
|
||||
if (anm2.spritesheets_deserialize(clipboard.get(), document.directory_get().string(), type, &errorString))
|
||||
document.change(Document::SPRITESHEETS);
|
||||
else
|
||||
toasts.error(std::format("Failed to deserialize spritesheet(s): {}", errorString));
|
||||
document.snapshot(localize.get(EDIT_PASTE_SPRITESHEETS));
|
||||
if (anm2.spritesheets_deserialize(clipboard.get(), document.directory_get().string(), type, &errorString))
|
||||
document.change(Document::SPRITESHEETS);
|
||||
else
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_DESERIALIZE_SPRITESHEETS_FAILED),
|
||||
std::make_format_args(errorString)));
|
||||
logger.error(std::vformat(localize.get(TOAST_DESERIALIZE_SPRITESHEETS_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(errorString)));
|
||||
}
|
||||
};
|
||||
|
||||
if (shortcut(manager.chords[SHORTCUT_COPY], shortcut::FOCUSED)) copy();
|
||||
@@ -59,14 +70,16 @@ namespace anm2ed::imgui
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing);
|
||||
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
|
||||
{
|
||||
ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, true);
|
||||
ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, true);
|
||||
|
||||
if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy();
|
||||
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false,
|
||||
!selection.empty() || hovered > -1))
|
||||
copy();
|
||||
|
||||
if (ImGui::BeginMenu("Paste", !clipboard.is_empty()))
|
||||
if (ImGui::BeginMenu(localize.get(BASIC_PASTE), !clipboard.is_empty()))
|
||||
{
|
||||
if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem("Replace")) paste(merge::REPLACE);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_APPEND), settings.shortcutPaste.c_str())) paste(merge::APPEND);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_REPLACE))) paste(merge::REPLACE);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -99,14 +112,21 @@ namespace anm2ed::imgui
|
||||
auto& texture = isTextureValid ? spritesheet.texture : resources.icons[icon::NONE];
|
||||
auto textureRef = ImTextureRef(texture.id);
|
||||
auto tintColor = !isTextureValid ? ImVec4(1.0f, 0.25f, 0.25f, 1.0f) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
const std::string pathString =
|
||||
spritesheet.path.empty() ? std::string{anm2::NO_PATH} : spritesheet.path.string();
|
||||
const char* pathCStr = pathString.c_str();
|
||||
auto pathString = spritesheet.path.empty() ? std::string{anm2::NO_PATH} : spritesheet.path.string();
|
||||
auto pathCStr = pathString.c_str();
|
||||
|
||||
ImGui::SetNextItemSelectionUserData(id);
|
||||
ImGui::SetNextItemStorageID(id);
|
||||
if (ImGui::Selectable("##Spritesheet Selectable", isSelected, 0, spritesheetChildSize)) reference = id;
|
||||
if (ImGui::IsItemHovered()) hovered = id;
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
filesystem::WorkingDirectory workingDirectory(document.directory_get());
|
||||
dialog.file_explorer_open(spritesheet.path.parent_path().string());
|
||||
}
|
||||
hovered = id;
|
||||
}
|
||||
if (newSpritesheetId == id)
|
||||
{
|
||||
ImGui::SetScrollHereY(0.5f);
|
||||
@@ -150,12 +170,16 @@ namespace anm2ed::imgui
|
||||
ImGui::TextUnformatted(pathCStr);
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::Text("ID: %d", id);
|
||||
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_ID), std::make_format_args(id)).c_str());
|
||||
|
||||
if (!isTextureValid)
|
||||
ImGui::Text("This spritesheet isn't valid!\nLoad an existing, valid texture.");
|
||||
ImGui::TextUnformatted(localize.get(TOOLTIP_SPRITESHEET_INVALID));
|
||||
else
|
||||
ImGui::Text("Size: %d x %d", texture.size.x, texture.size.y);
|
||||
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_TEXTURE_SIZE),
|
||||
std::make_format_args(texture.size.x, texture.size.y))
|
||||
.c_str());
|
||||
|
||||
ImGui::TextUnformatted(localize.get(TEXT_OPEN_DIRECTORY));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -179,7 +203,8 @@ namespace anm2ed::imgui
|
||||
spritesheetChildSize.y - spritesheetChildSize.y / 2 - ImGui::GetTextLineHeight() / 2));
|
||||
|
||||
if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE);
|
||||
ImGui::Text(anm2::SPRITESHEET_FORMAT_C, id, pathCStr);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_SPRITESHEET), std::make_format_args(id, pathCStr)).c_str());
|
||||
if (isReferenced) ImGui::PopFont();
|
||||
|
||||
context_menu();
|
||||
@@ -200,8 +225,8 @@ namespace anm2ed::imgui
|
||||
auto rowOneWidgetSize = widget_size_with_row_get(3);
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_ADD]);
|
||||
if (ImGui::Button("Add", rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_OPEN);
|
||||
set_item_tooltip_shortcut("Add a new spritesheet.", settings.shortcutAdd);
|
||||
if (ImGui::Button(localize.get(BASIC_ADD), rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_OPEN);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_SPRITESHEET), settings.shortcutAdd);
|
||||
|
||||
if (dialog.is_selected(dialog::SPRITESHEET_OPEN))
|
||||
{
|
||||
@@ -214,7 +239,7 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::BeginDisabled(selection.empty());
|
||||
{
|
||||
if (ImGui::Button("Reload", rowOneWidgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_RELOAD), rowOneWidgetSize))
|
||||
{
|
||||
auto reload = [&]()
|
||||
{
|
||||
@@ -222,13 +247,17 @@ namespace anm2ed::imgui
|
||||
{
|
||||
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
|
||||
spritesheet.reload(document.directory_get());
|
||||
toasts.info(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string()));
|
||||
auto pathString = spritesheet.path.string();
|
||||
toasts.push(std::vformat(localize.get(TOAST_RELOAD_SPRITESHEET),
|
||||
std::make_format_args(id, pathString)));
|
||||
logger.info(std::vformat(localize.get(TOAST_RELOAD_SPRITESHEET, anm2ed::ENGLISH),
|
||||
std::make_format_args(id, pathString)));
|
||||
}
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Reload Spritesheet(s)", Document::SPRITESHEETS, reload());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_RELOAD_SPRITESHEETS), Document::SPRITESHEETS, reload());
|
||||
}
|
||||
ImGui::SetItemTooltip("Reloads the selected spritesheets.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_RELOAD_SPRITESHEETS));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -236,8 +265,8 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::BeginDisabled(selection.size() != 1);
|
||||
{
|
||||
if (ImGui::Button("Replace", rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_REPLACE);
|
||||
ImGui::SetItemTooltip("Replace the selected spritesheet with a new one.");
|
||||
if (ImGui::Button(localize.get(BASIC_REPLACE), rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_REPLACE);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_REPLACE_SPRITESHEET));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -248,10 +277,13 @@ namespace anm2ed::imgui
|
||||
auto& id = *selection.begin();
|
||||
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
|
||||
spritesheet = anm2::Spritesheet(document.directory_get().string(), dialog.path);
|
||||
toasts.info(std::format("Replaced spritesheet #{}: {}", id, spritesheet.path.string()));
|
||||
auto pathString = spritesheet.path.string();
|
||||
toasts.push(std::vformat(localize.get(TOAST_REPLACE_SPRITESHEET), std::make_format_args(id, pathString)));
|
||||
logger.info(std::vformat(localize.get(TOAST_REPLACE_SPRITESHEET, anm2ed::ENGLISH),
|
||||
std::make_format_args(id, pathString)));
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Replace Spritesheet", Document::SPRITESHEETS, replace());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_REPLACE_SPRITESHEET), Document::SPRITESHEETS, replace());
|
||||
dialog.reset();
|
||||
}
|
||||
|
||||
@@ -260,23 +292,27 @@ namespace anm2ed::imgui
|
||||
ImGui::BeginDisabled(unused.empty());
|
||||
{
|
||||
shortcut(manager.chords[SHORTCUT_REMOVE]);
|
||||
if (ImGui::Button("Remove Unused", rowTwoWidgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_REMOVE_UNUSED), rowTwoWidgetSize))
|
||||
{
|
||||
auto remove_unused = [&]()
|
||||
{
|
||||
for (auto& id : unused)
|
||||
{
|
||||
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
|
||||
toasts.info(std::format("Removed spritesheet #{}: {}", id, spritesheet.path.string()));
|
||||
auto pathString = spritesheet.path.string();
|
||||
toasts.push(std::vformat(localize.get(TOAST_REMOVE_SPRITESHEET),
|
||||
std::make_format_args(id, pathString)));
|
||||
logger.info(std::vformat(localize.get(TOAST_REMOVE_SPRITESHEET, anm2ed::ENGLISH),
|
||||
std::make_format_args(id, pathString)));
|
||||
anm2.content.spritesheets.erase(id);
|
||||
}
|
||||
unused.clear();
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Remove Unused Spritesheets", Document::SPRITESHEETS, remove_unused());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_UNUSED_SPRITESHEETS), Document::SPRITESHEETS,
|
||||
remove_unused());
|
||||
}
|
||||
set_item_tooltip_shortcut("Remove all unused spritesheets (i.e., not used in any layer.).",
|
||||
settings.shortcutRemove);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_UNUSED_SPRITESHEETS), settings.shortcutRemove);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -284,20 +320,31 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::BeginDisabled(selection.empty());
|
||||
{
|
||||
if (ImGui::Button("Save", rowTwoWidgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_SAVE), rowTwoWidgetSize))
|
||||
{
|
||||
for (auto& id : selection)
|
||||
{
|
||||
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
|
||||
auto pathString = spritesheet.path.string();
|
||||
if (spritesheet.save(document.directory_get().string()))
|
||||
toasts.info(std::format("Saved spritesheet #{}: {}", id, spritesheet.path.string()));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_SAVE_SPRITESHEET),
|
||||
std::make_format_args(id, pathString)));
|
||||
logger.info(std::vformat(localize.get(TOAST_SAVE_SPRITESHEET, anm2ed::ENGLISH),
|
||||
std::make_format_args(id, pathString)));
|
||||
}
|
||||
else
|
||||
toasts.info(std::format("Unable to save spritesheet #{}: {}", id, spritesheet.path.string()));
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_SAVE_SPRITESHEET_FAILED),
|
||||
std::make_format_args(id, pathString)));
|
||||
logger.error(std::vformat(localize.get(TOAST_SAVE_SPRITESHEET_FAILED, anm2ed::ENGLISH),
|
||||
std::make_format_args(id, pathString)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SetItemTooltip("Save the selected spritesheets.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SAVE_SPRITESHEETS));
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
+318
-186
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "math_.h"
|
||||
#include "toast.h"
|
||||
|
||||
@@ -82,16 +83,6 @@ namespace anm2ed::imgui
|
||||
constexpr auto FRAME_TOOLTIP_HOVER_DELAY = 0.75f; // Extra delay for frame info tooltip.
|
||||
constexpr int ITEM_SELECTION_NULL_FLAG = 1 << 30;
|
||||
|
||||
constexpr auto HELP_FORMAT = R"(- Press {} to decrement time.
|
||||
- Press {} to increment time.
|
||||
- Press {} to shorten the selected frame, by one frame.
|
||||
- Press {} to extend the selected frame, by one frame.
|
||||
- Press {} to go to the previous frame.
|
||||
- Press {} to go to the next frame.
|
||||
- Click and hold on a frame while holding CTRL to change its duration.
|
||||
- Click and hold on a trigger to change its At Frame.
|
||||
- Hold Alt while clicking a non-trigger frame to toggle interpolation.)";
|
||||
|
||||
void Timeline::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard)
|
||||
{
|
||||
auto& document = *manager.get();
|
||||
@@ -325,7 +316,10 @@ namespace anm2ed::imgui
|
||||
item->frames.erase(item->frames.begin() + i);
|
||||
}
|
||||
|
||||
reference.frameIndex = glm::clamp(--reference.frameIndex, -1, (int)item->frames.size() - 1);
|
||||
if (item->frames.empty())
|
||||
reference.frameIndex = -1;
|
||||
else
|
||||
reference.frameIndex = glm::clamp(--reference.frameIndex, 0, (int)item->frames.size() - 1);
|
||||
frames_selection_set_reference();
|
||||
}
|
||||
};
|
||||
@@ -376,14 +370,14 @@ namespace anm2ed::imgui
|
||||
auto cut = [&]()
|
||||
{
|
||||
copy();
|
||||
DOCUMENT_EDIT(document, "Cut Frame(s)", Document::FRAMES, frames_delete());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_CUT_FRAMES), Document::FRAMES, frames_delete());
|
||||
};
|
||||
|
||||
auto paste = [&]()
|
||||
{
|
||||
if (auto item = animation->item_get(reference.itemType, reference.itemID))
|
||||
{
|
||||
document.snapshot("Paste Frame(s)");
|
||||
document.snapshot(localize.get(EDIT_PASTE_FRAMES));
|
||||
std::set<int> indices{};
|
||||
std::string errorString{};
|
||||
int insertIndex = (int)item->frames.size();
|
||||
@@ -403,10 +397,17 @@ namespace anm2ed::imgui
|
||||
document.change(Document::FRAMES);
|
||||
}
|
||||
else
|
||||
toasts.error(std::format("Failed to deserialize frame(s): {}", errorString));
|
||||
{
|
||||
toasts.push(std::format("{} {}", localize.get(TOAST_DESERIALIZE_FRAMES_FAILED), errorString));
|
||||
logger.error(std::format("{} {}", localize.get(TOAST_DESERIALIZE_FRAMES_FAILED, anm2ed::ENGLISH),
|
||||
errorString));
|
||||
}
|
||||
}
|
||||
else
|
||||
toasts.error(std::format("Failed to deserialize frame(s): select an item first!"));
|
||||
{
|
||||
toasts.push(localize.get(TOAST_DESERIALIZE_FRAMES_NO_SELECTION));
|
||||
logger.warning(localize.get(TOAST_DESERIALIZE_FRAMES_NO_SELECTION, anm2ed::ENGLISH));
|
||||
}
|
||||
};
|
||||
|
||||
if (shortcut(manager.chords[SHORTCUT_CUT], shortcut::FOCUSED)) cut();
|
||||
@@ -415,9 +416,11 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight))
|
||||
{
|
||||
if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, !frames.selection.empty())) cut();
|
||||
if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !frames.selection.empty())) copy();
|
||||
if (ImGui::MenuItem("Paste", nullptr, false, !clipboard.is_empty())) paste();
|
||||
if (ImGui::MenuItem(localize.get(BASIC_CUT), settings.shortcutCut.c_str(), false, !frames.selection.empty()))
|
||||
cut();
|
||||
if (ImGui::MenuItem(localize.get(BASIC_COPY), settings.shortcutCopy.c_str(), false, !frames.selection.empty()))
|
||||
copy();
|
||||
if (ImGui::MenuItem(localize.get(BASIC_PASTE), nullptr, false, !clipboard.is_empty())) paste();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
@@ -529,10 +532,12 @@ namespace anm2ed::imgui
|
||||
if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false;
|
||||
auto isActive = reference.itemType == type && reference.itemID == id;
|
||||
|
||||
auto label = type == anm2::LAYER ? std::format(anm2::LAYER_FORMAT, id, anm2.content.layers[id].name,
|
||||
anm2.content.layers[id].spritesheetID)
|
||||
: type == anm2::NULL_ ? std::format(anm2::NULL_FORMAT, id, anm2.content.nulls[id].name)
|
||||
: anm2::TYPE_STRINGS[type];
|
||||
auto label = type == anm2::LAYER ? std::vformat(localize.get(FORMAT_LAYER),
|
||||
std::make_format_args(id, anm2.content.layers[id].name,
|
||||
anm2.content.layers[id].spritesheetID))
|
||||
: type == anm2::NULL_
|
||||
? std::vformat(localize.get(FORMAT_NULL), std::make_format_args(id, anm2.content.nulls[id].name))
|
||||
: localize.get(anm2::TYPE_STRINGS[type]);
|
||||
auto icon = anm2::TYPE_ICONS[type];
|
||||
auto iconTintCurrent = isLightTheme && type == anm2::NONE ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) : itemIconTint;
|
||||
auto baseColorVec = item_color_vec(type);
|
||||
@@ -605,8 +610,9 @@ namespace anm2ed::imgui
|
||||
reference_set_item(type, id);
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
if (ImGui::IsItemHovered()) items.hovered = id;
|
||||
if (ImGui::IsItemHovered())
|
||||
bool isItemHovered = ImGui::IsItemHovered();
|
||||
if (isItemHovered) items.hovered = id;
|
||||
if (isItemHovered)
|
||||
{
|
||||
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
@@ -623,6 +629,98 @@ namespace anm2ed::imgui
|
||||
}
|
||||
}
|
||||
|
||||
if (isItemHovered)
|
||||
{
|
||||
auto& imguiStyle = ImGui::GetStyle();
|
||||
auto previousTooltipFlags = imguiStyle.HoverFlagsForTooltipMouse;
|
||||
auto previousTooltipDelay = imguiStyle.HoverDelayNormal;
|
||||
imguiStyle.HoverFlagsForTooltipMouse = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayNormal |
|
||||
ImGuiHoveredFlags_AllowWhenDisabled |
|
||||
ImGuiHoveredFlags_NoSharedDelay;
|
||||
imguiStyle.HoverDelayNormal = FRAME_TOOLTIP_HOVER_DELAY;
|
||||
bool showItemTooltip = ImGui::BeginItemTooltip();
|
||||
imguiStyle.HoverFlagsForTooltipMouse = previousTooltipFlags;
|
||||
imguiStyle.HoverDelayNormal = previousTooltipDelay;
|
||||
|
||||
if (showItemTooltip)
|
||||
{
|
||||
auto yesNoLabel = [&](bool value) { return value ? localize.get(BASIC_YES) : localize.get(BASIC_NO); };
|
||||
auto visibleLabel = yesNoLabel(isVisible);
|
||||
auto framesCount = item ? (int)item->frames.size() : 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case anm2::ROOT:
|
||||
{
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
|
||||
ImGui::TextUnformatted(localize.get(BASIC_ROOT));
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_VISIBLE), std::make_format_args(visibleLabel)).c_str());
|
||||
auto transformLabel = yesNoLabel(settings.previewIsRootTransform);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_TRANSFORM), std::make_format_args(transformLabel)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_FRAMES_COUNT), std::make_format_args(framesCount)).c_str());
|
||||
break;
|
||||
}
|
||||
case anm2::LAYER:
|
||||
{
|
||||
auto& layer = anm2.content.layers[id];
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
|
||||
ImGui::TextUnformatted(layer.name.c_str());
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_ID), std::make_format_args(id)).c_str());
|
||||
ImGui::TextUnformatted(std::vformat(localize.get(FORMAT_SPRITESHEET_ID),
|
||||
std::make_format_args(layer.spritesheetID))
|
||||
.c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_VISIBLE), std::make_format_args(visibleLabel)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_FRAMES_COUNT), std::make_format_args(framesCount)).c_str());
|
||||
break;
|
||||
}
|
||||
case anm2::NULL_:
|
||||
{
|
||||
auto& nullInfo = anm2.content.nulls[id];
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
|
||||
ImGui::TextUnformatted(nullInfo.name.c_str());
|
||||
ImGui::PopFont();
|
||||
|
||||
auto rectLabel = yesNoLabel(nullInfo.isShowRect);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_ID), std::make_format_args(id)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_RECT), std::make_format_args(rectLabel)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_VISIBLE), std::make_format_args(visibleLabel)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_FRAMES_COUNT), std::make_format_args(framesCount)).c_str());
|
||||
break;
|
||||
}
|
||||
case anm2::TRIGGER:
|
||||
{
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
|
||||
ImGui::TextUnformatted(localize.get(BASIC_TRIGGERS));
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_VISIBLE), std::make_format_args(visibleLabel)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_TRIGGERS_COUNT), std::make_format_args(framesCount)).c_str());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
if (type == anm2::LAYER)
|
||||
{
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip))
|
||||
@@ -645,7 +743,7 @@ namespace anm2ed::imgui
|
||||
if (source != -1 && destination != -1) vector::move_index(animation->layerOrder, source, destination);
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Move Layer Animation", Document::ITEMS, layer_order_move());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_MOVE_LAYER_ANIMATION), Document::ITEMS, layer_order_move());
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
@@ -673,9 +771,11 @@ namespace anm2ed::imgui
|
||||
(itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2));
|
||||
int visibleIcon = item->isVisible ? icon::VISIBLE : icon::INVISIBLE;
|
||||
if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, icon_size_get()))
|
||||
DOCUMENT_EDIT(document, "Item Visibility", Document::FRAMES, item->isVisible = !item->isVisible);
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_TOGGLE_ITEM_VISIBILITY), Document::FRAMES,
|
||||
item->isVisible = !item->isVisible);
|
||||
overlay_icon(resources.icons[visibleIcon].id, iconTintCurrent);
|
||||
ImGui::SetItemTooltip(isVisible ? "The item is shown. Press to hide." : "The item is hidden. Press to show.");
|
||||
ImGui::SetItemTooltip("%s", isVisible ? localize.get(TOOLTIP_ITEM_VISIBILITY_SHOWN)
|
||||
: localize.get(TOOLTIP_ITEM_VISIBILITY_HIDDEN));
|
||||
|
||||
if (type == anm2::NULL_)
|
||||
{
|
||||
@@ -686,10 +786,11 @@ namespace anm2ed::imgui
|
||||
ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x,
|
||||
(itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2));
|
||||
if (ImGui::ImageButton("##Rect Toggle", resources.icons[rectIcon].id, icon_size_get()))
|
||||
DOCUMENT_EDIT(document, "Null Rect", Document::FRAMES, null.isShowRect = !null.isShowRect);
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_TOGGLE_NULL_RECT), Document::FRAMES,
|
||||
null.isShowRect = !null.isShowRect);
|
||||
overlay_icon(resources.icons[rectIcon].id, iconTintCurrent);
|
||||
ImGui::SetItemTooltip(isShowRect ? "The null's rect is shown. Press to hide."
|
||||
: "The null's rect is hidden. Press to show.");
|
||||
ImGui::SetItemTooltip("%s", isShowRect ? localize.get(TOOLTIP_NULL_RECT_SHOWN)
|
||||
: localize.get(TOOLTIP_NULL_RECT_HIDDEN));
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
@@ -712,8 +813,8 @@ namespace anm2ed::imgui
|
||||
if (ImGui::ImageButton("##Unused Toggle", resources.icons[unusedIcon].id, icon_size_get()))
|
||||
isShowUnused = !isShowUnused;
|
||||
overlay_icon(resources.icons[unusedIcon].id, iconTintCurrent);
|
||||
ImGui::SetItemTooltip(isShowUnused ? "Unused layers/nulls are shown. Press to hide."
|
||||
: "Unused layers/nulls are hidden. Press to show.");
|
||||
ImGui::SetItemTooltip("%s", isShowUnused ? localize.get(TOOLTIP_UNUSED_ITEMS_SHOWN)
|
||||
: localize.get(TOOLTIP_UNUSED_ITEMS_HIDDEN));
|
||||
|
||||
auto& showLayersOnly = settings.timelineIsOnlyShowLayers;
|
||||
auto layersIcon = showLayersOnly ? icon::SHOW_LAYERS : icon::HIDE_LAYERS;
|
||||
@@ -723,8 +824,8 @@ namespace anm2ed::imgui
|
||||
if (ImGui::ImageButton("##Layers Toggle", resources.icons[layersIcon].id, icon_size_get()))
|
||||
showLayersOnly = !showLayersOnly;
|
||||
overlay_icon(resources.icons[layersIcon].id, iconTintCurrent);
|
||||
ImGui::SetItemTooltip(showLayersOnly ? "Only layers are visible. Press to show all items."
|
||||
: "All items are visible. Press to only show layers.");
|
||||
ImGui::SetItemTooltip("%s", showLayersOnly ? localize.get(TOOLTIP_ONLY_LAYERS_VISIBLE)
|
||||
: localize.get(TOOLTIP_ALL_ITEMS_VISIBLE));
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
@@ -734,11 +835,12 @@ namespace anm2ed::imgui
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
ImGui::Text("(?)");
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SetItemTooltip("%s", std::format(HELP_FORMAT, settings.shortcutMovePlayheadBack,
|
||||
settings.shortcutMovePlayheadForward, settings.shortcutShortenFrame,
|
||||
settings.shortcutExtendFrame, settings.shortcutPreviousFrame,
|
||||
settings.shortcutNextFrame)
|
||||
.c_str());
|
||||
auto tooltipShortcuts = std::vformat(
|
||||
localize.get(TOOLTIP_TIMELINE_SHORTCUTS),
|
||||
std::make_format_args(settings.shortcutMovePlayheadBack, settings.shortcutMovePlayheadForward,
|
||||
settings.shortcutShortenFrame, settings.shortcutExtendFrame,
|
||||
settings.shortcutPreviousFrame, settings.shortcutNextFrame));
|
||||
ImGui::SetItemTooltip("%s", tooltipShortcuts.c_str());
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
}
|
||||
@@ -863,12 +965,12 @@ namespace anm2ed::imgui
|
||||
ImGui::BeginDisabled(!animation);
|
||||
{
|
||||
shortcut(manager.chords[SHORTCUT_ADD]);
|
||||
if (ImGui::Button("Add", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize))
|
||||
{
|
||||
item_properties_reset();
|
||||
propertiesPopup.open();
|
||||
}
|
||||
set_item_tooltip_shortcut("Add a new item to the animation.", settings.shortcutAdd);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_ADD_ITEM), settings.shortcutAdd);
|
||||
ImGui::SameLine();
|
||||
|
||||
auto selectionType = item_selection_type_get();
|
||||
@@ -877,7 +979,7 @@ namespace anm2ed::imgui
|
||||
ImGui::BeginDisabled(!hasSelection && !hasReferenceItem);
|
||||
{
|
||||
shortcut(manager.chords[SHORTCUT_REMOVE]);
|
||||
if (ImGui::Button("Remove", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_REMOVE), widgetSize))
|
||||
{
|
||||
auto remove = [&]()
|
||||
{
|
||||
@@ -897,9 +999,9 @@ namespace anm2ed::imgui
|
||||
reference_clear();
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Remove Item(s)", Document::ITEMS, remove());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_REMOVE_ITEMS), Document::ITEMS, remove());
|
||||
}
|
||||
set_item_tooltip_shortcut("Remove the selected item(s) from the animation.", settings.shortcutRemove);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_REMOVE_ITEMS), settings.shortcutRemove);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
@@ -956,7 +1058,7 @@ namespace anm2ed::imgui
|
||||
|
||||
auto drawList = ImGui::GetWindowDrawList();
|
||||
auto clipMax = drawList->GetClipRectMax();
|
||||
auto length = animation ? animation->frameNum : anm2.animations.length();
|
||||
auto length = animation ? animation->frameNum : 0;
|
||||
auto frameSize = ImVec2(ImGui::GetTextLineHeight(), ImGui::GetContentRegionAvail().y);
|
||||
auto framesSize = ImVec2(frameSize.x * length, frameSize.y);
|
||||
auto cursorPos = ImGui::GetCursorPos();
|
||||
@@ -969,20 +1071,23 @@ namespace anm2ed::imgui
|
||||
|
||||
if (type == anm2::NONE)
|
||||
{
|
||||
if (isLightTheme)
|
||||
if (length > 0)
|
||||
{
|
||||
auto totalMax = ImVec2(cursorScreenPos.x + framesSize.x, cursorScreenPos.y + framesSize.y);
|
||||
drawList->AddRectFilled(cursorScreenPos, totalMax, ImGui::GetColorU32(timelineBackgroundColor));
|
||||
float animationWidth = std::min(framesSize.x, frameSize.x * (float)length);
|
||||
drawList->AddRectFilled(cursorScreenPos,
|
||||
ImVec2(cursorScreenPos.x + animationWidth, cursorScreenPos.y + framesSize.y),
|
||||
ImGui::GetColorU32(timelinePlayheadRectColor));
|
||||
}
|
||||
else
|
||||
{
|
||||
drawList->AddRectFilled(cursorScreenPos,
|
||||
ImVec2(cursorScreenPos.x + framesSize.x, cursorScreenPos.y + framesSize.y),
|
||||
ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Header)));
|
||||
if (isLightTheme)
|
||||
{
|
||||
auto totalMax = ImVec2(cursorScreenPos.x + framesSize.x, cursorScreenPos.y + framesSize.y);
|
||||
drawList->AddRectFilled(cursorScreenPos, totalMax, ImGui::GetColorU32(timelineBackgroundColor));
|
||||
float animationWidth = std::min(framesSize.x, frameSize.x * (float)length);
|
||||
drawList->AddRectFilled(cursorScreenPos,
|
||||
ImVec2(cursorScreenPos.x + animationWidth, cursorScreenPos.y + framesSize.y),
|
||||
ImGui::GetColorU32(timelinePlayheadRectColor));
|
||||
}
|
||||
else
|
||||
{
|
||||
drawList->AddRectFilled(cursorScreenPos,
|
||||
ImVec2(cursorScreenPos.x + framesSize.x, cursorScreenPos.y + framesSize.y),
|
||||
ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Header)));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = frameMin; i < frameMax; i++)
|
||||
@@ -1029,9 +1134,12 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::IsMouseReleased(0)) isDragging = false;
|
||||
|
||||
ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * floorf(playback.time), cursorPos.y));
|
||||
ImGui::Image(resources.icons[icon::PLAYHEAD].id, frameSize);
|
||||
overlay_icon(resources.icons[icon::PLAYHEAD].id, playheadIconTint, true);
|
||||
if (length > 0)
|
||||
{
|
||||
ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * floorf(playback.time), cursorPos.y));
|
||||
ImGui::Image(resources.icons[icon::PLAYHEAD].id, frameSize);
|
||||
overlay_icon(resources.icons[icon::PLAYHEAD].id, playheadIconTint, true);
|
||||
}
|
||||
}
|
||||
else if (animation)
|
||||
{
|
||||
@@ -1116,7 +1224,7 @@ namespace anm2ed::imgui
|
||||
if (type != anm2::TRIGGER)
|
||||
{
|
||||
if (ImGui::IsKeyDown(ImGuiMod_Alt))
|
||||
DOCUMENT_EDIT(document, "Frame Interpolation", Document::FRAMES,
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FRAME_INTERPOLATION), Document::FRAMES,
|
||||
frame.isInterpolated = !frame.isInterpolated);
|
||||
|
||||
document.frameTime = frameTime;
|
||||
@@ -1145,59 +1253,80 @@ namespace anm2ed::imgui
|
||||
|
||||
if (showFrameTooltip)
|
||||
{
|
||||
|
||||
if (type != anm2::TRIGGER)
|
||||
{
|
||||
auto cropX = frame.crop.x;
|
||||
auto cropY = frame.crop.y;
|
||||
auto sizeX = frame.size.x;
|
||||
auto sizeY = frame.size.y;
|
||||
auto pivotX = frame.pivot.x;
|
||||
auto pivotY = frame.pivot.y;
|
||||
auto scaleX = frame.scale.x;
|
||||
auto scaleY = frame.scale.y;
|
||||
auto rotationValue = frame.rotation;
|
||||
auto durationValue = frame.duration;
|
||||
auto tintR = math::float_to_uint8(frame.tint.r);
|
||||
auto tintG = math::float_to_uint8(frame.tint.g);
|
||||
auto tintB = math::float_to_uint8(frame.tint.b);
|
||||
auto tintA = math::float_to_uint8(frame.tint.a);
|
||||
auto visibleLabel = frame.isVisible ? localize.get(BASIC_YES) : localize.get(BASIC_NO);
|
||||
auto interpolatedLabel = frame.isInterpolated ? localize.get(BASIC_YES) : localize.get(BASIC_NO);
|
||||
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
|
||||
ImGui::Text("%s Frame", anm2::TYPE_STRINGS[type]);
|
||||
ImGui::Text("%s %s", localize.get(anm2::TYPE_STRINGS[type]), localize.get(BASIC_FRAME));
|
||||
ImGui::PopFont();
|
||||
|
||||
auto float_text = [&](std::string label, float& value)
|
||||
{
|
||||
std::string useFormat = math::float_format_get(value);
|
||||
std::string format(label + ": " + useFormat);
|
||||
ImGui::Text(format.c_str(), value);
|
||||
};
|
||||
|
||||
auto vec2_text = [&](std::string label, vec2& value)
|
||||
{
|
||||
std::string useFormat = math::vec2_format_get(value);
|
||||
std::string format(label + ": " + useFormat + ", " + useFormat);
|
||||
ImGui::Text(format.c_str(), value.x, value.y);
|
||||
};
|
||||
|
||||
ImGui::Text("Index: %i", (int)i);
|
||||
auto indexValue = (int)i;
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_INDEX), std::make_format_args(indexValue)).c_str());
|
||||
|
||||
if (type == anm2::LAYER)
|
||||
{
|
||||
vec2_text("Crop", frame.crop);
|
||||
vec2_text("Size", frame.size);
|
||||
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_CROP), std::make_format_args(cropX, cropY)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_SIZE), std::make_format_args(sizeX, sizeY)).c_str());
|
||||
}
|
||||
|
||||
vec2_text("Position", frame.size);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_POSITION), std::make_format_args(sizeX, sizeY)).c_str());
|
||||
|
||||
if (type == anm2::LAYER) vec2_text("Pivot", frame.pivot);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_PIVOT), std::make_format_args(pivotX, pivotY)).c_str());
|
||||
|
||||
vec2_text("Scale", frame.scale);
|
||||
float_text("Rotation", frame.rotation);
|
||||
ImGui::Text("Duration: %i", frame.duration);
|
||||
ImGui::Text("Tint: %i, %i, %i, %i", math::float_to_uint8(frame.tint.r),
|
||||
math::float_to_uint8(frame.tint.g), math::float_to_uint8(frame.tint.b),
|
||||
math::float_to_uint8(frame.tint.a));
|
||||
ImGui::Text("Color Offset: %i, %i, %i", math::float_to_uint8(frame.tint.r),
|
||||
math::float_to_uint8(frame.tint.g), math::float_to_uint8(frame.tint.b));
|
||||
ImGui::Text("Visible: %s", frame.isVisible ? "true" : "false");
|
||||
ImGui::Text("Interpolated: %s", frame.isInterpolated ? "true" : "false");
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_SCALE), std::make_format_args(scaleX, scaleY)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_ROTATION), std::make_format_args(rotationValue)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_DURATION), std::make_format_args(durationValue)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_TINT), std::make_format_args(tintR, tintG, tintB, tintA)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_COLOR_OFFSET), std::make_format_args(tintR, tintG, tintB))
|
||||
.c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_VISIBLE), std::make_format_args(visibleLabel)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_INTERPOLATED), std::make_format_args(interpolatedLabel)).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto atFrameValue = frame.atFrame;
|
||||
auto eventLabel = document.event.labels[frame.eventID + 1];
|
||||
auto soundLabel = document.sound.labels[frame.soundID + 1];
|
||||
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
|
||||
ImGui::Text("%s", anm2::TYPE_STRINGS[type]);
|
||||
ImGui::Text("%s %s", localize.get(anm2::TYPE_STRINGS[type]), localize.get(BASIC_FRAME));
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::Text("At Frame: %i", frame.atFrame);
|
||||
ImGui::Text("Event: %s", document.event.labels[frame.eventID + 1]);
|
||||
ImGui::Text("Sound: %s", document.sound.labels[frame.soundID + 1]);
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_AT_FRAME), std::make_format_args(atFrameValue)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_EVENT_LABEL), std::make_format_args(eventLabel)).c_str());
|
||||
ImGui::TextUnformatted(
|
||||
std::vformat(localize.get(FORMAT_SOUND_LABEL), std::make_format_args(soundLabel)).c_str());
|
||||
}
|
||||
|
||||
ImGui::EndTooltip();
|
||||
@@ -1294,7 +1423,7 @@ namespace anm2ed::imgui
|
||||
|
||||
int insertPosResult = -1;
|
||||
int insertedCount = 0;
|
||||
DOCUMENT_EDIT(document, "Move Frame(s)", Document::FRAMES, {
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_MOVE_FRAMES), Document::FRAMES, {
|
||||
std::vector<anm2::Frame> movedFrames;
|
||||
movedFrames.reserve(indices.size());
|
||||
|
||||
@@ -1393,7 +1522,8 @@ namespace anm2ed::imgui
|
||||
if (!isDraggedFrameSnapshot && hoveredTime != draggedFrameStart)
|
||||
{
|
||||
isDraggedFrameSnapshot = true;
|
||||
document.snapshot(type == anm2::TRIGGER ? "Trigger At Frame" : "Frame Duration");
|
||||
document.snapshot(type == anm2::TRIGGER ? localize.get(EDIT_TRIGGER_AT_FRAME)
|
||||
: localize.get(EDIT_FRAME_DURATION));
|
||||
}
|
||||
|
||||
if (type == anm2::TRIGGER)
|
||||
@@ -1562,8 +1692,9 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::BeginDisabled(!animation);
|
||||
{
|
||||
auto label = playback.isPlaying ? "Pause" : "Play";
|
||||
auto tooltip = playback.isPlaying ? "Pause the animation." : "Play the animation.";
|
||||
auto label = playback.isPlaying ? localize.get(LABEL_PAUSE) : localize.get(LABEL_PLAY);
|
||||
auto tooltip =
|
||||
playback.isPlaying ? localize.get(TOOLTIP_PAUSE_ANIMATION) : localize.get(TOOLTIP_PLAY_ANIMATION);
|
||||
|
||||
shortcut(manager.chords[SHORTCUT_PLAY_PAUSE]);
|
||||
if (ImGui::Button(label, widgetSize)) playback.toggle();
|
||||
@@ -1576,7 +1707,7 @@ namespace anm2ed::imgui
|
||||
ImGui::BeginDisabled(!item);
|
||||
{
|
||||
shortcut(manager.chords[SHORTCUT_INSERT_FRAME]);
|
||||
if (ImGui::Button("Insert", widgetSize))
|
||||
if (ImGui::Button(localize.get(LABEL_INSERT), widgetSize))
|
||||
{
|
||||
auto insert_frame = [&]()
|
||||
{
|
||||
@@ -1616,23 +1747,23 @@ namespace anm2ed::imgui
|
||||
frames_selection_set_reference();
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Insert Frame", Document::FRAMES, insert_frame());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_INSERT_FRAME), Document::FRAMES, insert_frame());
|
||||
}
|
||||
set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutInsertFrame);
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_INSERT_FRAME), settings.shortcutInsertFrame);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(!document.frame_get());
|
||||
{
|
||||
shortcut(manager.chords[SHORTCUT_REMOVE]);
|
||||
if (ImGui::Button("Delete", widgetSize))
|
||||
DOCUMENT_EDIT(document, "Delete Frame(s)", Document::FRAMES, frames_delete());
|
||||
set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove);
|
||||
if (ImGui::Button(localize.get(LABEL_DELETE), widgetSize))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_DELETE_FRAMES), Document::FRAMES, frames_delete());
|
||||
set_item_tooltip_shortcut(localize.get(TOOLTIP_DELETE_FRAMES), settings.shortcutRemove);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Bake", widgetSize)) bakePopup.open();
|
||||
ImGui::SetItemTooltip("Turn interpolated frames into uninterpolated ones.");
|
||||
if (ImGui::Button(localize.get(LABEL_BAKE), widgetSize)) bakePopup.open();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_BAKE_FRAMES));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
@@ -1641,27 +1772,29 @@ namespace anm2ed::imgui
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(!animation || animation->frameNum == animation->length());
|
||||
if (ImGui::Button("Fit Animation Length", widgetSize))
|
||||
DOCUMENT_EDIT(document, "Fit Animation Length", Document::ANIMATIONS, animation->fit_length());
|
||||
ImGui::SetItemTooltip("The animation length will be set to the effective length of the animation.");
|
||||
if (ImGui::Button(localize.get(LABEL_FIT_ANIMATION_LENGTH), widgetSize))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FIT_ANIMATION_LENGTH), Document::ANIMATIONS,
|
||||
animation->fit_length());
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_FIT_ANIMATION_LENGTH));
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
auto frameNum = animation ? animation->frameNum : dummy_value<int>();
|
||||
ImGui::SetNextItemWidth(widgetSize.x);
|
||||
if (input_int_range("Animation Length", frameNum, anm2::FRAME_NUM_MIN, anm2::FRAME_NUM_MAX, STEP, STEP_FAST,
|
||||
!animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0))
|
||||
DOCUMENT_EDIT(document, "Animation Length", Document::ANIMATIONS, animation->frameNum = frameNum);
|
||||
ImGui::SetItemTooltip("Set the animation's length.");
|
||||
if (input_int_range(localize.get(LABEL_ANIMATION_LENGTH), frameNum, anm2::FRAME_NUM_MIN, anm2::FRAME_NUM_MAX,
|
||||
STEP, STEP_FAST, !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_ANIMATION_LENGTH), Document::ANIMATIONS,
|
||||
animation->frameNum = frameNum);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ANIMATION_LENGTH));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
auto isLoop = animation ? animation->isLoop : dummy_value<bool>();
|
||||
ImGui::SetNextItemWidth(widgetSize.x);
|
||||
if (ImGui::Checkbox("Loop", &isLoop))
|
||||
DOCUMENT_EDIT(document, "Loop", Document::ANIMATIONS, animation->isLoop = isLoop);
|
||||
ImGui::SetItemTooltip("Toggle the animation looping.");
|
||||
if (ImGui::Checkbox(localize.get(LABEL_LOOP), &isLoop))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_LOOP), Document::ANIMATIONS, animation->isLoop = isLoop);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LOOP_ANIMATION));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -1669,23 +1802,23 @@ namespace anm2ed::imgui
|
||||
|
||||
auto fps = anm2.info.fps;
|
||||
ImGui::SetNextItemWidth(widgetSize.x);
|
||||
if (input_int_range("FPS", fps, anm2::FPS_MIN, anm2::FPS_MAX))
|
||||
DOCUMENT_EDIT(document, "FPS", Document::ANIMATIONS, anm2.info.fps = fps);
|
||||
ImGui::SetItemTooltip("Set the FPS of all animations.");
|
||||
if (input_int_range(localize.get(LABEL_FPS), fps, anm2::FPS_MIN, anm2::FPS_MAX))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_FPS), Document::ANIMATIONS, anm2.info.fps = fps);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_FPS));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
auto createdBy = anm2.info.createdBy;
|
||||
ImGui::SetNextItemWidth(widgetSize.x);
|
||||
if (input_text_string("Author", &createdBy))
|
||||
DOCUMENT_EDIT(document, "Author", Document::ANIMATIONS, anm2.info.createdBy = createdBy);
|
||||
ImGui::SetItemTooltip("Set the author of the document.");
|
||||
if (input_text_string(localize.get(LABEL_AUTHOR), &createdBy))
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_AUTHOR), Document::ANIMATIONS, anm2.info.createdBy = createdBy);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_AUTHOR));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetNextItemWidth(widgetSize.x);
|
||||
ImGui::Checkbox("Sound", &settings.timelineIsSound);
|
||||
ImGui::SetItemTooltip("Toggle sounds playing with triggers.\nBind sounds to events in the Events window.");
|
||||
ImGui::Checkbox(localize.get(LABEL_SOUND), &settings.timelineIsSound);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SOUND));
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
@@ -1695,7 +1828,7 @@ namespace anm2ed::imgui
|
||||
};
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2());
|
||||
if (ImGui::Begin("Timeline", &settings.windowIsTimeline))
|
||||
if (ImGui::Begin(localize.get(LABEL_TIMELINE_WINDOW), &settings.windowIsTimeline))
|
||||
{
|
||||
isWindowHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
|
||||
frames_child();
|
||||
@@ -1706,7 +1839,7 @@ namespace anm2ed::imgui
|
||||
|
||||
propertiesPopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(propertiesPopup.label(), &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
auto item_properties_close = [&]()
|
||||
{
|
||||
@@ -1722,80 +1855,79 @@ namespace anm2ed::imgui
|
||||
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))
|
||||
if (ImGui::BeginChild("##Options", optionsSize, ImGuiChildFlags_Borders))
|
||||
{
|
||||
ImGui::SeparatorText("Type");
|
||||
ImGui::SeparatorText(localize.get(LABEL_TYPE));
|
||||
|
||||
auto size = ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, ImGui::GetFrameHeightWithSpacing());
|
||||
|
||||
if (ImGui::BeginChild("Type Layer", size))
|
||||
if (ImGui::BeginChild("##Type 1", size))
|
||||
{
|
||||
ImGui::RadioButton("Layer", &type, anm2::LAYER);
|
||||
ImGui::SetItemTooltip("Layers are a basic visual element in an animation, used for displaying spritesheets.");
|
||||
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 Null", size))
|
||||
if (ImGui::BeginChild("##Type 2", size))
|
||||
{
|
||||
ImGui::RadioButton("Null", &type, anm2::NULL_);
|
||||
ImGui::SetItemTooltip(
|
||||
"Nulls are invisible elements in an animation, used for interfacing with a game engine.");
|
||||
ImGui::RadioButton(localize.get(LABEL_NULL), &type, anm2::NULL_);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_NULL_TYPE));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SeparatorText("Source");
|
||||
ImGui::SeparatorText(localize.get(LABEL_SOURCE));
|
||||
|
||||
if (ImGui::BeginChild("Source New", size))
|
||||
if (ImGui::BeginChild("##Source 1", size))
|
||||
{
|
||||
ImGui::RadioButton("New", &source, source::NEW);
|
||||
ImGui::SetItemTooltip("Create a new item to be used.");
|
||||
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 Existing", size))
|
||||
if (ImGui::BeginChild("##Source 2", size))
|
||||
{
|
||||
auto hasUnusedItems = animation && !unused_items_get((anm2::Type)type).empty();
|
||||
ImGui::BeginDisabled(!hasUnusedItems);
|
||||
ImGui::RadioButton("Existing", &source, source::EXISTING);
|
||||
auto isUnusedItems = animation && !unused_items_get((anm2::Type)type).empty();
|
||||
ImGui::BeginDisabled(!isUnusedItems);
|
||||
ImGui::RadioButton(localize.get(LABEL_EXISTING), &source, source::EXISTING);
|
||||
ImGui::EndDisabled();
|
||||
auto tooltip =
|
||||
hasUnusedItems ? "Use a pre-existing, presently unused item." : "No unused items are available.";
|
||||
ImGui::SetItemTooltip("%s", tooltip);
|
||||
ImGui::SetItemTooltip("%s", isUnusedItems ? localize.get(TOOLTIP_USE_EXISTING_ITEM)
|
||||
: localize.get(TOOLTIP_NO_UNUSED_ITEMS));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SeparatorText("Locale");
|
||||
ImGui::SeparatorText(localize.get(LABEL_LOCALE));
|
||||
|
||||
if (ImGui::BeginChild("Locale Global", size))
|
||||
if (ImGui::BeginChild("##Locale 1", size))
|
||||
{
|
||||
ImGui::RadioButton("Global", &locale, locale::GLOBAL);
|
||||
ImGui::SetItemTooltip("The item will be inserted into all animations, if not already present.");
|
||||
ImGui::RadioButton(localize.get(LABEL_GLOBAL), &locale, locale::GLOBAL);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_GLOBAL_LOCALE));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::BeginChild("Locale Local", size))
|
||||
if (ImGui::BeginChild("##Locale 2", size))
|
||||
{
|
||||
ImGui::RadioButton("Local", &locale, locale::LOCAL);
|
||||
ImGui::SetItemTooltip("The item will only be inserted into this animation.");
|
||||
ImGui::RadioButton(localize.get(LABEL_LOCAL), &locale, locale::LOCAL);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LOCAL_LOCALE));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SeparatorText("Options");
|
||||
ImGui::SeparatorText(localize.get(LABEL_OPTIONS));
|
||||
|
||||
ImGui::BeginDisabled(source == source::EXISTING);
|
||||
{
|
||||
input_text_string("Name", &addItemName);
|
||||
ImGui::SetItemTooltip("Set the item's name.");
|
||||
input_text_string(localize.get(BASIC_NAME), &addItemName);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ITEM_NAME));
|
||||
ImGui::BeginDisabled(type != anm2::LAYER);
|
||||
{
|
||||
combo_negative_one_indexed("Spritesheet", &addItemSpritesheetID, document.spritesheet.labels);
|
||||
ImGui::SetItemTooltip("Set the layer item's spritesheet.");
|
||||
combo_negative_one_indexed(localize.get(LABEL_SPRITESHEET), &addItemSpritesheetID,
|
||||
document.spritesheet.labels);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LAYER_SPRITESHEET));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
@@ -1803,7 +1935,7 @@ namespace anm2ed::imgui
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
if (ImGui::BeginChild("Items", itemsSize, ImGuiChildFlags_Borders))
|
||||
if (ImGui::BeginChild("##Items", itemsSize, ImGuiChildFlags_Borders))
|
||||
{
|
||||
if (animation && source == source::EXISTING)
|
||||
{
|
||||
@@ -1819,15 +1951,15 @@ namespace anm2ed::imgui
|
||||
if (type == anm2::LAYER)
|
||||
{
|
||||
auto& layer = anm2.content.layers[id];
|
||||
if (ImGui::Selectable(
|
||||
std::format("#{} {} (Spritesheet: #{})", id, layer.name, layer.spritesheetID).c_str(),
|
||||
isSelected))
|
||||
addItemID = id;
|
||||
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;
|
||||
}
|
||||
else if (type == anm2::NULL_)
|
||||
{
|
||||
auto& null = anm2.content.nulls[id];
|
||||
if (ImGui::Selectable(std::format("#{} {}", id, null.name).c_str(), isSelected)) addItemID = id;
|
||||
auto label = std::vformat(localize.get(FORMAT_NULL), std::make_format_args(id, null.name));
|
||||
if (ImGui::Selectable(label.c_str(), isSelected)) addItemID = id;
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -1839,11 +1971,11 @@ namespace anm2ed::imgui
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
ImGui::BeginDisabled(source == source::EXISTING && addItemID == -1);
|
||||
if (ImGui::Button("Add", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_ADD), widgetSize))
|
||||
{
|
||||
anm2::Reference addReference{};
|
||||
|
||||
document.snapshot("Add Item");
|
||||
document.snapshot(localize.get(EDIT_ADD_ITEM));
|
||||
if (type == anm2::LAYER)
|
||||
addReference = anm2.layer_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName,
|
||||
addItemSpritesheetID - 1, (locale::Type)locale);
|
||||
@@ -1864,19 +1996,19 @@ namespace anm2ed::imgui
|
||||
item_properties_close();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SetItemTooltip("Add the item, with the settings specified.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ADD_ITEM));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel", widgetSize)) item_properties_close();
|
||||
ImGui::SetItemTooltip("Cancel adding an item.");
|
||||
if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize)) item_properties_close();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CANCEL_ADD_ITEM));
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
bakePopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(bakePopup.label, &bakePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(bakePopup.label(), &bakePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
auto& interval = settings.bakeInterval;
|
||||
auto& isRoundRotation = settings.bakeIsRoundRotation;
|
||||
@@ -1884,19 +2016,19 @@ namespace anm2ed::imgui
|
||||
|
||||
auto frame = document.frame_get();
|
||||
|
||||
input_int_range("Interval", interval, anm2::FRAME_DURATION_MIN,
|
||||
input_int_range(localize.get(LABEL_INTERVAL), interval, anm2::FRAME_DURATION_MIN,
|
||||
frame ? frame->duration : anm2::FRAME_DURATION_MIN);
|
||||
ImGui::SetItemTooltip("Set the maximum duration of each frame that will be baked.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_INTERVAL));
|
||||
|
||||
ImGui::Checkbox("Round Rotation", &isRoundRotation);
|
||||
ImGui::SetItemTooltip("Rotation will be rounded to the nearest whole number.");
|
||||
ImGui::Checkbox(localize.get(LABEL_ROUND_ROTATION), &isRoundRotation);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ROUND_ROTATION));
|
||||
|
||||
ImGui::Checkbox("Round Scale", &isRoundScale);
|
||||
ImGui::SetItemTooltip("Scale will be rounded to the nearest whole number.");
|
||||
ImGui::Checkbox(localize.get(LABEL_ROUND_SCALE), &isRoundScale);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ROUND_SCALE));
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
if (ImGui::Button("Bake", widgetSize))
|
||||
if (ImGui::Button(localize.get(LABEL_BAKE), widgetSize))
|
||||
{
|
||||
auto frames_bake = [&]()
|
||||
{
|
||||
@@ -1907,16 +2039,16 @@ namespace anm2ed::imgui
|
||||
frames.clear();
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT(document, "Bake Frames", Document::FRAMES, frames_bake());
|
||||
DOCUMENT_EDIT(document, localize.get(EDIT_BAKE_FRAMES), Document::FRAMES, frames_bake());
|
||||
|
||||
bakePopup.close();
|
||||
}
|
||||
ImGui::SetItemTooltip("Bake the selected frame(s) with the options selected.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_BAKE_FRAMES_OPTIONS));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel", widgetSize)) bakePopup.close();
|
||||
ImGui::SetItemTooltip("Cancel baking frames.");
|
||||
if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize)) bakePopup.close();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CANCEL_BAKE_FRAMES));
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -1940,7 +2072,7 @@ namespace anm2ed::imgui
|
||||
static bool isShortenChordHeld = false;
|
||||
auto isShortenFrame = shortcut(manager.chords[SHORTCUT_SHORTEN_FRAME], shortcut::GLOBAL);
|
||||
|
||||
if (isShortenFrame && !isShortenChordHeld) document.snapshot("Shorten Frame");
|
||||
if (isShortenFrame && !isShortenChordHeld) document.snapshot(localize.get(EDIT_SHORTEN_FRAME));
|
||||
if (isShortenFrame)
|
||||
{
|
||||
|
||||
@@ -1954,7 +2086,7 @@ namespace anm2ed::imgui
|
||||
|
||||
static bool isExtendChordHeld = false;
|
||||
auto isExtendFrame = shortcut(manager.chords[SHORTCUT_EXTEND_FRAME], shortcut::GLOBAL);
|
||||
if (isExtendFrame && !isExtendChordHeld) document.snapshot("Extend Frame");
|
||||
if (isExtendFrame && !isExtendChordHeld) document.snapshot(localize.get(EDIT_EXTEND_FRAME));
|
||||
if (isExtendFrame)
|
||||
{
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "clipboard.h"
|
||||
#include "manager.h"
|
||||
#include "resources.h"
|
||||
#include "settings.h"
|
||||
#include "strings.h"
|
||||
|
||||
namespace anm2ed::imgui
|
||||
{
|
||||
@@ -23,9 +23,9 @@ namespace anm2ed::imgui
|
||||
bool isDragging{};
|
||||
bool isWindowHovered{};
|
||||
bool isHorizontalScroll{};
|
||||
PopupHelper propertiesPopup{PopupHelper("Item Properties", POPUP_NORMAL)};
|
||||
PopupHelper bakePopup{PopupHelper("Bake", POPUP_SMALL_NO_HEIGHT)};
|
||||
std::string addItemName{};
|
||||
PopupHelper propertiesPopup{PopupHelper(LABEL_TIMELINE_PROPERTIES_POPUP, POPUP_NORMAL)};
|
||||
PopupHelper bakePopup{PopupHelper(LABEL_TIMELINE_BAKE_POPUP, POPUP_SMALL_NO_HEIGHT)};
|
||||
std::string addItemName{"New Item"};
|
||||
bool addItemIsRect{};
|
||||
int addItemID{-1};
|
||||
int addItemSpritesheetID{-1};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "strings.h"
|
||||
#include "tool.h"
|
||||
#include "types.h"
|
||||
|
||||
@@ -16,7 +17,7 @@ namespace anm2ed::imgui
|
||||
{
|
||||
auto& document = *manager.get();
|
||||
|
||||
if (ImGui::Begin("Tools", &settings.windowIsTools))
|
||||
if (ImGui::Begin(localize.get(LABEL_TOOLS_WINDOW), &settings.windowIsTools))
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2));
|
||||
|
||||
@@ -54,10 +55,11 @@ namespace anm2ed::imgui
|
||||
|
||||
if (shortcut(manager.chords[info.shortcut], shortcut::GLOBAL)) tool_use((tool::Type)i);
|
||||
|
||||
auto labelText = info.label;
|
||||
if (i == tool::COLOR)
|
||||
{
|
||||
size += to_vec2(ImGui::GetStyle().FramePadding) * 2.0f;
|
||||
if (ImGui::ColorButton(info.label, to_imvec4(settings.toolColor), ImGuiColorEditFlags_NoTooltip,
|
||||
if (ImGui::ColorButton(labelText, to_imvec4(settings.toolColor), ImGuiColorEditFlags_NoTooltip,
|
||||
to_imvec2(size)))
|
||||
tool_use((tool::Type)i);
|
||||
|
||||
@@ -67,7 +69,7 @@ namespace anm2ed::imgui
|
||||
{
|
||||
if (i == tool::UNDO) ImGui::BeginDisabled(!document.is_able_to_undo());
|
||||
if (i == tool::REDO) ImGui::BeginDisabled(!document.is_able_to_redo());
|
||||
if (ImGui::ImageButton(info.label, resources.icons[info.icon].id, to_imvec2(size), ImVec2(0, 0), ImVec2(1, 1),
|
||||
if (ImGui::ImageButton(labelText, resources.icons[info.icon].id, to_imvec2(size), ImVec2(0, 0), ImVec2(1, 1),
|
||||
ImVec4(0, 0, 0, 0), iconTint))
|
||||
tool_use((tool::Type)i);
|
||||
if (i == tool::UNDO) ImGui::EndDisabled();
|
||||
@@ -81,7 +83,7 @@ namespace anm2ed::imgui
|
||||
ImGui::SameLine();
|
||||
else
|
||||
usedWidth = ImGui::GetStyle().WindowPadding.x;
|
||||
set_item_tooltip_shortcut(info.tooltip, settings.*SHORTCUT_MEMBERS[info.shortcut]);
|
||||
set_item_tooltip_shortcut(localize.get(info.tooltip), settings.*SHORTCUT_MEMBERS[info.shortcut]);
|
||||
|
||||
if (isSelected) ImGui::PopStyleColor();
|
||||
}
|
||||
@@ -90,9 +92,9 @@ namespace anm2ed::imgui
|
||||
|
||||
colorEditPopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopup(colorEditPopup.label))
|
||||
if (ImGui::BeginPopup(colorEditPopup.label()))
|
||||
{
|
||||
ImGui::ColorPicker4(colorEditPopup.label, value_ptr(settings.toolColor));
|
||||
ImGui::ColorPicker4(colorEditPopup.label(), value_ptr(settings.toolColor));
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "manager.h"
|
||||
#include "resources.h"
|
||||
#include "settings.h"
|
||||
#include "strings.h"
|
||||
|
||||
namespace anm2ed::imgui
|
||||
{
|
||||
@@ -11,7 +12,8 @@ namespace anm2ed::imgui
|
||||
bool isOpenColorEdit{};
|
||||
ImVec2 colorEditPosition{};
|
||||
|
||||
PopupHelper colorEditPopup{PopupHelper("##Color Edit", POPUP_TO_CONTENT, POPUP_BY_ITEM)};
|
||||
PopupHelper colorEditPopup{
|
||||
PopupHelper(LABEL_TOOLS_COLOR_EDIT_POPUP, POPUP_TO_CONTENT, POPUP_BY_ITEM)};
|
||||
|
||||
public:
|
||||
void update(Manager&, Settings&, Resources&);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "strings.h"
|
||||
|
||||
using namespace anm2ed::resource;
|
||||
|
||||
namespace anm2ed::imgui
|
||||
@@ -15,24 +17,23 @@ namespace anm2ed::imgui
|
||||
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height + documents.height));
|
||||
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight));
|
||||
|
||||
if (ImGui::Begin("Welcome", nullptr,
|
||||
if (ImGui::Begin(localize.get(LABEL_WELCOME_WINDOW), nullptr,
|
||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoScrollbar |
|
||||
ImGuiWindowFlags_NoScrollWithMouse))
|
||||
{
|
||||
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE);
|
||||
ImGui::TextUnformatted("Anm2Ed");
|
||||
ImGui::TextUnformatted(localize.get(LABEL_APPLICATION_NAME));
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::TextUnformatted("Select a recent file or open a new or existing document. You can also drag and drop "
|
||||
"files into the window to open them.");
|
||||
ImGui::TextUnformatted(localize.get(LABEL_WELCOME_DESCRIPTION));
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
if (ImGui::Button("New", widgetSize)) dialog.file_save(dialog::ANM2_NEW); // handled in taskbar.cpp
|
||||
if (ImGui::Button(localize.get(BASIC_NEW), widgetSize)) dialog.file_save(dialog::ANM2_NEW); // handled in taskbar.cpp
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Open", widgetSize)) dialog.file_open(dialog::ANM2_OPEN); // handled in taskbar.cpp
|
||||
if (ImGui::Button(localize.get(BASIC_OPEN), widgetSize)) dialog.file_open(dialog::ANM2_OPEN); // handled in taskbar.cpp
|
||||
|
||||
if (ImGui::BeginChild("##Recent Files Child", {}, ImGuiChildFlags_Borders))
|
||||
{
|
||||
@@ -61,9 +62,9 @@ namespace anm2ed::imgui
|
||||
|
||||
restorePopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(restorePopup.label, &restorePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(restorePopup.label(), &restorePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
ImGui::TextUnformatted("Autosaved documents detected. Would you like to restore them?");
|
||||
ImGui::TextUnformatted(localize.get(LABEL_RESTORE_AUTOSAVES_PROMPT));
|
||||
|
||||
auto childSize = child_size_get(5);
|
||||
|
||||
@@ -80,7 +81,7 @@ namespace anm2ed::imgui
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
if (ImGui::Button("Yes", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_YES), widgetSize))
|
||||
{
|
||||
manager.autosave_files_open();
|
||||
restorePopup.close();
|
||||
@@ -88,7 +89,7 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("No", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_NO), widgetSize))
|
||||
{
|
||||
manager.autosave_files_clear();
|
||||
restorePopup.close();
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
|
||||
#include "documents.h"
|
||||
#include "manager.h"
|
||||
#include "strings.h"
|
||||
#include "taskbar.h"
|
||||
|
||||
namespace anm2ed::imgui
|
||||
{
|
||||
class Welcome
|
||||
{
|
||||
PopupHelper restorePopup{PopupHelper("Restore", imgui::POPUP_SMALL_NO_HEIGHT)};
|
||||
PopupHelper restorePopup{PopupHelper(LABEL_WELCOME_RESTORE_POPUP, imgui::POPUP_SMALL_NO_HEIGHT)};
|
||||
|
||||
public:
|
||||
void update(Manager&, Resources&, Dialog&, Taskbar&, Documents&);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user