First Commit

This commit is contained in:
2025-05-18 22:39:39 +03:00
commit 042ede7228
440 changed files with 103153 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
using System;
namespace Golems.Attributes
{
/// <summary>
/// Adds an Inspector Button which Invokes
/// decorated methods
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class Button : Attribute
{
public string Ident = "";
public Button()
{
}
public Button(string ident)
{
Ident = ident;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f89f456d36a348344b864d363f48d953
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using UnityEngine;
using System;
namespace Golems.Attributes
{
/// <summary>
/// Draws the field/property ONLY if the compared property compared by the comparison type with the value of comparedValue returns true.
/// Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public class DrawIfAttribute : PropertyAttribute
{
#region Fields
public string comparedPropertyName { get; private set; }
public object comparedValue { get; private set; }
public DisablingType disablingType { get; private set; }
/// <summary>
/// Types of comperisons.
/// </summary>
public enum DisablingType
{
ReadOnly = 2,
DontDraw = 3
}
#endregion
/// <summary>
/// Only draws the field only if a condition is met. Supports enum and bools.
/// </summary>
/// <param name="comparedPropertyName">The name of the property that is being compared (case sensitive).</param>
/// <param name="comparedValue">The value the property is being compared to.</param>
/// <param name="disablingType">The type of disabling that should happen if the condition is NOT met. Defaulted to DisablingType.DontDraw.</param>
public DrawIfAttribute(string comparedPropertyName, object comparedValue, DisablingType disablingType = DisablingType.DontDraw)
{
this.comparedPropertyName = comparedPropertyName;
this.comparedValue = comparedValue;
this.disablingType = disablingType;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 50c83007ce1d47648bcadd778ed48e91
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: de1de1091ea1b8d4ba479915afce8358
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Golems
{
/// <summary>
/// Custom Editor for All Objects.
/// Checks for any custom RS Attributes.
/// *F Odin*
/// </summary>
[CustomEditor(typeof(Object), true)]
public partial class AttributesEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
//
// Button Attribute for automatic Inspector Buttons on
//
OnInspectorGUIButtonAttribute();
//
// OnValueChanged Attribute for callback on Field Value Changes
//
OnInspectorGUIOnValueChangedAttribute();
//
// ShowLevelAttribute
//
OnInspectorGUIShowLevelAttribute();
base.OnInspectorGUI();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 027fb565513fdd248b0c17fc81c6ca53
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using Golems.Attributes;
using Object = UnityEngine.Object;
namespace Golems
{
public partial class AttributesEditor
{
private const BindingFlags k_ButtonBindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public |
BindingFlags.NonPublic;
/// <summary>
/// Map between Method names and parameters for Methods
/// </summary>
private Dictionary<string, object[]> m_Parameters = new Dictionary<string, object[]>();
private void OnInspectorGUIButtonAttribute ()
{
var methods = target.GetType().GetMethods(k_ButtonBindingFlags);
//
// Search for Button Attribute within Each Method on this Object
//
for (int i = 0, counti = methods.Length; i < counti; ++i)
{
var method = methods[i];
var buttonAttribute = method.GetCustomAttribute<Button>(false);
if (buttonAttribute == null)
continue;
var name = string.IsNullOrEmpty(buttonAttribute.Ident) ? method.Name : buttonAttribute.Ident;
//
// Invoke Method with parms on button pressed
//
if (GUILayout.Button(name))
{
m_Parameters.TryGetValue(name, out var parms);
if (parms != null)
{
var p = new List<object>();
for (int j = 0, countj = parms.Length; j < countj; ++j)
{
p.Add(parms[j]);
//
// Skip over array size
//
if (parms[j].GetType().IsArray) ++j;
}
method.Invoke(target, p.ToArray());
} else method.Invoke(target, parms);
}
EditorGUI.indentLevel++;
SetUpParameters(name, method);
EditorGUI.indentLevel--;
}
}
/// <summary>
/// Set up Parameters for use on Method Invocation
/// </summary>
private void SetUpParameters(string name, MethodInfo method)
{
var parameterInfo = method.GetParameters();
if (parameterInfo.Length <= 0) return;
//
// Check if Method has already has its parameters setup.
// If not create a new array and add to dict.
//
if (!m_Parameters.TryGetValue(name, out var parameters))
{
var p = new List<object>(parameterInfo.Length);
for (int i = 0, counti = parameterInfo.Length; i < counti; ++i)
{
p.Add(default);
//
// If we have an Array add an additional parameter for size
//
if (parameterInfo[i].ParameterType.IsArray)
{
p.Add(default);
}
}
m_Parameters.Add(name, p.ToArray());
}
if (parameters == null) return;
//
// Iterate over each parameter and set up relevant display Field.
//
for (int i = 0, counti = parameters.Length, pi = 0; i < counti; ++i, ++pi)
{
var paramName = parameterInfo[pi].Name;
if (parameterInfo[pi].ParameterType == typeof(int))
{
int val = parameters[i] == null ? 0 : (int)parameters[i];
parameters[i] = EditorGUILayout.IntField(paramName, val);
}
else if (parameterInfo[pi].ParameterType == typeof(float))
{
float val = parameters[i] == null ? 0 : (float)parameters[i];
parameters[i] = EditorGUILayout.FloatField(paramName, val);
}
else if (parameterInfo[pi].ParameterType == typeof(string))
{
string val = String.IsNullOrEmpty((string)parameters[i]) ? "" : (string)parameters[i];
parameters[i] = EditorGUILayout.TextField(paramName, val);
}
else if (parameterInfo[pi].ParameterType == typeof(bool))
{
bool val = parameters[i] != null && (bool)parameters[i];
parameters[i] = EditorGUILayout.Toggle(paramName, val);
}
else if (parameterInfo[pi].ParameterType == typeof(char))
{
string val = "";
if (parameters[i] != null)
{
val = ((char)parameters[i]).ToString();
}
val = EditorGUILayout.TextField(paramName, val);
if (!String.IsNullOrEmpty(val))
{
parameters[i] = val[0];
}
}
else if (parameterInfo[pi].ParameterType == typeof(Sprite))
{
Sprite val = parameters[i] != null ? (Sprite)parameters[i] : default;
parameters[i] = EditorGUILayout.ObjectField(paramName, val, typeof(Sprite), false) as Sprite;
}
else
{
//
// GameObject Array support - copy me around if we want more Inspector Button Arrays
//
if (parameterInfo[pi].ParameterType.IsArray)
{
//
// We can Safely assume next item is index
//
var arraySizeIndex = i + 1;
int size = parameters[arraySizeIndex] == null ? 0 : (int)parameters[arraySizeIndex];
parameters[arraySizeIndex] = EditorGUILayout.IntField($"{paramName} Size: ", size);
var arrayParameter = (GameObject[]) parameters[i] ?? new GameObject[0];
if (arrayParameter.Length != size)
{
Array.Resize(ref arrayParameter, size);
}
EditorGUI.indentLevel++;
for (int j = 0, countj = size; j < countj; ++j)
{
GameObject val = arrayParameter[j] == null ? default : arrayParameter[j];
arrayParameter[j] = EditorGUILayout.ObjectField($"{paramName} - {j}", val, typeof(UnityEngine.GameObject), true) as GameObject;
}
EditorGUI.indentLevel--;
parameters[i] = arrayParameter;
//
// Advance an extra step to skip Array size
//
++i;
}
else
{
GameObject val = (UnityEngine.GameObject) parameters[i];
parameters[i] = EditorGUILayout.ObjectField(paramName, val, parameterInfo[pi].ParameterType, true);
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dc40108d26c2d2a4e97b205ed11e0666
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
using UnityEditor;
using UnityEngine;
namespace Golems.Attributes
{
/// <summary>
/// Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
/// </summary>
[CustomPropertyDrawer(typeof(DrawIfAttribute))]
public class DrawIfPropertyDrawer : PropertyDrawer
{
#region Fields
// Reference to the attribute on the property.
DrawIfAttribute drawIf;
// Field that is being compared.
SerializedProperty comparedField;
#endregion
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (!ShowMe(property) && drawIf.disablingType == DrawIfAttribute.DisablingType.DontDraw)
return 0f;
// The height of the property should be defaulted to the default height.
return base.GetPropertyHeight(property, label);
}
/// <summary>
/// Errors default to showing the property.
/// </summary>
private bool ShowMe(SerializedProperty property)
{
drawIf = attribute as DrawIfAttribute;
// Replace propertyname to the value from the parameter
string path = property.propertyPath.Contains(".") ? System.IO.Path.ChangeExtension(property.propertyPath, drawIf.comparedPropertyName) : drawIf.comparedPropertyName;
comparedField = property.serializedObject.FindProperty(path);
if (comparedField == null)
{
Debug.LogError("Cannot find property with name: " + path);
return true;
}
// get the value & compare based on types
switch (comparedField.type)
{ // Possible extend cases to support your own type
case "bool":
return comparedField.boolValue.Equals(drawIf.comparedValue);
case "Enum":
return comparedField.enumValueIndex.Equals((int)drawIf.comparedValue);
default:
Debug.LogError("Error: " + comparedField.type + " is not supported of " + path);
return true;
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// If the condition is met, simply draw the field.
if (ShowMe(property))
{
EditorGUI.PropertyField(position, property, new GUIContent($"{property.displayName}:"));
} //...check if the disabling type is read only. If it is, draw it disabled
else if (drawIf.disablingType == DrawIfAttribute.DisablingType.ReadOnly)
{
GUI.enabled = false;
EditorGUI.PropertyField(position, property);
GUI.enabled = true;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 055d2af24e193c44e85989dfd4427361
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Golems
{
// http://wiki.unity3d.com/index.php?title=EnumFlagPropertyDrawer&oldid=19986S
[CustomPropertyDrawer(typeof(EnumFlagAttribute))]
public class EnumFlagDrawer : PropertyDrawer
{
private const BindingFlags k_BindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public |
BindingFlags.NonPublic;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EnumFlagAttribute flagSettings = (EnumFlagAttribute) attribute;
Enum targetEnum = GetBaseProperty<Enum>(property);
string propName = flagSettings.AttributeName;
if (string.IsNullOrEmpty(propName))
propName = property.name;
EditorGUI.BeginProperty(position, label, property);
Enum enumNew = EditorGUI.EnumFlagsField(position, propName, targetEnum);
property.intValue = (int) Convert.ChangeType(enumNew, targetEnum.GetType());
EditorGUI.EndProperty();
}
static T GetBaseProperty<T>(SerializedProperty prop)
{
// Separate the steps it takes to get to this property
string[] separatedPaths = prop.propertyPath.Split('.');
// Go down to the root of this serialized property
System.Object reflectionTarget = prop.serializedObject.targetObject as object;
// Walk down the path to get the target object
foreach (var path in separatedPaths)
{
FieldInfo fieldInfo = reflectionTarget.GetType().GetField(path, k_BindingFlags);
reflectionTarget = fieldInfo.GetValue(reflectionTarget);
}
return (T) reflectionTarget;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04325198546078740b805eccad279563
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
namespace Golems.Attributes
{
[CustomPropertyDrawer(typeof(NavMeshMaskAttribute))]
public class NavMeshMaskDrawer : PropertyDrawer
{
// Draw the property inside the given rect
public override void OnGUI(Rect position, SerializedProperty serializedProperty, GUIContent label)
{
EditorGUI.BeginChangeCheck();
string[] navMeshAreaNames = GameObjectUtility.GetNavMeshAreaNames();
int navMeshArea = serializedProperty.intValue;
int selectedIndex = -1;
for (int i = 0; i < navMeshAreaNames.Length; i++)
{
if (GameObjectUtility.GetNavMeshAreaFromName(navMeshAreaNames[i]) == navMeshArea)
{
selectedIndex = i;
break;
}
}
int num = EditorGUI.Popup(position, "Navigation Area", selectedIndex, navMeshAreaNames);
if (EditorGUI.EndChangeCheck())
{
int navMeshAreaFromName = GameObjectUtility.GetNavMeshAreaFromName(navMeshAreaNames[num]);
serializedProperty.intValue = navMeshAreaFromName;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85aa6985c75db0041a410a92859bf2c7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Golems.Attributes;
namespace Golems
{
public partial class AttributesEditor
{
const BindingFlags k_OnValChangedFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private Dictionary<string, object> m_Fields = new Dictionary<string, object>();
private void OnInspectorGUIOnValueChangedAttribute()
{
var targetType = target.GetType();
var fields = targetType.GetFields(k_OnValChangedFlags);
//
// Search for OnValueChanged Attribute on Each Field on this Object
//
for (int i = 0, counti = fields.Length; i < counti; ++i)
{
var field = fields[i];
var onValueChangedAttribute = field.GetCustomAttribute<OnValueChanged>();
//
// If we find an attribute and haven't already included it in m_Fields, include it!
//
if (onValueChangedAttribute == null || m_Fields.TryGetValue(field.Name, out var fieldValue)) continue;
var method = targetType.GetMethod(onValueChangedAttribute.Method, k_ButtonBindingFlags);
if (method != null)
{
m_Fields.Add(field.Name, field.GetValue(this.target));
}
}
var changed = new List<Action>();
//
// Now check all our found Fields and see if a value has changed
//
foreach (var fieldValueKeypair in m_Fields)
{
//
// Retrieve the FieldInfo for the cached field name
//
var fieldInfo = targetType.GetField(fieldValueKeypair.Key, k_OnValChangedFlags);
if (fieldInfo == null) continue;
//
// Detect any change?
//
var currentValue = fieldInfo.GetValue(target);
if (currentValue != null && currentValue.Equals(fieldValueKeypair.Value) ||
currentValue == null && fieldValueKeypair.Value == null) continue;
var key = fieldValueKeypair.Key;
changed.Add(() => { m_Fields[key] = currentValue; });
// ...a bit lazy, probably should cache this stuff but here we are :(
var onValueChangedAttribute = fieldInfo.GetCustomAttribute<OnValueChanged>();
if (onValueChangedAttribute == null) continue;
var method = targetType.GetMethod(onValueChangedAttribute.Method, k_ButtonBindingFlags);
method?.Invoke(target, null);
}
//
// Update m_Fields which have been changed
//
changed.ForEach(x => x.Invoke());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 595d2059fa7c03f4c8c5601e985467cb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
using Golems.Attributes;
using UnityEditor;
using UnityEngine;
namespace Golems
{
[CustomPropertyDrawer(typeof(ReadOnly))]
public class ReadOnlyPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.LabelField(position, $"{property.displayName}");
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 419c0496451345568582194a3ca84016
timeCreated: 1629738460

View File

@@ -0,0 +1,15 @@
using Golems.Attributes;
namespace Golems
{
public partial class AttributesEditor
{
/// <summary>
/// Show the ShowLevelAttributes
/// </summary>
private void OnInspectorGUIShowLevelAttribute()
{
ShowLevelAttribute.EditorShowLevelInfo(target, "<color=green>Level info</color>");
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7a10473fb25a4548a133b600bdb80984
timeCreated: 1645812805

View File

@@ -0,0 +1,19 @@
using UnityEngine;
namespace Golems
{
// http://wiki.unity3d.com/index.php?title=EnumFlagPropertyDrawer&oldid=19986S
public class EnumFlagAttribute : PropertyAttribute
{
public string AttributeName;
public EnumFlagAttribute()
{
}
public EnumFlagAttribute(string name)
{
AttributeName = name;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 06d3d8b981898964da953a3cdce0bd42
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
namespace Golems.Attributes
{
[CustomPropertyDrawer(typeof(NavMeshMaskAttribute))]
public class NavMeshMaskDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty serializedProperty, GUIContent label)
{
float width = position.width;
position.width = EditorGUIUtility.labelWidth;
EditorGUI.PrefixLabel(position, label);
string[] areaNames = GameObjectUtility.GetNavMeshAreaNames();
int mask = serializedProperty.intValue;
position.x += EditorGUIUtility.labelWidth;
position.width = width - EditorGUIUtility.labelWidth;
EditorGUI.BeginChangeCheck();
mask = EditorGUI.MaskField(position, mask, areaNames);
if (EditorGUI.EndChangeCheck())
{
serializedProperty.intValue = mask;
}
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public class NavMeshMaskAttribute : PropertyAttribute // if there are build issues move the NavMeshMaskAttribute class out of the unity editor folder
{
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66f5c29600cacf64892081213937119e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
using System;
namespace Golems.Attributes
{
/// <summary>
/// OnValueChange Attribute Invokes
/// passed Method when Field Value is changed.
/// </summary>
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
public class OnValueChanged : Attribute
{
/// <summary>
/// Method to Invoke when Value change detected
/// </summary>
public string Method { get; private set; } = "";
public OnValueChanged(string method)
{
Method = method;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f31eac74bacac3c4f8138e10208ac952
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
using System;
using UnityEngine;
namespace Golems.Attributes
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public class ReadOnly : PropertyAttribute
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1b36eef4ba5e4a7290eab96d800a0c78
timeCreated: 1629738411

View File

@@ -0,0 +1,147 @@
using System;
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
#endif
namespace Golems.Attributes
{
/// <summary>
/// Show the EditorInspectableLevel property on the field.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public class ShowLevelAttribute : Attribute
{
public bool ShowWhenNotPlaying
{
get;
private set;
}
public ShowLevelAttribute()
{
ShowWhenNotPlaying = false;
}
public ShowLevelAttribute(bool showWhenNotPlaying)
{
ShowWhenNotPlaying = showWhenNotPlaying;
}
#if UNITY_EDITOR
private const BindingFlags k_ShowLevelBindingFlags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.DeclaredOnly;
private static readonly List<FieldInfo> s_Fields = new List<FieldInfo>();
private static GUIStyle s_LabelStyle = null;
private const string k_EditorLevelProperty = "EditorInspectableLevel";
public static void EditorShowLevelInfo(UnityEngine.Object target, string label)
{
s_Fields.Clear();
GetShowLevelAttributeFields(target, s_Fields, EditorApplication.isPlaying);
if (s_Fields.Count <= 0)
{
return;
}
if (!string.IsNullOrEmpty(label))
{
if (s_LabelStyle == null)
{
s_LabelStyle = EditorStyles.boldLabel;
s_LabelStyle.richText = true;
}
EditorGUILayout.LabelField(label, s_LabelStyle);
}
var origIndent = EditorGUI.indentLevel;
EditorGUI.indentLevel += 1;
for (int i = 0; i < s_Fields.Count; i++)
{
var field = s_Fields[i];
var niceName = ObjectNames.NicifyVariableName(field.Name);
var fieldValue = field.GetValue(target);
if (fieldValue != null)
{
var levelProperty = GetLevelNoSideEffectsProperty(fieldValue);
if (levelProperty != null)
{
var levelValue = levelProperty.GetValue(fieldValue);
var level = levelValue;
EditorGUI.BeginDisabledGroup(true);
EditorGUI.EndDisabledGroup();
}
else
{
EditorGUILayout.LabelField($"{niceName} does not implement LevelNoSideEffects");
}
}
else
{
EditorGUILayout.LabelField($"{niceName} is null");
}
}
EditorGUI.indentLevel = origIndent;
}
private static void GetShowLevelAttributeFields(object target, List<FieldInfo> resList, bool appPlaying)
{
int count = 0;
for (var currentType = target.GetType(); currentType != null; currentType = currentType.BaseType)
{
if (count == 100)
{
return;
}
var fields = currentType.GetFields(k_ShowLevelBindingFlags);
//
// Search for ShowLevelAttribute within each field on this Object
//
for (int i = 0, counti = fields.Length; i < counti; ++i)
{
var field = fields[i];
var showLevelAttribute = field.GetCustomAttribute<ShowLevelAttribute>(true);
if (showLevelAttribute == null)
continue;
if (!appPlaying && !showLevelAttribute.ShowWhenNotPlaying)
{
continue;
}
resList.Add(field);
}
count += 1;
}
}
private static PropertyInfo GetLevelNoSideEffectsProperty(object fieldValue)
{
var properties = fieldValue.GetType().GetProperties(BindingFlags.GetProperty |
BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < properties.Length; i++)
{
var property = properties[i];
if (k_EditorLevelProperty.CompareTo(property.Name) == 0)
{
return property;
}
}
return null;
}
#endif
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 39074075b7a640d2913b2dbdfed4d978
timeCreated: 1645812118