// This code dynamically discovers eligible classes and builds the menu // data for the various component pipeline stages. static void UpdateStaticData() { if (sStageData != null) { return; } sStageData = new StageData[Enum.GetValues(typeof(CinemachineCore.Stage)).Length]; var stageTypes = new List <Type> [Enum.GetValues(typeof(CinemachineCore.Stage)).Length]; for (int i = 0; i < stageTypes.Length; ++i) { sStageData[i].Name = ((CinemachineCore.Stage)i).ToString(); stageTypes[i] = new List <Type>(); } // Get all ICinemachineComponents var allTypes = ReflectionHelpers.GetTypesInAllDependentAssemblies( (Type t) => typeof(CinemachineComponentBase).IsAssignableFrom(t) && !t.IsAbstract); // Create a temp game object so we can instance behaviours GameObject go = new GameObject("Cinemachine Temp Object"); go.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor; foreach (Type t in allTypes) { MonoBehaviour b = go.AddComponent(t) as MonoBehaviour; CinemachineComponentBase c = b != null ? (CinemachineComponentBase)b : null; if (c != null) { CinemachineCore.Stage stage = c.Stage; stageTypes[(int)stage].Add(t); } } GameObject.DestroyImmediate(go); // Create the static lists for (int i = 0; i < stageTypes.Length; ++i) { stageTypes[i].Insert(0, null); // first item is "none" sStageData[i].types = stageTypes[i].ToArray(); GUIContent[] names = new GUIContent[sStageData[i].types.Length]; for (int n = 0; n < names.Length; ++n) { if (n == 0) { bool useSimple = (i == (int)CinemachineCore.Stage.Aim) || (i == (int)CinemachineCore.Stage.Body); names[n] = new GUIContent((useSimple) ? "Do nothing" : "none"); } else { names[n] = new GUIContent(InspectorUtility.NicifyClassName(sStageData[i].types[n].Name)); } } sStageData[i].PopupOptions = names; } }
PopupLists GetPopupLists(GameObject obj) { PopupLists lists = null; if (!mPopupCache.TryGetValue(obj, out lists)) { List <string> events = ReflectionHelpers.GetAllFieldOfType(typeof(UnityEvent), obj); events.Insert(0, string.Empty); List <string> displayNames = new List <string>(); displayNames.InsertRange(0, events); for (int i = 1; i < displayNames.Count; ++i) { string[] parts = displayNames[i].Split('.'); for (int j = 0; j < parts.Length; ++j) { parts[j] = InspectorUtility.NicifyClassName(parts[j]); } displayNames[i] = string.Join("/", parts); } displayNames[0] = "(none)"; lists = new PopupLists { eventNames = events, displayNames = displayNames }; } return(lists); }
protected void DrawPipelineInInspector() { UpdateInstanceData(); foreach (CinemachineCore.Stage stage in Enum.GetValues(typeof(CinemachineCore.Stage))) { int index = (int)stage; // Skip pipeline stages that have no implementations if (index < 0 || sStageData[index].PopupOptions.Length <= 1) { continue; } const float indentOffset = 4; GUIStyle stageBoxStyle = GUI.skin.box; EditorGUILayout.BeginVertical(stageBoxStyle); Rect rect = EditorGUILayout.GetControlRect(true); // Don't use PrefixLabel() because it will link the enabled status of field and label GUIContent label = new GUIContent(InspectorUtility.NicifyClassName(stage.ToString())); if (m_stageError[index]) { label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image; } float labelWidth = EditorGUIUtility.labelWidth - (indentOffset + EditorGUI.indentLevel * 15); Rect r = rect; r.width = labelWidth; EditorGUI.LabelField(r, label); r = rect; r.width -= labelWidth; r.x += labelWidth; EditorGUI.BeginChangeCheck(); GUI.enabled = !StageIsLocked(stage); EditorGUI.showMixedValue = !m_hasSameStageDataTypes[index]; int newSelection = EditorGUI.Popup(r, m_stageState[index], sStageData[index].PopupOptions); EditorGUI.showMixedValue = false; GUI.enabled = true; Type type = sStageData[index].types[newSelection]; if (EditorGUI.EndChangeCheck()) { SetPipelineStage(stage, type); if (newSelection != 0) { sStageData[index].IsExpanded = true; } UpdateInstanceData(); // because we changed it ResetTarget(); // to allow multi-selection correctly adjust every target return; } if (type != null) { Rect stageRect = new Rect( rect.x - indentOffset, rect.y, rect.width + indentOffset, rect.height); sStageData[index].IsExpanded = EditorGUI.Foldout( stageRect, sStageData[index].IsExpanded, GUIContent.none, true); if (sStageData[index].IsExpanded) { // Make the editor for that stage UnityEditor.Editor e = GetEditorForPipelineStage(stage); if (e != null) { ++EditorGUI.indentLevel; EditorGUILayout.Separator(); e.OnInspectorGUI(); EditorGUILayout.Separator(); --EditorGUI.indentLevel; } } } EditorGUILayout.EndVertical(); } }
private void DrawComponentInspector() { const float kBoxMargin = 4; // GML wtf get rid of this const float indentSize = 15; // GML wtf get rid of this int index = (int)mStage; EditorGUILayout.BeginVertical(GUI.skin.box); EditorGUIUtility.labelWidth -= kBoxMargin; Rect rect = EditorGUILayout.GetControlRect(true); // Don't use PrefixLabel() because it will link the enabled status of field and label GUIContent label = new GUIContent(InspectorUtility.NicifyClassName(mStage.ToString())); if (mStageError) { label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image; } float labelWidth = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * indentSize; Rect r = rect; r.width = labelWidth; r.x -= kBoxMargin; EditorGUI.LabelField(r, label); r = rect; r.width -= labelWidth; r.x += labelWidth; bool wasEnabled = GUI.enabled; if (TypeIsLocked) { GUI.enabled = false; } int newSelection = EditorGUI.Popup(r, mStageSelection, sStageData[index].PopupOptions); GUI.enabled = wasEnabled; Type type = sStageData[index].types[newSelection]; if (newSelection != mStageSelection) { if (mComponent != null) { if (DestroyComponent != null) { DestroyComponent(mComponent); } } if (newSelection != 0) { sStageData[index].IsExpanded = true; if (SetComponent != null) { SetComponent(type); } } mComponent = null; GUIUtility.ExitGUI(); return; // let the component editor be recreated } // Draw the embedded editor if (type != null) { r = new Rect(rect.x - kBoxMargin, rect.y, labelWidth, rect.height); sStageData[index].IsExpanded = EditorGUI.Foldout( r, sStageData[index].IsExpanded, GUIContent.none, true); if (sStageData[index].IsExpanded) { // Make the editor for that stage if (mComponentEditor != null) { ++EditorGUI.indentLevel; EditorGUILayout.Separator(); mComponentEditor.OnInspectorGUI(); EditorGUILayout.Separator(); --EditorGUI.indentLevel; } } } EditorGUILayout.EndVertical(); EditorGUIUtility.labelWidth += kBoxMargin; }
void AssetFieldWithCreateButton( Rect r, SerializedProperty property, bool warnIfNull, string defaultName) { // Collect all the eligible asset types Type type = EmbeddedAssetType(property); if (mAssetTypes == null) { mAssetTypes = ReflectionHelpers.GetTypesInAllLoadedAssemblies( (Type t) => t.IsSubclassOf(type)).ToArray(); } float iconSize = r.height + 4; r.width -= iconSize; GUIContent label = new GUIContent(property.displayName, property.tooltip); if (warnIfNull && property.objectReferenceValue == null) { label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image; } EditorGUI.PropertyField(r, property, label); r.x += r.width; r.width = iconSize; r.height = iconSize; if (GUI.Button(r, EditorGUIUtility.IconContent("_Popup"), GUI.skin.label)) { GenericMenu menu = new GenericMenu(); if (property.objectReferenceValue != null) { menu.AddItem(new GUIContent("Edit"), false, () => Selection.activeObject = property.objectReferenceValue); menu.AddItem(new GUIContent("Clone"), false, () => { ScriptableObject copyFrom = property.objectReferenceValue as ScriptableObject; if (copyFrom != null) { string title = "Create New " + copyFrom.GetType().Name + " asset"; ScriptableObject asset = CreateAsset( copyFrom.GetType(), copyFrom, defaultName, title); if (asset != null) { property.objectReferenceValue = asset; property.serializedObject.ApplyModifiedProperties(); } } }); menu.AddItem(new GUIContent("Locate"), false, () => EditorGUIUtility.PingObject(property.objectReferenceValue)); } RebuildPresetList(); int i = 0; foreach (var a in mAssetPresets) { menu.AddItem(mAssetPresetNames[i++], false, () => { property.objectReferenceValue = a; property.serializedObject.ApplyModifiedProperties(); }); } foreach (var t in mAssetTypes) { menu.AddItem(new GUIContent("New " + InspectorUtility.NicifyClassName(t.Name)), false, () => { string title = "Create New " + t.Name + " asset"; ScriptableObject asset = CreateAsset(t, null, defaultName, title); if (asset != null) { property.objectReferenceValue = asset; property.serializedObject.ApplyModifiedProperties(); } }); } menu.ShowAsContext(); } }
private void DrawComponentInspector() { const float indentSize = 15; // GML wtf get rid of this int index = (int)m_Stage; Rect rect = EditorGUILayout.GetControlRect(true); // Don't use PrefixLabel() because it will link the enabled status of field and label GUIContent label = new GUIContent(InspectorUtility.NicifyClassName(m_Stage.ToString())); if (m_StageError) { label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image; } float labelWidth = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * indentSize; Rect r = rect; r.width = labelWidth; EditorGUI.LabelField(r, label); r = rect; r.width -= labelWidth; r.x += labelWidth; EditorGUI.BeginChangeCheck(); bool wasEnabled = GUI.enabled; if (TypeIsLocked) { GUI.enabled = false; } EditorGUI.showMixedValue = m_IsMixedType; m_StageSelection = EditorGUI.Popup(r, m_StageSelection, sStageData[index].PopupOptions); EditorGUI.showMixedValue = false; GUI.enabled = wasEnabled; Type type = sStageData[index].types[m_StageSelection]; if (EditorGUI.EndChangeCheck()) { SetComponent(m_Stage, type); if (m_StageSelection != 0) { sStageData[index].IsExpanded = true; } Shutdown(); GUIUtility.ExitGUI(); return; // let the component editor be recreated } // Draw the embedded editor if (type != null) { r = new Rect(rect.x, rect.y, labelWidth, rect.height); var isExpanded = m_IsMixedType ? false : EditorGUI.Foldout( r, sStageData[index].IsExpanded, GUIContent.none, true); if (isExpanded || isExpanded != sStageData[index].IsExpanded) { // Make the editor for that stage ActiveEditorRegistry.SetActiveEditor(m_ComponentEditor, isExpanded); if (isExpanded && m_ComponentEditor != null) { ++EditorGUI.indentLevel; m_ComponentEditor.OnInspectorGUI(); --EditorGUI.indentLevel; } } sStageData[index].IsExpanded = isExpanded; } }