.........................................................

This commit is contained in:
2025-11-11 22:37:38 -05:00
parent d7c481a20b
commit a1f6bda59d
10 changed files with 74 additions and 43 deletions

View File

@@ -7,6 +7,10 @@
#include "anm2_type.h" #include "anm2_type.h"
#include "types.h" #include "types.h"
#if defined(TRANSPARENT)
#undef TRANSPARENT
#endif
namespace anm2ed::anm2 namespace anm2ed::anm2
{ {
constexpr auto FRAME_DURATION_MIN = 1; constexpr auto FRAME_DURATION_MIN = 1;
@@ -53,4 +57,4 @@ namespace anm2ed::anm2
}; };
#undef MEMBERS #undef MEMBERS
} }

View File

@@ -9,14 +9,14 @@ using namespace tinyxml2;
namespace anm2ed::anm2 namespace anm2ed::anm2
{ {
Sound::Sound(const Sound& other) : path(other.path) { audio = path.empty() ? Audio() : Audio(path.c_str()); } Sound::Sound(const Sound& other) : path(other.path) { audio = path.empty() ? Audio() : Audio(path); }
Sound& Sound::operator=(const Sound& other) Sound& Sound::operator=(const Sound& other)
{ {
if (this != &other) if (this != &other)
{ {
path = other.path; path = other.path;
audio = path.empty() ? Audio() : Audio(path.c_str()); audio = path.empty() ? Audio() : Audio(path);
} }
return *this; return *this;
} }
@@ -26,7 +26,7 @@ namespace anm2ed::anm2
filesystem::WorkingDirectory workingDirectory(directory); filesystem::WorkingDirectory workingDirectory(directory);
this->path = !path.empty() ? std::filesystem::relative(path) : this->path; this->path = !path.empty() ? std::filesystem::relative(path) : this->path;
this->path = filesystem::path_lower_case_backslash_handle(this->path); this->path = filesystem::path_lower_case_backslash_handle(this->path);
audio = Audio(this->path.c_str()); audio = Audio(this->path);
} }
Sound::Sound(const std::filesystem::path& directory, const std::filesystem::path& path) Sound::Sound(const std::filesystem::path& directory, const std::filesystem::path& path)
@@ -40,14 +40,15 @@ namespace anm2ed::anm2
element->QueryIntAttribute("Id", &id); element->QueryIntAttribute("Id", &id);
xml::query_path_attribute(element, "Path", &path); xml::query_path_attribute(element, "Path", &path);
path = filesystem::path_lower_case_backslash_handle(path); path = filesystem::path_lower_case_backslash_handle(path);
audio = Audio(path.c_str()); audio = Audio(path);
} }
XMLElement* Sound::to_element(XMLDocument& document, int id) XMLElement* Sound::to_element(XMLDocument& document, int id)
{ {
auto element = document.NewElement("Sound"); auto element = document.NewElement("Sound");
element->SetAttribute("Id", id); element->SetAttribute("Id", id);
element->SetAttribute("Path", path.c_str()); auto pathString = path.generic_string();
element->SetAttribute("Path", pathString.c_str());
return element; return element;
} }
@@ -63,7 +64,7 @@ namespace anm2ed::anm2
return xml::document_to_string(document); return xml::document_to_string(document);
} }
void Sound::reload(const std::string& directory) { *this = Sound(directory, this->path); } void Sound::reload(const std::filesystem::path& directory) { *this = Sound(directory, this->path); }
bool Sound::is_valid() { return audio.is_valid(); } bool Sound::is_valid() { return audio.is_valid(); }

View File

@@ -27,7 +27,7 @@ namespace anm2ed::anm2
tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int);
std::string to_string(int); std::string to_string(int);
void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int);
void reload(const std::string&); void reload(const std::filesystem::path&);
bool is_valid(); bool is_valid();
void play(); void play();
}; };

View File

