#include "Common.h" #include #include #include #include namespace bs { const std::string& engineAssetDir() { static const std::string dir = [] { std::filesystem::path packaged = executableDir() / "engine"; std::error_code ec; if (std::filesystem::exists(packaged / "shaders" / "common.glsl", ec)) return packaged.string(); return std::string(HD2D_ENGINE_ASSET_DIR); }(); return dir; } void UiTexture::upload(const hd2d::Image& img) { if (id_ && size_ != glm::ivec2(img.width, img.height)) reset(); if (!id_) { glCreateTextures(GL_TEXTURE_2D, 1, &id_); glTextureStorage2D(id_, 1, GL_RGBA8, img.width, img.height); glTextureParameteri(id_, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTextureParameteri(id_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTextureParameteri(id_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTextureParameteri(id_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); size_ = {img.width, img.height}; } // Upload top row first so ImGui's (0,0) = top-left. std::vector flipped(img.rgba.size()); size_t row = size_t(img.width) * 4; for (int y = 0; y < img.height; ++y) std::copy_n(img.rgba.data() + size_t(img.height - 1 - y) * row, row, flipped.data() + size_t(y) * row); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTextureSubImage2D(id_, 0, 0, 0, img.width, img.height, GL_RGBA, GL_UNSIGNED_BYTE, flipped.data()); } void UiTexture::reset() { if (id_) glDeleteTextures(1, &id_); id_ = 0; size_ = {0, 0}; } void UiTexture::cellUV(glm::ivec2 cell, int col, int row, ImVec2& uv0, ImVec2& uv1) const { float w = float(std::max(size_.x, 1)), h = float(std::max(size_.y, 1)); uv0 = ImVec2(float(col * cell.x) / w, float(row * cell.y) / h); uv1 = ImVec2(float((col + 1) * cell.x) / w, float((row + 1) * cell.y) / h); } float wrapAngle(float a) { constexpr float kTwoPi = 6.28318530718f; a = std::fmod(a + 3.14159265f, kTwoPi); if (a < 0.0f) a += kTwoPi; return a - 3.14159265f; } } // namespace bs