Node loaded from .csb has bounding box size 0 - cocos2d-x

I have created Node ( with images and labels inside ) and I instantiate and add to scene ( in C++ code )
auto item_one = CSLoader::createNode("item.csb");
sprite->addChild(item_one);
auto r = item_one->getBoundingBox();
and it is visible but r always has width and height equal to zero. That is a reason why I cannot fetch click on that item. Why is bounding box zero and how to change that ?
In cocos studio Node for item has dimensions of 542 x 542 but.
Can anyone help ?

The CSLoader::createNode("fileName.csb") loads the entire scene/layer (depending what you created). If you want the dimensions of a specific child use:
auto imageNode = item_node->getChildByName("NameOfChildInCocostudio");
auto spriteImage = dynamic_cast<Sprite*>(imageNode);
auto spriteBoundingBox = spriteImage->getBoundingBox();
At this point you should get the width and height of the image. If you want the size it appears at you have to multiply the bounds with the node scale. Use the code below to do that.
auto onScreenWidth = spriteBoundingBox.width * spriteNode->getScaleX();
auto onScreenHeight = spriteBoundingBox.height * spriteNode->getScaleY();
Let me know if this helps.

Related

Actionscript 3, What is the difference is between scale and dimension

I'd like to know if I change the scale value, what happened to the object? I'm using flash air system.
I draw a movie clip box with 1000 x 1000px dimension.
I might change the size with 2 ways :
1st : Control of dimension with mc.with or mc.height
2nd : Control of dimension with mc.scaleX or mc.scaleY
Once I try to change the object with 500 x 500px,
Which one do you prefer : mc.width = mc.height = 500 vs mc.scaleX = mc.scaleY = 0.5
What is the benefit of using scale method?
Some good reading in the documentation here.
Basically they do exactly the same thing. It just depends on the case which one is easier for the developer to define in that case. If you know you need the result to be as wide as 212 pixels or the same width as object1 it makes sense to say
object2.width = 212;
or
object2.width = object1.width;
Let's assume you prefer to keep object2's dimensions proportional. You could then say
object2.scaleY = object2.scaleX;
without even knowing how many pixels that is or having another object of that same height to set it to.
The final note is this: if you change scale, dimension changes, and when you change dimension, scale also does change. In other words, setting scaleX to 1 will also set it back to its original width. Use them interchangeably. Use the one that is simpler for you in that instance.

How get a string width in Libgdx?

I wonder know how to get the width of my string in pixels
BitmapFont API < 1.5.6
To mesure the width of a String you use your Font and get the bounds of the String, you are going to draw.
BitmapFont.getBounds(String str).width
BitmapFont API
You can get the height to for the right offset for drawing too. Just replace width with height.
In addition for multiline texts use getMultiLineBounds(someString).width to get the bounds.
BitmapFont API >= 1.5.6
The BitmapFont API changed in 1.5.7 so there is a different way to get the bounds now:
BitmapFont.TextBounds and getBounds are done. Instead, give the string to GlyphLayout and get the bounds using its width and height fields. You can then draw the text by passing the same GlyphLayout to BitmapFont, which means the glyphs don’t have to be laid out twice like they used to.
Source (Web archive)
Example:
GlyphLayout layout = new GlyphLayout(); //dont do this every frame! Store it as member
layout.setText("meow");
float width = layout.width;// contains the width of the current set text
float height = layout.height; // contains the height of the current set text
According to #Nates answer: https://stackoverflow.com/a/20759876/619673 calling method
BitmapFont.getBounds(String str).width
not always returns proper width! Especially when you are reusing font.
If you want draw text for example in the center of part of view port, you can avoid this problem by using another method
BitmapFont.drawWrapped(...)
Example code:
font.drawWrapped(spriteBatch, "text", x_pos, y_pos, your_area_for_text, BitmapFont.HAlignment.CENTER);
If you use skins in UI it is a hassle to find out the correct font to feed into the GlyphLayout.
In this case I use a throw away instance of Label to figure everything out for me then ask the Label for the width.
Skin skin = getMySkin();
Label cellExample = new Label("888.88888", skin);
cellExample.layout();
float cellWidth = cellExample.getWidth();
Table table = new Table(skin);
table.defaults().width(cellWidth);
// fill table width cells ...
This is not the answer if you want to position the text yourself, but it is useful to make a UI layout stable and less dependent on the actual content of the cells.

scaling object to match field of view

