jeekiii
jeekiii

Reputation: 296

Getting "invalid texture" depending on where I create the texture

The texture doesn't appear on the screen and SDL_RenderCopy returns the error code "invalid texture". However, this will only happen if I load the surface in the constructor, not in the Init function.

It also doesn't happen if I don't destruct the texture with:

SDL_DestroyTexture(image_);

I use this to load the images (didn't do this part of the code):

SDL_Texture* ImageFunc::LoadSprites(const char* filename,bool alpha,int r, int g, int b)
{
    SDL_Surface* old_image=NULL;
    SDL_Texture* new_image=NULL;
    old_image=SDL_LoadBMP(filename);

    if(!old_image)
        printf("image loadinf failure: image func: SDL_LoadBMP \n");

    if(alpha)
        SDL_SetColorKey( old_image, SDL_TRUE, SDL_MapRGB( old_image->format,r, g,b ) );

    new_image=SDL_CreateTextureFromSurface(Global::renderer,old_image);

    if(!new_image)
        printf("image loading failure: image_func\n");

    SDL_FreeSurface(old_image);
    return new_image;
}

(ImageFunc is a namespace)

So this will not work:

void Button::Init()
{
}

Button::Button()
{
    position_.x = 0;
    position_.y = 0;
    position_.w = 200;
    position_.h = 100;
    image_ = ImageFunc::LoadSprites("Images/ButtonPlay.bmp");
}

But if I put the loading LoadSprite in the Init method it'll work.

The constructor and init method are called at exactly the same time:

buttonPlay_ = Button();
buttonPlay_.Init();

It's worth noting that it's in a constructor and buttonPlay_ is an attribute.

Any idea what can cause this?

Upvotes: 1

Views: 663

Answers (1)

LogicStuff
LogicStuff

Reputation: 19617

You can't copy a class that contains a raw pointer that easily. The texture is a resource of your class, you have to manage it (and its lifetime).

buttonPlay_ = Button();

- creates temporary Button, copies that into buttonPlay_ and the temporary Button is destructed, SDL_DestroyTexture(image_) is called. That results in dangling image_ pointer in buttonPlay_. It points to texture that was destroyed.

If you can, the simplest thing to do is to forbid copying of Button and initialize buttonPlay_ just once and don't reassign it. But if you need Button to be copyable, you should be able make a deep copy with SDL_RenderCopy or SDL_RenderCopyEx. I recommend the first option, though.

Edit:

If buttonPlay_ = Button(); is in a constructor, it should be initialized in member initializer list, avoiding copy-constructor call:

SomeClass::SomeClass() :
buttonPlay_()
{
}

Your constructor would default-construct buttonPlay_ anyway, if you didn't declare it.

Upvotes: 1

Related Questions