So… i need to create an editor for my Textur Offset, border and slicing. I’m talking about UnityEditor, not ingame.
My idea is:
Put the Texture in a Box and draw dotted lines, colored fields…etc above it…
But it’s not working, since the lines, boxes and Co are drawn below the texture, instead of overlapping it.
So the Question is:
How can i get GUI Elements overlapping specific GUI Elements?
In general, without code, you can always use the GUI / Editor GUI functions, and not the layout ones. They use coordinates, so you can just define rects to draw stuff on, and it will draw them one on top of the other.
Okay… i tried with BeginArea.
This shows the texture correctly, and allows me to draw lines, Boxes and text above its texture.
Current Code (line 39-43):
#region Show The Inspector GUI
private void ShowControls(){
ListTilemaps();
//Show Default Prefab Field
myTarget.DefaultSpriteObject = (GameObject)EditorGUILayout.ObjectField("Default Prefab:", myTarget.DefaultSpriteObject, typeof(GameObject), true);
//Get the current Tilemap Index first (if possible)!
if(myTarget.CurrentCreatedTilemap != null){
myTarget.IndexTilemap = myTarget.GetTilemapIndexByName(myTarget.CurrentCreatedTilemap.transform.name);
}
//Show TilemapList Dropdown
myTarget.IndexTilemap = EditorGUILayout.Popup("Current selected Tilemap:", myTarget.IndexTilemap, TilemapList.ToArray());
//Check for new selected Index
CheckForTilemapIndex();
//Show Name Input Box for a new Tilemap
TilemapNewName = EditorGUILayout.TextField("New Tilemap Name:", TilemapNewName);
//Check if the name is different than Null or Empty signs, and show the Create Button
if(!String.IsNullOrEmpty(TilemapNewName)){
if(GUILayout.Button("Create Tilemap \"" + TilemapNewName + "\"")){
//Call creating Method
myTarget.CreateTilemap(TilemapNewName);
//Set the Name back to Empty
TilemapNewName = "";
EditorGUI.FocusTextInControl("");
FillEditorValues();
}
}
//Check if EditorValues are correct
if(myTarget.DataPerTilemap.Count > 0 && (myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapSizeX != (int)MapSize.x ||
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapSizeY != (int)MapSize.y ||
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX != (int)TileSize.x ||
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY != (int)TileSize.y)){
FillEditorValues(myTarget.IndexTilemap);
}
//This draws a Line to seperate the Controls
GUILayout.Box(GUIContent.none, GUILayout.Width(Screen.width), GUILayout.Height(2));
//Check if a Tilemap exists, to show the Tilemap Setups
if(myTarget.DataPerTilemap.Count > 0){
//Draw the Default Sprite texture in a Box Area
GUILayout.BeginArea(new Rect(0, 0, theSprite.width, theSprite.height), theSprite);
//Finish the Sprite texture Area
GUILayout.EndArea();
MapSize = EditorGUILayout.Vector2Field("Mapsize:", MapSize);
}
GUILayout.Box(GUIContent.none, GUILayout.Width(Screen.width), GUILayout.Height(2));
//DEBUG Clearing Datas
if(GUILayout.Button("Clear")){
myTarget.ClearDatas();
}
}
#endregion
Problem with BeginArea is, that it is positioned on the whole Inspector, and not like other Editor Controls below the Last drawn…
So… is there a way to set the Area Position correctly?
not really working, sincei think GUILayout, EditorGUILayout and GUI Components don´t create Rects that can be received by GUILayoutUtility.GetLastRect…
@Chaosgod_Esper . I’m still not 100% clear on what you wish to draw and where.
In general, what you can do, is to use BeginVertical() & BeginHorizontal() (in EditorGUILayout). Those return a rect value that is the size of the entire section that was defined (see the example in the docs). So you can do something like this:
Rect rect = EditorGUILayout.BeginVertical();
GUILayout.Button("I'm a button");
EditorGUILayout.EndVertical();
//This box will cover all controls between the former BeginVertical() & EndVertical()
GUI.Box(rect, GUIContent.none);
@Chaosgod_Esper This actually challenged me, so I had to find a solution
The key in mixing GUI / GUILayout calls, is to have proper spacing applied to the layout elements.
If you look , you have a GUILayout.Space() function, that does the trick. Here is sample code I used to get a texture displayed in the inspector between two lines.
Rect boxRect = EditorGUILayout.BeginVertical();
//This draws a Line to separate the Controls
GUILayout.Box(GUIContent.none, GUILayout.Width(Screen.width), GUILayout.Height(2));
EditorGUILayout.EndVertical();
//Now boxRect is exactly the box. so...
boxRect.y += 2f;
//Now boxRect will start right under the line, and will be the width of the line, with height 2
boxRect.height = m_casted.theSprite.texture.height;
boxRect.width = m_casted.theSprite.texture.width;
//Might want to move the X of boxRect so that it is more centered. (your choice)
GUI.DrawTexture(boxRect, m_casted.theSprite.texture);
//Now the Key Part, add a space the size of the texture, so that any other GUILayout draw calls
//will be placed below the texture
GUILayout.Space(boxRect.height);
//Draw whatever else you want.
GUILayout.Box(GUIContent.none, GUILayout.Width(Screen.width), GUILayout.Height(2));
This resulted in the following inspector :
boxRect will have the coordinates of the texture, so you can use that as a reference to draw anything using GUI calls on top of it.
if(myTarget.DataPerTilemap.Count > 0){
//Draw the Default Sprite texture in a Box Area
GUILayout.BeginArea(new Rect((Screen.width/2)-(theSprite.width/2), 0, theSprite.width, theSprite.height), theSprite);
//Draw SpriteSize as Red Lines Overlaying the Sprite Area
Handles.color = Color.red;
Handles.DrawLine(new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL,0,0), new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY,0));
Handles.DrawLine(new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX,0,0), new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY,0));
Handles.DrawLine(new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT, 0), new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT, 0));
Handles.DrawLine(new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY, 0), new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY, 0));
Handles.color = Color.white;
//Finish the Sprite texture Area
GUILayout.EndArea();
//Show the Controls to define the Tilesize in pixels
GUILayout.BeginHorizontal();
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX = EditorGUILayout.IntField("Tile Size:", myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX);
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY = EditorGUILayout.IntField("", myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY);
GUILayout.EndHorizontal();
//Show the Control to define the Offset from the Bottom of the Sprite
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileOffsetCenter = EditorGUILayout.IntField("Offset from Bottom:", myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileOffsetCenter);
//Calculate the Border Left and Top
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL = (theSprite.width - myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX) / 2;
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT = (theSprite.height - myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY) - myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileOffsetCenter;
}
But cause of the BeginArea, it is wrong positioned:
For sure, i could set the Position of the Area Rect by myself… But that won´t be dynamic… and when i want to change things, the Position is wrong again
managed to get my working Result with a ScrollView and a Box:
if(myTarget.DataPerTilemap.Count > 0){
ScrollViewPos1 = EditorGUILayout.BeginScrollView(ScrollViewPos1, false, false, GUILayout.Height((theSprite.height>128)?128:theSprite.height));
//Draw background Box
GUILayout.Space(-16);
GUILayout.Box(TileSizeBox);
//Draw the Default Sprite texture in a Box Area
GUILayout.BeginArea(new Rect((Screen.width/2)-(theSprite.width/2), 0, theSprite.width, theSprite.height), theSprite);
//Draw SpriteSize as Red Lines Overlaying the Sprite Area, to show current Tile Pixel Size
Handles.color = BoxSizeColor;
Handles.DrawLine(new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL,myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT,0), new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT,0));
Handles.DrawLine(new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX,myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT,0), new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT,0));
Handles.DrawLine(new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT, 0), new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT, 0));
Handles.DrawLine(new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY, 0), new Vector3(myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX, myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT+myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY, 0));
Handles.color = Color.white;
//Finish the Sprite texture Area
GUILayout.EndArea();
EditorGUILayout.EndScrollView();
//Show Control to define the LineColor
BoxSizeColor = EditorGUILayout.ColorField("Box Line Color:", BoxSizeColor);
//Show the Controls to define the Tilesize in pixels
GUILayout.BeginHorizontal();
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX = EditorGUILayout.IntField("Tile Size:", myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX, GUILayout.Width((Screen.width/4)*3));
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY = EditorGUILayout.IntField("", myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY, GUILayout.Width((Screen.width/4)-23));
GUILayout.EndHorizontal();
//Show the Control to define the Offset from the Bottom of the Sprite
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileOffsetCenter = EditorGUILayout.IntField("Offset from Bottom:", myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileOffsetCenter);
//Calculate the Border Left and Top
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderL = (theSprite.width - myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeX) / 2;
myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileborderT = (theSprite.height - myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTilesizeY) - myTarget.DataPerTilemap[myTarget.IndexTilemap].TilemapTileOffsetCenter;
}