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

Author Topic: Trouble managing resources (probably a scoping issue?)  (Read 2521 times)

0 Members and 1 Guest are viewing this topic.

nailuj

  • Newbie
  • *
  • Posts: 8
    • View Profile
Trouble managing resources (probably a scoping issue?)
« on: December 31, 2011, 01:02:02 pm »
Hi everybody,
I have some trouble managing resources, which is probably less of a SFML question but rather a general C++ question.
I have written a resource manager which returns a const pointer to a const sf::Texture.
Code: [Select]

class ResourceManager {
public:
    const sf::Texture *getResource(std::string resourceName) const;
private:
    std::map<std::string, sf::Texture> resourceMap;
};

This is all working fine and well. Then I have another class which manages drawing the actual display, which has a blit() function, which is supposed to get a Texture from the ResourceManager and draw it using a Sprite.
Code: [Select]

class DisplayManager {
public:
    void drawDisplay(); // calls Clear() at the beginning and Display() at the end
private:
    sf::Sprite drawSprite;
    void drawMainMenu();
    void drawOptionsMenu(); // etc, etc...
    void blit(int screenX, int screenY, float scaleX, float scaleY, std::string resourceName);
};

My main() function calls drawDisplay() every frame, which queries the game state and then decides what to draw (main menu, or options menu, etc). It also runs Clear() at the beginning and Display() at the end.
In my example, it decides to call drawMainMenu(), which then calls
Code: [Select]
blit(0, 0, 1, 1, "MainmenuBackground");
to draw the background of the main menu. The blit() function uses the member Sprite drawSprite everytime it's called and overwrites its configuration. It basically looks like this:
Code: [Select]

void DisplayManager::blit(int screenX, int screenY, float scaleX, float scaleY, std::string resourceName) {
    const sf::Texture* const renderTexture = resourceManager.getResource(resourceName);
    drawSprite.SetTexture(*renderTexture);
    drawSprite.SetPosition((float) screenX, (float) screenY);
    // omitted the scaling code, which is currently commented out anyway
    mainWindow.Draw(drawSprite);
};

The code is compiling cleanly, and is also working in some way. I'm getting the resource from the ResourceManager. I can also set it as the sprite's Texture via SetTexture.
Even more, I can access the texture I set in blit() in the drawScreen() function right before the Display() call, can for example use drawSprite.GetTexture()->GetWidth() and GetHeight() with correct results.
But nonetheless, the application only runs for two frames (it's 2 frames every time), where the first frame is actually showing a "raw" RenderWindow (I can see the contents of the window behind it, using SFML on Linux), and the second frame at least applies the Clear() and draws the contents of the window black.
Then the application just closes (no crash).

Through trial and error I found out that if I comment out the mainWindow.Draw(drawSprite) call in blit(), the application runs just fine (only clearing the screen).

I'm probably misunderstanding how the memory management works in this case, but I just can't understand why it's not displaying anything and just closing the application. Manually drawing primitive shapes in the drawDisplay() function works just fine. Also, if I manually create a sf::Texture and sf::Sprite in the drawDisplay() function before the mainWindow.Display(), it can be displayed.

Thanks in advance, and a happy new year everybody. May SFML continue to be a great library in 2012 :)

PS: I'm using a current git checkout of SFML 2.0 on Fedora 16, 64 bit.

nailuj

  • Newbie
  • *
  • Posts: 8
    • View Profile
Trouble managing resources (probably a scoping issue?)
« Reply #1 on: January 04, 2012, 05:56:45 pm »
I have managed to work around this issue by creating a copy of the sf::Texture as a member in my DisplayManager class and then setting this copy as the Sprite's texture, but for obvious reasons I'm not really happy with that, and I also don't really know why this works, but the other version doesn't.

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Trouble managing resources (probably a scoping issue?)
« Reply #2 on: January 05, 2012, 12:45:41 am »
Haven't checked the source for sf::Texture, but I'm using a similar approach just fine (I'm using a std::map of pointers though). I'm not 100% sure but using the actual sf::Texture as elements in the map might break something (due to copies being created).

Mine works like this (making it up right now, so might include mistakes):
Code: [Select]
sf::Texture *GetTexture(const char *file)
{
    std::map<...>::iterator a = textures.find(file);
    if(a != textures.end())
        return a->second;
    sf::Texture *nt = new sf::Texture();
    nt->LoadFromFile(...);
    textures.insert(std::pair<...>(file, nt), textures.end());
    return nt;
}

Just don't forget to free them later on.

nailuj

  • Newbie
  • *
  • Posts: 8
    • View Profile
Trouble managing resources (probably a scoping issue?)
« Reply #3 on: January 05, 2012, 03:40:05 am »
Thanks for the reply :)
I've tried out your approach with both raw and smart pointers, but without success. I store pointers in the ResourceManager's map now and return these.
Again, they seem to point to valid Textures right before calling Display() on the main window, but again the window just closes after two frames.
Copying the Texture the pointer points to over to a member of the DisplayManager class and using this for the Sprite fixes this.

After debugging around a bit, I found out that the thing that actually closes the program is the call to glXSwapBuffers() during the second frame in src/Window/Linux/GlxContext.cpp of SFML. After that, gdb tells me that the process exited with return code 1. Just for the fun of it I'll try compiling the thing on Windows tomorrow and see if that changes anything.

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Trouble managing resources (probably a scoping issue?)
« Reply #4 on: January 05, 2012, 04:22:13 pm »
This sounds like some more serious issue happening outside your resource handling. You should try to fix this issue the right way instead of applying workarounds.

nailuj

  • Newbie
  • *
  • Posts: 8
    • View Profile
Trouble managing resources (probably a scoping issue?)
« Reply #5 on: January 06, 2012, 06:25:10 pm »
That's what I was thinking. I'm trying to look further into the problem (if it works on Windows, I'll know where to start looking at least), but I wouldn't rule out the chance that there's some problem in my code yet.

nailuj

  • Newbie
  • *
  • Posts: 8
    • View Profile
Trouble managing resources (probably a scoping issue?)
« Reply #6 on: January 27, 2012, 05:17:10 pm »
I got around to building it on Windows now (finally), and the exact same codebase that gives me trouble on Linux runs just fine on Windows. I have played around with the issue, and it looks like I hit this bug that is already reported at https://github.com/SFML/SFML/issues/160 , except that it also crashes my window. Initializing a main window before loading the resources fixes the problem for me.