- Home /
NGUI- Adding children under UIDraggable panel at runtime
Hi all
Here is my situation - I have a UIDraggable panel with UITable script on it.
So till now everything works fine, when I am adding some gameObject's as a children to the UIDraggable panel, and then reposition the UITable afterwords( to make all the children's separated from each other). This adding as a child is done at runtime using NGUITools.AddChild().
Now the problem occurs when I have to add some children at the top of the UI table and some at bottom, as previously all the children's were added at the bottom only. Here's what I wanna achieve :
Lets assume that this is my UIDraggable panel with 2, 3 and 4 as panel's children :
2
3
4
Now I have to add 5 at top and 6 at bottom of the table like this:
5
2
3
4
6
The bottom one can be added easily according to my current flow, but the top one make some issues for me. Please help me here, as I am kinds stuck here.
Answer by vexe · Sep 09, 2013 at 03:44 PM
You got 2 options:
Get into UITable code, figure out what to edit, hack it and get what you need out of it - Specifically the repositioning method inside UITable.
Make your own placement code. Which is what I always used to do since I didn't know about UITable.
Here's a code I recently wrote to organize my files/folders inside my file manager, you can use it if you're storing your items in a 1D list (not 2d ie a List of a List), just give it your item that you're trying to position and where you want it to be, works for any number of columns and rows.
public void PositionItem(Item item, int atIndex)
{
// since I'm placing the item in a 1 dimensional list (List<Item>, and not a List<List<Item>>
// I have to get the 2D index of the item to position it.
// This is a known way to treat a 1d list/array as 2d.
// an example: the 6th item has an index of 5 (in 1d),
// now in a 4x4 grid its 2d index is (1,1) (2nd row, 2nd col)
// The next line gets that result:
var index2d = new Vector2(atIndex / nCols, atIndex % nRows);
// Note that, nRows and nCols are how many rows/cols you have in your grid, if you wanna
// You could pre-set this, or calculate it.
// To calculate it you could compute the width/height of whatever it is that you're
// placing your items at (ex: a background), and then divide that width by
// itemWidth + spaceBetweenItems in case of columns,
// and itemHeight + spaceBetweenItems in case of rows.
// now get the new x,y for our item
float x = index2d.x * ItemWidth + (index2d.x + 1) * spaceBetweenItems;
float y = index2d.y * ItemHeight + (index2d.y + 1) * spaceBetweenItems;
var trans = item.transform;
trans.localPosition = Vector3.zero;
var newLocalPos = trans.localPosition;
newLocalPos.x += x;
newLocalPos.y -= y;
trans.localPosition = newLocalPos;
}
If you're storing your items in a 2D list, it will be shorter. This example will create a brand new item for you and position it correctly at the index you specify (row, col):
public override void CreateItem(int row, int col)
{
GameObject itemObj = NGUITools.AddChild(grid.gameObject, itemPrefab);
Transform itemtrans = itemObj.transform;
// let's say you wanna get your Item script and initialize your item for example
var item = slotObj.GetComponent<Item>();
item.Init(/* the info you need */ );
// add the item to your 2d list
items[row].Add(item);
// and apply the same code above - you can even call the method above, here.
float x = col * ItemWidth + (col + 1) * spaceBetweenItems;
float y = row * ItemHeight + (row + 1) * spaceBetweenItems;
itemTrans.localPosition = new Vector3();
var newLocalPos = slotTrans.localPosition;
newLocalPos.x += x;
newLocalPos.y -= y;
itemTrans.localPosition = newLocalPos;
}
You might not get it right the first time you use the code, but just fiddle around with it till it serves you well, I'm sure it will :)
Here's a very useful method to calculate the width/height of your widgets and objects in screen coords:
public static Vector3 GetObjectScreenDims(Transform trans)
{
var cam = FindCameraForLayer(trans.gameObject.layer);
// the idea is to get the bounds of the object
// which could be found in its collider, if it had one
var collider = trans.collider;
Bounds bounds;
if (collider != null)
bounds = collider.bounds;
else
{
// if that fails, try the renderer
var renderer = trans.renderer;
if (renderer != null)
bounds = renderer.bounds;
else // if it didn't have a collider nor a renderer component, we fall back to:
bounds = NGUIMath.CalculateAbsoluteWidgetBounds(trans);
}
// get the min and max in screen coords
var sMax = cam.WorldToScreenPoint(bounds.max);
var sMin = cam.WorldToScreenPoint(bounds.min);
// subtract max from min to get what we want
// now, (sMax - sMin).x is the width of the object,
// (sMax - sMin).y is the height.
return sMax - sMin;
}
Hope I helped.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Getting the text from UIInput 1 Answer
Load the main volume and put its value on a NGUI slider 3 Answers