2025-01-23 10:16:47 +08:00
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 ;
2025-05-15 10:40:15 +08:00
case PropType . Double : // todo support double
2025-01-23 10:16:47 +08:00
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 ( ) ;
2025-05-15 10:40:15 +08:00
case PropType . Double : // todo support double with EditorGUI.DoubleField()?
2025-01-23 10:16:47 +08:00
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 ( ) ;
}
}