Reputation: 296
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
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