Changing the texture of a SPImage
Closed this issue · 14 comments
When you create an image with a texture it sets up the quad to match the texture size. But when you change the texture the quad is not updated. And it is not even possible to change the quad manually because the setWidth and setHeight methods only change the scale (!).
Hi!
I don't quite understand your problem: when you call
image.width = newTexture.width;
image.height = newTexture.height;
that should set the image to the new texture's width, doesn't it?
BTW: width and scaleX are, just as height and scaleY, just 2 different views on the same thing. It's just a convenience to have them both.
No, the setWidth method just sets the scale. If I need the scale to be for example 50% of the texture size setting myImage.scaleX = 0.5 will not work (after doing myImage.texture=newTexture).
- (void)setWidth:(float)value
{
// this method calls 'self.scaleX' instead of changing mScaleX directly.
// that way, subclasses reacting on size changes need to override only the scaleX method.
mScaleX = 1.0f;
float actualWidth = self.width;
if (actualWidth != 0.0f) self.scaleX = value / actualWidth;
else self.scaleX = 1.0f;
}
The basic problem is that I need to know the size of the texture I used originally to create the image in order to set the scale value. It doesn't make sense for me to have to track the size of the original texture. Not to mention that it is an unexpected side effect that setting the width changes the scale.
This is how I think the width and height should be handled for SPQuads
- (float)width
{
return mVertexCoords[6];
}
- (void)setWidth:(float)value
{
mVertexCoords[2] = value;
mVertexCoords[6] = value;
}
- (float)height
{
return mVertexCoords[7];
}
- (void)setHeight:(float)value
{
mVertexCoords[5] = value;
mVertexCoords[7] = value;
}
And this is how setTexture should be implemented on SPImage
- (void)setTexture:(SPTexture*)texture
{
if (mTexture == texture)
return;
[mTexture release];
mTexture = [texture retain];
if (mTexture) {
self.width = mTexture.width;
self.height = mTexture.height;
}
}
It's unfortunately not possible to do it that way. :-(
As you might know, Sparrow is modeled after the Flash API, which handles width/height and scaleX/scaleY in the same way. So, one reason that I don't want to change this is that those coming from a Flash background would be completely puzzled by that behaviour.
But the main reason is this: the width and height properties are defined to return the size of the bounds of the object, from the perspective of its parent! Thus, if you rotate an object, the width and height will change accordingly, as the bounding box gets bigger. (!)
I must admit that I was surprised to find that out about Flash, too; I had not noticed this after years of using it. But it makes perfect sense, once you've thought about it. I explain some of the reasoning behind it here.
I hope that I could explain it well enough!
The bottom line is that if you want that behaviour, you'll have to subclass SPImage and save the original values for width and height yourself.
Ok, I understand. But in that case the initWithWidth:height:
method of SPQuad is misleading because in this case width and height take on a different meaning. And it still makes no sense to have to know the texture size to properly set the scale. Maybe the quad should always have unit coordinates, regardless of the texture size.
What about this solution: leave the width and height methods unchanged but in SPImage do
- (void)setTexture:(SPTexture*)texture
{
if (mTexture == texture)
return;
[mTexture release];
mTexture = [texture retain];
if (mTexture) {
mVertexCoords[2] = texture.width;
mVertexCoords[5] = texture.height;
mVertexCoords[6] = texture.width;
mVertexCoords[7] = texture.height;
}
}
This way I can properly set myImage.scaleX = 1 and get what I expect (i.e. no scaling).
That makes sense, I agree! And I don't see anything that would speak against changing that. I will do so!
Thanks for the suggestion!
Awesome! Thanks.
changing the texture of an image updates its dimensions (closed by b065804)
After a discussion in the forum, it turned out that my decision was rather controversial -- most other users I talked with would like to have this change undone.
The problem is that changing the size of the image when the texture changes is a side-effect that might not be anticipated by all users. It's no problem when you change the texture of an unscaled SPImage; but when your image is scaled to something different than "1", it's difficult to see why it suddenly changes from, say, 1.5 to 0.8.
Thus, since this change is rather controversial, I'll undo that change to keep compatibility with previous Sparrow versions.
BTW, here is the forum discussion:
http://forum.sparrow-framework.org/topic/scale-is-broken-in-development-branch