AnimatedSprite in a TGUI instance ?

Started by Aiiro, 18 January 2016, 12:55:26

Aiiro

Hello again.

I have a question about the class AnimatedSprite (https://github.com/SFML/SFML/wiki/Source:-AnimatedSprite) in SFML and TGUI.
So I created the class AnimatedSprite and tested it, it works well with a SFML window, however it doesn't work in a TGUI window. I suppose it's because TGUI only draw the widgets once and don't update unless an event is trigerred.
Do you know a way to add animated sprites in a TGUI window or it's just impossible ?

Thanks in advance,
Aiiro

texus

What you are saying doesn't make much sense. There hasn't been such a thing as a "tgui window" since 0.5 and I doubt you are using such old version. TGUI just draws on top of the SFML window just like you would do yourself, so there is no reason why it wouldn't work.

So you probably just made a small mistake in the code, but I can only help you with that if you show the code where you use both TGUI and the AnimatedSprite.

Aiiro

Yes, sorry I didn't make much sense. Here is how I do it :
void Widgets::pkmAnim(Gui& gui, string pkmName)
{

    sf::Texture textTest;
    if (!textTest.loadFromFile("Sprites/" + pkmName + "/" + pkmName + ".png"))
    {
        cout << "Failed to load spritesheet" << endl;
    }

    Animation pkmAnim;
    pkmAnim.setSpriteSheet(textTest);

    string line;

    fstream txtFile;
    txtFile.open("Sprites/" + pkmName + "/" + pkmName + ".txt");

    string val1, val2, val3, val4, val5, val6;
    int i;

    while(getline(txtFile, line))
    {
        istringstream isstream(line);

        getline(isstream,val1, ' ');
        getline(isstream,val2, ' ');
        getline(isstream,val3, ' ');
        getline(isstream,val4, ' ');
        getline(isstream,val5, ' ');
        getline(isstream,val6, ' ');

        pkmAnim.addFrame(IntRect(stoi(val3), stoi(val4), stoi(val5), stoi(val6)));
        i++;
    }

    AnimatedSprite animatedSprite(sf::seconds(0.05), true, false);

    sf::Clock frameClock;

    sf::Time frameTime = frameClock.restart();

    animatedSprite.play(pkmAnim);

    animatedSprite.update(frameTime);

    auto panel = std::make_shared<tgui::Panel>(windowWidth / 5, windowHeight * 2/10);
    panel->setBackgroundColor(sf::Color::Black);
    panel->setPosition(windowWidth / 20, windowHeight * 0.3/10);

    auto canvasAnim = std::make_shared<tgui::Canvas>(windowWidth / 5, windowHeight * 2/10);
    canvasAnim->setPosition(windowWidth / 20, windowHeight * 0.4/10);
    panel->add(canvasAnim);
    gui.add(panel);

    canvasAnim->clear();
    canvasAnim->draw(animatedSprite);
    canvasAnim->display();

}

Aiiro

I forgot to add windowWidth and windowHeight in the code I gave you, but it's not what causes the issue.

texus

I'm not even sure where to start with correcting this, the code obviously doesn't do what you need it to.
You create an animation object, load its frames, then draw the first frame and then the function ends and the animation object is destroyed. Just like you need to do in the sfml code, you have to keep the animation object and draw it every frame.

If you can provide a simple example code inside a main function then I can correct if for you, but this code depends too much on your existing other code (e.g. the Widgets class).

But maybe you are making it way too difficult for yourself. Why even use a tgui canvas? Just use identical code as you have with sfml and have the rendering loop look like this:
Code (cpp) Select
window.clear();
gui.draw();
window.draw(animatedSprite);
window.display();

Aiiro

Alright I'll give you a bit of context.
So I have the Widgets class, which has all the widgets I need for my game.
I call the loadMainMenu function of the widget class and then I only call other loadWidgets class with events that start in loadMainMenu, so that's the only thing that I have in my main about the Widgets class.
After the Main menu I press a button and then have other steps before going into a form where I would want the AnimatedSprite there. I also have a combobox where I have a list of name and when I select another item, the Animatedsprite should change according to what was selected..
What my main function looks like (without includes) :
RenderWindow window(VideoMode(1080, 720), "CatherineIA");
    window.setFramerateLimit(60);
    tgui::Gui gui(window);

    Widgets widgetHandler;

    widgetHandler.loadMainMenu(gui);

    sf::Music music;
    music.openFromFile("Music_&_Sounds/Music_Wally.ogg");
    music.setLoop(true);
    music.setVolume(50);
    music.play();

    while (window.isOpen())
    {

        sf::Event event;

        while (window.pollEvent(event))
        {

            if (event.type == sf::Event::Closed)
            {

                window.close();

            } else if (event.type == sf::Event::Resized)
            {
                window.setView(sf::View(sf::FloatRect(0, 0, event.size.width, event.size.height)));
                gui.setView(window.getView());
            }

            gui.handleEvent(event);


        }


        window.clear();

        gui.draw();

        window.display();

    }


Thanks for your help.

texus

My point is that there is no simple solution with your current code structure. If you have a short and simple code without classes and you have a problem then I can help and tell you what to change, but I can't say exactly which lines to change in such code as this.
I know solutions that could help you, but I think it would be better if you change the design now than to fix this issue and just end up with other issues later on.

Unless you have a really good reason to do so (e.g. the animated picture is to be drawn inside a tgui child window), you should NOT use tgui to draw it. You should only use tgui for what it is meant to be used: as a user interface. The rest of your code should just use sfml like you would when you aren't using tgui.