#if !CINEMACHINE_NO_CM2_SUPPORT
using UnityEngine;
using UnityEditor;
using System;
using System.Collections.Generic;
namespace Unity.Cinemachine.Editor
{
static partial class InspectorUtility
{
/// Put multiple properties on a single inspector line, with
/// optional label overrides. Passing null as a label (or sublabel) override will
/// cause the property's displayName to be used as a label. For no label at all,
/// pass GUIContent.none.
/// Rect in which to draw
/// Main label
/// Properties to place on the line
/// Sublabels for the properties
public static void MultiPropertyOnLine(
Rect rect,
GUIContent label,
SerializedProperty[] props, GUIContent[] subLabels)
{
if (props == null || props.Length == 0)
return;
const int hSpace = 2;
int indentLevel = EditorGUI.indentLevel;
float labelWidth = EditorGUIUtility.labelWidth;
float totalSubLabelWidth = 0;
int numBoolColumns = 0;
List actualLabels = new List();
for (int i = 0; i < props.Length; ++i)
{
GUIContent sublabel = new GUIContent(props[i].displayName, props[i].tooltip);
if (subLabels != null && subLabels.Length > i && subLabels[i] != null)
sublabel = subLabels[i];
actualLabels.Add(sublabel);
totalSubLabelWidth += GUI.skin.label.CalcSize(sublabel).x;
if (i > 0)
totalSubLabelWidth += hSpace;
// Special handling for toggles, or it looks stupid
if (props[i].propertyType == SerializedPropertyType.Boolean)
{
totalSubLabelWidth += rect.height + hSpace;
++numBoolColumns;
}
}
float subFieldWidth = rect.width - labelWidth - totalSubLabelWidth;
float numCols = props.Length - numBoolColumns;
float colWidth = numCols == 0 ? 0 : subFieldWidth / numCols;
// Main label. If no first sublabel, then main label must take on that
// role, for mouse dragging value-scrolling support
int subfieldStartIndex = 0;
if (label == null)
label = new GUIContent(props[0].displayName, props[0].tooltip);
if (actualLabels[0] != GUIContent.none)
rect = EditorGUI.PrefixLabel(rect, label);
else
{
rect.width = labelWidth + colWidth;
EditorGUI.PropertyField(rect, props[0], label);
rect.x += rect.width + hSpace;
subfieldStartIndex = 1;
}
for (int i = subfieldStartIndex; i < props.Length; ++i)
{
EditorGUI.indentLevel = 0;
EditorGUIUtility.labelWidth = GUI.skin.label.CalcSize(actualLabels[i]).x;
if (props[i].propertyType == SerializedPropertyType.Boolean)
{
rect.x += hSpace;
rect.width = EditorGUIUtility.labelWidth + rect.height;
EditorGUI.BeginProperty(rect, actualLabels[i], props[i]);
props[i].boolValue = EditorGUI.ToggleLeft(rect, actualLabels[i], props[i].boolValue);
}
else
{
rect.width = EditorGUIUtility.labelWidth + colWidth;
EditorGUI.BeginProperty(rect, actualLabels[i], props[i]);
EditorGUI.PropertyField(rect, props[i], actualLabels[i]);
}
EditorGUI.EndProperty();
rect.x += rect.width + hSpace;
}
EditorGUIUtility.labelWidth = labelWidth;
EditorGUI.indentLevel = indentLevel;
}
public static float PropertyHeightOfChidren(SerializedProperty property)
{
float height = 0;
var childProperty = property.Copy();
var endProperty = childProperty.GetEndProperty();
childProperty.NextVisible(true);
while (!SerializedProperty.EqualContents(childProperty, endProperty))
{
height += EditorGUI.GetPropertyHeight(childProperty)
+ EditorGUIUtility.standardVerticalSpacing;
childProperty.NextVisible(false);
}
return height - EditorGUIUtility.standardVerticalSpacing;
}
public static void DrawChildProperties(Rect position, SerializedProperty property)
{
var childProperty = property.Copy();
var endProperty = childProperty.GetEndProperty();
childProperty.NextVisible(true);
while (!SerializedProperty.EqualContents(childProperty, endProperty))
{
position.height = EditorGUI.GetPropertyHeight(childProperty);
EditorGUI.PropertyField(position, childProperty, true);
position.y += position.height + EditorGUIUtility.standardVerticalSpacing;
childProperty.NextVisible(false);
}
}
public static void HelpBoxWithButton(
string message, MessageType messageType,
GUIContent buttonContent, Action onClicked)
{
EditorGUILayout.HelpBox(message + "\n\n", messageType, true);
var rect = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect(false, 2));
float lineHeight = EditorGUIUtility.singleLineHeight;
var buttonSize = GUI.skin.label.CalcSize(buttonContent);
buttonSize.x += lineHeight;
rect.x += rect.width - buttonSize.x - 6; rect.width = buttonSize.x;
rect.y += rect.height - buttonSize.y - 12; rect.height = buttonSize.y + 3;
if (GUI.Button(rect, buttonContent))
onClicked();
}
public static float EnabledFoldoutHeight(SerializedProperty property, string enabledPropertyName)
{
var enabledProp = property.FindPropertyRelative(enabledPropertyName);
if (enabledProp == null)
return EditorGUI.GetPropertyHeight(property);
if (!enabledProp.boolValue)
return EditorGUIUtility.singleLineHeight;
return PropertyHeightOfChidren(property);
}
public static bool EnabledFoldout(
Rect rect, SerializedProperty property, string enabledPropertyName,
GUIContent label = null)
{
var enabledProp = property.FindPropertyRelative(enabledPropertyName);
if (enabledProp == null)
{
EditorGUI.PropertyField(rect, property, true);
rect.x += EditorGUIUtility.labelWidth;
EditorGUI.LabelField(rect, new GUIContent($"unknown field `{enabledPropertyName}`"));
return property.isExpanded;
}
rect.height = EditorGUIUtility.singleLineHeight;
label ??= new GUIContent(property.displayName, enabledProp.tooltip);
EditorGUI.PropertyField(rect, enabledProp, label);
if (enabledProp.boolValue)
{
++EditorGUI.indentLevel;
var childProperty = property.Copy();
var endProperty = childProperty.GetEndProperty();
childProperty.NextVisible(true);
while (!SerializedProperty.EqualContents(childProperty, endProperty))
{
if (!SerializedProperty.EqualContents(childProperty, enabledProp))
{
rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing;
rect.height = EditorGUI.GetPropertyHeight(childProperty);
EditorGUI.PropertyField(rect, childProperty, true);
}
childProperty.NextVisible(false);
}
--EditorGUI.indentLevel;
}
return enabledProp.boolValue;
}
public static bool EnabledFoldoutSingleLine(
Rect rect, SerializedProperty property,
string enabledPropertyName, string disabledToggleLabel,
GUIContent label = null)
{
var enabledProp = property.FindPropertyRelative(enabledPropertyName);
if (enabledProp == null)
{
EditorGUI.PropertyField(rect, property, true);
rect.x += EditorGUIUtility.labelWidth;
EditorGUI.LabelField(rect, new GUIContent($"unknown field `{enabledPropertyName}`"));
return property.isExpanded;
}
rect.height = EditorGUIUtility.singleLineHeight;
label ??= new GUIContent(property.displayName, enabledProp.tooltip);
EditorGUI.PropertyField(rect, enabledProp, label);
if (!enabledProp.boolValue)
{
if (!string.IsNullOrEmpty(disabledToggleLabel))
{
var w = EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight + 3;
var r = rect; r.x += w; r.width -= w;
var oldColor = GUI.color;
GUI.color = new(oldColor.r, oldColor.g, oldColor.g, 0.5f);
EditorGUI.LabelField(r, disabledToggleLabel);
GUI.color = oldColor;
}
}
else
{
rect.width -= EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight;
rect.x += EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight;
var childProperty = property.Copy();
var endProperty = childProperty.GetEndProperty();
childProperty.NextVisible(true);
while (!SerializedProperty.EqualContents(childProperty, endProperty))
{
if (!SerializedProperty.EqualContents(childProperty, enabledProp))
{
var oldWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 6; // for dragging
EditorGUI.PropertyField(rect, childProperty, new GUIContent(" "));
EditorGUIUtility.labelWidth = oldWidth;
break; // Draw only the first property
}
childProperty.NextVisible(false);
}
}
return enabledProp.boolValue;
}
}
}
#endif