NumericFactory/FactoryNumeric/Packages/PrimeTween/Editor/ValueContainerStartEndPropDrawer.cs

144 lines
6.3 KiB
C#

using System;
using PrimeTween;
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(ValueContainerStartEnd))]
public class ValueContainerStartEndPropDrawer : PropertyDrawer {
public override float GetPropertyHeight(SerializedProperty prop, GUIContent label) {
prop.Next(true);
var tweenType = (TweenType)prop.enumValueIndex;
prop.Next(false);
return GetHeight(prop, label, tweenType);
}
internal static float GetHeight(SerializedProperty prop, GUIContent label, TweenType tweenType) {
var propType = Utils.TweenTypeToTweenData(tweenType).Item1;
Assert.AreNotEqual(PropType.None, propType);
bool startFromCurrent = prop.boolValue;
bool hasStartValue = !startFromCurrent;
if (hasStartValue) {
return GetSingleItemHeight(propType, label) * 2f + EditorGUIUtility.standardVerticalSpacing;
}
return EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing + GetSingleItemHeight(propType, label);
}
static float GetSingleItemHeight(PropType propType, GUIContent label) {
return EditorGUI.GetPropertyHeight(ToSerializedPropType(), label);
SerializedPropertyType ToSerializedPropType() {
switch (propType) {
case PropType.Float:
return SerializedPropertyType.Float;
case PropType.Color:
return SerializedPropertyType.Color;
case PropType.Vector2:
return SerializedPropertyType.Vector2;
case PropType.Vector3:
return SerializedPropertyType.Vector3;
case PropType.Vector4:
case PropType.Quaternion:
return SerializedPropertyType.Vector4;
case PropType.Rect:
return SerializedPropertyType.Rect;
case PropType.Int:
return SerializedPropertyType.Integer;
case PropType.Double: // todo support double
case PropType.None:
default:
throw new Exception();
}
}
}
public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent label) {
prop.Next(true);
var tweenType = (TweenType)prop.enumValueIndex;
prop.Next(false);
Draw(ref pos, prop, tweenType);
}
internal static void Draw(ref Rect pos, SerializedProperty prop, TweenType tweenType) {
var propType = Utils.TweenTypeToTweenData(tweenType).Item1;
Assert.AreNotEqual(PropType.None, propType);
const float toggleWidth = 18f;
EditorGUIUtility.labelWidth -= toggleWidth;
var togglePos = new Rect(pos.x + 2, pos.y, toggleWidth - 2, EditorGUIUtility.singleLineHeight);
var guiContent = EditorGUI.BeginProperty(togglePos, new GUIContent(), prop); // todo is it possible to display tooltip? tooltip is only displayed over the label, but I need to display it over the ToggleLeft
EditorGUI.BeginChangeCheck();
bool newStartFromCurrent = !EditorGUI.ToggleLeft(togglePos, guiContent, !prop.boolValue);
if (EditorGUI.EndChangeCheck()) {
prop.boolValue = newStartFromCurrent;
}
EditorGUI.EndProperty();
pos.x += toggleWidth;
pos.width -= toggleWidth;
prop.Next(false);
if (newStartFromCurrent) {
pos.height = EditorGUIUtility.singleLineHeight;
EditorGUI.LabelField(pos, new GUIContent(prop.displayName, prop.tooltip));
prop.Next(false);
} else {
DrawValueContainer(ref pos, prop, propType);
}
pos.y += pos.height + EditorGUIUtility.standardVerticalSpacing;
DrawValueContainer(ref pos, prop, propType);
pos.y += pos.height + EditorGUIUtility.standardVerticalSpacing;
pos.x -= toggleWidth;
pos.width += toggleWidth;
}
static void DrawValueContainer(ref Rect pos, SerializedProperty prop, PropType propType) {
var root = prop.Copy();
prop.Next(true);
ValueContainer valueContainer = default;
for (int i = 0; i < 4; i++) {
valueContainer[i] = prop.floatValue;
prop.Next(false);
}
var guiContent = new GUIContent(root.displayName, root.tooltip);
pos.height = GetSingleItemHeight(propType, guiContent);
guiContent = EditorGUI.BeginProperty(pos, guiContent, root);
EditorGUI.BeginChangeCheck();
ValueContainer newVal = DrawField(pos);
ValueContainer DrawField(Rect position) {
switch (propType) {
case PropType.Float:
return EditorGUI.FloatField(position, guiContent, valueContainer.FloatVal).ToContainer();
case PropType.Color:
return EditorGUI.ColorField(position, guiContent, valueContainer.ColorVal).ToContainer();
case PropType.Vector2:
return EditorGUI.Vector2Field(position, guiContent, valueContainer.Vector2Val).ToContainer();
case PropType.Vector3:
return EditorGUI.Vector3Field(position, guiContent, valueContainer.Vector3Val).ToContainer();
case PropType.Vector4:
case PropType.Quaternion: // todo don't draw quaternion
return EditorGUI.Vector4Field(position, guiContent, valueContainer.Vector4Val).ToContainer();
case PropType.Rect:
return EditorGUI.RectField(position, guiContent, valueContainer.RectVal).ToContainer();
case PropType.Int:
var newIntVal = EditorGUI.IntField(position, guiContent, Mathf.RoundToInt(valueContainer.FloatVal));
return ((float)newIntVal).ToContainer();
case PropType.Double: // todo support double with EditorGUI.DoubleField()?
case PropType.None:
default:
throw new Exception();
}
}
if (EditorGUI.EndChangeCheck()) {
root.Next(true);
for (int i = 0; i < 4; i++) {
// ReSharper disable once CompareOfFloatsByEqualityOperator
if (root.floatValue != newVal[i]) {
root.floatValue = newVal[i];
}
root.Next(false);
}
}
EditorGUI.EndProperty();
}
}