2021-12-07 22:47:41 +01:00
|
|
|
#include "content/views/view_constants.hpp"
|
2021-06-26 01:18:33 +02:00
|
|
|
|
2022-03-04 11:36:37 +01:00
|
|
|
#include <hex/helpers/fs.hpp>
|
2021-08-29 22:15:18 +02:00
|
|
|
#include <hex/helpers/logger.hpp>
|
2021-09-09 12:58:44 +02:00
|
|
|
#include <hex/helpers/utils.hpp>
|
2021-08-29 22:15:18 +02:00
|
|
|
|
2023-03-12 18:43:05 +01:00
|
|
|
#include <wolv/utils/string.hpp>
|
2023-03-23 11:23:07 +01:00
|
|
|
#include <wolv/io/file.hpp>
|
2023-03-12 18:43:05 +01:00
|
|
|
|
2021-06-26 01:18:33 +02:00
|
|
|
#include <filesystem>
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
namespace hex::plugin::builtin {
|
2021-06-26 01:18:33 +02:00
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
ViewConstants::ViewConstants() : View("hex.builtin.view.constants.name") {
|
2021-06-26 01:18:33 +02:00
|
|
|
this->reloadConstants();
|
2021-09-09 12:58:44 +02:00
|
|
|
|
|
|
|
this->m_filter.reserve(0xFFFF);
|
|
|
|
std::memset(this->m_filter.data(), 0x00, this->m_filter.capacity());
|
2021-06-26 01:18:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ViewConstants::reloadConstants() {
|
|
|
|
this->m_constants.clear();
|
2021-09-09 12:58:44 +02:00
|
|
|
this->m_filterIndices.clear();
|
2021-06-26 01:18:33 +02:00
|
|
|
|
2022-03-04 11:36:37 +01:00
|
|
|
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Constants)) {
|
2023-03-12 18:27:29 +01:00
|
|
|
if (!wolv::io::fs::exists(path)) continue;
|
2021-06-26 01:18:33 +02:00
|
|
|
|
2022-03-04 11:36:37 +01:00
|
|
|
std::error_code error;
|
|
|
|
for (auto &file : std::fs::directory_iterator(path, error)) {
|
2021-06-26 01:18:33 +02:00
|
|
|
if (!file.is_regular_file()) continue;
|
|
|
|
|
|
|
|
try {
|
2023-03-23 11:23:07 +01:00
|
|
|
auto fileData = wolv::io::File(file.path(), wolv::io::File::Mode::Read).readString();
|
|
|
|
auto content = nlohmann::json::parse(fileData);
|
2021-06-26 01:18:33 +02:00
|
|
|
|
2023-05-16 11:33:00 +02:00
|
|
|
for (auto value : content.at("values")) {
|
2021-06-26 01:18:33 +02:00
|
|
|
Constant constant;
|
2023-05-16 11:33:00 +02:00
|
|
|
constant.category = content.at("name").get<std::string>();
|
|
|
|
constant.name = value.at("name").get<std::string>();
|
2021-06-26 01:18:33 +02:00
|
|
|
if (value.contains("desc"))
|
2023-05-16 11:33:00 +02:00
|
|
|
constant.description = value.at("desc").get<std::string>();
|
|
|
|
constant.value = value.at("value").get<std::string>();
|
2021-06-26 01:18:33 +02:00
|
|
|
|
2023-05-16 11:33:00 +02:00
|
|
|
auto type = value.at("type");
|
2021-06-26 01:18:33 +02:00
|
|
|
if (type == "int10")
|
|
|
|
constant.type = ConstantType::Int10;
|
|
|
|
else if (type == "int16be")
|
|
|
|
constant.type = ConstantType::Int16BigEndian;
|
|
|
|
else if (type == "int16le")
|
|
|
|
constant.type = ConstantType::Int16LittleEndian;
|
|
|
|
else
|
|
|
|
throw std::runtime_error("Invalid type");
|
|
|
|
|
2021-09-09 12:58:44 +02:00
|
|
|
this->m_filterIndices.push_back(this->m_constants.size());
|
2021-06-26 01:18:33 +02:00
|
|
|
this->m_constants.push_back(constant);
|
|
|
|
}
|
|
|
|
} catch (...) {
|
2023-03-12 18:43:05 +01:00
|
|
|
log::error("Failed to parse constants file {}", wolv::util::toUTF8String(file.path()));
|
2021-06-26 01:18:33 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ViewConstants::drawContent() {
|
2021-12-07 22:47:41 +01:00
|
|
|
if (ImGui::Begin(View::toWindowName("hex.builtin.view.constants.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
2021-06-26 01:18:33 +02:00
|
|
|
|
2023-04-10 21:30:27 +02:00
|
|
|
ImGui::PushItemWidth(-1);
|
2022-01-24 20:53:17 +01:00
|
|
|
ImGui::InputText(
|
|
|
|
"##search", this->m_filter.data(), this->m_filter.capacity(), ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) {
|
|
|
|
auto &view = *static_cast<ViewConstants *>(data->UserData);
|
|
|
|
view.m_filter.resize(data->BufTextLen);
|
|
|
|
|
|
|
|
view.m_filterIndices.clear();
|
|
|
|
for (u64 i = 0; i < view.m_constants.size(); i++) {
|
|
|
|
auto &constant = view.m_constants[i];
|
|
|
|
if (hex::containsIgnoreCase(constant.name, data->Buf) ||
|
|
|
|
hex::containsIgnoreCase(constant.category, data->Buf) ||
|
|
|
|
hex::containsIgnoreCase(constant.description, data->Buf) ||
|
|
|
|
hex::containsIgnoreCase(constant.value, data->Buf))
|
2021-09-09 12:58:44 +02:00
|
|
|
view.m_filterIndices.push_back(i);
|
2022-01-24 20:53:17 +01:00
|
|
|
}
|
2021-09-09 12:58:44 +02:00
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
return 0;
|
|
|
|
},
|
|
|
|
this);
|
2023-04-10 21:30:27 +02:00
|
|
|
ImGui::PopItemWidth();
|
2021-06-26 01:18:33 +02:00
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
if (ImGui::BeginTable("##strings", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
|
2021-06-26 01:18:33 +02:00
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
2021-12-07 22:47:41 +01:00
|
|
|
ImGui::TableSetupColumn("hex.builtin.view.constants.row.category"_lang, 0, -1, ImGui::GetID("category"));
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.view.constants.row.name"_lang, 0, -1, ImGui::GetID("name"));
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.view.constants.row.desc"_lang, 0, -1, ImGui::GetID("desc"));
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.view.constants.row.value"_lang, 0, -1, ImGui::GetID("value"));
|
2021-09-09 12:58:44 +02:00
|
|
|
|
|
|
|
auto sortSpecs = ImGui::TableGetSortSpecs();
|
|
|
|
|
|
|
|
if (sortSpecs->SpecsDirty) {
|
2022-01-24 20:53:17 +01:00
|
|
|
std::sort(this->m_constants.begin(), this->m_constants.end(), [&sortSpecs](Constant &left, Constant &right) -> bool {
|
2021-09-09 12:58:44 +02:00
|
|
|
if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("category")) {
|
|
|
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
|
|
|
return left.category > right.category;
|
|
|
|
else
|
|
|
|
return left.category < right.category;
|
|
|
|
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("name")) {
|
|
|
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
|
|
|
return left.name > right.name;
|
|
|
|
else
|
|
|
|
return left.name < right.name;
|
|
|
|
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("desc")) {
|
|
|
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
|
|
|
return left.description > right.description;
|
|
|
|
else
|
|
|
|
return left.description < right.description;
|
|
|
|
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("value")) {
|
|
|
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
|
|
|
return left.value > right.value;
|
|
|
|
else
|
|
|
|
return left.value < right.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
sortSpecs->SpecsDirty = false;
|
|
|
|
}
|
2021-06-26 01:18:33 +02:00
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
|
|
|
ImGuiListClipper clipper;
|
2021-09-09 12:58:44 +02:00
|
|
|
clipper.Begin(this->m_filterIndices.size());
|
2021-06-26 01:18:33 +02:00
|
|
|
|
|
|
|
while (clipper.Step()) {
|
2022-03-27 00:01:28 +01:00
|
|
|
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
2021-09-09 12:58:44 +02:00
|
|
|
auto &constant = this->m_constants[this->m_filterIndices[i]];
|
2021-06-26 01:18:33 +02:00
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
2021-12-31 01:10:06 +01:00
|
|
|
ImGui::TextUnformatted(constant.category.c_str());
|
2021-06-26 01:18:33 +02:00
|
|
|
ImGui::TableNextColumn();
|
2021-12-31 01:10:06 +01:00
|
|
|
ImGui::TextUnformatted(constant.name.c_str());
|
2021-06-26 01:18:33 +02:00
|
|
|
ImGui::TableNextColumn();
|
2021-12-31 01:10:06 +01:00
|
|
|
ImGui::TextUnformatted(constant.description.c_str());
|
2021-06-26 01:18:33 +02:00
|
|
|
ImGui::TableNextColumn();
|
2021-12-31 01:10:06 +01:00
|
|
|
ImGui::TextUnformatted(constant.value.c_str());
|
2021-06-26 01:18:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
clipper.End();
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ImGui::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|