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

Author Topic: setTextureRect on iterator  (Read 1702 times)

0 Members and 1 Guest are viewing this topic.

aeacus

  • Newbie
  • *
  • Posts: 4
    • View Profile
setTextureRect on iterator
« on: October 15, 2013, 05:15:51 pm »
Im pretty new to c++ in general so this might be a basic thing im getting wrong but my googling has failed me so far. Basically i have a menu class with a struct for menu items and on every update call im checking to see if the mouse is over one of those items and if it is change the texture rectangle however whenever i call setTextureRect from the iterator it just doesnt work. All relevant code is below so if anyone can point me in the right direction it'd be greatly appreciated.

struct MenuItem
{
public:
        sf::Sprite sprite;
        sf::IntRect defaultRect; // rectangle coords for sprite when mouse not over
        sf::IntRect hoverRect; // rectangle coords for sprite when mouse over
        sf::IntRect rect; // rectangle coords of item position on screen
};


void StartMenu::initiate(TextureManager &resManager)
{      
        playButton.sprite.setTexture(resManager.getTexture("images/mainMenuButtons.png"));
        playButton.defaultRect = sf::IntRect(0,0,200,50);
        playButton.hoverRect = sf::IntRect(0,50,200,50);
        playButton.sprite.setTextureRect(playButton.defaultRect);
}

void StartMenu::update(sf::RenderWindow &renderWindow, sf::Event &event, float &delta)
{      
        HandleHover(renderWindow);
        renderWindow.draw(playButton.sprite);
}

void StartMenu::HandleHover(sf::RenderWindow &renderWindow)
{
        int x = sf::Mouse::getPosition(renderWindow).x;
        int y = sf::Mouse::getPosition(renderWindow).y;
        std::list<MenuItem>::iterator it;

        for(it = menuItems.begin(); it != menuItems.end(); ++it)
        {
                sf::IntRect menuItemRect = (*it).rect;
                if ((menuItemRect.top + menuItemRect.height) > y
                        && menuItemRect.top < y
                        && menuItemRect.left < x
                        && (menuItemRect.left + menuItemRect.width) > x)
                {
                        it->sprite.setTextureRect((*it).hoverRect);
                }
                else
                {
                        it->sprite.setTextureRect((*it).defaultRect);
                }
        }
}

 
« Last Edit: October 16, 2013, 11:11:41 am by aeacus »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: setTextureRect on iterator
« Reply #1 on: October 15, 2013, 05:47:02 pm »
Btw you can just use rect.contains(sf::Vector2f(x, y)) much easier and less error prone to check whether a point is inside a rectangle.

What if you add some simple logging (e.g. std::cout << "Setting Hover Rect: " << rect-data << std::endl;) to your code and see if it really gets set?
You could also do this by setting a break point and run it through a debugger.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

aeacus

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: setTextureRect on iterator
« Reply #2 on: October 16, 2013, 10:13:09 am »
Ah thanks for that, too used to doing things manually forgot to check if there was a "contains" function. I took out the logging stuff from the posted code but have re-added it below with your suggestion and the output. Realised i was only checking if it worked changing the iterator though. I've added code to hard check the playButton which isnt being changed so it seems changing the iterator isnt kicking back to the original list. Will i then have to cast the iterator back to the menu some how to make it work?

void StartMenu::initiate(TextureManager &resManager)
{      
        playButton.sprite.setTexture(resManager.getTexture("images/mainMenuButtons.png"));
        playButton.defaultRect = sf::IntRect(0,0,200,50);
        playButton.hoverRect = sf::IntRect(0,50,200,50);
        playButton.sprite.setTextureRect(playButton.defaultRect);
}

void StartMenu::update(sf::RenderWindow &renderWindow, sf::Event &event, float &delta)
{      
        HandleHover(renderWindow);
        std::cout<<"update play button: "<< playButton.sprite.getTextureRect().top <<std::endl;
        renderWindow.draw(playButton.sprite);
}

void StartMenu::HandleHover(sf::RenderWindow &renderWindow)
{
        int x = sf::Mouse::getPosition(renderWindow).x;
        int y = sf::Mouse::getPosition(renderWindow).y;
        std::list<MenuItem>::iterator it;

        for(it = menuItems.begin(); it != menuItems.end(); ++it)
        {
                if ((*it).rect.contains(x,y))
                {                      
                        it->sprite.setTextureRect((*it).hoverRect);
                        std::cout<<"handle hover iterator: "<< it->sprite.getTextureRect().top <<std::endl;                    
                        std::cout<<"handle hover play button: "<< playButton.sprite.getTextureRect().top <<std::endl;
                }
                else
                {
                        it->sprite.setTextureRect((*it).defaultRect);
                }
        }
}

####### OUTPUT #########
handle hover iterator: 50
handle hover play button: 0
update play button: 0
 



Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: setTextureRect on iterator
« Reply #3 on: October 16, 2013, 10:20:29 am »
If playButton is inserted in the menuItems list (we can't see it in the code you posted but it seems like it's the case), then don't forget that the list is storing a copy of it. Therefore, playButton and *it are two separate objects.
Laurent Gomila - SFML developer

aeacus

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: setTextureRect on iterator
« Reply #4 on: October 16, 2013, 10:26:36 am »
Oh sorry, thought i had all relevant code. Yeah playButton was added to the list.

I had guessed thats what was happening, currently trying to figure out how to cast the iterator back to the list but none of my googling is helping.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: setTextureRect on iterator
« Reply #5 on: October 16, 2013, 10:36:55 am »
currently trying to figure out how to cast the iterator back to the list but none of my googling is helping.
This doesn't make any sense. Maybe you should read a bit more about STL containers and iterators, you're mixing unrelated terms here.

If you need an indirection to an element in the container, use a pointer or reference.

By the way, you can always use it->member instead of (*it).member for dereferencing, and sf::Vector2i to store the result of sf::Mouse::getPosition().
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

aeacus

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: setTextureRect on iterator
« Reply #6 on: October 16, 2013, 11:08:53 am »
Bah im an eejit. Only just realised what Laurent was getting at. Got it working now by rendering the sprites in the list rather than directly from the buttons.

Thanks guys.