Sound drag/drop
This commit is contained in:
+22
-16
@@ -1,7 +1,9 @@
|
||||
#include "documents.h"
|
||||
|
||||
#include <format>
|
||||
#include <vector>
|
||||
|
||||
#include "strings.h"
|
||||
#include "time_.h"
|
||||
|
||||
using namespace anm2ed::resource;
|
||||
@@ -44,7 +46,7 @@ namespace anm2ed::imgui
|
||||
{
|
||||
height = ImGui::GetWindowSize().y;
|
||||
|
||||
if (ImGui::BeginTabBar("Documents Bar", ImGuiTabBarFlags_Reorderable))
|
||||
if (ImGui::BeginTabBar("##Documents Bar", ImGuiTabBarFlags_Reorderable))
|
||||
{
|
||||
auto documentsCount = (int)manager.documents.size();
|
||||
bool isCloseShortcut = shortcut(manager.chords[SHORTCUT_CLOSE], shortcut::GLOBAL) && !closePopup.is_open();
|
||||
@@ -84,8 +86,9 @@ namespace anm2ed::imgui
|
||||
|
||||
auto isRequested = i == manager.pendingSelected;
|
||||
auto font = isDirty ? font::ITALICS : font::REGULAR;
|
||||
auto string = isDirty ? std::format("[Not Saved] {}", document.filename_get().string())
|
||||
: document.filename_get().string();
|
||||
auto filename = document.filename_get().string();
|
||||
auto string =
|
||||
isDirty ? std::vformat(localize.get(FORMAT_NOT_SAVED), std::make_format_args(filename)) : filename;
|
||||
auto label = std::format("{}###Document{}", string, i);
|
||||
|
||||
auto flags = isDirty ? ImGuiTabItemFlags_UnsavedDocument : 0;
|
||||
@@ -116,15 +119,15 @@ namespace anm2ed::imgui
|
||||
|
||||
closePopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(closePopup.label, &closePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(closePopup.label(), &closePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
if (closeDocumentIndex >= 0 && closeDocumentIndex < (int)manager.documents.size())
|
||||
{
|
||||
auto& closeDocument = manager.documents[closeDocumentIndex];
|
||||
|
||||
ImGui::TextUnformatted(std::format("The document \"{}\" has been modified.\nDo you want to save it?",
|
||||
closeDocument.filename_get().string())
|
||||
.c_str());
|
||||
auto filename = closeDocument.filename_get().string();
|
||||
auto prompt = std::vformat(localize.get(LABEL_DOCUMENT_MODIFIED_PROMPT), std::make_format_args(filename));
|
||||
ImGui::TextUnformatted(prompt.c_str());
|
||||
|
||||
auto widgetSize = imgui::widget_size_with_row_get(3);
|
||||
|
||||
@@ -134,7 +137,7 @@ namespace anm2ed::imgui
|
||||
closePopup.close();
|
||||
};
|
||||
|
||||
if (ImGui::Button("Yes", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_YES), widgetSize))
|
||||
{
|
||||
manager.save(closeDocumentIndex);
|
||||
manager.close(closeDocumentIndex);
|
||||
@@ -143,7 +146,7 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("No", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_NO), widgetSize))
|
||||
{
|
||||
manager.close(closeDocumentIndex);
|
||||
close();
|
||||
@@ -151,7 +154,7 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize))
|
||||
{
|
||||
isQuitting = false;
|
||||
close();
|
||||
@@ -187,17 +190,18 @@ namespace anm2ed::imgui
|
||||
|
||||
manager.anm2DragDropPopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupContextWindow(manager.anm2DragDropPopup.label, ImGuiPopupFlags_None))
|
||||
if (ImGui::BeginPopupContextWindow(manager.anm2DragDropPopup.label(), ImGuiPopupFlags_None))
|
||||
{
|
||||
auto document = manager.get();
|
||||
if (ImGui::MenuItem(manager.anm2DragDropPaths.size() > 1 ? "Open Many Documents" : "Open New Document"))
|
||||
if (ImGui::MenuItem(manager.anm2DragDropPaths.size() > 1 ? localize.get(LABEL_DOCUMENTS_OPEN_MANY)
|
||||
: localize.get(LABEL_DOCUMENTS_OPEN_NEW)))
|
||||
{
|
||||
for (auto& path : manager.anm2DragDropPaths)
|
||||
manager.open(path);
|
||||
drag_drop_reset();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Merge into Current Document", nullptr, false,
|
||||
if (ImGui::MenuItem(localize.get(LABEL_DOCUMENTS_MERGE_INTO_CURRENT), nullptr, false,
|
||||
document && !manager.anm2DragDropPaths.empty()))
|
||||
{
|
||||
if (document)
|
||||
@@ -211,17 +215,19 @@ namespace anm2ed::imgui
|
||||
}
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT_PTR(document, "Merge Anm2", Document::ALL, merge_anm2s());
|
||||
DOCUMENT_EDIT_PTR(document, localize.get(EDIT_MERGE_ANM2), Document::ALL, merge_anm2s());
|
||||
drag_drop_reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Cancel")) drag_drop_reset();
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem(localize.get(BASIC_CANCEL))) drag_drop_reset();
|
||||
|
||||
manager.anm2DragDropPopup.end();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
else if (!ImGui::IsPopupOpen(manager.anm2DragDropPopup.label))
|
||||
else if (!ImGui::IsPopupOpen(manager.anm2DragDropPopup.label()))
|
||||
drag_drop_reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "manager.h"
|
||||
#include "resources.h"
|
||||
#include "settings.h"
|
||||
#include "strings.h"
|
||||
#include "taskbar.h"
|
||||
|
||||
namespace anm2ed::imgui
|
||||
@@ -10,7 +11,7 @@ namespace anm2ed::imgui
|
||||
class Documents
|
||||
{
|
||||
int closeDocumentIndex{-1};
|
||||
imgui::PopupHelper closePopup{imgui::PopupHelper("Close Document", imgui::POPUP_TO_CONTENT)};
|
||||
imgui::PopupHelper closePopup{imgui::PopupHelper(LABEL_DOCUMENT_CLOSE, imgui::POPUP_TO_CONTENT)};
|
||||
|
||||
public:
|
||||
float height{};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "imgui_.h"
|
||||
#include "strings.h"
|
||||
|
||||
#include <imgui/imgui_internal.h>
|
||||
|
||||
@@ -161,7 +162,8 @@ namespace anm2ed::imgui
|
||||
|
||||
void set_item_tooltip_shortcut(const char* tooltip, const std::string& shortcut)
|
||||
{
|
||||
ImGui::SetItemTooltip("%s\n(Shortcut: %s)", tooltip, shortcut.c_str());
|
||||
ImGui::SetItemTooltip(
|
||||
"%s", std::vformat(localize.get(FORMAT_TOOLTIP_SHORTCUT), std::make_format_args(tooltip, shortcut)).c_str());
|
||||
}
|
||||
|
||||
namespace
|
||||
@@ -343,9 +345,9 @@ namespace anm2ed::imgui
|
||||
return (*indexMap)[index];
|
||||
}
|
||||
|
||||
PopupHelper::PopupHelper(const char* label, PopupType type, PopupPosition position)
|
||||
PopupHelper::PopupHelper(StringType labelId, PopupType type, PopupPosition position)
|
||||
{
|
||||
this->label = label;
|
||||
this->labelId = labelId;
|
||||
this->type = type;
|
||||
this->position = position;
|
||||
}
|
||||
@@ -361,7 +363,7 @@ namespace anm2ed::imgui
|
||||
|
||||
void PopupHelper::trigger()
|
||||
{
|
||||
if (isTriggered) ImGui::OpenPopup(label);
|
||||
if (isTriggered) ImGui::OpenPopup(localize.get(labelId));
|
||||
isTriggered = false;
|
||||
|
||||
auto viewport = ImGui::GetMainViewport();
|
||||
|
||||
+4
-2
@@ -7,6 +7,7 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "strings.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace anm2ed::imgui
|
||||
@@ -216,14 +217,15 @@ namespace anm2ed::imgui
|
||||
class PopupHelper
|
||||
{
|
||||
public:
|
||||
const char* label{};
|
||||
StringType labelId{};
|
||||
PopupType type{};
|
||||
PopupPosition position{};
|
||||
bool isOpen{};
|
||||
bool isTriggered{};
|
||||
bool isJustOpened{};
|
||||
|
||||
PopupHelper(const char*, PopupType = POPUP_NORMAL, PopupPosition = POPUP_CENTER);
|
||||
PopupHelper(StringType, PopupType = POPUP_NORMAL, PopupPosition = POPUP_CENTER);
|
||||
const char* label() const { return localize.get(labelId); }
|
||||
bool is_open();
|
||||
void open();
|
||||
void trigger();
|
||||
|
||||
+234
-197
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "math_.h"
|
||||
#include "render.h"
|
||||
#include "shader.h"
|
||||
@@ -22,6 +23,8 @@
|
||||
#include "icon.h"
|
||||
#include "toast.h"
|
||||
|
||||
#include "strings.h"
|
||||
|
||||
using namespace anm2ed::resource;
|
||||
using namespace anm2ed::types;
|
||||
using namespace anm2ed::canvas;
|
||||
@@ -30,8 +33,76 @@ using namespace glm;
|
||||
|
||||
namespace anm2ed::imgui
|
||||
{
|
||||
static constexpr auto ANM2ED_LABEL = "Anm2Ed";
|
||||
static constexpr auto VERSION_LABEL = "Version 2.0";
|
||||
namespace
|
||||
{
|
||||
#ifndef _WIN32
|
||||
constexpr auto EXEC_PERMS =
|
||||
std::filesystem::perms::owner_exec | std::filesystem::perms::group_exec | std::filesystem::perms::others_exec;
|
||||
#endif
|
||||
|
||||
bool ffmpeg_is_executable(const std::string& pathString)
|
||||
{
|
||||
if (pathString.empty()) return false;
|
||||
|
||||
std::error_code ec{};
|
||||
auto status = std::filesystem::status(pathString, ec);
|
||||
if (ec || !std::filesystem::is_regular_file(status)) return false;
|
||||
|
||||
#ifndef _WIN32
|
||||
if ((status.permissions() & EXEC_PERMS) == std::filesystem::perms::none) return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool png_directory_ensure(const std::string& directory)
|
||||
{
|
||||
if (directory.empty())
|
||||
{
|
||||
toasts.push(localize.get(TOAST_PNG_DIRECTORY_NOT_SET));
|
||||
logger.warning(localize.get(TOAST_PNG_DIRECTORY_NOT_SET, anm2ed::ENGLISH));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec{};
|
||||
auto pathValue = std::filesystem::path(directory);
|
||||
auto exists = std::filesystem::exists(pathValue, ec);
|
||||
|
||||
if (ec)
|
||||
{
|
||||
auto errorMessage = ec.message();
|
||||
toasts.push(std::vformat(localize.get(TOAST_PNG_DIRECTORY_ACCESS_ERROR),
|
||||
std::make_format_args(directory, errorMessage)));
|
||||
logger.error(std::vformat(localize.get(TOAST_PNG_DIRECTORY_ACCESS_ERROR, anm2ed::ENGLISH),
|
||||
std::make_format_args(directory, errorMessage)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists)
|
||||
{
|
||||
if (!std::filesystem::is_directory(pathValue, ec) || ec)
|
||||
{
|
||||
toasts.push(std::vformat(localize.get(TOAST_PNG_DIRECTORY_NOT_DIRECTORY), std::make_format_args(directory)));
|
||||
logger.warning(std::vformat(localize.get(TOAST_PNG_DIRECTORY_NOT_DIRECTORY, anm2ed::ENGLISH),
|
||||
std::make_format_args(directory)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!std::filesystem::create_directories(pathValue, ec) || ec)
|
||||
{
|
||||
auto errorMessage = ec.message();
|
||||
toasts.push(std::vformat(localize.get(TOAST_PNG_DIRECTORY_CREATE_ERROR),
|
||||
std::make_format_args(directory, errorMessage)));
|
||||
logger.error(std::vformat(localize.get(TOAST_PNG_DIRECTORY_CREATE_ERROR, anm2ed::ENGLISH),
|
||||
std::make_format_args(directory, errorMessage)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto CREDIT_DELAY = 1.0f;
|
||||
static constexpr auto CREDIT_SCROLL_SPEED = 25.0f;
|
||||
|
||||
@@ -64,6 +135,10 @@ namespace anm2ed::imgui
|
||||
{"Additional Help", font::BOLD},
|
||||
{"im-tem"},
|
||||
{""},
|
||||
{"Localization", font::BOLD},
|
||||
{"ExtremeThreat (Russian)"},
|
||||
{"sawalk/사왈이 (Korean)"},
|
||||
{""},
|
||||
{"Based on the work of:", font::BOLD},
|
||||
{"Adrian Gavrilita"},
|
||||
{"Simon Parzer"},
|
||||
@@ -122,12 +197,21 @@ namespace anm2ed::imgui
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{"enjoy the jams :)"},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
{""},
|
||||
};
|
||||
static constexpr auto CREDIT_COUNT = (int)(sizeof(CREDITS) / sizeof(Credit));
|
||||
|
||||
@@ -143,13 +227,14 @@ namespace anm2ed::imgui
|
||||
{
|
||||
height = ImGui::GetWindowSize().y;
|
||||
|
||||
if (ImGui::BeginMenu("File"))
|
||||
if (ImGui::BeginMenu(localize.get(LABEL_FILE_MENU)))
|
||||
{
|
||||
if (ImGui::MenuItem("New", settings.shortcutNew.c_str())) dialog.file_save(dialog::ANM2_NEW);
|
||||
if (ImGui::MenuItem("Open", settings.shortcutOpen.c_str())) dialog.file_open(dialog::ANM2_OPEN);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_NEW), settings.shortcutNew.c_str())) dialog.file_save(dialog::ANM2_NEW);
|
||||
if (ImGui::MenuItem(localize.get(BASIC_OPEN), settings.shortcutOpen.c_str()))
|
||||
dialog.file_open(dialog::ANM2_OPEN);
|
||||
|
||||
auto recentFiles = manager.recent_files_ordered();
|
||||
if (ImGui::BeginMenu("Open Recent", !recentFiles.empty()))
|
||||
if (ImGui::BeginMenu(localize.get(LABEL_OPEN_RECENT), !recentFiles.empty()))
|
||||
{
|
||||
for (std::size_t index = 0; index < recentFiles.size(); ++index)
|
||||
{
|
||||
@@ -162,21 +247,26 @@ namespace anm2ed::imgui
|
||||
}
|
||||
|
||||
if (!recentFiles.empty())
|
||||
if (ImGui::MenuItem("Clear List")) manager.recent_files_clear();
|
||||
if (ImGui::MenuItem(localize.get(LABEL_CLEAR_LIST))) manager.recent_files_clear();
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Save", settings.shortcutSave.c_str(), false, document))
|
||||
if (settings.fileIsWarnOverwrite) overwritePopup.open();
|
||||
if (ImGui::MenuItem(localize.get(BASIC_SAVE), settings.shortcutSave.c_str(), false, document))
|
||||
{
|
||||
if (settings.fileIsWarnOverwrite)
|
||||
overwritePopup.open();
|
||||
else
|
||||
manager.save(document->path);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Save As", settings.shortcutSaveAs.c_str(), false, document))
|
||||
if (ImGui::MenuItem(localize.get(LABEL_SAVE_AS), settings.shortcutSaveAs.c_str(), false, document))
|
||||
dialog.file_save(dialog::ANM2_SAVE);
|
||||
if (ImGui::MenuItem("Explore XML Location", nullptr, false, document))
|
||||
if (ImGui::MenuItem(localize.get(LABEL_EXPLORE_XML_LOCATION), nullptr, false, document))
|
||||
dialog.file_explorer_open(document->directory_get().string());
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Exit", settings.shortcutExit.c_str())) isQuitting = true;
|
||||
if (ImGui::MenuItem(localize.get(LABEL_EXIT), settings.shortcutExit.c_str())) isQuitting = true;
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (dialog.is_selected(dialog::ANM2_NEW))
|
||||
@@ -197,43 +287,43 @@ namespace anm2ed::imgui
|
||||
dialog.reset();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Wizard"))
|
||||
if (ImGui::BeginMenu(localize.get(LABEL_WIZARD_MENU)))
|
||||
{
|
||||
if (ImGui::MenuItem("Generate Animation From Grid", nullptr, false,
|
||||
if (ImGui::MenuItem(localize.get(LABEL_TASKBAR_GENERATE_ANIMATION_FROM_GRID), nullptr, false,
|
||||
item && document->reference.itemType == anm2::LAYER))
|
||||
generatePopup.open();
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Render Animation", nullptr, false, animation)) renderPopup.open();
|
||||
if (ImGui::MenuItem(localize.get(LABEL_TASKBAR_RENDER_ANIMATION), nullptr, false, animation))
|
||||
renderPopup.open();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Playback"))
|
||||
if (ImGui::BeginMenu(localize.get(LABEL_PLAYBACK_MENU)))
|
||||
{
|
||||
ImGui::MenuItem("Always Loop", nullptr, &settings.playbackIsLoop);
|
||||
ImGui::SetItemTooltip("%s", "Animations will always loop during playback, even if looping isn't set.");
|
||||
ImGui::MenuItem(localize.get(LABEL_PLAYBACK_ALWAYS_LOOP), nullptr, &settings.playbackIsLoop);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_PLAYBACK_ALWAYS_LOOP));
|
||||
|
||||
ImGui::MenuItem("Clamp", nullptr, &settings.playbackIsClamp);
|
||||
ImGui::SetItemTooltip("%s", "Operations will always be clamped to within the animation's bounds.\nFor example, "
|
||||
"dragging the playhead, or triggers.");
|
||||
ImGui::MenuItem(localize.get(LABEL_CLAMP), nullptr, &settings.playbackIsClamp);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_PLAYBACK_CLAMP));
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Window"))
|
||||
if (ImGui::BeginMenu(localize.get(LABEL_WINDOW_MENU)))
|
||||
{
|
||||
for (std::size_t index = 0; index < WINDOW_COUNT; ++index)
|
||||
{
|
||||
auto member = WINDOW_MEMBERS[index];
|
||||
ImGui::MenuItem(WINDOW_STRINGS[index], nullptr, &(settings.*member));
|
||||
ImGui::MenuItem(localize.get(::anm2ed::WINDOW_STRING_TYPES[index]), nullptr, &(settings.*member));
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Settings"))
|
||||
if (ImGui::BeginMenu(localize.get(LABEL_SETTINGS_MENU)))
|
||||
{
|
||||
if (ImGui::MenuItem("Configure"))
|
||||
if (ImGui::MenuItem(localize.get(LABEL_TASKBAR_CONFIGURE)))
|
||||
{
|
||||
editSettings = settings;
|
||||
configurePopup.open();
|
||||
@@ -242,10 +332,10 @@ namespace anm2ed::imgui
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Help"))
|
||||
if (ImGui::BeginMenu(localize.get(LABEL_HELP_MENU)))
|
||||
{
|
||||
|
||||
if (ImGui::MenuItem("About")) aboutPopup.open();
|
||||
if (ImGui::MenuItem(localize.get(LABEL_TASKBAR_ABOUT))) aboutPopup.open();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -254,7 +344,7 @@ namespace anm2ed::imgui
|
||||
|
||||
generatePopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(generatePopup.label, &generatePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(generatePopup.label(), &generatePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
auto& startPosition = settings.generateStartPosition;
|
||||
auto& size = settings.generateSize;
|
||||
@@ -270,15 +360,15 @@ namespace anm2ed::imgui
|
||||
|
||||
if (ImGui::BeginChild("##Options Child", childSize, ImGuiChildFlags_Borders))
|
||||
{
|
||||
ImGui::InputInt2("Start Position", value_ptr(startPosition));
|
||||
ImGui::InputInt2("Frame Size", value_ptr(size));
|
||||
ImGui::InputInt2("Pivot", value_ptr(pivot));
|
||||
ImGui::InputInt("Rows", &rows, STEP, STEP_FAST);
|
||||
ImGui::InputInt("Columns", &columns, STEP, STEP_FAST);
|
||||
ImGui::InputInt2(localize.get(LABEL_GENERATE_START_POSITION), value_ptr(startPosition));
|
||||
ImGui::InputInt2(localize.get(LABEL_GENERATE_FRAME_SIZE), value_ptr(size));
|
||||
ImGui::InputInt2(localize.get(BASIC_PIVOT), value_ptr(pivot));
|
||||
ImGui::InputInt(localize.get(LABEL_GENERATE_ROWS), &rows, STEP, STEP_FAST);
|
||||
ImGui::InputInt(localize.get(LABEL_GENERATE_COLUMNS), &columns, STEP, STEP_FAST);
|
||||
|
||||
input_int_range("Count", count, anm2::FRAME_NUM_MIN, rows * columns);
|
||||
input_int_range(localize.get(LABEL_GENERATE_COUNT), count, anm2::FRAME_NUM_MIN, rows * columns);
|
||||
|
||||
ImGui::InputInt("Duration", &delay, STEP, STEP_FAST);
|
||||
ImGui::InputInt(localize.get(BASIC_DURATION), &delay, STEP, STEP_FAST);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -331,7 +421,7 @@ namespace anm2ed::imgui
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
if (ImGui::Button("Generate", widgetSize))
|
||||
if (ImGui::Button(localize.get(LABEL_GENERATE), widgetSize))
|
||||
{
|
||||
auto generate_from_grid = [&]()
|
||||
{
|
||||
@@ -339,41 +429,46 @@ namespace anm2ed::imgui
|
||||
animation->frameNum = animation->length();
|
||||
};
|
||||
|
||||
DOCUMENT_EDIT_PTR(document, "Generate Animation from Grid", Document::FRAMES, generate_from_grid());
|
||||
DOCUMENT_EDIT_PTR(document, localize.get(EDIT_GENERATE_ANIMATION_FROM_GRID), Document::FRAMES,
|
||||
generate_from_grid());
|
||||
|
||||
generatePopup.close();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel", widgetSize)) generatePopup.close();
|
||||
if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize)) generatePopup.close();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
configurePopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(configurePopup.label, &configurePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(configurePopup.label(), &configurePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
auto childSize = size_without_footer_get(2);
|
||||
|
||||
if (ImGui::BeginTabBar("##Configure Tabs"))
|
||||
{
|
||||
if (ImGui::BeginTabItem("Display"))
|
||||
if (ImGui::BeginTabItem(localize.get(LABEL_DISPLAY)))
|
||||
{
|
||||
if (ImGui::BeginChild("##Tab Child", childSize, true))
|
||||
{
|
||||
input_float_range("UI Scale", editSettings.uiScale, 0.5f, 2.0f, 0.25f, 0.25f, "%.2f");
|
||||
ImGui::SetItemTooltip("Change the scale of the UI.");
|
||||
ImGui::SeparatorText(localize.get(LABEL_WINDOW_MENU));
|
||||
input_float_range(localize.get(LABEL_UI_SCALE), editSettings.uiScale, 0.5f, 2.0f, 0.25f, 0.25f, "%.2f");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_UI_SCALE));
|
||||
ImGui::Checkbox(localize.get(LABEL_VSYNC), &editSettings.isVsync);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_VSYNC));
|
||||
|
||||
ImGui::Checkbox("Vsync", &editSettings.isVsync);
|
||||
ImGui::SetItemTooltip("Toggle vertical sync; synchronizes program update rate with monitor refresh rate.");
|
||||
ImGui::SeparatorText(localize.get(LABEL_LOCALIZATION));
|
||||
ImGui::Combo(localize.get(LABEL_LANGUAGE), &editSettings.language, LANGUAGE_STRINGS, LANGUAGE_COUNT);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LANGUAGE));
|
||||
|
||||
ImGui::SeparatorText("Theme");
|
||||
ImGui::SeparatorText(localize.get(LABEL_THEME));
|
||||
|
||||
for (int i = 0; i < theme::COUNT; i++)
|
||||
{
|
||||
ImGui::RadioButton(theme::STRINGS[i], &editSettings.theme, i);
|
||||
ImGui::RadioButton(localize.get(theme::STRINGS[i]), &editSettings.theme, i);
|
||||
ImGui::SameLine();
|
||||
}
|
||||
}
|
||||
@@ -382,76 +477,75 @@ namespace anm2ed::imgui
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("File"))
|
||||
if (ImGui::BeginTabItem(localize.get(LABEL_FILE_MENU)))
|
||||
{
|
||||
if (ImGui::BeginChild("##Tab Child", childSize, true))
|
||||
{
|
||||
ImGui::SeparatorText("Autosave");
|
||||
ImGui::SeparatorText(localize.get(LABEL_AUTOSAVE));
|
||||
|
||||
ImGui::Checkbox("Enabled", &editSettings.fileIsAutosave);
|
||||
ImGui::SetItemTooltip(
|
||||
"Enables autosaving of documents.\n(Does not overwrite files; makes copies to restore later.)");
|
||||
ImGui::Checkbox(localize.get(BASIC_ENABLED), &editSettings.fileIsAutosave);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_AUTOSAVE_ENABLED));
|
||||
|
||||
ImGui::BeginDisabled(!editSettings.fileIsAutosave);
|
||||
input_int_range("Time (minutes)", editSettings.fileAutosaveTime, 0, 10);
|
||||
ImGui::SetItemTooltip("If changed, will autosave documents using this interval.");
|
||||
input_int_range(localize.get(LABEL_TIME_MINUTES), editSettings.fileAutosaveTime, 0, 10);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_AUTOSAVE_INTERVAL));
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SeparatorText("Snapshots");
|
||||
input_int_range("Stack Size", editSettings.fileSnapshotStackSize, 0, 100);
|
||||
ImGui::SetItemTooltip("Set the maximum snapshot stack size of a document (i.e., how many undo/redos are "
|
||||
"preserved at a time).");
|
||||
ImGui::SeparatorText(localize.get(LABEL_SNAPSHOTS));
|
||||
input_int_range(localize.get(LABEL_STACK_SIZE), editSettings.fileSnapshotStackSize, 0, 100);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_STACK_SIZE));
|
||||
|
||||
ImGui::SeparatorText("Options");
|
||||
ImGui::Checkbox("Overwrite Warning", &editSettings.fileIsWarnOverwrite);
|
||||
ImGui::SetItemTooltip("A warning will be shown when saving/overwriting a file.");
|
||||
ImGui::SeparatorText(localize.get(LABEL_OPTIONS));
|
||||
ImGui::Checkbox(localize.get(LABEL_OVERWRITE_WARNING), &editSettings.fileIsWarnOverwrite);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_OVERWRITE_WARNING));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Input"))
|
||||
if (ImGui::BeginTabItem(localize.get(LABEL_INPUT)))
|
||||
{
|
||||
if (ImGui::BeginChild("##Tab Child", childSize, true))
|
||||
{
|
||||
ImGui::SeparatorText("Keyboard");
|
||||
ImGui::SeparatorText(localize.get(LABEL_KEYBOARD));
|
||||
|
||||
input_float_range("Repeat Delay (seconds)", editSettings.keyboardRepeatDelay, 0.05f, 1.0f, 0.05f, 0.05f,
|
||||
"%.2f");
|
||||
ImGui::SetItemTooltip("Set how often, after repeating begins, key inputs will be fired.");
|
||||
input_float_range(localize.get(LABEL_REPEAT_DELAY), editSettings.keyboardRepeatDelay, 0.05f, 1.0f, 0.05f,
|
||||
0.05f, "%.2f");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_REPEAT_DELAY));
|
||||
|
||||
input_float_range("Repeat Rate (seconds)", editSettings.keyboardRepeatRate, 0.005f, 1.0f, 0.005f, 0.005f,
|
||||
"%.3f");
|
||||
ImGui::SetItemTooltip("Set how often, after repeating begins, key inputs will be fired.");
|
||||
input_float_range(localize.get(LABEL_REPEAT_RATE), editSettings.keyboardRepeatRate, 0.005f, 1.0f, 0.005f,
|
||||
0.005f, "%.3f");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_REPEAT_DELAY));
|
||||
|
||||
ImGui::SeparatorText("Zoom");
|
||||
ImGui::SeparatorText(localize.get(LABEL_ZOOM));
|
||||
|
||||
input_float_range("Step", editSettings.inputZoomStep, 10.0f, 250.0f, 10.0f, 10.0f, "%.0f%%");
|
||||
ImGui::SetItemTooltip("When zooming in/out with mouse or shortcut, this value will be used.");
|
||||
input_float_range(localize.get(LABEL_ZOOM_STEP), editSettings.inputZoomStep, 10.0f, 250.0f, 10.0f, 10.0f,
|
||||
"%.0f%%");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ZOOM_STEP));
|
||||
|
||||
ImGui::SeparatorText("Tool");
|
||||
ImGui::SeparatorText(localize.get(LABEL_TOOL));
|
||||
|
||||
ImGui::Checkbox("Move Tool: Snap to Mouse", &editSettings.inputIsMoveToolSnapToMouse);
|
||||
ImGui::SetItemTooltip("In Animation Preview, the Move tool will snap the frame's position right to the "
|
||||
"cursor, instead of being moved at a distance.");
|
||||
ImGui::Checkbox(localize.get(LABEL_MOVE_TOOL_SNAP), &editSettings.inputIsMoveToolSnapToMouse);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_MOVE_TOOL_SNAP));
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Shortcuts"))
|
||||
if (ImGui::BeginTabItem(localize.get(LABEL_SHORTCUTS_TAB)))
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2());
|
||||
|
||||
if (ImGui::BeginChild("##Tab Child", childSize, true))
|
||||
{
|
||||
if (ImGui::BeginTable("Shortcuts", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY))
|
||||
if (ImGui::BeginTable(localize.get(LABEL_SHORTCUTS_TAB), 2,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY))
|
||||
{
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("Shortcut");
|
||||
ImGui::TableSetupColumn("Value");
|
||||
ImGui::TableSetupColumn(localize.get(LABEL_SHORTCUT_COLUMN));
|
||||
ImGui::TableSetupColumn(localize.get(LABEL_VALUE_COLUMN));
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (int i = 0; i < SHORTCUT_COUNT; ++i)
|
||||
@@ -465,7 +559,7 @@ namespace anm2ed::imgui
|
||||
ImGui::PushID(i);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::TextUnformatted(SHORTCUT_STRINGS[i]);
|
||||
ImGui::TextUnformatted(localize.get(::anm2ed::SHORTCUT_STRING_TYPES[i]));
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
|
||||
if (ImGui::Selectable(chordString.c_str(), isSelected)) selectedShortcut = i;
|
||||
@@ -509,39 +603,41 @@ namespace anm2ed::imgui
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(3);
|
||||
|
||||
if (ImGui::Button("Save", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_SAVE), widgetSize))
|
||||
{
|
||||
settings = editSettings;
|
||||
imgui::theme_set((theme::Type)editSettings.theme);
|
||||
manager.chords_set(settings);
|
||||
|
||||
ImGui::GetIO().KeyRepeatDelay = settings.keyboardRepeatDelay;
|
||||
ImGui::GetIO().KeyRepeatRate = settings.keyboardRepeatRate;
|
||||
ImGui::GetStyle().FontScaleMain = settings.uiScale;
|
||||
|
||||
SnapshotStack::max_size_set(settings.fileSnapshotStackSize);
|
||||
imgui::theme_set((theme::Type)settings.theme);
|
||||
localize.language = (Language)settings.language;
|
||||
manager.chords_set(settings);
|
||||
|
||||
for (auto& document : manager.documents)
|
||||
document.snapshots.apply_limit();
|
||||
|
||||
configurePopup.close();
|
||||
}
|
||||
ImGui::SetItemTooltip("Use the configured settings.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SETTINGS_SAVE));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Use Default Settings", widgetSize)) editSettings = Settings();
|
||||
ImGui::SetItemTooltip("Reset the settings to their defaults.");
|
||||
if (ImGui::Button(localize.get(LABEL_USE_DEFAULT_SETTINGS), widgetSize)) editSettings = Settings();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_USE_DEFAULT_SETTINGS));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Close", widgetSize)) configurePopup.close();
|
||||
ImGui::SetItemTooltip("Close without updating settings.");
|
||||
if (ImGui::Button(localize.get(LABEL_CLOSE), widgetSize)) configurePopup.close();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CLOSE_SETTINGS));
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
renderPopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(renderPopup.label, &renderPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(renderPopup.label(), &renderPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
auto& ffmpegPath = settings.renderFFmpegPath;
|
||||
auto& path = settings.renderPath;
|
||||
@@ -557,59 +653,6 @@ namespace anm2ed::imgui
|
||||
auto& frames = document->frames.selection;
|
||||
int length = std::max(1, end - start + 1);
|
||||
|
||||
auto ffmpeg_is_executable = [](const std::string& pathString)
|
||||
{
|
||||
if (pathString.empty()) return false;
|
||||
|
||||
std::error_code ec{};
|
||||
auto status = std::filesystem::status(pathString, ec);
|
||||
if (ec || !std::filesystem::is_regular_file(status)) return false;
|
||||
|
||||
#ifndef _WIN32
|
||||
constexpr auto EXEC_PERMS = std::filesystem::perms::owner_exec | std::filesystem::perms::group_exec |
|
||||
std::filesystem::perms::others_exec;
|
||||
if ((status.permissions() & EXEC_PERMS) == std::filesystem::perms::none) return false;
|
||||
#endif
|
||||
return true;
|
||||
};
|
||||
|
||||
auto png_directory_ensure = [](const std::string& directory)
|
||||
{
|
||||
if (directory.empty())
|
||||
{
|
||||
toasts.error("PNG output directory must be set.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec{};
|
||||
auto pathValue = std::filesystem::path(directory);
|
||||
auto exists = std::filesystem::exists(pathValue, ec);
|
||||
|
||||
if (ec)
|
||||
{
|
||||
toasts.error(std::format("Could not access directory: {} ({})", directory, ec.message()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists)
|
||||
{
|
||||
if (!std::filesystem::is_directory(pathValue, ec) || ec)
|
||||
{
|
||||
toasts.error(std::format("PNG output path must be a directory: {}", directory));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!std::filesystem::create_directories(pathValue, ec) || ec)
|
||||
{
|
||||
toasts.error(std::format("Could not create directory: {} ({})", directory, ec.message()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
auto range_to_frames_set = [&]()
|
||||
{
|
||||
if (auto item = document->item_get())
|
||||
@@ -640,11 +683,7 @@ namespace anm2ed::imgui
|
||||
|
||||
auto range_set = [&]()
|
||||
{
|
||||
if (!frames.empty())
|
||||
range_to_frames_set();
|
||||
else if (!isRange)
|
||||
range_to_animation_set();
|
||||
|
||||
if (!isRange) range_to_animation_set();
|
||||
length = std::max(1, end - (start + 1));
|
||||
};
|
||||
|
||||
@@ -698,9 +737,8 @@ namespace anm2ed::imgui
|
||||
if (ImGui::ImageButton("##FFmpeg Path Set", resources.icons[icon::FOLDER].id, icon_size_get()))
|
||||
dialog.file_open(dialog::FFMPEG_PATH_SET);
|
||||
ImGui::SameLine();
|
||||
input_text_string("FFmpeg Path", &ffmpegPath);
|
||||
ImGui::SetItemTooltip("Set the path where the FFmpeg installation is located.\nFFmpeg is required to render "
|
||||
"animations.\nhttps://ffmpeg.org");
|
||||
input_text_string(localize.get(LABEL_FFMPEG_PATH), &ffmpegPath);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_FFMPEG_PATH));
|
||||
dialog.set_string_to_selected_path(ffmpegPath, dialog::FFMPEG_PATH_SET);
|
||||
|
||||
if (ImGui::ImageButton("##Path Set", resources.icons[icon::FOLDER].id, icon_size_get()))
|
||||
@@ -711,89 +749,89 @@ namespace anm2ed::imgui
|
||||
dialog.file_save(dialogType);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
input_text_string(type == render::PNGS ? "Directory" : "Path", &path);
|
||||
ImGui::SetItemTooltip("Set the output path or directory for the animation.");
|
||||
auto pathLabel = type == render::PNGS ? LABEL_OUTPUT_DIRECTORY : LABEL_OUTPUT_PATH;
|
||||
input_text_string(localize.get(pathLabel), &path);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_OUTPUT_PATH));
|
||||
dialog.set_string_to_selected_path(path, dialogType);
|
||||
|
||||
if (ImGui::Combo("Type", &type, render::STRINGS, render::COUNT)) render_set();
|
||||
ImGui::SetItemTooltip("Set the type of the output.");
|
||||
if (ImGui::Combo(localize.get(LABEL_TYPE), &type, render::STRINGS, render::COUNT)) render_set();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_RENDER_TYPE));
|
||||
|
||||
if (type == render::PNGS || type == render::SPRITESHEET) ImGui::Separator();
|
||||
|
||||
if (type == render::PNGS)
|
||||
{
|
||||
if (input_text_string("Format", &format))
|
||||
if (input_text_string(localize.get(LABEL_FORMAT), &format))
|
||||
format = std::filesystem::path(format).replace_extension(".png").string();
|
||||
ImGui::SetItemTooltip(
|
||||
"For outputted images, each image will use this format.\n{} represents the index of each image.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_FORMAT));
|
||||
}
|
||||
else if (type == render::SPRITESHEET)
|
||||
{
|
||||
input_int_range("Rows", rows, 1, length);
|
||||
ImGui::SetItemTooltip("Set how many rows the spritesheet will have.");
|
||||
input_int_range(localize.get(LABEL_GENERATE_ROWS), rows, 1, length);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_ROWS));
|
||||
|
||||
input_int_range("Columns", columns, 1, length);
|
||||
ImGui::SetItemTooltip("Set how many columns the spritesheet will have.");
|
||||
input_int_range(localize.get(LABEL_GENERATE_COLUMNS), columns, 1, length);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_COLUMNS));
|
||||
|
||||
if (ImGui::Button("Set to Recommended")) rows_columns_set();
|
||||
ImGui::SetItemTooltip("Use a recommended value for rows/columns.");
|
||||
if (ImGui::Button(localize.get(LABEL_SET_TO_RECOMMENDED))) rows_columns_set();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SET_TO_RECOMMENDED));
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Checkbox("Custom Range", &isRange))
|
||||
if (ImGui::Checkbox(localize.get(LABEL_CUSTOM_RANGE), &isRange))
|
||||
{
|
||||
range_set();
|
||||
ImGui::SetItemTooltip("Toggle using a custom range for the animation.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_CUSTOM_RANGE));
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(frames.empty());
|
||||
if (ImGui::Button("To Selected Frames")) range_to_frames_set();
|
||||
ImGui::SetItemTooltip("If frames are selected, use that range for the rendered animation.");
|
||||
if (ImGui::Button(localize.get(LABEL_TO_SELECTED_FRAMES))) range_to_frames_set();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_TO_SELECTED_FRAMES));
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("To Animation Range")) range_to_animation_set();
|
||||
ImGui::SetItemTooltip("Set the range to the normal range of the animation.");
|
||||
if (ImGui::Button(localize.get(LABEL_TO_ANIMATION_RANGE))) range_to_animation_set();
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_TO_ANIMATION_RANGE));
|
||||
|
||||
ImGui::BeginDisabled(!isRange);
|
||||
{
|
||||
input_int_range("Start", start, 0, animation->frameNum);
|
||||
ImGui::SetItemTooltip("Set the starting time of the animation.");
|
||||
input_int_range("End", end, start, animation->frameNum);
|
||||
ImGui::SetItemTooltip("Set the ending time of the animation.");
|
||||
input_int_range(localize.get(LABEL_START), start, 0, animation->frameNum);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_START));
|
||||
input_int_range(localize.get(LABEL_END), end, start, animation->frameNum);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_END));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Checkbox("Raw", &isRaw);
|
||||
ImGui::SetItemTooltip("Record only the raw animation; i.e., only its layers, to its bounds.");
|
||||
ImGui::Checkbox(localize.get(LABEL_RAW), &isRaw);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_RAW));
|
||||
|
||||
ImGui::BeginDisabled(!isRaw);
|
||||
{
|
||||
input_float_range("Scale", scale, 1.0f, 100.0f, STEP, STEP_FAST, "%.1fx");
|
||||
ImGui::SetItemTooltip("Set the output scale of the animation.");
|
||||
input_float_range(localize.get(BASIC_SCALE), scale, 1.0f, 100.0f, STEP, STEP_FAST, "%.1fx");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SCALE_OUTPUT));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Checkbox("Sound", &settings.timelineIsSound);
|
||||
ImGui::SetItemTooltip("Toggle sounds playing with triggers.\nBind sounds to events in the Events window.\nThe "
|
||||
"output animation will use the played sounds.");
|
||||
ImGui::Checkbox(localize.get(LABEL_SOUND), &settings.timelineIsSound);
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_SOUND));
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("Render", widgetSize))
|
||||
if (ImGui::Button(localize.get(LABEL_RENDER), widgetSize))
|
||||
{
|
||||
bool isRender = true;
|
||||
if (!ffmpeg_is_executable(ffmpegPath))
|
||||
{
|
||||
toasts.error("FFmpeg path must point to a valid executable file.");
|
||||
toasts.push(localize.get(TOAST_INVALID_FFMPEG_PATH));
|
||||
logger.error(localize.get(TOAST_INVALID_FFMPEG_PATH, anm2ed::ENGLISH));
|
||||
isRender = false;
|
||||
}
|
||||
|
||||
@@ -807,11 +845,11 @@ namespace anm2ed::imgui
|
||||
|
||||
renderPopup.close();
|
||||
}
|
||||
ImGui::SetItemTooltip("Render the animation using the current settings.");
|
||||
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_RENDER_BUTTON));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel", widgetSize)) renderPopup.close();
|
||||
if (ImGui::Button(localize.get(BASIC_CANCEL), widgetSize)) renderPopup.close();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -820,7 +858,7 @@ namespace anm2ed::imgui
|
||||
|
||||
aboutPopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(aboutPopup.label, &aboutPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(aboutPopup.label(), &aboutPopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
static CreditsState creditsState{};
|
||||
|
||||
@@ -834,14 +872,16 @@ namespace anm2ed::imgui
|
||||
if (aboutPopup.isJustOpened) credits_reset();
|
||||
|
||||
auto size = ImGui::GetContentRegionAvail();
|
||||
auto applicationLabel = localize.get(LABEL_APPLICATION_NAME);
|
||||
auto versionLabel = localize.get(LABEL_APPLICATION_VERSION);
|
||||
|
||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE);
|
||||
|
||||
ImGui::SetCursorPosX((size.x - ImGui::CalcTextSize(ANM2ED_LABEL).x) / 2);
|
||||
ImGui::Text(ANM2ED_LABEL);
|
||||
ImGui::SetCursorPosX((size.x - ImGui::CalcTextSize(applicationLabel).x) / 2);
|
||||
ImGui::TextUnformatted(applicationLabel);
|
||||
|
||||
ImGui::SetCursorPosX((size.x - ImGui::CalcTextSize(VERSION_LABEL).x) / 2);
|
||||
ImGui::Text(VERSION_LABEL);
|
||||
ImGui::SetCursorPosX((size.x - ImGui::CalcTextSize(versionLabel).x) / 2);
|
||||
ImGui::TextUnformatted(versionLabel);
|
||||
|
||||
ImGui::PopFont();
|
||||
|
||||
@@ -914,13 +954,13 @@ namespace anm2ed::imgui
|
||||
|
||||
overwritePopup.trigger();
|
||||
|
||||
if (ImGui::BeginPopupModal(overwritePopup.label, &overwritePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
if (ImGui::BeginPopupModal(overwritePopup.label(), &overwritePopup.isOpen, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
ImGui::Text("Are you sure? This will overwrite the existing file.");
|
||||
ImGui::TextUnformatted(localize.get(LABEL_OVERWRITE_CONFIRMATION));
|
||||
|
||||
auto widgetSize = widget_size_with_row_get(2);
|
||||
|
||||
if (ImGui::Button("Yes", widgetSize))
|
||||
if (ImGui::Button(localize.get(BASIC_YES), widgetSize))
|
||||
{
|
||||
manager.save();
|
||||
overwritePopup.close();
|
||||
@@ -928,7 +968,7 @@ namespace anm2ed::imgui
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("No", widgetSize)) overwritePopup.close();
|
||||
if (ImGui::Button(localize.get(BASIC_NO), widgetSize)) overwritePopup.close();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -948,6 +988,3 @@ namespace anm2ed::imgui
|
||||
if (shortcut(manager.chords[SHORTCUT_EXIT], shortcut::GLOBAL)) isQuitting = true;
|
||||
}
|
||||
}
|
||||
#ifndef ANM2ED_USE_LIBXM
|
||||
#define ANM2ED_USE_LIBXM 1
|
||||
#endif
|
||||
|
||||
+9
-6
@@ -6,6 +6,7 @@
|
||||
#include "manager.h"
|
||||
#include "resources.h"
|
||||
#include "settings.h"
|
||||
#include "strings.h"
|
||||
|
||||
namespace anm2ed::imgui
|
||||
{
|
||||
@@ -13,11 +14,13 @@ namespace anm2ed::imgui
|
||||
{
|
||||
Canvas generate;
|
||||
float generateTime{};
|
||||
PopupHelper generatePopup{PopupHelper("Generate Animation from Grid")};
|
||||
PopupHelper overwritePopup{PopupHelper("Overwrite File", imgui::POPUP_SMALL_NO_HEIGHT)};
|
||||
PopupHelper renderPopup{PopupHelper("Render Animation", imgui::POPUP_SMALL_NO_HEIGHT)};
|
||||
PopupHelper configurePopup{PopupHelper("Configure")};
|
||||
PopupHelper aboutPopup{PopupHelper("About")};
|
||||
PopupHelper generatePopup{PopupHelper(LABEL_TASKBAR_GENERATE_ANIMATION_FROM_GRID)};
|
||||
PopupHelper overwritePopup{
|
||||
PopupHelper(LABEL_TASKBAR_OVERWRITE_FILE, imgui::POPUP_SMALL_NO_HEIGHT)};
|
||||
PopupHelper renderPopup{
|
||||
PopupHelper(LABEL_TASKBAR_RENDER_ANIMATION, imgui::POPUP_SMALL_NO_HEIGHT)};
|
||||
PopupHelper configurePopup{PopupHelper(LABEL_TASKBAR_CONFIGURE)};
|
||||
PopupHelper aboutPopup{PopupHelper(LABEL_TASKBAR_ABOUT)};
|
||||
Settings editSettings{};
|
||||
int selectedShortcut{-1};
|
||||
int creditsIndex{};
|
||||
@@ -29,4 +32,4 @@ namespace anm2ed::imgui
|
||||
Taskbar();
|
||||
void update(Manager&, Settings&, Resources&, Dialog&, bool&);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
+1
-18
@@ -66,24 +66,7 @@ namespace anm2ed::imgui
|
||||
}
|
||||
}
|
||||
|
||||
void Toasts::info(const std::string& message)
|
||||
{
|
||||
toasts.emplace_back(Toast(message));
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
void Toasts::error(const std::string& message)
|
||||
{
|
||||
toasts.emplace_back(Toast(message));
|
||||
logger.error(message);
|
||||
}
|
||||
|
||||
void Toasts::warning(const std::string& message)
|
||||
{
|
||||
toasts.emplace_back(Toast(message));
|
||||
logger.warning(message);
|
||||
}
|
||||
|
||||
void Toasts::push(const std::string& message) { toasts.emplace_back(Toast(message)); }
|
||||
}
|
||||
|
||||
anm2ed::imgui::Toasts toasts;
|
||||
|
||||
+1
-3
@@ -20,9 +20,7 @@ namespace anm2ed::imgui
|
||||
std::vector<Toast> toasts{};
|
||||
|
||||
void update();
|
||||
void info(const std::string&);
|
||||
void error(const std::string&);
|
||||
void warning(const std::string&);
|
||||
void push(const std::string&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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