impr: Add support for specifying filtering mode when loading textures
This commit is contained in:
parent
e49c3182ce
commit
ef7898ea8d
@ -150,7 +150,7 @@ namespace hex {
|
|||||||
if (this->m_icon.isValid())
|
if (this->m_icon.isValid())
|
||||||
return m_icon;
|
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;
|
return this->m_icon;
|
||||||
}
|
}
|
||||||
|
@ -70,11 +70,16 @@ namespace ImGuiExt {
|
|||||||
|
|
||||||
class Texture {
|
class Texture {
|
||||||
public:
|
public:
|
||||||
|
enum class Filter {
|
||||||
|
Linear,
|
||||||
|
Nearest
|
||||||
|
};
|
||||||
|
|
||||||
Texture() = default;
|
Texture() = default;
|
||||||
Texture(const ImU8 *buffer, int size, int width = 0, int height = 0);
|
Texture(const ImU8 *buffer, int size, Filter filter = Filter::Nearest, int width = 0, int height = 0);
|
||||||
Texture(std::span<const std::byte> bytes, int width = 0, int height = 0);
|
Texture(std::span<const std::byte> bytes, Filter filter = Filter::Nearest, int width = 0, int height = 0);
|
||||||
explicit Texture(const char *path);
|
explicit Texture(const char *path, Filter filter = Filter::Nearest);
|
||||||
explicit Texture(const std::fs::path &path);
|
explicit Texture(const std::fs::path &path, Filter filter = Filter::Nearest);
|
||||||
Texture(unsigned int texture, int width, int height);
|
Texture(unsigned int texture, int width, int height);
|
||||||
Texture(const Texture&) = delete;
|
Texture(const Texture&) = delete;
|
||||||
Texture(Texture&& other) noexcept;
|
Texture(Texture&& other) noexcept;
|
||||||
|
@ -22,8 +22,24 @@
|
|||||||
namespace ImGuiExt {
|
namespace ImGuiExt {
|
||||||
|
|
||||||
using namespace ImGui;
|
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);
|
unsigned char *imageData = stbi_load_from_memory(buffer, size, &this->m_width, &this->m_height, nullptr, 4);
|
||||||
if (imageData == nullptr) {
|
if (imageData == nullptr) {
|
||||||
if (width * height * 4 > size)
|
if (width * height * 4 > size)
|
||||||
@ -41,8 +57,8 @@ namespace ImGuiExt {
|
|||||||
glGenTextures(1, &texture);
|
glGenTextures(1, &texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter(filter));
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter(filter));
|
||||||
|
|
||||||
#if defined(GL_UNPACK_ROW_LENGTH)
|
#if defined(GL_UNPACK_ROW_LENGTH)
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
@ -54,11 +70,11 @@ namespace ImGuiExt {
|
|||||||
this->m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
|
this->m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(std::span<const std::byte> bytes, int width, int height) : Texture(reinterpret_cast<const ImU8*>(bytes.data()), bytes.size(), width, height) { }
|
Texture::Texture(std::span<const std::byte> bytes, Filter filter, int width, int height) : Texture(reinterpret_cast<const ImU8*>(bytes.data()), bytes.size(), filter, width, height) { }
|
||||||
|
|
||||||
Texture::Texture(const std::fs::path &path) : Texture(reinterpret_cast<const char *>(path.u8string().c_str())) { }
|
Texture::Texture(const std::fs::path &path, Filter filter) : Texture(reinterpret_cast<const char *>(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);
|
unsigned char *imageData = stbi_load(path, &this->m_width, &this->m_height, nullptr, 4);
|
||||||
if (imageData == nullptr)
|
if (imageData == nullptr)
|
||||||
return;
|
return;
|
||||||
@ -67,8 +83,8 @@ namespace ImGuiExt {
|
|||||||
glGenTextures(1, &texture);
|
glGenTextures(1, &texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter(filter));
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter(filter));
|
||||||
|
|
||||||
#if defined(GL_UNPACK_ROW_LENGTH)
|
#if defined(GL_UNPACK_ROW_LENGTH)
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
@ -962,8 +978,8 @@ namespace ImGuiExt {
|
|||||||
ImGui::EndChild();
|
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) {
|
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 == NULL)
|
if (format == nullptr)
|
||||||
format = "%.0f deg";
|
format = "%.0f deg";
|
||||||
float v_deg = (*v_rad) * 360.0f / (2 * IM_PI);
|
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);
|
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;
|
ImGuiContext& g = *GImGui;
|
||||||
const ImGuiStyle& style = g.Style;
|
const ImGuiStyle& style = g.Style;
|
||||||
const ImGuiID id = window->GetID(label);
|
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 size = ImVec2(GetFrameHeight() * 2.0F, GetFrameHeight());
|
||||||
const ImVec2 pos = window->DC.CursorPos;
|
const ImVec2 pos = window->DC.CursorPos;
|
||||||
|
@ -443,8 +443,8 @@ namespace hex::init {
|
|||||||
void WindowSplash::initMyself() {
|
void WindowSplash::initMyself() {
|
||||||
|
|
||||||
// Load splash screen image from romfs
|
// Load splash screen image from romfs
|
||||||
this->splashBackgroundTexture = ImGuiExt::Texture(romfs::get("splash_background.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());
|
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
|
// 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.
|
// Close the application since this would lead to errors later on anyway.
|
||||||
|
@ -83,7 +83,7 @@ namespace hex {
|
|||||||
this->setupNativeWindow();
|
this->setupNativeWindow();
|
||||||
this->registerEventHandlers();
|
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();
|
ContentRegistry::Settings::impl::store();
|
||||||
EventSettingsChanged::post();
|
EventSettingsChanged::post();
|
||||||
|
@ -286,7 +286,7 @@ namespace hex::plugin::builtin {
|
|||||||
void process() override {
|
void process() override {
|
||||||
const auto &rawData = this->getBufferOnInput(0);
|
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:
|
private:
|
||||||
@ -317,7 +317,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (requiredBytes > rawData.size())
|
if (requiredBytes > rawData.size())
|
||||||
throwNodeError(hex::format("Image requires at least {} bytes of data, but only {} bytes are available", 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:
|
private:
|
||||||
|
@ -783,7 +783,7 @@ namespace hex::plugin::builtin {
|
|||||||
vertexArray.bind();
|
vertexArray.bind();
|
||||||
if (s_shouldUpdateTexture) {
|
if (s_shouldUpdateTexture) {
|
||||||
s_shouldUpdateTexture = false;
|
s_shouldUpdateTexture = false;
|
||||||
s_modelTexture = ImGuiExt::Texture(s_texturePath);
|
s_modelTexture = ImGuiExt::Texture(s_texturePath, ImGuiExt::Texture::Filter::Nearest);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_drawTexture)
|
if (s_drawTexture)
|
||||||
|
@ -20,7 +20,7 @@ namespace hex::plugin::builtin {
|
|||||||
static std::mutex addressMutex;
|
static std::mutex addressMutex;
|
||||||
static TaskHolder addressTask;
|
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()));
|
static ImVec2 mapSize = scaled(ImVec2(500, 500 / mapTexture.getAspectRatio()));
|
||||||
|
|
||||||
if (shouldReset) {
|
if (shouldReset) {
|
||||||
|
@ -17,7 +17,7 @@ namespace hex::plugin::builtin {
|
|||||||
auto pattern = arguments[0].toPattern();
|
auto pattern = arguments[0].toPattern();
|
||||||
|
|
||||||
auto data = pattern->getBytes();
|
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;
|
scale = 200_scaled / texture.getSize().x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ namespace hex::plugin::builtin {
|
|||||||
auto height = arguments[2].toUnsigned();
|
auto height = arguments[2].toUnsigned();
|
||||||
|
|
||||||
auto data = pattern->getBytes();
|
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())
|
if (texture.isValid())
|
||||||
|
@ -163,7 +163,7 @@ namespace hex::plugin::builtin {
|
|||||||
for (auto &pixel : pixels)
|
for (auto &pixel : pixels)
|
||||||
pixel = (pixel & 0xFF00FF00) | ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16);
|
pixel = (pixel & 0xFF00FF00) | ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16);
|
||||||
|
|
||||||
texture = ImGuiExt::Texture(reinterpret_cast<const u8*>(pixels.data()), pixels.size(), bitmap.bmWidth, bitmap.bmHeight);
|
texture = ImGuiExt::Texture(reinterpret_cast<const u8*>(pixels.data()), pixels.size(), ImGuiExt::Texture::Filter::Nearest, bitmap.bmWidth, bitmap.bmHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
// Draw the ImHex icon
|
// Draw the ImHex icon
|
||||||
if (!this->m_logoTexture.isValid())
|
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 }));
|
ImGui::Image(this->m_logoTexture, scaled({ 100, 100 }));
|
||||||
if (ImGui::IsItemHovered() && ImGui::IsItemClicked()) {
|
if (ImGui::IsItemHovered() && ImGui::IsItemClicked()) {
|
||||||
@ -116,9 +116,9 @@ namespace hex::plugin::builtin {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static std::array DonationPages = {
|
static std::array DonationPages = {
|
||||||
DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/paypal.png").span<std::byte>()), "https://werwolv.net/donate" },
|
DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/paypal.png").span<std::byte>(), ImGuiExt::Texture::Filter::Linear), "https://werwolv.net/donate" },
|
||||||
DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/github.png").span<std::byte>()), "https://github.com/sponsors/WerWolv" },
|
DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/github.png").span<std::byte>(), ImGuiExt::Texture::Filter::Linear), "https://github.com/sponsors/WerWolv" },
|
||||||
DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/patreon.png").span<std::byte>()), "https://patreon.com/werwolv" },
|
DonationPage { ImGuiExt::Texture(romfs::get("assets/common/donation/patreon.png").span<std::byte>(), ImGuiExt::Texture::Filter::Linear), "https://patreon.com/werwolv" },
|
||||||
};
|
};
|
||||||
|
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
|
@ -513,7 +513,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
(void)RequestChangeTheme::subscribe([](const std::string &theme) {
|
(void)RequestChangeTheme::subscribe([](const std::string &theme) {
|
||||||
auto changeTexture = [&](const std::string &path) {
|
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);
|
ThemeManager::changeTheme(theme);
|
||||||
@ -639,7 +639,7 @@ namespace hex::plugin::builtin {
|
|||||||
for (const auto &defaultPath : fs::getDefaultPaths(fs::ImHexPath::Resources)) {
|
for (const auto &defaultPath : fs::getDefaultPaths(fs::ImHexPath::Resources)) {
|
||||||
const auto infoBannerPath = defaultPath / "info_banner.png";
|
const auto infoBannerPath = defaultPath / "info_banner.png";
|
||||||
if (wolv::io::fs::exists(infoBannerPath)) {
|
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())
|
if (s_infoBannerTexture.isValid())
|
||||||
break;
|
break;
|
||||||
@ -656,7 +656,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (response.isSuccess()) {
|
if (response.isSuccess()) {
|
||||||
const auto &data = response.getData();
|
const auto &data = response.getData();
|
||||||
TaskManager::doLater([data] {
|
TaskManager::doLater([data] {
|
||||||
s_infoBannerTexture = ImGuiExt::Texture(data.data(), data.size());
|
s_infoBannerTexture = ImGuiExt::Texture(data.data(), data.size(), ImGuiExt::Texture::Filter::Linear);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user