@@ -38,7 +38,8 @@ namespace anm2ed::anm2
{ {
auto element = document.NewElement("Spritesheet"); auto element = document.NewElement("Spritesheet");
element->SetAttribute("Id", id); element->SetAttribute("Id", id);
element->SetAttribute("Path", path.c_str()); auto pathString = path.generic_string();
element->SetAttribute("Path", pathString.c_str());
return element; return element;
} }
@@ -57,11 +58,11 @@ namespace anm2ed::anm2
bool Spritesheet::save(const std::string& directory, const std::string& path) bool Spritesheet::save(const std::string& directory, const std::string& path)
{ {
filesystem::WorkingDirectory workingDirectory(directory); filesystem::WorkingDirectory workingDirectory(directory);
this->path = !path.empty() ? std::filesystem::relative(path).string() : this->path.string(); this->path = !path.empty() ? std::filesystem::relative(path) : this->path;
return texture.write_png(this->path); return texture.write_png(this->path);
} }
void Spritesheet::reload(const std::string& directory) { *this = Spritesheet(directory, this->path); } void Spritesheet::reload(const std::filesystem::path& directory) { *this = Spritesheet(directory, this->path); }
bool Spritesheet::is_valid() { return texture.is_valid(); } bool Spritesheet::is_valid() { return texture.is_valid(); }

View File

@@ -25,7 +25,7 @@ namespace anm2ed::anm2
std::string to_string(int id); std::string to_string(int id);
bool save(const std::string&, const std::string& = {}); bool save(const std::string&, const std::string& = {});
void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int);
void reload(const std::string&); void reload(const std::filesystem::path&);
bool is_valid(); bool is_valid();
}; };
} }

View File

@@ -33,11 +33,14 @@ namespace anm2ed::imgui
{ {
auto isSelected = selection.contains(id); auto isSelected = selection.contains(id);
auto isReferenced = reference == id; auto isReferenced = reference == id;
const std::string pathString =
sound.path.empty() ? std::string{anm2::NO_PATH} : sound.path.string();
const char* pathLabel = pathString.c_str();
ImGui::PushID(id); ImGui::PushID(id);
ImGui::SetNextItemSelectionUserData(id); ImGui::SetNextItemSelectionUserData(id);
if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE);
if (ImGui::Selectable(sound.path.c_str(), isSelected)) sound.play(); if (ImGui::Selectable(pathLabel, isSelected)) sound.play();
if (ImGui::IsItemHovered()) hovered = id; if (ImGui::IsItemHovered()) hovered = id;
if (isReferenced) ImGui::PopFont(); if (isReferenced) ImGui::PopFont();
@@ -45,7 +48,7 @@ namespace anm2ed::imgui
if (ImGui::BeginItemTooltip()) if (ImGui::BeginItemTooltip())
{ {
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
ImGui::TextUnformatted(sound.path.c_str()); ImGui::TextUnformatted(pathLabel);
ImGui::PopFont(); ImGui::PopFont();
ImGui::Text("ID: %d", id); ImGui::Text("ID: %d", id);
ImGui::Text("Click to play."); ImGui::Text("Click to play.");

View File

@@ -97,7 +97,9 @@ namespace anm2ed::imgui
auto isReferenced = id == reference; auto isReferenced = id == reference;
auto cursorPos = ImGui::GetCursorPos(); auto cursorPos = ImGui::GetCursorPos();
auto& texture = spritesheet.texture.is_valid() ? spritesheet.texture : resources.icons[icon::NONE]; auto& texture = spritesheet.texture.is_valid() ? spritesheet.texture : resources.icons[icon::NONE];
auto path = spritesheet.path.empty() ? anm2::NO_PATH : spritesheet.path.c_str(); const std::string pathString =
spritesheet.path.empty() ? std::string{anm2::NO_PATH} : spritesheet.path.string();
const char* pathCStr = pathString.c_str();
ImGui::SetNextItemSelectionUserData(id); ImGui::SetNextItemSelectionUserData(id);
ImGui::SetNextItemStorageID(id); ImGui::SetNextItemStorageID(id);
@@ -117,7 +119,7 @@ namespace anm2ed::imgui
else else
textureSize.y = textureSize.x / aspectRatio; textureSize.y = textureSize.x / aspectRatio;
auto textWidth = ImGui::CalcTextSize(path).x; auto textWidth = ImGui::CalcTextSize(pathCStr).x;
auto tooltipPadding = style.WindowPadding.x * 4.0f; auto tooltipPadding = style.WindowPadding.x * 4.0f;
auto minWidth = textureSize.x + style.ItemSpacing.x + textWidth + tooltipPadding; auto minWidth = textureSize.x + style.ItemSpacing.x + textWidth + tooltipPadding;
ImGui::SetNextWindowSize(ImVec2(minWidth, 0), ImGuiCond_Appearing); ImGui::SetNextWindowSize(ImVec2(minWidth, 0), ImGuiCond_Appearing);
@@ -140,7 +142,7 @@ namespace anm2ed::imgui
if (ImGui::BeginChild("##Spritesheet Info Tooltip Child")) if (ImGui::BeginChild("##Spritesheet Info Tooltip Child"))
{ {
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE);
ImGui::TextUnformatted(path); ImGui::TextUnformatted(pathCStr);
ImGui::PopFont(); ImGui::PopFont();
ImGui::Text("ID: %d", id); ImGui::Text("ID: %d", id);
ImGui::Text("Size: %d x %d", texture.size.x, texture.size.y); ImGui::Text("Size: %d x %d", texture.size.x, texture.size.y);
@@ -167,7 +169,7 @@ namespace anm2ed::imgui
spritesheetChildSize.y - spritesheetChildSize.y / 2 - ImGui::GetTextLineHeight() / 2)); spritesheetChildSize.y - spritesheetChildSize.y / 2 - ImGui::GetTextLineHeight() / 2));
if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE);
ImGui::Text(anm2::SPRITESHEET_FORMAT_C, id, path); ImGui::Text(anm2::SPRITESHEET_FORMAT_C, id, pathCStr);
if (isReferenced) ImGui::PopFont(); if (isReferenced) ImGui::PopFont();
context_menu(); context_menu();
@@ -208,7 +210,7 @@ namespace anm2ed::imgui
for (auto& id : selection) for (auto& id : selection)
{ {
anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id];
spritesheet.reload(document.directory_get().string()); spritesheet.reload(document.directory_get());
toasts.info(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string())); toasts.info(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string()));
} }
}; };

