IlludiumPu36
IlludiumPu36

Reputation: 4304

Unity - Set GUI.Box background color

I'm trying to set the background color of a GUI.Box:

void OnGUI()
        {
            string LatLong;
           LatLong = map.calc.prettyCurrentLatLon;
            var mousePosition = Input.mousePosition;
            float x = mousePosition.x + 10;
            float y = Screen.height - mousePosition.y + 10;
            GUI.backgroundColor = Color.red;
            GUI.Box(new Rect(x, y, 200, 200), LatLong);
        }

However, the box is showing in a semi-transparent black, and the white text is subdued, not opaque white.

enter image description here

Upvotes: 3

Views: 11806

Answers (3)

neopolitans
neopolitans

Reputation: 21

REVISION - 17 July 2022 - GUI Style Creation and Storage

Prelude

Style creation through the methods provided by others are certainly functional methods of providing your custom editors with a unique look. They have some fundamental issues I should point out, which my method doesn't outright correct, just alleviate. This method still needs to be expanded upon and is still a partly experimental progression from a personal plugin.

  1. Creating styles every OnGUI Call creates unnecessary, extra instructions for your editor window. This doesn't scale well past a handful (4~) styles.

  2. By creating styles every time OnGUI is called, you're creating textures repeatedly for the background colour (not good). Over prolonged use of this method, memory leaks can occur although unlikely.

What does my method do differently?

  • Creates GUIStyle and Texture2D files. GUIStyles are saved as .JSON files, which is best compatible for [JSON <-> GUIStyle] conversion and storage.

  • Texture2Ds are encoded from raw data to PNG format through UnityEngine.

  • Checks if a style file is null before fetching or creating any missing styles again.

  • Contains a list of all styles through the use of a Style Manifest (struct) to store the names of all textures and styles to iteratively load on fetch.

  • Only creates styles if they are missing. Does not spend resources on creating pre-existing styles and pre-existing styles.

GUIStyles (as JSONs) and Texture2D files are stored in a Resources folder within the Plugin folder.

It should be noted that my style methods are done with the express understanding and consideration of GUISkins existing. They are not suitable for my UI/UX needs.

How is this done?

Plugin Style Handing Diagram

I separate Style Loading into a unique namespace for style handling and contain functions, as well as public variables for global plugin access, within. This namespace creates, loads and can send back styles on the requests sent by other scripts.

A call to a function is made when the plugin is opened to load the style manifest and subsequently all styles and textures are loaded, to be relinked for use.

If the styles manifest is missing then it is recreated along with all GUIStyle files. If the styles manifest is not missing but a style is then that style is recreated and the style manifest is modified to reference the new style.

Textures are handled separately from GUIStyle loading and are collected in a separate array. They are independently checked to see if they still exist and missing textures are recreated and encoded from raw data to PNG format, with the style manifest being modified when necessary.

Instead of repeatedly creating all styles or repeatedly loading them each frame, the plugin sends a request to fetch the first style from memory and checks if the result is null. If the first style returns as null then the plugin assumes all styles have been dereferenced and calls a reload or recreation of the relevant GUIStyle files (this can happen because of the engine entering/exiting play mode and is necessary to preserve UI/UX legibility).

If the style returns as a valid reference, plugins of mine do use it but this is risky. It's a good idea to also check at least one texture because textures are at risk of being dereferenced from the Texture2D array.

Once each check is done, the plugin renders the layout as normal and the next cycle begins. Using this method overall requires extra processing time and extra storage space for the plugin but in turn:

  • Quicker over a longer period of time due to styles being created or loaded only when necessary
  • Easier to modify themes for plugins, allowing individuals to customize the tools to their preferred theme. This can also be expanded on custom "theme packs" for a plugin.
  • Scalable for large amounts of styles to an extent.

This method still requires experience in GUI Styles, Data Saving, JSON Utilisation and C#.

Upvotes: 2

Andrew900460
Andrew900460

Reputation: 721

I'm gonna slide in with a more elegant solution here before this question gets old. I saw Thomas's answer and started to wonder if there is a way to do that without having to do the "InitStyles" in the OnGUI loop. Since ideally you only want to init the GuiSkin once in Awake or Start or wherever, but only once, and then never check to see if it's null ever again.

Anyway, after some trial and error, I came up with this.

private void Awake() {
    // this variable is stored in the class
    // 1 pixel image, only 1 color to set
    consoleBackground = new Texture2D(1, 1, TextureFormat.RGBAFloat, false); 
    consoleBackground.SetPixel(0, 0, new Color(1, 1, 1, 0.25f));
    consoleBackground.Apply(); // not sure if this is necessary

    // basically just create a copy of the "none style"
    // and then change the properties as desired
    debugStyle = new GUIStyle(GUIStyle.none); 
    debugStyle.fontSize = 24;
    debugStyle.normal.textColor = Color.white;
    debugStyle.normal.background = consoleBackground;
}

Upvotes: 4

Thomas
Thomas

Reputation: 1257

You have to use s gui style:

private GUIStyle currentStyle = null;
 
void OnGUI()
{  
    InitStyles();
    GUI.Box( new Rect( 0, 0, 100, 100 ), "Hello", currentStyle );
}
 
private void InitStyles()
{
    if( currentStyle == null )
    {
        currentStyle = new GUIStyle( GUI.skin.box );
        currentStyle.normal.background = MakeTex( 2, 2, new Color( 0f, 1f, 0f, 0.5f ) );
    }
}
 
private Texture2D MakeTex( int width, int height, Color col )
{
    Color[] pix = new Color[width * height];
    for( int i = 0; i < pix.Length; ++i )
    {
        pix[ i ] = col;
    }
    Texture2D result = new Texture2D( width, height );
    result.SetPixels( pix );
    result.Apply();
    return result;
}

Taken from unity forum.

Upvotes: 3

Related Questions