Allow icons to have a variable anchor

This commit is contained in:
Dan Paulat 2024-03-05 22:55:42 -06:00
parent 50e0036e0b
commit f6ac027725
4 changed files with 67 additions and 36 deletions

View file

@ -1,5 +1,4 @@
#include <scwx/qt/gl/draw/icons.hpp> #include <scwx/qt/gl/draw/icons.hpp>
#include <scwx/qt/types/icon_types.hpp>
#include <scwx/qt/util/maplibre.hpp> #include <scwx/qt/util/maplibre.hpp>
#include <scwx/qt/util/texture_atlas.hpp> #include <scwx/qt/util/texture_atlas.hpp>
#include <scwx/qt/util/tooltip.hpp> #include <scwx/qt/util/tooltip.hpp>
@ -80,9 +79,10 @@ public:
std::mutex iconMutex_; std::mutex iconMutex_;
boost::unordered_flat_map<std::string, types::IconInfo> boost::unordered_flat_map<std::string, std::shared_ptr<types::IconInfo>>
currentIconSheets_ {}; currentIconSheets_ {};
boost::unordered_flat_map<std::string, types::IconInfo> newIconSheets_ {}; boost::unordered_flat_map<std::string, std::shared_ptr<types::IconInfo>>
newIconSheets_ {};
std::vector<std::shared_ptr<IconDrawItem>> currentIconList_ {}; std::vector<std::shared_ptr<IconDrawItem>> currentIconList_ {};
std::vector<std::shared_ptr<IconDrawItem>> newIconList_ {}; std::vector<std::shared_ptr<IconDrawItem>> newIconList_ {};
@ -243,17 +243,19 @@ void Icons::StartIconSheets()
p->newIconSheets_.clear(); p->newIconSheets_.clear();
} }
void Icons::AddIconSheet(const std::string& name, std::shared_ptr<types::IconInfo> Icons::AddIconSheet(const std::string& name,
std::size_t iconWidth, std::size_t iconWidth,
std::size_t iconHeight, std::size_t iconHeight,
std::int32_t hotX, std::int32_t hotX,
std::int32_t hotY) std::int32_t hotY)
{ {
// Populate icon sheet map // Populate icon sheet map
p->newIconSheets_.emplace(std::piecewise_construct, return p->newIconSheets_
std::tuple {name}, .emplace(std::piecewise_construct,
std::forward_as_tuple(types::IconInfo { std::tuple {name},
name, iconWidth, iconHeight, hotX, hotY})); std::forward_as_tuple(std::make_shared<types::IconInfo>(
name, iconWidth, iconHeight, hotX, hotY)))
.first->second;
} }
void Icons::FinishIconSheets() void Icons::FinishIconSheets()
@ -261,7 +263,7 @@ void Icons::FinishIconSheets()
// Update icon sheets // Update icon sheets
for (auto& iconSheet : p->newIconSheets_) for (auto& iconSheet : p->newIconSheets_)
{ {
iconSheet.second.UpdateTextureInfo(); iconSheet.second->UpdateTextureInfo();
} }
std::unique_lock lock {p->iconMutex_}; std::unique_lock lock {p->iconMutex_};
@ -375,7 +377,7 @@ void Icons::Impl::UpdateBuffers()
auto& icon = it->second; auto& icon = it->second;
// Validate icon // Validate icon
if (di->iconIndex_ >= icon.numIcons_) if (di->iconIndex_ >= icon->numIcons_)
{ {
// No icon found // No icon found
logger_->warn("Invalid icon index: {}", di->iconIndex_); logger_->warn("Invalid icon index: {}", di->iconIndex_);
@ -390,12 +392,12 @@ void Icons::Impl::UpdateBuffers()
const float y = static_cast<float>(di->y_); const float y = static_cast<float>(di->y_);
// Icon size // Icon size
const float iw = static_cast<float>(icon.iconWidth_); const float iw = static_cast<float>(icon->iconWidth_);
const float ih = static_cast<float>(icon.iconHeight_); const float ih = static_cast<float>(icon->iconHeight_);
// Hot X/Y (zero-based icon center) // Hot X/Y (zero-based icon center)
const float hx = static_cast<float>(icon.hotX_); const float hx = static_cast<float>(icon->hotX_);
const float hy = static_cast<float>(icon.hotY_); const float hy = static_cast<float>(icon->hotY_);
// Final X/Y offsets in pixels // Final X/Y offsets in pixels
const float lx = std::roundf(-hx); const float lx = std::roundf(-hx);
@ -477,7 +479,7 @@ void Icons::Impl::UpdateTextureBuffer()
auto& icon = it->second; auto& icon = it->second;
// Validate icon // Validate icon
if (di->iconIndex_ >= icon.numIcons_) if (di->iconIndex_ >= icon->numIcons_)
{ {
// No icon found // No icon found
logger_->error("Invalid icon index: {}", di->iconIndex_); logger_->error("Invalid icon index: {}", di->iconIndex_);
@ -503,17 +505,17 @@ void Icons::Impl::UpdateTextureBuffer()
} }
// Texture coordinates // Texture coordinates
const std::size_t iconRow = (di->iconIndex_) / icon.columns_; const std::size_t iconRow = (di->iconIndex_) / icon->columns_;
const std::size_t iconColumn = (di->iconIndex_) % icon.columns_; const std::size_t iconColumn = (di->iconIndex_) % icon->columns_;
const float iconX = iconColumn * icon.scaledWidth_; const float iconX = iconColumn * icon->scaledWidth_;
const float iconY = iconRow * icon.scaledHeight_; const float iconY = iconRow * icon->scaledHeight_;
const float ls = icon.texture_.sLeft_ + iconX; const float ls = icon->texture_.sLeft_ + iconX;
const float rs = ls + icon.scaledWidth_; const float rs = ls + icon->scaledWidth_;
const float tt = icon.texture_.tTop_ + iconY; const float tt = icon->texture_.tTop_ + iconY;
const float bt = tt + icon.scaledHeight_; const float bt = tt + icon->scaledHeight_;
const float r = static_cast<float>(icon.texture_.layerId_); const float r = static_cast<float>(icon->texture_.layerId_);
// clang-format off // clang-format off
textureBuffer_.insert( textureBuffer_.insert(
@ -541,7 +543,7 @@ void Icons::Impl::Update(bool textureAtlasChanged)
// Update texture coordinates // Update texture coordinates
for (auto& iconSheet : currentIconSheets_) for (auto& iconSheet : currentIconSheets_)
{ {
iconSheet.second.UpdateTextureInfo(); iconSheet.second->UpdateTextureInfo();
} }
// Update OpenGL texture buffer data // Update OpenGL texture buffer data

View file

@ -2,6 +2,7 @@
#include <scwx/qt/gl/gl_context.hpp> #include <scwx/qt/gl/gl_context.hpp>
#include <scwx/qt/gl/draw/draw_item.hpp> #include <scwx/qt/gl/draw/draw_item.hpp>
#include <scwx/qt/types/icon_types.hpp>
#include <boost/gil.hpp> #include <boost/gil.hpp>
#include <units/angle.h> #include <units/angle.h>
@ -69,12 +70,14 @@ public:
* Default is -1 to center the icon. * Default is -1 to center the icon.
* @param [in] hotY The zero-based center of the each icon in the icon sheet. * @param [in] hotY The zero-based center of the each icon in the icon sheet.
* Default is -1 to center the icon. * Default is -1 to center the icon.
*
* @return Icon info
*/ */
void AddIconSheet(const std::string& name, std::shared_ptr<types::IconInfo> AddIconSheet(const std::string& name,
std::size_t iconWidth = 0, std::size_t iconWidth = 0,
std::size_t iconHeight = 0, std::size_t iconHeight = 0,
std::int32_t hotX = -1, std::int32_t hotX = -1,
std::int32_t hotY = -1); std::int32_t hotY = -1);
/** /**
* Resets and prepares the draw item for adding a new set of icon sheets. * Resets and prepares the draw item for adding a new set of icon sheets.

View file

@ -7,6 +7,11 @@ namespace qt
namespace types namespace types
{ {
void IconInfo::SetAnchor(float anchorX, float anchorY)
{
anchor_ = {anchorX, anchorY};
}
void IconInfo::UpdateTextureInfo() void IconInfo::UpdateTextureInfo()
{ {
texture_ = util::TextureAtlas::Instance().GetTextureAttributes(iconSheet_); texture_ = util::TextureAtlas::Instance().GetTextureAttributes(iconSheet_);
@ -27,8 +32,24 @@ void IconInfo::UpdateTextureInfo()
if (hotX_ == -1 || hotY_ == -1) if (hotX_ == -1 || hotY_ == -1)
{ {
hotX_ = static_cast<std::int32_t>(iconWidth_ / 2); if (anchor_.has_value())
hotY_ = static_cast<std::int32_t>(iconHeight_ / 2); {
hotX_ =
std::clamp<std::int32_t>(static_cast<std::int32_t>(std::lround(
iconWidth_ * anchor_.value().first)),
0,
static_cast<std::int32_t>(iconWidth_));
hotY_ =
std::clamp<std::int32_t>(static_cast<std::int32_t>(std::lround(
iconHeight_ * anchor_.value().second)),
0,
static_cast<std::int32_t>(iconHeight_));
}
else
{
hotX_ = static_cast<std::int32_t>(iconWidth_ / 2);
hotY_ = static_cast<std::int32_t>(iconHeight_ / 2);
}
} }
numIcons_ = columns_ * rows_; numIcons_ = columns_ * rows_;

View file

@ -2,7 +2,9 @@
#include <scwx/qt/util/texture_atlas.hpp> #include <scwx/qt/util/texture_atlas.hpp>
#include <optional>
#include <string> #include <string>
#include <utility>
namespace scwx namespace scwx
{ {
@ -26,6 +28,7 @@ struct IconInfo
{ {
} }
void SetAnchor(float anchorX, float anchorY);
void UpdateTextureInfo(); void UpdateTextureInfo();
std::string iconSheet_; std::string iconSheet_;
@ -39,6 +42,8 @@ struct IconInfo
std::size_t numIcons_ {}; std::size_t numIcons_ {};
float scaledWidth_ {}; float scaledWidth_ {};
float scaledHeight_ {}; float scaledHeight_ {};
std::optional<std::pair<float, float>> anchor_ {};
}; };
} // namespace types } // namespace types