You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CrowdControl/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ProgressBarPropertyDrawer.cs

155 lines
4.8 KiB
C#

3 months ago
using UnityEngine;
using UnityEditor;
using System.Reflection;
namespace NaughtyAttributes.Editor
{
[CustomPropertyDrawer(typeof(ProgressBarAttribute))]
public class ProgressBarPropertyDrawer : PropertyDrawerBase
{
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
{
ProgressBarAttribute progressBarAttribute = PropertyUtility.GetAttribute<ProgressBarAttribute>(property);
var maxValue = GetMaxValue(property, progressBarAttribute);
return IsNumber(property) && IsNumber(maxValue)
? GetPropertyHeight(property)
: GetPropertyHeight(property) + GetHelpBoxHeight();
}
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(rect, label, property);
if (!IsNumber(property))
{
string message = string.Format("Field {0} is not a number", property.name);
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
return;
}
ProgressBarAttribute progressBarAttribute = PropertyUtility.GetAttribute<ProgressBarAttribute>(property);
var value = property.propertyType == SerializedPropertyType.Integer ? property.intValue : property.floatValue;
var valueFormatted = property.propertyType == SerializedPropertyType.Integer ? value.ToString() : string.Format("{0:0.00}", value);
var maxValue = GetMaxValue(property, progressBarAttribute);
if (maxValue != null && IsNumber(maxValue))
{
var fillPercentage = value / CastToFloat(maxValue);
var barLabel = (!string.IsNullOrEmpty(progressBarAttribute.Name) ? "[" + progressBarAttribute.Name + "] " : "") + valueFormatted + "/" + maxValue;
var barColor = progressBarAttribute.Color.GetColor();
var labelColor = Color.white;
var indentLength = NaughtyEditorGUI.GetIndentLength(rect);
Rect barRect = new Rect()
{
x = rect.x + indentLength,
y = rect.y,
width = rect.width - indentLength,
height = EditorGUIUtility.singleLineHeight
};
DrawBar(barRect, Mathf.Clamp01(fillPercentage), barLabel, barColor, labelColor);
}
else
{
string message = string.Format(
"The provided dynamic max value for the progress bar is not correct. Please check if the '{0}' is correct, or the return type is float/int",
nameof(progressBarAttribute.MaxValueName));
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
}
EditorGUI.EndProperty();
}
private object GetMaxValue(SerializedProperty property, ProgressBarAttribute progressBarAttribute)
{
if (string.IsNullOrEmpty(progressBarAttribute.MaxValueName))
{
return progressBarAttribute.MaxValue;
}
else
{
object target = PropertyUtility.GetTargetObjectWithProperty(property);
FieldInfo valuesFieldInfo = ReflectionUtility.GetField(target, progressBarAttribute.MaxValueName);
if (valuesFieldInfo != null)
{
return valuesFieldInfo.GetValue(target);
}
PropertyInfo valuesPropertyInfo = ReflectionUtility.GetProperty(target, progressBarAttribute.MaxValueName);
if (valuesPropertyInfo != null)
{
return valuesPropertyInfo.GetValue(target);
}
MethodInfo methodValuesInfo = ReflectionUtility.GetMethod(target, progressBarAttribute.MaxValueName);
if (methodValuesInfo != null &&
(methodValuesInfo.ReturnType == typeof(float) || methodValuesInfo.ReturnType == typeof(int)) &&
methodValuesInfo.GetParameters().Length == 0)
{
return methodValuesInfo.Invoke(target, null);
}
return null;
}
}
private void DrawBar(Rect rect, float fillPercent, string label, Color barColor, Color labelColor)
{
if (Event.current.type != EventType.Repaint)
{
return;
}
var fillRect = new Rect(rect.x, rect.y, rect.width * fillPercent, rect.height);
EditorGUI.DrawRect(rect, new Color(0.13f, 0.13f, 0.13f));
EditorGUI.DrawRect(fillRect, barColor);
// set alignment and cache the default
var align = GUI.skin.label.alignment;
GUI.skin.label.alignment = TextAnchor.UpperCenter;
// set the color and cache the default
var c = GUI.contentColor;
GUI.contentColor = labelColor;
// calculate the position
var labelRect = new Rect(rect.x, rect.y - 2, rect.width, rect.height);
// draw~
EditorGUI.DropShadowLabel(labelRect, label);
// reset color and alignment
GUI.contentColor = c;
GUI.skin.label.alignment = align;
}
private bool IsNumber(SerializedProperty property)
{
bool isNumber = property.propertyType == SerializedPropertyType.Float || property.propertyType == SerializedPropertyType.Integer;
return isNumber;
}
private bool IsNumber(object obj)
{
return (obj is float) || (obj is int);
}
private float CastToFloat(object obj)
{
if (obj is int)
{
return (int)obj;
}
else
{
return (float)obj;
}
}
}
}