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,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