/// <summary>
        /// Auto GUI generating function.
        /// </summary>
        /// <param name="targetObject">The object instance to draw.</param>
        public static void DrawGUI(object targetObject)
        {
            Type targetType = targetObject.GetType();

            foreach (FieldInfo fieldInfo in targetType.GetFields())
            {
                if (!ShouldDisplay(fieldInfo, targetObject))
                {
                    continue;
                }

                HeaderAttribute header = GetAttribute <HeaderAttribute>(fieldInfo);
                if (header != null)
                {
                    GUIStyle headerStyle = new GUIStyle(EditorStyles.boldLabel);
                    headerStyle.padding.top += _headerHeightOffset;
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField(
                        header.header,
                        headerStyle,
                        GUILayout.Height((2 * _headerHeightOffset) + headerStyle.lineHeight));
                    EditorGUILayout.EndHorizontal();
                }

                string fieldName;
                DisplayNameAttribute fieldDisplay = GetAttribute <DisplayNameAttribute>(fieldInfo);
                if (fieldDisplay == null)
                {
                    fieldName = string.Format("{0}", fieldInfo.Name);
                }
                else
                {
                    fieldName = fieldDisplay.DisplayString;
                }

                if (fieldInfo.FieldType.IsEnum)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField(fieldName);

                    Array availableEnums;
                    EnumRangeAttribute enumRange = GetAttribute <EnumRangeAttribute>(fieldInfo);
                    if (enumRange != null)
                    {
                        MethodInfo checkingFunction =
                            targetType.GetMethod(enumRange.CheckingFunction);
                        availableEnums = (Array)checkingFunction.Invoke(
                            targetObject, new object[] { });
                    }
                    else
                    {
                        availableEnums = Enum.GetValues(fieldInfo.FieldType);
                    }

                    string[] enumNames =
                        (string[])typeof(ARCoreExtensionsProjectSettingsGUI)
                        .GetMethod("GetEnumNames")
                        .MakeGenericMethod(fieldInfo.FieldType)
                        .Invoke(null, new object[] { availableEnums });
                    var currentValue = fieldInfo.GetValue(targetObject);
                    int currentIndex = Array.IndexOf(availableEnums, currentValue);
                    if (currentIndex == -1)
                    {
                        currentIndex = 0;
                    }

                    var selectedIndex =
                        EditorGUILayout.Popup(
                            currentIndex,
                            enumNames,
                            GUILayout.Width(_groupFieldIndent));
                    fieldInfo.SetValue(targetObject, availableEnums.GetValue(selectedIndex));
                    EditorGUILayout.EndHorizontal();
                }
                else if (fieldInfo.FieldType == typeof(Boolean))
                {
                    float   originalWidth = EditorGUIUtility.labelWidth;
                    Boolean value         = (Boolean)fieldInfo.GetValue(targetObject);
                    EditorGUIUtility.labelWidth = _toggleLabelWidth;
                    value = EditorGUILayout.Toggle(new GUIContent(fieldName), value);
                    EditorGUIUtility.labelWidth = originalWidth;
                    fieldInfo.SetValue(targetObject, value);
                }
                else if (fieldInfo.FieldType == typeof(string))
                {
                    EditorGUILayout.BeginHorizontal();
                    string value = (string)fieldInfo.GetValue(targetObject);
                    EditorGUILayout.LabelField(fieldName, GUILayout.Width(_groupFieldIndent));
                    value = EditorGUILayout.TextField(value);
                    fieldInfo.SetValue(targetObject, value);
                    EditorGUILayout.EndHorizontal();
                }
                else if (fieldInfo.FieldType == typeof(int))
                {
                    EditorGUILayout.BeginHorizontal();
                    int value = (int)fieldInfo.GetValue(targetObject);
                    EditorGUILayout.LabelField(fieldName, GUILayout.Width(_groupFieldIndent));
                    value = (int)Convert.ToInt32(EditorGUILayout.TextField(value.ToString()));
                    fieldInfo.SetValue(targetObject, value);
                    EditorGUILayout.EndHorizontal();
                }
                else if (fieldInfo.FieldType == typeof(long))
                {
                    EditorGUILayout.BeginHorizontal();
                    long value = (long)fieldInfo.GetValue(targetObject);
                    EditorGUILayout.LabelField(fieldName, GUILayout.Width(_groupFieldIndent));
                    value = (long)Convert.ToInt64(EditorGUILayout.TextField(value.ToString()));
                    fieldInfo.SetValue(targetObject, value);
                    EditorGUILayout.EndHorizontal();
                }
                else if (fieldInfo.FieldType == typeof(float))
                {
                    EditorGUILayout.BeginHorizontal();
                    float value = (float)fieldInfo.GetValue(targetObject);
                    EditorGUILayout.LabelField(fieldName, GUILayout.Width(_groupFieldIndent));
                    value = (float)Convert.ToSingle(EditorGUILayout.TextField(value.ToString()));
                    fieldInfo.SetValue(targetObject, value);
                    EditorGUILayout.EndHorizontal();
                }
                else if (fieldInfo.FieldType == typeof(double))
                {
                    EditorGUILayout.BeginHorizontal();
                    double value = (double)fieldInfo.GetValue(targetObject);
                    EditorGUILayout.LabelField(fieldName, GUILayout.Width(_groupFieldIndent));
                    value = (double)Convert.ToDouble(EditorGUILayout.TextField(value.ToString()));
                    fieldInfo.SetValue(targetObject, value);
                    EditorGUILayout.EndHorizontal();
                }

                GUILayout.Space(EditorGUIUtility.standardVerticalSpacing);
                DisplayHelpInfo(fieldInfo, targetObject);
            }
        }