Personally, I'd probably go with a separate view and calculate the position and size of each text to be perfectly matching the objects in the map. It gives complete control over the sizing of the text, and you don't have to adjust for world zoom/rotation etc.
Plus it also allows you to focus on texts that are currently visible.
I am trying to prototype this world's behavior. The moving entities work fine and the text is as it should be - placed over the top left corner with offset relating to the text size.
sf::Vector2f transformText (const sf::Vector2f& position, const sf::RenderWindow& window, const sf::View& viewFrom, const sf::View& viewTo)
{
sf::Vector2i positionInWindow = window.mapCoordsToPixel (position, viewFrom);
return window.mapPixelToCoords (positionInWindow, viewTo);
}
text2.setPosition(transformText(entity2.getPosition() + textOffset, window, mainView, textView));
When I tried to start zooming and rotating the view, the text follow the entity's left corner, however, as the entity is rotating the top left corner is not the top left anymore so with 180° rotation the text is under the entity.
I understand that I need to take the entity to apply the transformation of the view and get the bounding box of the entity and use the top left corner as a place for the text before offset.
Can SFML help me with that? The function transformText transforms a single coordinate but I need the whole entity to get global bounds. Can I achieve that without making a shadow copy of the entity to just have this entity with view transformation to achieve global bounds and that top left corner?
note: the whole prototype is in the attachment
I used this for CircleShape. It works fine.
sf::Vector2f getPositionForText (const sf::CircleShape& shape,
const sf::RenderWindow& window,
const sf::View& viewFrom,
const sf::View& viewTo)
{
float radius = shape.getRadius();
sf::Vector2f center {shape.getPosition().x, shape.getPosition().y};
sf::Vector2i positionInWindow = window.mapCoordsToPixel(center,viewFrom);
center = window.mapPixelToCoords (positionInWindow, viewTo);
center += sf::Vector2f {-radius * shape.getScale().x, -radius * shape.getScale().y}
* (viewTo.getSize().x / viewFrom.getSize().x);
return center;
}
// and calling this function
text3.setPosition(getPositionForText(entity2, window, mainView, textView)
+ sf::Vector2f{0.f, -textSpaceHeight}); // text offset
Thinking about doing similar for any sf::Shape or VertexArray. I am thinking about 2 ways:
1. through bounding box
- getting sf::FloatRect bounding box of the entity
- transform between views using sf::Transform
- getting a new bounding box from a transformed bounding box
Advantages: relatively simple and probably reasonably fast
Disadvantages: position of text will be simplified as in the bounding box from the transformed bounding box could be large, especially if the transformed bounding box is at 45°.
2. through transforming entity
- copy entity
- transform entity between views
- finding the bounding box from the transformed entity
Advantages: Much more precise as the bounding box is found on top of transformed entity
Disadvantages: If there are many text labels over an entity it practically make no sense for the view and all these entities need to be copied transformed one by one