public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { int pos = int.Parse(property.propertyPath.Split('[', ']')[1]); // Using BeginProperty / EndProperty on the parent property means that // prefab override logic works on the entire property. EditorGUI.BeginProperty(position, label, property); // Draw label and calculate new position position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent(((ControlPointAttribute)attribute).names[pos])); // Don't make child fields be indented int indent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; // Calculate positions and dimensions for the GUI elements // - min-field ... X-pos: 0%, width: 40% \ // - mirror-checkbox ... X-pos: 40%, width: 20% |> 100% of available width // - max-field ... X-pos: 60%, width: 40% / float p1 = position.x; float w1 = position.width * 0.25f; Rect timeRect = new Rect(p1, position.y, w1, position.height); float p2 = p1 + w1; float w2 = 70; Rect timeValueRect = new Rect(p2, position.y, w2, position.height); float p3 = p2 + w2; float w3 = position.width * 0.25f; Rect valueRect = new Rect(p3, position.y, w3, position.height); // Get properties by exactly passing the names of the interval's attributes SerializedProperty timeProp = property.FindPropertyRelative("time"); SerializedProperty valueProp = property.FindPropertyRelative("value"); SerializedProperty indexProp = property.FindPropertyRelative("index"); SerializedProperty firstProp = property.FindPropertyRelative("first"); SerializedProperty lastProp = property.FindPropertyRelative("last"); ControlPoints cpTarget = (ControlPoints)property.serializedObject.targetObject; bool first = pos == 0; bool last = pos == cpTarget.controlPoints.Length - 1; timeProp.floatValue = timeProp.floatValue > 1f ? 1f : timeProp.floatValue < 0f ? 0f : timeProp.floatValue; timeProp.floatValue = first ? 0f : last ? 1f : timeProp.floatValue; valueProp.floatValue = valueProp.floatValue > 1f ? 1f : valueProp.floatValue < 0f ? 0f : valueProp.floatValue; // Draw minimum-field - pass GUIContent.none to not draw the // label of the property EditorGUI.PropertyField(timeRect, timeProp, GUIContent.none); EditorGUI.PrefixLabel(timeValueRect, timeValueLabel); // Draw maximum-field EditorGUI.PropertyField(valueRect, valueProp, GUIContent.none); // Set indent back to what it was EditorGUI.indentLevel = indent; EditorGUI.EndProperty(); int cpLength = cpTarget.controlPoints.Length; if (first) { cpTarget.Update(); times = new float[cpLength]; values = new float[cpLength]; cpTarget.curve = new AnimationCurve(); } if (pos < times.Length) { times[pos] = timeProp.floatValue; values[pos] = valueProp.floatValue; } if (last) { for (int l = 0; l < cpLength; l++) { if (l < cpLength - 1) { cpTarget.curve.AddKey(times[l], values[l]); } else { cpTarget.curve.AddKey(times[cpLength - 1], values[cpLength - 1]); } } cpTarget.list = cpTarget.CurveToString(cpTarget.curve); cpTarget.Sample(); } }