I am overlaying some clickable hotspots on top of a proprietary panorama viewer application in flash (as3), and I need to make sure that the hotspots scale according to the changing field of view as the user zooms in / zooms out, but I'm not sure what formula to use.
I set a maximum and minimum field of view of 90 and 25, respectively. I've been given some suggestions of how to calculate the scale of the icons:
from the maker of the panorama software:
Scale => 1/tan(FoV)
This doesn't seem to work for me. And:
scalar += (ZOOM_SCALE_UPPER - ZOOM_SCALE_LOWER) * ( ZOOM_LIMIT_OUT - tempFOV )/( ZOOM_LIMIT_OUT-ZOOM_LIMIT_IN) ;
hotspot.scaleX = hotspot.scaleY = scalar;
Gets me close, but at some point the hotspot stops scaling even though the panorama continues to scale. I thought I could just do something like:
diffFOV = previousFOV - currentFOV.
hotspot.scale = currentScale*(1-diffFov)
But that's not quite right either. Everything gets way too big or too small.
Any ideas?
You may be over thinking it.
//assume we change the scale
var NEW_SCALE:Number = currentScale*(1-(previousFOV-currentFOV));
//1. change the scale of the parent containing both the view and the hotspots
viewSprite.scale = NEW_SCALE;
//this way the hotspot and the panorama will scale together
//2. if they are not in the same parent... then set them both to the same view
hotspot.scale = panorama.scale;
Only thing you may have to do after is reposition if they are not registered on their center point.

Why do we divide by 2 getContentSize?

In sample from Cocos2d-x Tutorials when we describe actionMove
CCFiniteTimeAction* actionMove =
CCMoveTo::create( (float)actualDuration,
ccp(0 - target->getContentSize().width/2, actualY) );
we set a point ccp(0 - target->getContentSize().width/2, actualY). If we have target with 20 width then we have point (-10, actualY), and half target must be visible, but it's not so. Why?
Initial target position
target->setPosition(
ccp(winSize.width + (target->getContentSize().width/2),
actualY) );
Here we also divide by 2, but I understand it (winSize.width + any number and target becomes invisible, outside the screen).
Cocos2d-x uses the center of the object as the origin/anchor point, rather than the corner. So if you want half of your object to be visible on the edge of the screen, use:
ccp(0, actualY)
or
ccp(winSize.width)
You add half of the contentSize if you want the object to be completely off the screen.

MovieClip resizes, but its children's height and width are not changed?

Changing the width and height of the parent MovieClip does not bring change in the width and height of the inner MovieClip. The parent MovieClip is placed at Stage and is resized manually. When I assign the dimension of the parent MovieClip to the inner MovieClip through code, the parent MovieClip dimension is changed. I want both MovieClip to be of same width and height at runtime. However, parent MovieClip dimension is changed at design time by me.
Example:
There are two MovieClip, one inside another. Now parent MovieClip is placed at Stage at design time and its dimension is (50,50) and the child MovieClip which is inside the parent MovieClip has also same dimensions (50,50). Now, I manually change the parent MovieClip dimension by pressing Q and stretching it with mouse, the dimension of the parent MovieClip is now (100,150) or whatever I like. Now double-click on parent MovieClip and check that inner MovieClip dimension remains same i.e. (50,50)
Now in AS3 code, I change the width and height of inner MovieClip like this:
saveheight = parentmc.height;
savewidth = parentmc.width;
now I change the child MovieClip according to the dimensions of the parent MovieClip like this:
parentmc.inner_mc.width = parentmc.width;
parentmc.inner_mc.height = parentmc.height;
but this brings change in parentmc also so I reassign value to parentmc like this:
parentmc.height = saveheight;
parentmc.width = savewidth;
In above case, parentmc and inne_rmc dimension should be same i.e (100 ,150). With swapping the values as above, I get parentmc and inner_mc to be of same dimension, but object size is never (100, 150), I have checked it with pixel-perfect air app.
In your code, you are neglecting to account for the transformation to the parent that you did with the 'Q' tool in the authoring environment. The childmc's width and height are expressed in terms of parentmc's transformed coordinate space. If you wish to scale the inner clip to a specific size in stage coordinate space you need to account for the scale of the parent that resulted from your transform:
parentmc.inner_mc.width = parentmc.width/parentmc.scaleX;
parentmc.inner_mc.height= parentmc.height/parentmc.scaleY;
Also, if the clips aren't aligned (e.g. registered by their upper left corner and with the child at 0,0), enlarging the child could push out the boundaries of the parent.
You can also use the parent's transform matrix if you prefer that over using scaleX and scaleY.
UPDATE 4.8.11: Were you perhaps asking to do this (runtime removal of the authoring-time transform)?
saveheight = parentmc.height;
savewidth = parentmc.width;
parentmc.scaleX = 1.0; // Undo authoring-time scale transform
parentmc.scaleY = 1.0; // Undo authoring-time scale transform
parentmc.inner_mc.width = savewidth;
parentmc.inner_mc.height = saveheight;
parentmc.width = savewidth;
parentmc.height = saveheight;
Note: I'm not at a computer set up with Flash to test this, so please leave me a comment if this does not do what you are expecting, and I will happily check my work and follow up.
it doesn't quite work like that,
you need to multiply the children by the scale of the parent.
the other thing you can do is use getBounds and then you can get the bounding rectangle of any child (and child's children etc) relative to the parent
I honestly don't understand what you're asking, because what you describe should work!
If we have a parentMC and a childMC both with a 50 height and 50 width, if you change the parentMC.scaleX = 2; it will apear to be 100 in width. The same goes for the childMC.
Could you please provide an example of what you're trying to do here? - or some code.