diff --git a/src/app/core/common.cc b/src/app/core/common.cc index 135f3365..fd2851cc 100644 --- a/src/app/core/common.cc +++ b/src/app/core/common.cc @@ -4,13 +4,20 @@ #include #include +#include #include +#include #include +#include #include #include "absl/status/statusor.h" #include "absl/strings/str_format.h" +#include "absl/strings/string_view.h" #include "app/core/constants.h" +#include "app/gui/icons.h" +#include "imgui/imgui.h" +#include "imgui/misc/cpp/imgui_stdlib.h" namespace yaze { namespace app { @@ -93,6 +100,40 @@ uint32_t ldle3(uint8_t const *const p_arr) { return ldle(p_arr, 3); } } // namespace +std::string UppercaseHexByte(uint8_t byte, bool leading) { + if (leading) { + std::string result = absl::StrFormat("0x%02X", byte); + return result; + } + std::string result = absl::StrFormat("%02X", byte); + return result; +} +std::string UppercaseHexWord(uint16_t word, bool leading) { + if (leading) { + std::string result = absl::StrFormat("0x%04X", word); + return result; + } + std::string result = absl::StrFormat("%04X", word); + return result; +} +std::string UppercaseHexLong(uint32_t dword) { + std::string result = absl::StrFormat("0x%06X", dword); + return result; +} +std::string UppercaseHexLongLong(uint64_t qword) { + std::string result = absl::StrFormat("0x%08X", qword); + return result; +} + +bool StringReplace(std::string &str, const std::string &from, + const std::string &to) { + size_t start = str.find(from); + if (start == std::string::npos) return false; + + str.replace(start, from.length(), to); + return true; +} + std::shared_ptr ExperimentFlags::flags_; uint32_t Get24LocalFromPC(uint8_t *data, int addr, bool pc) { diff --git a/src/app/core/common.h b/src/app/core/common.h index 75b6701d..2cb7cd61 100644 --- a/src/app/core/common.h +++ b/src/app/core/common.h @@ -19,6 +19,14 @@ namespace app { */ namespace core { +std::string UppercaseHexByte(uint8_t byte, bool leading = false); +std::string UppercaseHexWord(uint16_t word, bool leading = false); +std::string UppercaseHexLong(uint32_t dword); +std::string UppercaseHexLongLong(uint64_t qword); + +bool StringReplace(std::string &str, const std::string &from, + const std::string &to); + /** * @class ExperimentFlags * @brief A class to manage experimental feature flags. diff --git a/src/app/core/core.cmake b/src/app/core/core.cmake index 4afed1ab..e9a18c68 100644 --- a/src/app/core/core.cmake +++ b/src/app/core/core.cmake @@ -2,7 +2,6 @@ set( YAZE_APP_CORE_SRC app/core/common.cc app/core/controller.cc - app/core/labeling.cc app/emu/emulator.cc app/core/project.cc app/core/utils/file_util.cc diff --git a/src/app/core/labeling.cc b/src/app/core/labeling.cc deleted file mode 100644 index 884083a7..00000000 --- a/src/app/core/labeling.cc +++ /dev/null @@ -1,178 +0,0 @@ -#include "app/core/labeling.h" - -#include -#include -#include -#include -#include - -#include "absl/strings/str_format.h" - -#include "app/gui/icons.h" -#include "imgui/imgui.h" -#include "imgui/misc/cpp/imgui_stdlib.h" - -namespace yaze { -namespace app { -namespace core { - -std::string UppercaseHexByte(uint8_t byte, bool leading) { - if (leading) { - std::string result = absl::StrFormat("0x%02X", byte); - return result; - } - std::string result = absl::StrFormat("%02X", byte); - return result; -} -std::string UppercaseHexWord(uint16_t word, bool leading) { - if (leading) { - std::string result = absl::StrFormat("0x%04X", word); - return result; - } - std::string result = absl::StrFormat("%04X", word); - return result; -} -std::string UppercaseHexLong(uint32_t dword) { - std::string result = absl::StrFormat("0x%06X", dword); - return result; -} -std::string UppercaseHexLongLong(uint64_t qword) { - std::string result = absl::StrFormat("0x%08X", qword); - return result; -} - -bool StringReplace(std::string& str, const std::string& from, - const std::string& to) { - size_t start = str.find(from); - if (start == std::string::npos) return false; - - str.replace(start, from.length(), to); - return true; -} - -bool ResourceLabelManager::LoadLabels(const std::string& filename) { - std::ifstream file(filename); - if (!file.is_open()) { - // Create the file if it does not exist - std::ofstream create_file(filename); - if (!create_file.is_open()) { - return false; - } - create_file.close(); - file.open(filename); - if (!file.is_open()) { - return false; - } - } - filename_ = filename; - - std::string line; - while (std::getline(file, line)) { - std::istringstream iss(line); - std::string type, key, value; - if (std::getline(iss, type, ',') && std::getline(iss, key, ',') && - std::getline(iss, value)) { - labels_[type][key] = value; - } - } - labels_loaded_ = true; - return true; -} - -bool ResourceLabelManager::SaveLabels() { - if (!labels_loaded_) { - return false; - } - std::ofstream file(filename_); - if (!file.is_open()) { - return false; - } - for (const auto& type_pair : labels_) { - for (const auto& label_pair : type_pair.second) { - file << type_pair.first << "," << label_pair.first << "," - << label_pair.second << std::endl; - } - } - file.close(); - return true; -} - -void ResourceLabelManager::DisplayLabels(bool* p_open) { - if (!labels_loaded_) { - ImGui::Text("No labels loaded."); - return; - } - - if (ImGui::Begin("Resource Labels", p_open)) { - for (const auto& type_pair : labels_) { - if (ImGui::TreeNode(type_pair.first.c_str())) { - for (const auto& label_pair : type_pair.second) { - std::string label_id = type_pair.first + "_" + label_pair.first; - ImGui::Text("%s: %s", label_pair.first.c_str(), - label_pair.second.c_str()); - } - ImGui::TreePop(); - } - } - - if (ImGui::Button("Update Labels")) { - if (SaveLabels()) { - ImGui::Text("Labels updated successfully!"); - } else { - ImGui::Text("Failed to update labels."); - } - } - } - ImGui::End(); -} - -void ResourceLabelManager::EditLabel(const std::string& type, - const std::string& key, - const std::string& newValue) { - labels_[type][key] = newValue; -} - -void ResourceLabelManager::SelectableLabelWithNameEdit( - bool selected, const std::string& type, const std::string& key, - const std::string& defaultValue) { - std::string label = CreateOrGetLabel(type, key, defaultValue); - ImGui::Selectable(label.c_str(), selected, - ImGuiSelectableFlags_AllowDoubleClick); - std::string label_id = type + "_" + key; - if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) { - ImGui::OpenPopup(label_id.c_str()); - } - - if (ImGui::BeginPopupContextItem(label_id.c_str())) { - std::string* new_label = &labels_[type][key]; - if (ImGui::InputText("##Label", new_label, - ImGuiInputTextFlags_EnterReturnsTrue)) { - labels_[type][key] = *new_label; - } - if (ImGui::Button(ICON_MD_CLOSE)) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); - } -} - -std::string ResourceLabelManager::GetLabel(const std::string& type, - const std::string& key) { - return labels_[type][key]; -} - -std::string ResourceLabelManager::CreateOrGetLabel( - const std::string& type, const std::string& key, - const std::string& defaultValue) { - if (labels_.find(type) == labels_.end()) { - labels_[type] = std::unordered_map(); - } - if (labels_[type].find(key) == labels_[type].end()) { - labels_[type][key] = defaultValue; - } - return labels_[type][key]; -} - -} // namespace core -} // namespace app -} // namespace yaze diff --git a/src/app/core/labeling.h b/src/app/core/labeling.h deleted file mode 100644 index 282a442b..00000000 --- a/src/app/core/labeling.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef YAZE_APP_CORE_LABELING_H_ -#define YAZE_APP_CORE_LABELING_H_ - -#include -#include -#include - -#include "absl/strings/string_view.h" - -namespace yaze { -namespace app { -namespace core { - -std::string UppercaseHexByte(uint8_t byte, bool leading = false); -std::string UppercaseHexWord(uint16_t word, bool leading = false); -std::string UppercaseHexLong(uint32_t dword); -std::string UppercaseHexLongLong(uint64_t qword); - -bool StringReplace(std::string& str, const std::string& from, - const std::string& to); - -// Default types -static constexpr absl::string_view kDefaultTypes[] = { - "Dungeon Names", "Dungeon Room Names", "Overworld Map Names"}; - -struct ResourceLabelManager { - bool LoadLabels(const std::string& filename); - bool SaveLabels(); - void DisplayLabels(bool* p_open); - void EditLabel(const std::string& type, const std::string& key, - const std::string& newValue); - void SelectableLabelWithNameEdit(bool selected, const std::string& type, - const std::string& key, - const std::string& defaultValue); - std::string GetLabel(const std::string& type, const std::string& key); - std::string CreateOrGetLabel(const std::string& type, const std::string& key, - const std::string& defaultValue); - - bool labels_loaded_ = false; - std::string filename_; - struct ResourceType { - std::string key_name; - std::string display_description; - }; - - std::unordered_map> - labels_; -}; - -} // namespace core -} // namespace app -} // namespace yaze - -#endif // YAZE_APP_CORE_LABELING_H_ diff --git a/src/app/core/project.cc b/src/app/core/project.cc index 508d4ec0..406dd1cd 100644 --- a/src/app/core/project.cc +++ b/src/app/core/project.cc @@ -1,9 +1,16 @@ #include "project.h" +#include +#include + +#include "app/gui/icons.h" +#include "imgui/imgui.h" +#include "imgui/misc/cpp/imgui_stdlib.h" + namespace yaze { namespace app { -absl::Status Project::Open(const std::string &project_path) { +absl::Status Project::Open(const std::string& project_path) { filepath = project_path; name = project_path.substr(project_path.find_last_of("/") + 1); @@ -54,5 +61,128 @@ absl::Status Project::Save() { return absl::OkStatus(); } +bool ResourceLabelManager::LoadLabels(const std::string& filename) { + std::ifstream file(filename); + if (!file.is_open()) { + // Create the file if it does not exist + std::ofstream create_file(filename); + if (!create_file.is_open()) { + return false; + } + create_file.close(); + file.open(filename); + if (!file.is_open()) { + return false; + } + } + filename_ = filename; + + std::string line; + while (std::getline(file, line)) { + std::istringstream iss(line); + std::string type, key, value; + if (std::getline(iss, type, ',') && std::getline(iss, key, ',') && + std::getline(iss, value)) { + labels_[type][key] = value; + } + } + labels_loaded_ = true; + return true; +} + +bool ResourceLabelManager::SaveLabels() { + if (!labels_loaded_) { + return false; + } + std::ofstream file(filename_); + if (!file.is_open()) { + return false; + } + for (const auto& type_pair : labels_) { + for (const auto& label_pair : type_pair.second) { + file << type_pair.first << "," << label_pair.first << "," + << label_pair.second << std::endl; + } + } + file.close(); + return true; +} + +void ResourceLabelManager::DisplayLabels(bool* p_open) { + if (!labels_loaded_) { + ImGui::Text("No labels loaded."); + return; + } + + if (ImGui::Begin("Resource Labels", p_open)) { + for (const auto& type_pair : labels_) { + if (ImGui::TreeNode(type_pair.first.c_str())) { + for (const auto& label_pair : type_pair.second) { + std::string label_id = type_pair.first + "_" + label_pair.first; + ImGui::Text("%s: %s", label_pair.first.c_str(), + label_pair.second.c_str()); + } + ImGui::TreePop(); + } + } + + if (ImGui::Button("Update Labels")) { + if (SaveLabels()) { + ImGui::Text("Labels updated successfully!"); + } else { + ImGui::Text("Failed to update labels."); + } + } + } + ImGui::End(); +} + +void ResourceLabelManager::EditLabel(const std::string& type, + const std::string& key, + const std::string& newValue) { + labels_[type][key] = newValue; +} + +void ResourceLabelManager::SelectableLabelWithNameEdit( + bool selected, const std::string& type, const std::string& key, + const std::string& defaultValue) { + std::string label = CreateOrGetLabel(type, key, defaultValue); + ImGui::Selectable(label.c_str(), selected, + ImGuiSelectableFlags_AllowDoubleClick); + std::string label_id = type + "_" + key; + if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) { + ImGui::OpenPopup(label_id.c_str()); + } + + if (ImGui::BeginPopupContextItem(label_id.c_str())) { + std::string* new_label = &labels_[type][key]; + if (ImGui::InputText("##Label", new_label, + ImGuiInputTextFlags_EnterReturnsTrue)) { + labels_[type][key] = *new_label; + } + if (ImGui::Button(ICON_MD_CLOSE)) { + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } +} + +std::string ResourceLabelManager::GetLabel(const std::string& type, + const std::string& key) { + return labels_[type][key]; +} + +std::string ResourceLabelManager::CreateOrGetLabel( + const std::string& type, const std::string& key, + const std::string& defaultValue) { + if (labels_.find(type) == labels_.end()) { + labels_[type] = std::unordered_map(); + } + if (labels_[type].find(key) == labels_[type].end()) { + labels_[type][key] = defaultValue; + } + return labels_[type][key]; +} + } // namespace app } // namespace yaze diff --git a/src/app/core/project.h b/src/app/core/project.h index cc60d178..573de3a8 100644 --- a/src/app/core/project.h +++ b/src/app/core/project.h @@ -65,6 +65,34 @@ struct Project : public core::ExperimentFlags { std::string keybindings_file = ""; }; +// Default types +static constexpr absl::string_view kDefaultTypes[] = { + "Dungeon Names", "Dungeon Room Names", "Overworld Map Names"}; + +struct ResourceLabelManager { + bool LoadLabels(const std::string& filename); + bool SaveLabels(); + void DisplayLabels(bool* p_open); + void EditLabel(const std::string& type, const std::string& key, + const std::string& newValue); + void SelectableLabelWithNameEdit(bool selected, const std::string& type, + const std::string& key, + const std::string& defaultValue); + std::string GetLabel(const std::string& type, const std::string& key); + std::string CreateOrGetLabel(const std::string& type, const std::string& key, + const std::string& defaultValue); + + bool labels_loaded_ = false; + std::string filename_; + struct ResourceType { + std::string key_name; + std::string display_description; + }; + + std::unordered_map> + labels_; +}; + class RecentFilesManager { public: RecentFilesManager() : RecentFilesManager(kRecentFilesFilename) {} diff --git a/src/app/editor/dungeon/dungeon_editor.cc b/src/app/editor/dungeon/dungeon_editor.cc index 817b1423..dacbf4b1 100644 --- a/src/app/editor/dungeon/dungeon_editor.cc +++ b/src/app/editor/dungeon/dungeon_editor.cc @@ -1,6 +1,5 @@ #include "dungeon_editor.h" -#include "app/core/labeling.h" #include "app/core/platform/renderer.h" #include "app/gfx/snes_palette.h" #include "app/gui/canvas.h" diff --git a/src/app/editor/dungeon/dungeon_editor.h b/src/app/editor/dungeon/dungeon_editor.h index 3e5536ba..f4d0ef89 100644 --- a/src/app/editor/dungeon/dungeon_editor.h +++ b/src/app/editor/dungeon/dungeon_editor.h @@ -2,7 +2,7 @@ #define YAZE_APP_EDITOR_DUNGEONEDITOR_H #include "app/core/common.h" -#include "app/core/labeling.h" +#include "app/core/project.h" #include "app/editor/graphics/gfx_group_editor.h" #include "app/editor/graphics/palette_editor.h" #include "app/editor/utils/editor.h" diff --git a/src/app/rom.h b/src/app/rom.h index ee7733db..62018069 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -21,7 +21,7 @@ #include "absl/strings/string_view.h" #include "app/core/common.h" #include "app/core/constants.h" -#include "app/core/labeling.h" +#include "app/core/project.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" #include "app/gfx/snes_tile.h" @@ -476,9 +476,7 @@ class Rom : public core::ExperimentFlags { return palette_groups_.dungeon_main.mutable_palette(i); } - core::ResourceLabelManager* resource_label() { - return &resource_label_manager_; - } + ResourceLabelManager* resource_label() { return &resource_label_manager_; } VersionConstants version_constants() const { return kVersionConstantsMap.at(version_); } @@ -561,7 +559,7 @@ class Rom : public core::ExperimentFlags { std::array link_graphics_; // Label manager for unique resource names. - core::ResourceLabelManager resource_label_manager_; + ResourceLabelManager resource_label_manager_; // All palette groups in the game gfx::PaletteGroupMap palette_groups_; diff --git a/src/cli/z3ed.cmake b/src/cli/z3ed.cmake index 2eb41974..633b3286 100644 --- a/src/cli/z3ed.cmake +++ b/src/cli/z3ed.cmake @@ -6,7 +6,6 @@ add_executable( cli/handlers/tile16_transfer.cc app/rom.cc app/core/common.cc - app/core/labeling.cc app/editor/utils/gfx_context.cc ${YAZE_APP_EMU_SRC} ${YAZE_APP_GFX_SRC} diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 90570018..42662524 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -11,7 +11,6 @@ add_executable( test/zelda3/sprite_builder_test.cc app/rom.cc app/core/common.cc - app/core/labeling.cc app/editor/utils/gfx_context.cc ${ASAR_STATIC_SRC} ${YAZE_APP_CORE_SRC}