#include #include #include #include #include namespace hex::plugin::builtin { class NodeDisplayInteger : public dp::Node { public: NodeDisplayInteger() : Node("hex.builtin.nodes.display.int.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "hex.builtin.nodes.common.input") }) { } void drawNode() override { ImGui::PushItemWidth(150_scaled); if (this->m_value.has_value()) ImGuiExt::TextFormatted("0x{0:X}", this->m_value.value()); else ImGui::TextUnformatted("???"); ImGui::PopItemWidth(); } void process() override { this->m_value.reset(); const auto &input = this->getIntegerOnInput(0); this->m_value = input; } private: std::optional m_value; }; class NodeDisplayFloat : public dp::Node { public: NodeDisplayFloat() : Node("hex.builtin.nodes.display.float.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Float, "hex.builtin.nodes.common.input") }) { } void drawNode() override { ImGui::PushItemWidth(150_scaled); if (this->m_value.has_value()) ImGuiExt::TextFormatted("{0}", this->m_value.value()); else ImGui::TextUnformatted("???"); ImGui::PopItemWidth(); } void process() override { this->m_value.reset(); const auto &input = this->getFloatOnInput(0); this->m_value = input; } private: std::optional m_value; }; class NodeDisplayBuffer : public dp::Node { public: NodeDisplayBuffer() : Node("hex.builtin.nodes.display.buffer.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input") }) { } void drawNode() override { static const std::string Header = " Address 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "; if (ImGui::BeginChild("##hex_view", scaled(ImVec2(ImGui::CalcTextSize(Header.c_str()).x, 200)), true)) { ImGui::TextUnformatted(Header.c_str()); auto size = this->m_buffer.size(); ImGuiListClipper clipper; clipper.Begin((size + 0x0F) / 0x10); while (clipper.Step()) for (auto y = clipper.DisplayStart; y < clipper.DisplayEnd; y++) { auto lineSize = ((size - y * 0x10) < 0x10) ? size % 0x10 : 0x10; std::string line = hex::format(" {:08X}: ", y * 0x10); for (u32 x = 0; x < 0x10; x++) { if (x < lineSize) line += hex::format("{:02X} ", this->m_buffer[y * 0x10 + x]); else line += " "; if (x == 7) line += " "; } line += " "; for (u32 x = 0; x < lineSize; x++) { auto c = char(this->m_buffer[y * 0x10 + x]); if (std::isprint(c)) line += c; else line += "."; } ImGui::TextUnformatted(line.c_str()); } clipper.End(); } ImGui::EndChild(); } void process() override { this->m_buffer = this->getBufferOnInput(0); } private: std::vector m_buffer; }; class NodeDisplayString : public dp::Node { public: NodeDisplayString() : Node("hex.builtin.nodes.display.string.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input") }) { } void drawNode() override { constexpr static auto LineLength = 50; if (ImGui::BeginChild("##string_view", scaled(ImVec2(ImGui::CalcTextSize(" ").x * (LineLength + 4), 150)), true)) { std::string_view string = this->m_value; ImGuiListClipper clipper; clipper.Begin((string.length() + (LineLength - 1)) / LineLength); while (clipper.Step()) for (auto i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { auto line = string.substr(i * LineLength, LineLength); ImGui::TextUnformatted(""); ImGui::SameLine(); ImGui::TextUnformatted(line.data(), line.data() + line.length()); } clipper.End(); } ImGui::EndChild(); } void process() override { const auto &input = this->getBufferOnInput(0); this->m_value = hex::encodeByteString(input); } private: std::string m_value; }; class NodeDisplayBits : public dp::Node { public: NodeDisplayBits() : Node("hex.builtin.nodes.display.bits.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input") }) { } void drawNode() override { ImGui::PushItemWidth(100_scaled); ImGui::Text("%s", this->m_display.c_str()); ImGui::PopItemWidth(); } void process() override { const auto &buffer = this->getBufferOnInput(0); // Display bits in groups of 4 bits std::string display; display.reserve(buffer.size() * 9 + 2); // 8 bits + 1 space at beginning + 1 space every 4 bits for (const auto &byte : buffer) { for (size_t i = 0; i < 8; i++) { if (i % 4 == 0) { display += ' '; } display += (byte & (1 << i)) != 0 ? '1' : '0'; } } this->m_display = wolv::util::trim(display); } private: std::string m_display = "???"; }; void registerVisualDataProcessorNodes() { ContentRegistry::DataProcessorNode::add("hex.builtin.nodes.display", "hex.builtin.nodes.display.int"); ContentRegistry::DataProcessorNode::add("hex.builtin.nodes.display", "hex.builtin.nodes.display.float"); ContentRegistry::DataProcessorNode::add("hex.builtin.nodes.display", "hex.builtin.nodes.display.buffer"); ContentRegistry::DataProcessorNode::add("hex.builtin.nodes.display", "hex.builtin.nodes.display.string"); ContentRegistry::DataProcessorNode::add("hex.builtin.nodes.display", "hex.builtin.nodes.display.bits"); } }