Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Resolved How to get current editor UI Scaling value with scripting?

Discussion in 'Immediate Mode GUI (IMGUI)' started by eses, May 21, 2021.

  1. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    Hi.

    How can I get current editor UI Scaling value with scripting?

    Seems like some editor IMGUI rect values change when one has used editor preferences UI scaling. For example, if I scale UI to 150% Screen.width will give correct value for the width of EditorWindow, but a button of width 100 pixels isn't actually 100 pixels but 150 pixels wide.

    I haven't been able to find anything about this in Editor API documentation. Is it possible to get this scaling value and use it for GUI / EditorGUI rect placement? I can use EditorGUILayout or GUILayout to circumvent this issue, but that isn't the question.

    Thanks in advance!

    editor_ui_scaling.PNG
     
  2. IDK the answer to your question, but you can check the
    EditorGUIUtility.pixelsPerPoint
    , maybe it contains a coefficient you're looking for.
     
    oscarAbraham and eses like this.
  3. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @Lurking-Ninja

    Hey - thanks a lot!

    I thought I went through all the GUI Utility / helper classes, but obviously I missed pixelsPerPoint. I did a test, I set UI Scaling to 150% and pixels per point seems to be the right thing... now I can get the UI scaling.

    Pixels Per Point value will be in this case 1.5.
    Code (CSharp):
    1. private void OnGUI()
    2. {
    3.     // This shows the actual pixel width of EditorWindow etc.
    4.     EditorGUILayout.LabelField("Screen width: " + Screen.width);
    5.  
    6.     // Button, width 200 pixels
    7.     GUILayout.Button("Button", GUILayout.Width(200));
    8.  
    9.     // This shows 200, but the actual pixel width is 300
    10.     var prevRect = GUILayoutUtility.GetLastRect();
    11.     EditorGUILayout.LabelField("Button width: " + prevRect.width);
    12.  
    13.     // Get pixels per point
    14.     var ppp = EditorGUIUtility.pixelsPerPoint;
    15.     EditorGUILayout.LabelField("PPP: " + ppp);
    16.  
    17.  
    18.     // Button created with scaling multiplier
    19.     GUILayout.Button("Button", GUILayout.Width(200 / ppp));
    20.     prevRect = GUILayoutUtility.GetLastRect();
    21.  
    22.     // prevRect shows 133 pixels, while the actual button pixel width is now 200
    23.     EditorGUILayout.LabelField("Button width: " + prevRect.width);
    24. }
     
    Last edited: May 22, 2021
    Lurking-Ninja likes this.
  4. JasonC_

    JasonC_

    Joined:
    Oct 27, 2019
    Posts:
    66
    Correct, that is what it is supposed to do.

    Please don't. UI scaling exists to support High DPI displays. Also, if a user sets their UI scaling to something besides 100%, they expect it to work. When you do things like this:

    Code (CSharp):
    1. var ppp = EditorGUIUtility.pixelsPerPoint;
    2. GUILayout.Button("Button", GUILayout.Width(200 / ppp));
    What you're actually doing is completely ignoring the user's scaling setting, which they set for a reason.

    For example, I have a 3840 x 2160, 17.3" display on my laptop. My system scaling is set to 250% and Unity is set to use that value as well. This is what happens if you undo the scaling when positioning UI elements:

    shot.png

    The dialog on top, as you can see, looks fine and matches everything else. The one on the bottom was created by doing what you are trying to do and dividing all sizes by the scale factor.

    The requested size for the window on top was 490 x 204; giving it an actual pixel size of 1225 x 510.

    The window on the bottom has an actual pixel size of 490 x 204. It's clearly not correct.

    Please just let the scaler do its thing. Ignore pixelsPerPoint unless you're converting unscaled values (such as Screen.currentResolution) to scaled ones -- which is generally pretty rare.

    Code with assets for the pictured example above is in the attached unitypackage; and also here is just the code:

    Code (CSharp):
    1. using System.IO;
    2. using UnityEditor;
    3. using UnityEngine;
    4.  
    5. public class ScalingExample : EditorWindow {
    6.  
    7.     #region Menu Items
    8.     [MenuItem("Scaling Example/Do not do this")]
    9.     public static void ShowUnmultiply () {
    10.         var win = EditorWindow.CreateWindow<ScalingExample>();
    11.         win.UnmultiplyScaling = true;
    12.         win.Prepare();
    13.         win.Show();
    14.     }
    15.  
    16.     [MenuItem("Scaling Example/Let scaling do its thing")]
    17.     public static void ShowNormal () {
    18.         var win = EditorWindow.CreateWindow<ScalingExample>();
    19.         win.UnmultiplyScaling = false;
    20.         win.Prepare();
    21.         win.Show();
    22.     }
    23.     #endregion
    24.  
    25.     private bool UnmultiplyScaling;
    26.  
    27.     // If UnmultiplyScaling is true, divides by UI scale factor, else does nothing.
    28.     private float S (float value) => UnmultiplyScaling ? (value / EditorGUIUtility.pixelsPerPoint) : value;
    29.     private int S (int value) => Mathf.RoundToInt(S((float)value));
    30.  
    31.     private Texture CatImage;
    32.     private Texture SplooshImage;
    33.     private GUIStyle WindowMargins;
    34.     private int Margin, Spacing, CatWidth, CatHeight, LabelWidth, FieldWidth, SplooshSize, ButtonPad, ButtonBorder;
    35.     private float MultiLineHeight;
    36.  
    37.     private void Prepare () {
    38.  
    39.         string path = Path.GetDirectoryName(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(this)));
    40.         CatImage = AssetDatabase.LoadAssetAtPath<Texture2D>(Path.Combine(path, "KittyCat.png"));
    41.         SplooshImage = AssetDatabase.LoadAssetAtPath<Texture2D>(Path.Combine(path, "Sploosh.png"));
    42.  
    43.         Margin = S(10);
    44.         Spacing = S(10);
    45.         CatWidth = S(110);
    46.         CatHeight = S(128);
    47.         LabelWidth = S(100);
    48.         FieldWidth = S(250);
    49.         SplooshSize = S(32);
    50.         ButtonPad = S(5);
    51.         ButtonBorder = S(2);
    52.         MultiLineHeight = S(EditorGUIUtility.singleLineHeight * 3);
    53.  
    54.         int WindowWidth = Margin + CatWidth + Spacing + LabelWidth + FieldWidth + Margin;
    55.         int WindowHeight = Margin + CatHeight + Spacing + SplooshSize + 2 * (ButtonBorder + ButtonPad) + Margin;
    56.         minSize = maxSize = new Vector2(WindowWidth, WindowHeight);
    57.  
    58.     }
    59.  
    60.     void OnEnable () {
    61.         Prepare();
    62.     }
    63.  
    64.     private string firstName = "William", lastName = "Wallace", comment = "FREEEEEEEEEDOMMMMMM";
    65.     private enum DeathStyles { Slow = 1, Painful = 2, Public = 4, Disemboweled = 8 }
    66.     private DeathStyles deathStyle;
    67.  
    68.     void OnGUI () {
    69.  
    70.         WindowMargins ??= new GUIStyle() { margin = new RectOffset(Margin, Margin, Margin, Margin) };
    71.         EditorGUIUtility.labelWidth = LabelWidth;
    72.  
    73.         using (new GUILayout.VerticalScope(WindowMargins)) {
    74.             using (new GUILayout.HorizontalScope(GUILayout.Height(CatHeight))) {
    75.                 GUILayout.Label(CatImage, GUILayout.Width(CatWidth));
    76.                 GUILayout.Space(Spacing);
    77.                 using (new GUILayout.VerticalScope(GUILayout.ExpandHeight(true))) {
    78.                     GUILayout.FlexibleSpace();
    79.                     firstName = EditorGUILayout.TextField("First Name:", firstName);
    80.                     lastName = EditorGUILayout.TextField("Last Name:", lastName);
    81.                     deathStyle = (DeathStyles)EditorGUILayout.EnumFlagsField("Execution Style:", deathStyle);
    82.                     comment = EditorGUILayout.TextField("Comment:", comment, GUILayout.Height(MultiLineHeight));
    83.                     GUILayout.FlexibleSpace();
    84.                 }
    85.             }
    86.             GUILayout.Space(Spacing);
    87.             using (new GUILayout.HorizontalScope()) {
    88.                 GUILayoutOption[] buttonSize = { GUILayout.Width(SplooshSize*2 + ButtonPad*2), GUILayout.Height(SplooshSize + ButtonPad*2) };
    89.                 GUILayout.Label(GUIContent.none, GUILayout.ExpandWidth(true)); // less aggressive than FlexibleSpace
    90.                 GUILayout.Button("Kill", buttonSize);
    91.                 GUILayout.Button("Spare", buttonSize);
    92.                 GUILayout.Button(SplooshImage, buttonSize);
    93.                 GUILayout.Label(GUIContent.none, GUILayout.ExpandWidth(true));
    94.             }
    95.         }
    96.  
    97.     }
    98.  
    99. }
    100.  
     

    Attached Files:

  5. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    "Please don't."

    This is something I needed for a special case. And I'll be the only one using this solution, so high DPI and such stuff doesn't matter in this case.
     
    JasonC_ likes this.