Search Unity

UnityEngine.LogType enumeration values

Discussion in 'Scripting' started by jnbbender, Jun 17, 2022.

  1. jnbbender

    jnbbender

    Joined:
    May 25, 2017
    Posts:
    487
    I was trying to implement a custom on screen logging solution and I have an interface which captures the UnityEngine.LogXXX calls. As LogType is used as a parameter I wanted to filter it by using a custom mask. I noticed that LogType defines it enumerated values as 1, 2, 3, 4, 5. This is pretty rudimentary and I am wondering why Unity does not define the enumerated values with bit mask values? (1<<0, 1<<2, etc.)
    This would allow for greater flexibility.

    A possible mod for upcoming versions?
     
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,003
    Certainly not as this may break previous versions. It's an ordinary enumeration since it represents a log type and you barely need a bitmask for log types, especially there are just a handful of values.

    Apart from that a log message can only have one log type at a time. Yes for filters a mask may be useful, but you can create that mask for yourself. You can always convert the LogType into a mask by using the left shift operator.

    So just create this:
    Code (CSharp):
    1. public enum LogTypeMask
    2. {
    3.     Error = 0x01,
    4.     Assert = 0x02,
    5.     Warning 0x04,
    6.     Log = 0x08,
    7.     Exception = 0x10
    8. }
    If you want to test a certain log message against that mask, just use
    (LogTypeMask)(1<<(int)logType)
    and you get the actual mask from the LogType that you can test against your mask

    If you don't like this nasty casting, you can instead implement a struct like this:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [System.Serializable]
    4. public struct LogTypeMask
    5. {
    6.     public static readonly LogTypeMask Error = LogType.Error;
    7.     public static readonly LogTypeMask Assert = LogType.Assert;
    8.     public static readonly LogTypeMask Warning = LogType.Warning;
    9.     public static readonly LogTypeMask Log = LogType.Log;
    10.     public static readonly LogTypeMask Exception = LogType.Exception;
    11.     public int mask;
    12.  
    13.     public LogTypeMask(params LogType[] aTypes)
    14.     {
    15.         mask = 0;
    16.         foreach (LogTypeMask t in aTypes)
    17.             mask |= t;
    18.     }
    19.  
    20.     public static implicit operator int(LogTypeMask aMask)
    21.     {
    22.         return aMask.mask;
    23.     }
    24.     public static implicit operator LogTypeMask(int aMask)
    25.     {
    26.         return new LogTypeMask { mask = aMask };
    27.     }
    28.  
    29.     public static implicit operator LogTypeMask(LogType aType)
    30.     {
    31.         return new LogTypeMask { mask = 1 << (int)aType };
    32.     }
    33.  
    34.     public static LogTypeMask operator &(LogTypeMask aMaskA, LogTypeMask aMaskB)
    35.     {
    36.         return new LogTypeMask { mask = aMaskA.mask & aMaskB.mask };
    37.     }
    38.     public static LogTypeMask operator |(LogTypeMask aMaskA, LogTypeMask aMaskB)
    39.     {
    40.         return new LogTypeMask { mask = aMaskA.mask | aMaskB.mask };
    41.     }
    42.     public static LogTypeMask operator ~(LogTypeMask aMask)
    43.     {
    44.         return new LogTypeMask { mask = ~aMask.mask };
    45.     }
    46. }
    47.  
    48. #if UNITY_EDITOR
    49. namespace UnityEditor.B83
    50. {
    51.     using UnityEditor;
    52.     using System.Text;
    53.  
    54.     [CustomPropertyDrawer(typeof(LogTypeMask))]
    55.     public class LogTypeMaskPropertyDrawer : PropertyDrawer
    56.     {
    57.         static string[] m_Options;
    58.         static LogTypeMaskPropertyDrawer()
    59.         {
    60.             m_Options = new string[5];
    61.             for (int i = 0; i < m_Options.Length; i++)
    62.                 m_Options[i] = ((LogType)i).ToString();
    63.         }
    64.         public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    65.         {
    66.             var prop = property.FindPropertyRelative("mask");
    67.             prop.intValue = EditorGUI.MaskField(position, label, prop.intValue, m_Options);
    68.         }
    69.     }
    70. }
    71. #endif
    72.  
    edit
    I quickly added a property drawer, so you get a neat mask field dropdown. Originally I had the mask field as uint, however since Unity always uses "int" for masks and the MaskField behaves a bit strange (it returns -1 when everything is selected), I changed it to int as well.

    Technically we don't need the readonly fields inside the struct, as we can now implicitly convert LogType into LogTypeMask. So this actually does work:

    Code (CSharp):
    1. LogTypeMask mask = LogType.Log | LogType.Error;
    2. LogType someLogType = LogType.Log;
    3.  
    4. if ((someLogType & mask) != 0)
    5.  
     
    Last edited: Jun 17, 2022