Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Displaced bounding box of Node  (Read 1272 times)

0 Members and 1 Guest are viewing this topic.

unixorn

  • Newbie
  • *
  • Posts: 4
    • View Profile
Displaced bounding box of Node
« on: December 15, 2019, 08:16:29 pm »
Hello.
I have a class called Node which is derived from a class called NodePrototype which is derived from sf::Drawable and sf::Transformable. I've managed to create a root node and plug a Button (a class that is derived from Node) object into the root's children container. The button is displayed, in the specified coordinates moreover, but when I attempt to check if the mouse is clicked while hovering over the button something very strange happens. So far I have been unable to pinpoint the cause of this behavior, but here is what I have figured out so far:
  • The bounding box of the object is always located at the top left corner of the monitor (not the app window) even when I move the window. Even when the window is launched at different coordinates.
  • The click verification detects the click provided it is done within the specified area (top left corner of the monitor with the width and height = object width and height)
In the attachment the situation is presented. It seems that no matter where the button is, its bounds are always in the top left corner.
Here is the class definition and currently used constructor of the button:
struct TextProps { sf::String text; unsigned text_size; sf::Color text_fill_color; sf::Font* fptr; };
    struct ButtonProps { union { sf::Color bg_color; sf::Texture* bg_texture; }; std::unique_ptr<sf::Text> btext; unsigned bwidth; unsigned bheight; };
    const sf::Vector2f DEFPOS{500,100};
    class Button : public Node<sf::RectangleShape>
    {  
        public:
            Button(sf::Color);
            Button(sf::Color, TextProps&);
            Button(sf::Texture&);
            Button(sf::Texture&, TextProps&);
            Button(ButtonProps& bprops) : m_properties{ std::move(bprops) } {}
            ButtonProps& get_handle() { return m_properties; }
            virtual void render_current(sf::RenderTarget&, sf::RenderStates) const;
            virtual void listen_current(); //For testing
            virtual void update_current();
            virtual void on_click();
        private:
            ButtonProps m_properties;
            bool m_clicked;
            // indirectly the class inherits m_object which is of type: std::unique_ptr<sf::RectangleShape>
    };  
Button::Button(sf::Color color, TextProps& textp) : m_properties{ {color}, std::unique_ptr<sf::Text>(new sf::Text), 80, 60}, m_clicked{false}
    {  
        m_properties.btext->setFont(*textp.fptr);
        m_properties.btext->setString(textp.text);
        m_properties.btext->setCharacterSize(textp.text_size);
        m_properties.btext->setFillColor(textp.text_fill_color);
        m_properties.btext->setOrigin(m_properties.btext->getGlobalBounds().width / 2, m_properties.btext->getGlobalBounds().height / 2);
        m_object->setFillColor(m_properties.bg_color);
        m_object->setSize(sf::Vector2f(m_properties.bwidth, m_properties.bheight));
        m_object->setPosition(DEFPOS);
        m_properties.btext->setPosition(m_object->getGlobalBounds().width / 2, m_object->getGlobalBounds().height / 2);
    }  

 
Also, i used the following approach to check for a hover over + button click:
void Button::listen_current()
    {
        m_clicked = false;
        if (ASys<ListenerType>::was_triggered(ListenerType::PrimaryMouseInput))
        {
            sf::Vector2f mp(sf::Mouse::getPosition());
            if (m_object->getLocalBounds().contains(mp))
                m_clicked = true;
        }

 
However I doubt that changes anything because the click verification works everywhere. No matter where I click, the solo click detection mechanism works fine. This implies the problem is somewhere with the button rect shape m_object.
I have no idea where. I place it at DEFPOS(500,100) to see if the area where the click+hover detection works has changed, but no. So I wonder what is going on. Perhaps this is happening because Node indirectly inherits the sf::Drawable class?
I don't know how that could be connected in any obvious way, especially since I am running the check directly on m_object which is not a node, but simply a sf::RectangleShape.
I had a look at the following thread:
https://en.sfml-dev.org/forums/index.php?topic=14914.0
From there I adapted the idea to create an sf::RectangleShape that is equal to the globalbounds.
And I when it gets drawn (i set the fill color to green) it is directly on top of the red button.
So I don't understand what is going on. I thought the globalBounds function wasn't working correctly, but now I have no idea how to explain the app's behavior.





I have found a partial solution:
The globalBounds returns a FloatRect meanwhile the Mouse::getPosition returns a Vector2i; so after casting the mp(Vector2i holding the mouse position) as a Vector2f the area where the click+hover detection works is a rectangle about the size of the button, but about half-height displaced upwards from the button. Any ideas? Could this be the result of bad approximation from int to float?
« Last Edit: December 15, 2019, 09:35:31 pm by unixorn »

Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: Displaced bounding box of Node
« Reply #1 on: December 15, 2019, 10:42:43 pm »
i think you need to pass window to the `sf::Mouse::getPosition(window)` to get the relative mouse position to your app window.

unixorn

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Displaced bounding box of Node
« Reply #2 on: December 15, 2019, 11:04:18 pm »
You are a GENIUS!!!! Thanks so much! I couldn't figure that out for four hours!
(For anyone wanting in on the working code:)
  void Button::listen_current()
    {
        m_clicked = false;
        if (ASys<ListenerType>::was_triggered(ListenerType::PrimaryMouseInput))
        {
            if (m_object->getGlobalBounds().contains((sf::Vector2f)sf::Mouse::getPosition(*WindowPTR->get())))
                m_clicked = true;
        }
    }

 
Thanks again.