diff --git a/src/anm2/anm2.cpp b/src/anm2/anm2.cpp index a4c286a..f7aefdb 100644 --- a/src/anm2/anm2.cpp +++ b/src/anm2/anm2.cpp @@ -24,20 +24,22 @@ namespace anm2ed::anm2 XMLDocument document; #ifdef _WIN32 - FILE* file = _wfopen(path.native().c_str(), L"wb"); + FILE* file = _wfopen(path.native().c_str(), L"rb"); #else - FILE* file = fopen(path.c_str(), "wb"); + FILE* file = fopen(path.c_str(), "rb"); #endif if (!file) { if (errorString) *errorString = localize.get(ERROR_FILE_NOT_FOUND); + isValid = false; return; } if (document.LoadFile(file) != XML_SUCCESS) { if (errorString) *errorString = document.ErrorStr(); + isValid = false; return; } diff --git a/src/anm2/anm2.h b/src/anm2/anm2.h index 84de141..71f3fbe 100644 --- a/src/anm2/anm2.h +++ b/src/anm2/anm2.h @@ -27,6 +27,7 @@ namespace anm2ed::anm2 class Anm2 { public: + bool isValid{true}; Info info{}; Content content{}; Animations animations{}; diff --git a/src/document.cpp b/src/document.cpp index aa88add..0443b49 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -4,6 +4,7 @@ #include +#include "filesystem_.h" #include "log.h" #include "strings.h" #include "toast.h" @@ -11,33 +12,47 @@ using namespace anm2ed::anm2; using namespace anm2ed::imgui; using namespace anm2ed::types; - using namespace glm; +namespace filesystem = anm2ed::util::filesystem; + namespace anm2ed { - Document::Document(Anm2& anm2, const std::string& path) + Document::Document(Anm2& anm2, const std::filesystem::path& path) { this->anm2 = std::move(anm2); this->path = path; + isValid = this->anm2.isValid; + if (!isValid) return; clean(); change(Document::ALL); } - Document::Document(const std::string& path, bool isNew, std::string* errorString) + Document::Document(const std::filesystem::path& path, bool isNew, std::string* errorString) { if (isNew) { anm2 = anm2::Anm2(); - if (!save(path)) return; + if (!save(path, errorString)) + { + isValid = false; + this->path.clear(); + return; + } } else { anm2 = Anm2(path, errorString); - if (errorString && !errorString->empty()) return; + if (!anm2.isValid) + { + isValid = false; + this->path.clear(); + return; + } } this->path = path; + isValid = anm2.isValid; clean(); change(Document::ALL); } @@ -49,8 +64,8 @@ namespace anm2ed spritesheet(current.spritesheet), frames(current.frames), message(current.message), previewZoom(other.previewZoom), previewPan(other.previewPan), editorPan(other.editorPan), editorZoom(other.editorZoom), overlayIndex(other.overlayIndex), hash(other.hash), saveHash(other.saveHash), - autosaveHash(other.autosaveHash), lastAutosaveTime(other.lastAutosaveTime), isOpen(other.isOpen), - isForceDirty(other.isForceDirty), isAnimationPreviewSet(other.isAnimationPreviewSet), + autosaveHash(other.autosaveHash), lastAutosaveTime(other.lastAutosaveTime), isValid(other.isValid), + isOpen(other.isOpen), isForceDirty(other.isForceDirty), isAnimationPreviewSet(other.isAnimationPreviewSet), isSpritesheetEditorSet(other.isSpritesheetEditorSet) { } @@ -70,6 +85,7 @@ namespace anm2ed saveHash = other.saveHash; autosaveHash = other.autosaveHash; lastAutosaveTime = other.lastAutosaveTime; + isValid = other.isValid; isOpen = other.isOpen; isForceDirty = other.isForceDirty; isAnimationPreviewSet = other.isAnimationPreviewSet; @@ -78,25 +94,26 @@ namespace anm2ed return *this; } - bool Document::save(const std::string& path, std::string* errorString) + bool Document::save(const std::filesystem::path& path, std::string* errorString) { - this->path = !path.empty() ? path : this->path.string(); + this->path = !path.empty() ? path : this->path; - auto absolutePath = this->path.string(); + auto absolutePath = this->path; + auto absolutePathUtf8 = filesystem::path_to_utf8(absolutePath); if (anm2.serialize(absolutePath, errorString)) { - toasts.push(std::vformat(localize.get(TOAST_SAVE_DOCUMENT), std::make_format_args(absolutePath))); - logger.info( - std::vformat(localize.get(TOAST_SAVE_DOCUMENT, anm2ed::ENGLISH), std::make_format_args(absolutePath))); + toasts.push(std::vformat(localize.get(TOAST_SAVE_DOCUMENT), std::make_format_args(absolutePathUtf8))); + logger.info(std::vformat(localize.get(TOAST_SAVE_DOCUMENT, anm2ed::ENGLISH), + std::make_format_args(absolutePathUtf8))); clean(); return true; } else if (errorString) { - toasts.push( - std::vformat(localize.get(TOAST_SAVE_DOCUMENT_FAILED), std::make_format_args(absolutePath, *errorString))); + toasts.push(std::vformat(localize.get(TOAST_SAVE_DOCUMENT_FAILED), + std::make_format_args(absolutePathUtf8, *errorString))); logger.error(std::vformat(localize.get(TOAST_SAVE_DOCUMENT_FAILED, anm2ed::ENGLISH), - std::make_format_args(absolutePath, *errorString))); + std::make_format_args(absolutePathUtf8, *errorString))); } return false; @@ -104,39 +121,41 @@ namespace anm2ed std::filesystem::path Document::autosave_path_get() { - return directory_get() / std::string("." + filename_get().string() + ".autosave"); + auto fileNameUtf8 = filesystem::path_to_utf8(filename_get()); + auto autosaveNameUtf8 = "." + fileNameUtf8 + ".autosave"; + return directory_get() / filesystem::path_from_utf8(autosaveNameUtf8); } std::filesystem::path Document::path_from_autosave_get(std::filesystem::path& path) { - auto fileName = path.filename().string(); + auto fileName = path.filename().u8string(); if (!fileName.empty() && fileName.front() == '.') fileName.erase(fileName.begin()); - auto restorePath = path.parent_path() / fileName; + auto restorePath = path.parent_path() / std::filesystem::path(std::u8string(fileName.begin(), fileName.end())); restorePath.replace_extension(""); - return path; + return restorePath; } bool Document::autosave(std::string* errorString) { auto autosavePath = autosave_path_get(); - auto autosavePathString = autosavePath.string(); - if (anm2.serialize(autosavePathString, errorString)) + auto autosavePathUtf8 = filesystem::path_to_utf8(autosavePath); + if (anm2.serialize(autosavePath, errorString)) { autosaveHash = hash; lastAutosaveTime = 0.0f; toasts.push(localize.get(TOAST_AUTOSAVING)); logger.info(localize.get(TOAST_AUTOSAVING, anm2ed::ENGLISH)); - logger.info(std::format("Autosaved document to: {}", autosavePath.string())); + logger.info(std::format("Autosaved document to: {}", autosavePathUtf8)); return true; } else if (errorString) { - toasts.push( - std::vformat(localize.get(TOAST_AUTOSAVE_FAILED), std::make_format_args(autosavePathString, *errorString))); + toasts.push(std::vformat(localize.get(TOAST_AUTOSAVE_FAILED), + std::make_format_args(autosavePathUtf8, *errorString))); logger.error(std::vformat(localize.get(TOAST_AUTOSAVE_FAILED, anm2ed::ENGLISH), - std::make_format_args(autosavePathString, *errorString))); + std::make_format_args(autosavePathUtf8, *errorString))); } return false; @@ -223,7 +242,7 @@ namespace anm2ed bool Document::is_autosave_dirty() const { return hash != autosaveHash; } std::filesystem::path Document::directory_get() const { return path.parent_path(); } std::filesystem::path Document::filename_get() const { return path.filename(); } - bool Document::is_valid() const { return !path.empty(); } + bool Document::is_valid() const { return isValid && !path.empty(); } anm2::Frame* Document::frame_get() { @@ -237,43 +256,45 @@ namespace anm2ed anm2::Animation* Document::animation_get() { return anm2.animation_get(reference.animationIndex); } anm2::Spritesheet* Document::spritesheet_get() { return anm2.spritesheet_get(spritesheet.reference); } - void Document::spritesheet_add(const std::string& path) + void Document::spritesheet_add(const std::filesystem::path& path) { auto add = [&]() { int id{}; auto pathCopy = path; - if (anm2.spritesheet_add(directory_get().string(), path, id)) + if (anm2.spritesheet_add(directory_get(), path, id)) { anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; - auto path = spritesheet.path.string(); + auto pathString = filesystem::path_to_utf8(spritesheet.path); this->spritesheet.selection = {id}; this->spritesheet.reference = id; - toasts.push(std::vformat(localize.get(TOAST_SPRITESHEET_INITIALIZED), std::make_format_args(id, path))); + toasts.push( + std::vformat(localize.get(TOAST_SPRITESHEET_INITIALIZED), std::make_format_args(id, pathString))); logger.info(std::vformat(localize.get(TOAST_SPRITESHEET_INITIALIZED, anm2ed::ENGLISH), - std::make_format_args(id, path))); + std::make_format_args(id, pathString))); } else { - toasts.push(std::vformat(localize.get(TOAST_SPRITESHEET_INIT_FAILED), std::make_format_args(pathCopy))); + auto pathUtf8 = filesystem::path_to_utf8(pathCopy); + toasts.push(std::vformat(localize.get(TOAST_SPRITESHEET_INIT_FAILED), std::make_format_args(pathUtf8))); logger.error(std::vformat(localize.get(TOAST_SPRITESHEET_INIT_FAILED, anm2ed::ENGLISH), - std::make_format_args(pathCopy))); + std::make_format_args(pathUtf8))); } }; DOCUMENT_EDIT_PTR(this, localize.get(EDIT_ADD_SPRITESHEET), Document::SPRITESHEETS, add()); } - void Document::sound_add(const std::string& path) + void Document::sound_add(const std::filesystem::path& path) { auto add = [&]() { int id{}; auto pathCopy = path; - if (anm2.sound_add(directory_get().string(), path, id)) + if (anm2.sound_add(directory_get(), path, id)) { auto& soundInfo = anm2.content.sounds[id]; - auto soundPath = soundInfo.path.string(); + auto soundPath = filesystem::path_to_utf8(soundInfo.path); sound.selection = {id}; sound.reference = id; toasts.push(std::vformat(localize.get(TOAST_SOUND_INITIALIZED), std::make_format_args(id, soundPath))); @@ -282,9 +303,10 @@ namespace anm2ed } else { - toasts.push(std::vformat(localize.get(TOAST_SOUND_INITIALIZE_FAILED), std::make_format_args(pathCopy))); + auto pathUtf8 = filesystem::path_to_utf8(pathCopy); + toasts.push(std::vformat(localize.get(TOAST_SOUND_INITIALIZE_FAILED), std::make_format_args(pathUtf8))); logger.error(std::vformat(localize.get(TOAST_SOUND_INITIALIZE_FAILED, anm2ed::ENGLISH), - std::make_format_args(pathCopy))); + std::make_format_args(pathUtf8))); } }; diff --git a/src/document.h b/src/document.h index d869ad0..29fff1c 100644 --- a/src/document.h +++ b/src/document.h @@ -58,18 +58,19 @@ namespace anm2ed uint64_t saveHash{}; uint64_t autosaveHash{}; double lastAutosaveTime{}; + bool isValid{true}; bool isOpen{true}; bool isForceDirty{false}; bool isAnimationPreviewSet{false}; bool isSpritesheetEditorSet{false}; - Document(anm2::Anm2& anm2, const std::string&); - Document(const std::string&, bool = false, std::string* = nullptr); + Document(anm2::Anm2& anm2, const std::filesystem::path&); + Document(const std::filesystem::path&, bool = false, std::string* = nullptr); Document(const Document&) = delete; Document& operator=(const Document&) = delete; Document(Document&&) noexcept; Document& operator=(Document&&) noexcept; - bool save(const std::string& = {}, std::string* = nullptr); + bool save(const std::filesystem::path& = {}, std::string* = nullptr); void hash_set(); void clean(); void change(ChangeType); @@ -84,8 +85,8 @@ namespace anm2ed anm2::Spritesheet* spritesheet_get(); anm2::Animation* animation_get(); - void spritesheet_add(const std::string&); - void sound_add(const std::string&); + void spritesheet_add(const std::filesystem::path&); + void sound_add(const std::filesystem::path&); bool autosave(std::string* = nullptr); std::filesystem::path autosave_path_get(); diff --git a/src/imgui/taskbar.cpp b/src/imgui/taskbar.cpp index e883882..048a7b8 100644 --- a/src/imgui/taskbar.cpp +++ b/src/imgui/taskbar.cpp @@ -268,7 +268,7 @@ namespace anm2ed::imgui if (ImGui::MenuItem(localize.get(LABEL_SAVE_AS), settings.shortcutSaveAs.c_str(), false, document)) dialog.file_save(dialog::ANM2_SAVE); if (ImGui::MenuItem(localize.get(LABEL_EXPLORE_XML_LOCATION), nullptr, false, document)) - dialog.file_explorer_open(document->directory_get().string()); + dialog.file_explorer_open(document->directory_get()); ImGui::Separator(); if (ImGui::MenuItem(localize.get(LABEL_EXIT), settings.shortcutExit.c_str())) isQuitting = true; diff --git a/src/imgui/window/sounds.cpp b/src/imgui/window/sounds.cpp index 0ff7e90..63bfa62 100644 --- a/src/imgui/window/sounds.cpp +++ b/src/imgui/window/sounds.cpp @@ -94,7 +94,7 @@ namespace anm2ed::imgui { auto& id = *selection.begin(); anm2::Sound& sound = anm2.content.sounds[id]; - sound = anm2::Sound(document.directory_get().string(), path); + sound = anm2::Sound(document.directory_get(), path); auto pathString = sound.path.string(); toasts.push(std::vformat(localize.get(TOAST_REPLACE_SOUND), std::make_format_args(id, pathString))); logger.info( @@ -129,7 +129,7 @@ namespace anm2ed::imgui { std::string errorString{}; document.snapshot(localize.get(TOAST_SOUNDS_PASTE)); - if (anm2.sounds_deserialize(clipboard.get(), document.directory_get().string(), merge::APPEND, &errorString)) + if (anm2.sounds_deserialize(clipboard.get(), document.directory_get(), merge::APPEND, &errorString)) document.change(Document::SOUNDS); else { diff --git a/src/imgui/window/spritesheets.cpp b/src/imgui/window/spritesheets.cpp index 411754a..c72c39e 100644 --- a/src/imgui/window/spritesheets.cpp +++ b/src/imgui/window/spritesheets.cpp @@ -34,7 +34,7 @@ namespace anm2ed::imgui auto add = [&](const std::filesystem::path& path) { if (path.empty()) return; - document.spritesheet_add(path.string()); + document.spritesheet_add(path); newSpritesheetId = document.spritesheet.reference; }; @@ -87,7 +87,7 @@ namespace anm2ed::imgui { auto& id = *selection.begin(); anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; - spritesheet = anm2::Spritesheet(document.directory_get().string(), path); + spritesheet = anm2::Spritesheet(document.directory_get(), path); 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), @@ -105,7 +105,7 @@ namespace anm2ed::imgui { anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; auto pathString = spritesheet.path.string(); - if (spritesheet.save(document.directory_get().string())) + if (spritesheet.save(document.directory_get())) { 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), @@ -145,7 +145,7 @@ namespace anm2ed::imgui { std::string errorString{}; document.snapshot(localize.get(EDIT_PASTE_SPRITESHEETS)); - if (anm2.spritesheets_deserialize(clipboard.get(), document.directory_get().string(), merge::APPEND, + if (anm2.spritesheets_deserialize(clipboard.get(), document.directory_get(), merge::APPEND, &errorString)) document.change(Document::SPRITESHEETS); else diff --git a/src/manager.cpp b/src/manager.cpp index b198fae..e807b20 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -26,7 +26,9 @@ namespace anm2ed if (parent.empty()) return; std::error_code ec{}; std::filesystem::create_directories(parent, ec); - if (ec) logger.warning(std::format("Could not create directory for {}: {}", path.string(), ec.message())); + if (ec) + logger.warning( + std::format("Could not create directory for {}: {}", filesystem::path_to_utf8(path), ec.message())); } } @@ -70,9 +72,9 @@ namespace anm2ed void Manager::open(const std::filesystem::path& path, bool isNew, bool isRecent) { - const auto pathString = path.string(); std::string errorString{}; - documents.emplace_back(pathString, isNew, &errorString); + documents.emplace_back(path, isNew, &errorString); + auto pathString = filesystem::path_to_utf8(path); auto& document = documents.back(); if (!document.is_valid()) @@ -103,7 +105,7 @@ namespace anm2ed std::string errorString{}; document->path = !path.empty() ? path : document->path; document->path.replace_extension(".anm2"); - document->save(document->path.string(), &errorString); + document->save(document->path, &errorString); recent_file_add(document->path); } } @@ -133,7 +135,9 @@ namespace anm2ed { std::error_code ec{}; std::filesystem::remove(autosavePath, ec); - if (ec) logger.warning(std::format("Could not remove autosave file {}: {}", autosavePath.string(), ec.message())); + if (ec) + logger.warning(std::format("Could not remove autosave file {}: {}", filesystem::path_to_utf8(autosavePath), + ec.message())); } autosave_files_write(); @@ -248,7 +252,7 @@ namespace anm2ed std::vector ordered; ordered.reserve(orderedEntries.size()); for (const auto& [pathString, _] : orderedEntries) - ordered.emplace_back(pathString); + ordered.emplace_back(filesystem::path_from_utf8(pathString)); return ordered; } @@ -258,11 +262,11 @@ namespace anm2ed std::error_code ec{}; if (!std::filesystem::exists(path, ec)) { - logger.warning(std::format("Skipping missing recent file: {}", path.string())); + logger.warning(std::format("Skipping missing recent file: {}", filesystem::path_to_utf8(path))); return; } - recentFiles[path.string()] = ++recentFilesCounter; + recentFiles[filesystem::path_to_utf8(path)] = ++recentFilesCounter; recent_files_trim(); recent_files_write(); } @@ -274,11 +278,12 @@ namespace anm2ed std::ifstream file(path); if (!file) { - logger.warning(std::format("Could not load recent files from: {}. Skipping...", path.string())); + logger.warning( + std::format("Could not load recent files from: {}. Skipping...", filesystem::path_to_utf8(path))); return; } - logger.info(std::format("Loading recent files from: {}", path.string())); + logger.info(std::format("Loading recent files from: {}", filesystem::path_to_utf8(path))); std::string line{}; std::vector loaded{}; @@ -288,14 +293,14 @@ namespace anm2ed { if (line.empty()) continue; if (!line.empty() && line.back() == '\r') line.pop_back(); - std::filesystem::path entry = line; + auto entry = filesystem::path_from_utf8(line); std::error_code ec{}; if (!std::filesystem::exists(entry, ec)) { logger.warning(std::format("Skipping missing recent file: {}", line)); continue; } - auto entryString = entry.string(); + auto entryString = filesystem::path_to_utf8(entry); if (!seen.insert(entryString).second) continue; loaded.emplace_back(std::move(entryString)); } @@ -319,13 +324,14 @@ namespace anm2ed if (!file.is_open()) { - logger.warning(std::format("Could not write recent files to: {}. Skipping...", path.string())); + logger.warning( + std::format("Could not write recent files to: {}. Skipping...", filesystem::path_to_utf8(path))); return; } auto ordered = recent_files_ordered(); for (auto& entry : ordered) - file << entry.string() << '\n'; + file << filesystem::path_to_utf8(entry) << '\n'; } void Manager::recent_files_clear() @@ -339,10 +345,12 @@ namespace anm2ed { for (auto& path : autosaveFiles) { - auto fileName = path.filename().string(); - if (!fileName.empty() && fileName.front() == '.') fileName.erase(fileName.begin()); + auto fileNamePath = path.filename(); + auto fileNameUtf8 = filesystem::path_to_utf8(fileNamePath); + if (!fileNameUtf8.empty() && fileNameUtf8.front() == '.') fileNameUtf8.erase(fileNameUtf8.begin()); + fileNamePath = filesystem::path_from_utf8(fileNameUtf8); - auto restorePath = path.parent_path() / fileName; + auto restorePath = path.parent_path() / fileNamePath; restorePath.replace_extension(""); open(path, false, false); @@ -364,11 +372,12 @@ namespace anm2ed std::ifstream file(path); if (!file) { - logger.warning(std::format("Could not load autosave files from: {}. Skipping...", path.string())); + logger.warning( + std::format("Could not load autosave files from: {}. Skipping...", filesystem::path_to_utf8(path))); return; } - logger.info(std::format("Loading autosave files from: {}", path.string())); + logger.info(std::format("Loading autosave files from: {}", filesystem::path_to_utf8(path))); std::string line{}; @@ -376,7 +385,7 @@ namespace anm2ed { if (line.empty()) continue; if (!line.empty() && line.back() == '\r') line.pop_back(); - std::filesystem::path entry = line; + auto entry = filesystem::path_from_utf8(line); if (std::find(autosaveFiles.begin(), autosaveFiles.end(), entry) != autosaveFiles.end()) continue; autosaveFiles.emplace_back(std::move(entry)); } @@ -389,7 +398,7 @@ namespace anm2ed autosaveWriteFile.open(autosave_path_get(), std::ofstream::out | std::ofstream::trunc); for (auto& path : autosaveFiles) - autosaveWriteFile << path.string() << "\n"; + autosaveWriteFile << filesystem::path_to_utf8(path) << "\n"; autosaveWriteFile.close(); } diff --git a/src/resource/texture.cpp b/src/resource/texture.cpp index 6aae222..f667b41 100644 --- a/src/resource/texture.cpp +++ b/src/resource/texture.cpp @@ -21,11 +21,13 @@ #pragma GCC diagnostic pop #endif +#include "filesystem_.h" #include "math_.h" using namespace anm2ed::resource::texture; using namespace anm2ed::util::math; using namespace glm; +namespace filesystem = anm2ed::util::filesystem; namespace anm2ed::resource { @@ -116,7 +118,8 @@ namespace anm2ed::resource Texture::Texture(const std::filesystem::path& pngPath) { - if (const uint8_t* data = stbi_load(pngPath.string().c_str(), &size.x, &size.y, nullptr, CHANNELS); data) + auto pngPathUtf8 = filesystem::path_to_utf8(pngPath); + if (const uint8_t* data = stbi_load(pngPathUtf8.c_str(), &size.x, &size.y, nullptr, CHANNELS); data) { upload(data); stbi_image_free((void*)data); @@ -125,7 +128,8 @@ namespace anm2ed::resource bool Texture::write_png(const std::filesystem::path& path) { - return stbi_write_png(path.string().c_str(), size.x, size.y, CHANNELS, this->pixels.data(), size.x * CHANNELS); + auto pathUtf8 = filesystem::path_to_utf8(path); + return stbi_write_png(pathUtf8.c_str(), size.x, size.y, CHANNELS, this->pixels.data(), size.x * CHANNELS); } vec4 Texture::pixel_read(vec2 position) const diff --git a/src/settings.cpp b/src/settings.cpp index 3cdc795..ad5ac38 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -5,6 +5,7 @@ using namespace anm2ed::util; using namespace glm; +namespace filesystem = anm2ed::util::filesystem; namespace anm2ed { @@ -121,8 +122,9 @@ DockSpace ID=0x123F8F08 Window=0x6D581B32 Pos=8,62 Size=1902,994 Spl Settings::Settings(const std::filesystem::path& path) { + auto pathUtf8 = filesystem::path_to_utf8(path); if (filesystem::path_is_exist(path)) - logger.info(std::format("Using settings from: {}", path.string())); + logger.info(std::format("Using settings from: {}", pathUtf8)); else { logger.warning("Settings file does not exist; using default"); @@ -133,7 +135,7 @@ DockSpace ID=0x123F8F08 Window=0x6D581B32 Pos=8,62 Size=1902,994 Spl std::ifstream file(path); if (!file.is_open()) { - logger.error(std::format("Failed to open settings file: {}", path.string())); + logger.error(std::format("Failed to open settings file: {}", pathUtf8)); return; } @@ -325,4 +327,4 @@ DockSpace ID=0x123F8F08 Window=0x6D581B32 Pos=8,62 Size=1902,994 Spl file.flush(); file.close(); } -} \ No newline at end of file +} diff --git a/src/state.cpp b/src/state.cpp index 45a6a00..037bc67 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -26,7 +26,7 @@ namespace anm2ed dialog = Dialog(window); for (const auto& argument : arguments) - manager.open(argument); + manager.open(filesystem::path_from_utf8(argument)); manager.chords_set(settings); } @@ -44,10 +44,11 @@ namespace anm2ed { case SDL_EVENT_DROP_FILE: { - auto droppedFile = event.drop.data; - if (filesystem::path_is_extension(droppedFile, "anm2")) + std::string droppedFile = event.drop.data ? event.drop.data : ""; + if (droppedFile.empty()) break; + auto droppedPath = filesystem::path_from_utf8(droppedFile); + if (filesystem::path_is_extension(droppedPath, "anm2")) { - std::filesystem::path droppedPath{droppedFile}; if (manager.documents.empty()) manager.open(droppedPath); else @@ -59,21 +60,21 @@ namespace anm2ed } SDL_FlashWindow(window, SDL_FLASH_UNTIL_FOCUSED); } - else if (filesystem::path_is_extension(droppedFile, "png")) + else if (filesystem::path_is_extension(droppedPath, "png")) { if (auto document = manager.get()) - document->spritesheet_add(droppedFile); + document->spritesheet_add(droppedPath); else { toasts.push(localize.get(TOAST_ADD_SPRITESHEET_FAILED)); logger.warning(localize.get(TOAST_ADD_SPRITESHEET_FAILED, anm2ed::ENGLISH)); } } - else if (filesystem::path_is_extension(droppedFile, "wav") || - filesystem::path_is_extension(droppedFile, "ogg")) + else if (filesystem::path_is_extension(droppedPath, "wav") || + filesystem::path_is_extension(droppedPath, "ogg")) { if (auto document = manager.get()) - document->sound_add(droppedFile); + document->sound_add(droppedPath); else { toasts.push(localize.get(TOAST_ADD_SOUND_FAILED)); @@ -84,10 +85,12 @@ namespace anm2ed } case SDL_EVENT_USER: // Opening files { - auto droppedFile = event.drop.data; - if (filesystem::path_is_extension(droppedFile, "anm2")) + std::string droppedFile = event.drop.data ? event.drop.data : ""; + if (droppedFile.empty()) break; + auto droppedPath = filesystem::path_from_utf8(droppedFile); + if (filesystem::path_is_extension(droppedPath, "anm2")) { - manager.open(droppedFile); + manager.open(droppedPath); SDL_FlashWindow(window, SDL_FLASH_UNTIL_FOCUSED); } break; diff --git a/src/util/filesystem_.cpp b/src/util/filesystem_.cpp index a4471e6..3b5a8e8 100644 --- a/src/util/filesystem_.cpp +++ b/src/util/filesystem_.cpp @@ -22,9 +22,10 @@ namespace anm2ed::util::filesystem std::filesystem::path path_preferences_get() { - auto path = SDL_GetPrefPath(nullptr, "anm2ed"); - auto filePath = std::filesystem::path(path); - SDL_free(path); + auto sdlPath = SDL_GetPrefPath(nullptr, "anm2ed"); + if (!sdlPath) return {}; + auto filePath = path_from_utf8(sdlPath); + SDL_free(sdlPath); return filePath; } @@ -46,6 +47,17 @@ namespace anm2ed::util::filesystem return std::filesystem::path(native); } + std::string path_to_utf8(const std::filesystem::path& path) + { + auto u8 = path.u8string(); + return std::string(u8.begin(), u8.end()); + } + + std::filesystem::path path_from_utf8(const std::string& utf8) + { + return std::filesystem::path(std::u8string(utf8.begin(), utf8.end())); + } + bool path_is_exist(const std::filesystem::path& path) { std::error_code errorCode; @@ -54,9 +66,9 @@ namespace anm2ed::util::filesystem bool path_is_extension(const std::filesystem::path& path, const std::string& extension) { - auto e = std::filesystem::path(path).extension().string(); - std::transform(e.begin(), e.end(), e.begin(), ::tolower); - return e == ("." + extension); + auto extensionUtf8 = path_to_utf8(std::filesystem::path(path).extension()); + std::transform(extensionUtf8.begin(), extensionUtf8.end(), extensionUtf8.begin(), ::tolower); + return extensionUtf8 == ("." + extension); } std::filesystem::path path_lower_case_backslash_handle(const std::filesystem::path& path) diff --git a/src/util/filesystem_.h b/src/util/filesystem_.h index 7aa4a68..0fd6808 100644 --- a/src/util/filesystem_.h +++ b/src/util/filesystem_.h @@ -8,6 +8,8 @@ namespace anm2ed::util::filesystem std::filesystem::path path_preferences_get(); std::filesystem::path path_to_lower(const std::filesystem::path&); std::filesystem::path path_backslash_replace(const std::filesystem::path&); + std::string path_to_utf8(const std::filesystem::path&); + std::filesystem::path path_from_utf8(const std::string&); bool path_is_exist(const std::filesystem::path&); bool path_is_extension(const std::filesystem::path&, const std::string&);