View File

@@ -2,9 +2,24 @@
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <string>
#include <string_view>
namespace anm2ed namespace anm2ed
{ {
#if defined(INFO)
#undef INFO
#endif
#if defined(WARNING)
#undef WARNING
#endif
#if defined(ERROR)
#undef ERROR
#endif
#if defined(FATAL)
#undef FATAL
#endif
#define LEVELS \ #define LEVELS \
X(INFO, "[INFO]") \ X(INFO, "[INFO]") \
X(WARNING, "[WARNING]") \ X(WARNING, "[WARNING]") \

View File

@@ -26,16 +26,17 @@ namespace anm2ed
Document* Manager::get(int index) { return vector::find(documents, index > -1 ? index : selected); } Document* Manager::get(int index) { return vector::find(documents, index > -1 ? index : selected); }
void Manager::open(const std::string& path, bool isNew, bool isRecent) void Manager::open(const std::filesystem::path& path, bool isNew, bool isRecent)
{ {
const auto pathString = path.string();
std::string errorString{}; std::string errorString{};
documents.emplace_back(path, isNew, &errorString); documents.emplace_back(pathString, isNew, &errorString);
auto& document = documents.back(); auto& document = documents.back();
if (!document.is_valid()) if (!document.is_valid())
{ {
documents.pop_back(); documents.pop_back();
toasts.error(std::format("Failed to open document: {} ({})", path, errorString)); toasts.error(std::format("Failed to open document: {} ({})", pathString, errorString));
return; return;
} }
@@ -43,23 +44,23 @@ namespace anm2ed
selected = (int)documents.size() - 1; selected = (int)documents.size() - 1;
pendingSelected = selected; pendingSelected = selected;
toasts.info(std::format("Opened document: {}", path)); toasts.info(std::format("Opened document: {}", pathString));
} }
void Manager::new_(const std::string& path) { open(path, true); } void Manager::new_(const std::filesystem::path& path) { open(path, true); }
void Manager::save(int index, const std::string& path) void Manager::save(int index, const std::filesystem::path& path)
{ {
if (auto document = get(index); document) if (auto document = get(index); document)
{ {
std::string errorString{}; std::string errorString{};
document->path = !path.empty() ? path : document->path.string(); document->path = !path.empty() ? path : document->path;
document->save(document->path.string(), &errorString); document->save(document->path.string(), &errorString);
recent_file_add(document->path.string()); recent_file_add(document->path);
} }
} }
void Manager::save(const std::string& path) { save(selected, path); } void Manager::save(const std::filesystem::path& path) { save(selected, path); }
void Manager::autosave(Document& document) void Manager::autosave(Document& document)
{ {
@@ -163,13 +164,14 @@ namespace anm2ed
nullPropertiesPopup.close(); nullPropertiesPopup.close();
} }
void Manager::recent_file_add(const std::string& path) void Manager::recent_file_add(const std::filesystem::path& path)
{ {
if (path.empty()) return; if (path.empty()) return;
const auto pathString = path.string();
std::error_code ec{}; std::error_code ec{};
if (!std::filesystem::exists(path, ec)) if (!std::filesystem::exists(path, ec))
{ {
logger.warning(std::format("Skipping missing recent file: {}", path)); logger.warning(std::format("Skipping missing recent file: {}", pathString));
return; return;
} }
@@ -197,14 +199,15 @@ namespace anm2ed
while (std::getline(file, line)) while (std::getline(file, line))
{ {
if (line.empty()) continue; if (line.empty()) continue;
if (std::find(recentFiles.begin(), recentFiles.end(), line) != recentFiles.end()) continue; std::filesystem::path entry = line;
if (std::find(recentFiles.begin(), recentFiles.end(), entry) != recentFiles.end()) continue;
std::error_code ec{}; std::error_code ec{};
if (!std::filesystem::exists(line, ec)) if (!std::filesystem::exists(entry, ec))
{ {
logger.warning(std::format("Skipping missing recent file: {}", line)); logger.warning(std::format("Skipping missing recent file: {}", line));
continue; continue;
} }
recentFiles.emplace_back(line); recentFiles.emplace_back(std::move(entry));
} }
} }
@@ -221,8 +224,8 @@ namespace anm2ed
return; return;
} }
for (auto& path : recentFiles) for (auto& entry : recentFiles)
file << path.string() << '\n'; file << entry.string() << '\n';
} }
void Manager::recent_files_clear() void Manager::recent_files_clear()
@@ -240,7 +243,7 @@ namespace anm2ed
auto restorePath = path.parent_path() / fileName; auto restorePath = path.parent_path() / fileName;
restorePath.replace_extension(""); restorePath.replace_extension("");
open(path.string(), false, false); open(path, false, false);
if (auto document = get()) if (auto document = get())
{ {
@@ -271,8 +274,9 @@ namespace anm2ed
while (std::getline(file, line)) while (std::getline(file, line))
{ {
if (line.empty()) continue; if (line.empty()) continue;
if (std::find(autosaveFiles.begin(), autosaveFiles.end(), line) != autosaveFiles.end()) continue; std::filesystem::path entry = line;
autosaveFiles.emplace_back(line); if (std::find(autosaveFiles.begin(), autosaveFiles.end(), entry) != autosaveFiles.end()) continue;
autosaveFiles.emplace_back(std::move(entry));
} }
} }

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <filesystem>
#include <vector> #include <vector>
#include "document.h" #include "document.h"
@@ -42,10 +43,10 @@ namespace anm2ed
~Manager(); ~Manager();
Document* get(int = -1); Document* get(int = -1);
void open(const std::string&, bool = false, bool = true); void open(const std::filesystem::path&, bool = false, bool = true);
void new_(const std::string&); void new_(const std::filesystem::path&);
void save(int, const std::string& = {}); void save(int, const std::filesystem::path& = {});
void save(const std::string& = {}); void save(const std::filesystem::path& = {});
void autosave(Document&); void autosave(Document&);
void set(int); void set(int);
void close(int); void close(int);
@@ -61,7 +62,7 @@ namespace anm2ed
void recent_files_load(); void recent_files_load();
void recent_files_write(); void recent_files_write();
void recent_files_clear(); void recent_files_clear();
void recent_file_add(const std::string&); void recent_file_add(const std::filesystem::path&);
void autosave_files_load(); void autosave_files_load();
void autosave_files_open(); void autosave_files_open();