diff --git a/lib/libimhex/include/hex/api/achievement_manager.hpp b/lib/libimhex/include/hex/api/achievement_manager.hpp index d66358a3a..7c0c6e5e3 100644 --- a/lib/libimhex/include/hex/api/achievement_manager.hpp +++ b/lib/libimhex/include/hex/api/achievement_manager.hpp @@ -150,7 +150,7 @@ namespace hex { if (this->m_icon.isValid()) return m_icon; - this->m_icon = ImGuiExt::Texture(this->m_iconData.data(), this->m_iconData.size()); + this->m_icon = ImGuiExt::Texture(this->m_iconData.data(), this->m_iconData.size(), ImGuiExt::Texture::Filter::Linear); return this->m_icon; } diff --git a/lib/libimhex/include/hex/ui/imgui_imhex_extensions.h b/lib/libimhex/include/hex/ui/imgui_imhex_extensions.h index 873d11561..438dd0341 100644 --- a/lib/libimhex/include/hex/ui/imgui_imhex_extensions.h +++ b/lib/libimhex/include/hex/ui/imgui_imhex_extensions.h @@ -70,11 +70,16 @@ namespace ImGuiExt { class Texture { public: + enum class Filter { + Linear, + Nearest + }; + Texture() = default; - Texture(const ImU8 *buffer, int size, int width = 0, int height = 0); - Texture(std::span bytes, int width = 0, int height = 0); - explicit Texture(const char *path); - explicit Texture(const std::fs::path &path); + Texture(const ImU8 *buffer, int size, Filter filter = Filter::Nearest, int width = 0, int height = 0); + Texture(std::span bytes, Filter filter = Filter::Nearest, int width = 0, int height = 0); + explicit Texture(const char *path, Filter filter = Filter::Nearest); + explicit Texture(const std::fs::path &path, Filter filter = Filter::Nearest); Texture(unsigned int texture, int width, int height); Texture(const Texture&) = delete; Texture(Texture&& other) noexcept; diff --git a/lib/libimhex/source/ui/imgui_imhex_extensions.cpp b/lib/libimhex/source/ui/imgui_imhex_extensions.cpp index 6b340ab45..5fef5ae03 100644 --- a/lib/libimhex/source/ui/imgui_imhex_extensions.cpp +++ b/lib/libimhex/source/ui/imgui_imhex_extensions.cpp @@ -22,8 +22,24 @@ namespace ImGuiExt { using namespace ImGui; + + namespace { + + constexpr auto getGLFilter(Texture::Filter filter) { + switch (filter) { + using enum Texture::Filter; + case Nearest: + return GL_NEAREST; + case Linear: + return GL_LINEAR; + } + + return GL_NEAREST; + } + + } - Texture::Texture(const ImU8 *buffer, int size, int width, int height) { + Texture::Texture(const ImU8 *buffer, int size, Filter filter, int width, int height) { unsigned char *imageData = stbi_load_from_memory(buffer, size, &this->m_width, &this->m_height, nullptr, 4); if (imageData == nullptr) { if (width * height * 4 > size) @@ -41,8 +57,8 @@ namespace ImGuiExt { glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter(filter)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter(filter)); #if defined(GL_UNPACK_ROW_LENGTH) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); @@ -54,11 +70,11 @@ namespace ImGuiExt { this->m_textureId = reinterpret_cast(static_cast(texture)); } - Texture::Texture(std::span bytes, int width, int height) : Texture(reinterpret_cast(bytes.data()), bytes.size(), width, height) { } + Texture::Texture(std::span bytes, Filter filter, int width, int height) : Texture(reinterpret_cast(bytes.data()), bytes.size(), filter, width, height) { } - Texture::Texture(const std::fs::path &path) : Texture(reinterpret_cast(path.u8string().c_str())) { } + Texture::Texture(const std::fs::path &path, Filter filter) : Texture(reinterpret_cast(path.u8string().c_str()), filter) { } - Texture::Texture(const char *path) { + Texture::Texture(const char *path, Filter filter) { unsigned char *imageData = stbi_load(path, &this->m_width, &this->m_height, nullptr, 4); if (imageData == nullptr) return; @@ -67,8 +83,8 @@ namespace ImGuiExt { glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter(filter)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter(filter)); #if defined(GL_UNPACK_ROW_LENGTH) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); @@ -962,8 +978,8 @@ namespace ImGuiExt { ImGui::EndChild(); } - bool VSliderAngle(const char* label, ImVec2& size, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags) { - if (format == NULL) + bool VSliderAngle(const char* label, const ImVec2& size, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags) { + if (format == nullptr) format = "%.0f deg"; float v_deg = (*v_rad) * 360.0f / (2 * IM_PI); bool value_changed = ImGui::VSliderFloat(label, size, &v_deg, v_degrees_min, v_degrees_max, format, flags); @@ -1011,7 +1027,7 @@ namespace ImGuiExt { ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImVec2 label_size = CalcTextSize(label, nullptr, true); const ImVec2 size = ImVec2(GetFrameHeight() * 2.0F, GetFrameHeight()); const ImVec2 pos = window->DC.CursorPos; diff --git a/main/gui/source/init/splash_window.cpp b/main/gui/source/init/splash_window.cpp index b71cbc552..55c9da828 100644 --- a/main/gui/source/init/splash_window.cpp +++ b/main/gui/source/init/splash_window.cpp @@ -443,8 +443,8 @@ namespace hex::init { void WindowSplash::initMyself() { // Load splash screen image from romfs - this->splashBackgroundTexture = ImGuiExt::Texture(romfs::get("splash_background.png").span()); - this->splashTextTexture = ImGuiExt::Texture(romfs::get("splash_text.png").span()); + this->splashBackgroundTexture = ImGuiExt::Texture(romfs::get("splash_background.png").span(), ImGuiExt::Texture::Filter::Linear); + this->splashTextTexture = ImGuiExt::Texture(romfs::get("splash_text.png").span(), ImGuiExt::Texture::Filter::Linear); // If the image couldn't be loaded correctly, something went wrong during the build process // Close the application since this would lead to errors later on anyway. diff --git a/main/gui/source/window/window.cpp b/main/gui/source/window/window.cpp index fb116279b..2cba48adc 100644 --- a/main/gui/source/window/window.cpp +++ b/main/gui/source/window/window.cpp @@ -83,7 +83,7 @@ namespace hex { this->setupNativeWindow(); this->registerEventHandlers(); - this->m_logoTexture = ImGuiExt::Texture(romfs::get("logo.png").span()); + this->m_logoTexture = ImGuiExt::Texture(romfs::get("logo.png").span(), ImGuiExt::Texture::Filter::Linear); ContentRegistry::Settings::impl::store(); EventSettingsChanged::post(); diff --git a/plugins/builtin/source/content/data_processor_nodes/other_nodes.cpp b/plugins/builtin/source/content/data_processor_nodes/other_nodes.cpp index 06d51eb06..9af5990c5 100644 --- a/plugins/builtin/source/content/data_processor_nodes/other_nodes.cpp +++ b/plugins/builtin/source/content/data_processor_nodes/other_nodes.cpp @@ -286,7 +286,7 @@ namespace hex::plugin::builtin { void process() override { const auto &rawData = this->getBufferOnInput(0); - this->m_texture = ImGuiExt::Texture(rawData.data(), rawData.size()); + this->m_texture = ImGuiExt::Texture(rawData.data(), rawData.size(), ImGuiExt::Texture::Filter::Nearest); } private: @@ -317,7 +317,7 @@ namespace hex::plugin::builtin { if (requiredBytes > rawData.size()) throwNodeError(hex::format("Image requires at least {} bytes of data, but only {} bytes are available", requiredBytes, rawData.size())); - this->m_texture = ImGuiExt::Texture(rawData.data(), rawData.size(), width, height); + this->m_texture = ImGuiExt::Texture(rawData.data(), rawData.size(), ImGuiExt::Texture::Filter::Nearest, width, height); } private: diff --git a/plugins/builtin/source/content/pl_visualizers/3d_model.cpp b/plugins/builtin/source/content/pl_visualizers/3d_model.cpp index e1aa31ea9..0c4364bab 100644 --- a/plugins/builtin/source/content/pl_visualizers/3d_model.cpp +++ b/plugins/builtin/source/content/pl_visualizers/3d_model.cpp @@ -783,7 +783,7 @@ namespace hex::plugin::builtin { vertexArray.bind(); if (s_shouldUpdateTexture) { s_shouldUpdateTexture = false; - s_modelTexture = ImGuiExt::Texture(s_texturePath); + s_modelTexture = ImGuiExt::Texture(s_texturePath, ImGuiExt::Texture::Filter::Nearest); } if (s_drawTexture) diff --git a/plugins/builtin/source/content/pl_visualizers/coordinates.cpp b/plugins/builtin/source/content/pl_visualizers/coordinates.cpp index 3d8e9ca03..7b0988e68 100644 --- a/plugins/builtin/source/content/pl_visualizers/coordinates.cpp +++ b/plugins/builtin/source/content/pl_visualizers/coordinates.cpp @@ -20,7 +20,7 @@ namespace hex::plugin::builtin { static std::mutex addressMutex; static TaskHolder addressTask; - static auto mapTexture = ImGuiExt::Texture(romfs::get("assets/common/map.jpg").span()); + static auto mapTexture = ImGuiExt::Texture(romfs::get("assets/common/map.jpg").span(), ImGuiExt::Texture::Filter::Linear); static ImVec2 mapSize = scaled(ImVec2(500, 500 / mapTexture.getAspectRatio())); if (shouldReset) { diff --git a/plugins/builtin/source/content/pl_visualizers/image.cpp b/plugins/builtin/source/content/pl_visualizers/image.cpp index 8396af7fc..40cbb01c6 100644 --- a/plugins/builtin/source/content/pl_visualizers/image.cpp +++ b/plugins/builtin/source/content/pl_visualizers/image.cpp @@ -17,7 +17,7 @@ namespace hex::plugin::builtin { auto pattern = arguments[0].toPattern(); auto data = pattern->getBytes(); - texture = ImGuiExt::Texture(data.data(), data.size()); + texture = ImGuiExt::Texture(data.data(), data.size(), ImGuiExt::Texture::Filter::Nearest); scale = 200_scaled / texture.getSize().x; } @@ -43,7 +43,7 @@ namespace hex::plugin::builtin { auto height = arguments[2].toUnsigned(); auto data = pattern->getBytes(); - texture = ImGuiExt::Texture(data.data(), data.size(), width, height); + texture = ImGuiExt::Texture(data.data(), data.size(), ImGuiExt::Texture::Filter::Nearest, width, height); } if (texture.isValid()) diff --git a/plugins/builtin/source/content/providers/process_memory_provider.cpp b/plugins/builtin/source/content/providers/process_memory_provider.cpp index 1f0a1d42d..2c93ac74c 100644 --- a/plugins/builtin/source/content/providers/process_memory_provider.cpp +++ b/plugins/builtin/source/content/providers/process_memory_provider.cpp @@ -163,7 +163,7 @@ namespace hex::plugin::builtin { for (auto &pixel : pixels) pixel = (pixel & 0xFF00FF00) | ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16); - texture = ImGuiExt::Texture(reinterpret_cast(pixels.data()), pixels.size(), bitmap.bmWidth, bitmap.bmHeight); + texture = ImGuiExt::Texture(reinterpret_cast(pixels.data()), pixels.size(), ImGuiExt::Texture::Filter::Nearest, bitmap.bmWidth, bitmap.bmHeight); } } } diff --git a/plugins/builtin/source/content/views/view_about.cpp b/plugins/builtin/source/content/views/view_about.cpp index cbd989462..ddad932e3 100644 --- a/plugins/builtin/source/content/views/view_about.cpp +++ b/plugins/builtin/source/content/views/view_about.cpp @@ -45,7 +45,7 @@ namespace hex::plugin::builtin { // Draw the ImHex icon if (!this->m_logoTexture.isValid()) - this->m_logoTexture = ImGuiExt::Texture(romfs::get("assets/common/logo.png").span()); + this->m_logoTexture = ImGuiExt::Texture(romfs::get("assets/common/logo.png").span(), ImGuiExt::Texture::Filter::Linear); ImGui::Image(this->m_logoTexture, scaled({ 100, 100 })); if (ImGui::IsItemHovered() && ImGui::IsItemClicked()) { @@ -116,9 +116,9 @@ namespace hex::plugin::builtin { }; static std::array DonationPages = { - DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/paypal.png").span()), "https://werwolv.net/donate" }, - DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/github.png").span()), "https://github.com/sponsors/WerWolv" }, - DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/patreon.png").span()), "https://patreon.com/werwolv" }, + DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/paypal.png").span(), ImGuiExt::Texture::Filter::Linear), "https://werwolv.net/donate" }, + DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/github.png").span(), ImGuiExt::Texture::Filter::Linear), "https://github.com/sponsors/WerWolv" }, + DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/patreon.png").span(), ImGuiExt::Texture::Filter::Linear), "https://patreon.com/werwolv" }, }; ImGui::NewLine(); diff --git a/plugins/builtin/source/content/welcome_screen.cpp b/plugins/builtin/source/content/welcome_screen.cpp index e865e62f1..b92a4f68d 100644 --- a/plugins/builtin/source/content/welcome_screen.cpp +++ b/plugins/builtin/source/content/welcome_screen.cpp @@ -513,7 +513,7 @@ namespace hex::plugin::builtin { (void)RequestChangeTheme::subscribe([](const std::string &theme) { auto changeTexture = [&](const std::string &path) { - return ImGuiExt::Texture(romfs::get(path).span()); + return ImGuiExt::Texture(romfs::get(path).span(), ImGuiExt::Texture::Filter::Linear); }; ThemeManager::changeTheme(theme); @@ -639,7 +639,7 @@ namespace hex::plugin::builtin { for (const auto &defaultPath : fs::getDefaultPaths(fs::ImHexPath::Resources)) { const auto infoBannerPath = defaultPath / "info_banner.png"; if (wolv::io::fs::exists(infoBannerPath)) { - s_infoBannerTexture = ImGuiExt::Texture(wolv::util::toUTF8String(infoBannerPath).c_str()); + s_infoBannerTexture = ImGuiExt::Texture(wolv::util::toUTF8String(infoBannerPath).c_str(), ImGuiExt::Texture::Filter::Linear); if (s_infoBannerTexture.isValid()) break; @@ -656,7 +656,7 @@ namespace hex::plugin::builtin { if (response.isSuccess()) { const auto &data = response.getData(); TaskManager::doLater([data] { - s_infoBannerTexture = ImGuiExt::Texture(data.data(), data.size()); + s_infoBannerTexture = ImGuiExt::Texture(data.data(), data.size(), ImGuiExt::Texture::Filter::Linear); }); } });