From f6ac027725435d846e1bde3d8d0506b8161d29da Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Tue, 5 Mar 2024 22:55:42 -0600 Subject: [PATCH] Allow icons to have a variable anchor --- scwx-qt/source/scwx/qt/gl/draw/icons.cpp | 60 +++++++++++---------- scwx-qt/source/scwx/qt/gl/draw/icons.hpp | 13 +++-- scwx-qt/source/scwx/qt/types/icon_types.cpp | 25 ++++++++- scwx-qt/source/scwx/qt/types/icon_types.hpp | 5 ++ 4 files changed, 67 insertions(+), 36 deletions(-) diff --git a/scwx-qt/source/scwx/qt/gl/draw/icons.cpp b/scwx-qt/source/scwx/qt/gl/draw/icons.cpp index 86e7e542..d2c3d709 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/icons.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -80,9 +79,10 @@ public: std::mutex iconMutex_; - boost::unordered_flat_map + boost::unordered_flat_map> currentIconSheets_ {}; - boost::unordered_flat_map newIconSheets_ {}; + boost::unordered_flat_map> + newIconSheets_ {}; std::vector> currentIconList_ {}; std::vector> newIconList_ {}; @@ -243,17 +243,19 @@ void Icons::StartIconSheets() p->newIconSheets_.clear(); } -void Icons::AddIconSheet(const std::string& name, - std::size_t iconWidth, - std::size_t iconHeight, - std::int32_t hotX, - std::int32_t hotY) +std::shared_ptr Icons::AddIconSheet(const std::string& name, + std::size_t iconWidth, + std::size_t iconHeight, + std::int32_t hotX, + std::int32_t hotY) { // Populate icon sheet map - p->newIconSheets_.emplace(std::piecewise_construct, - std::tuple {name}, - std::forward_as_tuple(types::IconInfo { - name, iconWidth, iconHeight, hotX, hotY})); + return p->newIconSheets_ + .emplace(std::piecewise_construct, + std::tuple {name}, + std::forward_as_tuple(std::make_shared( + name, iconWidth, iconHeight, hotX, hotY))) + .first->second; } void Icons::FinishIconSheets() @@ -261,7 +263,7 @@ void Icons::FinishIconSheets() // Update icon sheets for (auto& iconSheet : p->newIconSheets_) { - iconSheet.second.UpdateTextureInfo(); + iconSheet.second->UpdateTextureInfo(); } std::unique_lock lock {p->iconMutex_}; @@ -375,7 +377,7 @@ void Icons::Impl::UpdateBuffers() auto& icon = it->second; // Validate icon - if (di->iconIndex_ >= icon.numIcons_) + if (di->iconIndex_ >= icon->numIcons_) { // No icon found logger_->warn("Invalid icon index: {}", di->iconIndex_); @@ -390,12 +392,12 @@ void Icons::Impl::UpdateBuffers() const float y = static_cast(di->y_); // Icon size - const float iw = static_cast(icon.iconWidth_); - const float ih = static_cast(icon.iconHeight_); + const float iw = static_cast(icon->iconWidth_); + const float ih = static_cast(icon->iconHeight_); // Hot X/Y (zero-based icon center) - const float hx = static_cast(icon.hotX_); - const float hy = static_cast(icon.hotY_); + const float hx = static_cast(icon->hotX_); + const float hy = static_cast(icon->hotY_); // Final X/Y offsets in pixels const float lx = std::roundf(-hx); @@ -477,7 +479,7 @@ void Icons::Impl::UpdateTextureBuffer() auto& icon = it->second; // Validate icon - if (di->iconIndex_ >= icon.numIcons_) + if (di->iconIndex_ >= icon->numIcons_) { // No icon found logger_->error("Invalid icon index: {}", di->iconIndex_); @@ -503,17 +505,17 @@ void Icons::Impl::UpdateTextureBuffer() } // Texture coordinates - const std::size_t iconRow = (di->iconIndex_) / icon.columns_; - const std::size_t iconColumn = (di->iconIndex_) % icon.columns_; + const std::size_t iconRow = (di->iconIndex_) / icon->columns_; + const std::size_t iconColumn = (di->iconIndex_) % icon->columns_; - const float iconX = iconColumn * icon.scaledWidth_; - const float iconY = iconRow * icon.scaledHeight_; + const float iconX = iconColumn * icon->scaledWidth_; + const float iconY = iconRow * icon->scaledHeight_; - const float ls = icon.texture_.sLeft_ + iconX; - const float rs = ls + icon.scaledWidth_; - const float tt = icon.texture_.tTop_ + iconY; - const float bt = tt + icon.scaledHeight_; - const float r = static_cast(icon.texture_.layerId_); + const float ls = icon->texture_.sLeft_ + iconX; + const float rs = ls + icon->scaledWidth_; + const float tt = icon->texture_.tTop_ + iconY; + const float bt = tt + icon->scaledHeight_; + const float r = static_cast(icon->texture_.layerId_); // clang-format off textureBuffer_.insert( @@ -541,7 +543,7 @@ void Icons::Impl::Update(bool textureAtlasChanged) // Update texture coordinates for (auto& iconSheet : currentIconSheets_) { - iconSheet.second.UpdateTextureInfo(); + iconSheet.second->UpdateTextureInfo(); } // Update OpenGL texture buffer data diff --git a/scwx-qt/source/scwx/qt/gl/draw/icons.hpp b/scwx-qt/source/scwx/qt/gl/draw/icons.hpp index d7207a11..f9e4c91c 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/icons.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/icons.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -69,12 +70,14 @@ public: * Default is -1 to center the icon. * @param [in] hotY The zero-based center of the each icon in the icon sheet. * Default is -1 to center the icon. + * + * @return Icon info */ - void AddIconSheet(const std::string& name, - std::size_t iconWidth = 0, - std::size_t iconHeight = 0, - std::int32_t hotX = -1, - std::int32_t hotY = -1); + std::shared_ptr AddIconSheet(const std::string& name, + std::size_t iconWidth = 0, + std::size_t iconHeight = 0, + std::int32_t hotX = -1, + std::int32_t hotY = -1); /** * Resets and prepares the draw item for adding a new set of icon sheets. diff --git a/scwx-qt/source/scwx/qt/types/icon_types.cpp b/scwx-qt/source/scwx/qt/types/icon_types.cpp index 8323ef83..87bdb631 100644 --- a/scwx-qt/source/scwx/qt/types/icon_types.cpp +++ b/scwx-qt/source/scwx/qt/types/icon_types.cpp @@ -7,6 +7,11 @@ namespace qt namespace types { +void IconInfo::SetAnchor(float anchorX, float anchorY) +{ + anchor_ = {anchorX, anchorY}; +} + void IconInfo::UpdateTextureInfo() { texture_ = util::TextureAtlas::Instance().GetTextureAttributes(iconSheet_); @@ -27,8 +32,24 @@ void IconInfo::UpdateTextureInfo() if (hotX_ == -1 || hotY_ == -1) { - hotX_ = static_cast(iconWidth_ / 2); - hotY_ = static_cast(iconHeight_ / 2); + if (anchor_.has_value()) + { + hotX_ = + std::clamp(static_cast(std::lround( + iconWidth_ * anchor_.value().first)), + 0, + static_cast(iconWidth_)); + hotY_ = + std::clamp(static_cast(std::lround( + iconHeight_ * anchor_.value().second)), + 0, + static_cast(iconHeight_)); + } + else + { + hotX_ = static_cast(iconWidth_ / 2); + hotY_ = static_cast(iconHeight_ / 2); + } } numIcons_ = columns_ * rows_; diff --git a/scwx-qt/source/scwx/qt/types/icon_types.hpp b/scwx-qt/source/scwx/qt/types/icon_types.hpp index c6ae7abe..4535012c 100644 --- a/scwx-qt/source/scwx/qt/types/icon_types.hpp +++ b/scwx-qt/source/scwx/qt/types/icon_types.hpp @@ -2,7 +2,9 @@ #include +#include #include +#include namespace scwx { @@ -26,6 +28,7 @@ struct IconInfo { } + void SetAnchor(float anchorX, float anchorY); void UpdateTextureInfo(); std::string iconSheet_; @@ -39,6 +42,8 @@ struct IconInfo std::size_t numIcons_ {}; float scaledWidth_ {}; float scaledHeight_ {}; + + std::optional> anchor_ {}; }; } // namespace types