/// <summary> /// Raises the GUI event. /// </summary> /// <param name="position">Position.</param> /// <param name="property">Property.</param> /// <param name="label">Label.</param> public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(position, label, property); { if (label != null && label != GUIContent.none) { EditorGUI.PrefixLabel(position, label); position.x = position.x + EditorGUIUtility.labelWidth; } FontStyle fontStyle = (FontStyle)property.intValue; position.width = EditorGUIUtility.singleLineHeight * 1.25f; position.height -= 1f; EditorGUI.BeginChangeCheck(); bool bold = fontStyle == FontStyle.Bold || fontStyle == FontStyle.BoldAndItalic; if (EditorGUIX.DisplayButton(position, "b", BoldButtonStyle, bold)) { bold = !bold; } position.x += position.width; bool italic = fontStyle == FontStyle.Italic || fontStyle == FontStyle.BoldAndItalic; if (EditorGUIX.DisplayButton(position, "i", ItalicButtonStyle, italic)) { italic = !italic; } if (EditorGUI.EndChangeCheck()) { property.intValue = (int)( bold && italic ? FontStyle.BoldAndItalic : bold ? FontStyle.Bold : italic ? FontStyle.Italic : FontStyle.Normal ); } } EditorGUI.EndProperty(); }
/// <summary> /// Raises the GUI event. /// </summary> /// <param name="position">Position.</param> /// <param name="property">Property.</param> /// <param name="label">Label.</param> public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { // initialize the getter method if (m_PopupContentsGetter == null) { m_PopupContentsGetter = fieldInfo.ReflectedType.GetMethod( Attribute.PopupContentsGetter, ReflectionX.instanceBindingFlags, null, new System.Type[] { typeof(List <GUIContent>), typeof(List <object>) }, null ); } // if method cannot be found, display error icon if (m_PopupContentsGetter == null) { EditorGUIX.DisplayPropertyFieldWithStatus( position, property, ValidationStatus.Error, label, true, string.Format( "Unabled to find method: int {0}.{1} (List<GUIContent> labels, List<object> values)", fieldInfo.ReflectedType.FullName, Attribute.PopupContentsGetter ) ); } else if ( property.propertyType == SerializedPropertyType.Generic || property.propertyType == SerializedPropertyType.Gradient ) { EditorGUIX.DisplayPropertyFieldWithStatus( position, property, ValidationStatus.Error, label, true, string.Format( "SerializedPropertyType.{0} not currently supported for popup drawer.", property.propertyType ) ); } else { EditorGUI.BeginProperty(position, label, property); { s_PopupContentsArgs[0] = m_PopupLabels; s_PopupContentsArgs[1] = m_PopupValues; int index = (int)m_PopupContentsGetter.Invoke(property.serializedObject.targetObject, s_PopupContentsArgs); index = EditorGUI.Popup(position, label, index, m_PopupLabels.ToArray()); property.SetValue(m_PopupValues[index]); } EditorGUI.EndProperty(); } }
/// <summary> /// Raises the GUI event. /// </summary> /// <param name="position">Position.</param> /// <param name="property">Property.</param> /// <param name="label">Label.</param> public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { // initialize the status getter method string key = property.propertyPath; if (!m_PopupData.ContainsKey(key)) { m_PopupData[key] = new PopupData(); } PopupData popupData = m_PopupData[key]; if (!string.IsNullOrEmpty(this.Attribute.StatusGetter)) { popupData.GetStatusCallback = StatusPropertyDrawer.GetStatusCallback(property, this.Attribute.StatusGetter); } Rect iconPosition = new Rect(); ValidationStatus status = ValidationStatus.None; string statusTooltip = null; if (popupData.GetStatusCallback != null || !string.IsNullOrEmpty(this.Attribute.StatusGetter)) { FieldInfo field; object provider = property.GetProvider(out field); if (popupData.GetStatusCallback != null) { status = popupData.GetStatusCallback(provider, property.GetValue(), out statusTooltip); } else { status = ValidationStatus.Warning; statusTooltip = string.Format( "{0} {1}.{2} not found.", typeof(StatusPropertyAttribute.GetStatusCallback), provider.GetType(), this.Attribute.StatusGetter ); } if (status != ValidationStatus.None) { position.width -= EditorGUIUtility.singleLineHeight; iconPosition = position; iconPosition.x += iconPosition.width; iconPosition.width = EditorGUIUtility.singleLineHeight; } } DisplayPopup(position, property, label); if (status != ValidationStatus.None) { EditorGUIX.DisplayValidationStatusIcon(iconPosition, status, statusTooltip); } }
/// <summary> /// Displays the preferences for a feature. /// </summary> /// <param name="product">Product.</param> private void DisplayPreferences(AssetStoreProduct product) { m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition); { foreach (MethodInfo method in s_ProductMenuItems[product]) { EditorGUILayout.LabelField( method.ReflectedType.IsGenericType ? string.Format( "{0} ({1})", method.ReflectedType.Name.ToWords().Range(0, -2), ", ".Join(from t in method.ReflectedType.GetGenericArguments() select t.Name.ToWords()) ) : method.ReflectedType.Name.ToWords(), EditorStyles.boldLabel ); EditorGUIX.DisplayHorizontalLine(); EditorGUI.indentLevel += 1; method.Invoke(null, null); EditorGUI.indentLevel -= 1; } } EditorGUILayout.EndScrollView(); // bug report button DisplayBugReportButton(product); // forum link button if ( s_ProductForumUrls.ContainsKey(product) && !string.IsNullOrEmpty(s_ProductForumUrls[product]) && EditorGUIX.DisplayButton(string.Format("Get Help with {0}", product.ToString().ToWords())) ) { OpenUrl(s_ProductForumUrls[product]); } // asset store page if ( s_ProductPageUrls.ContainsKey(product) && !string.IsNullOrEmpty(s_ProductPageUrls[product]) && EditorGUIX.DisplayButton( string.Format("Review {0} on the Unity Asset Store", product.ToString().ToWords()) ) ) { OpenUrl(s_ProductPageUrls[product]); } // products page if (EditorGUIX.DisplayButton("More Products by Candlelight Interactive")) { OpenUrl(s_PublisherPage); } }
/// <summary> /// Displays an error message with optional buttons to fix errors. /// </summary> /// <returns> /// <see langword="true"/> if the fix button was pressed; otherwise, <see langword="false"/>. /// </returns> /// <param name="errorMessage">Error message to display.</param> /// <param name="buttonTexts">Button texts. If null or empty then no buttons will be displayed.</param> /// <param name="messageType">Message type.</param> /// <param name="controlIds"> /// Control identifiers. If left unspecified, then the text of each label will be used to generate them. /// </param> protected static int DisplayErrorMessageWithFixButtons( string errorMessage, GUIContent[] buttonTexts, MessageType messageType = MessageType.Error, int[] controlIds = null ) { int result = -1; Color oldColor = GUI.color; switch (messageType) { case MessageType.Error: GUI.color = Color.red; break; case MessageType.Warning: GUI.color = Color.yellow; break; } if (controlIds != null && controlIds.Length != buttonTexts.Length) { Debug.LogError( "Different number of button labels and control identifiers specified. " + "Specified control identifiers will be ignored." ); controlIds = null; } EditorGUILayout.BeginVertical(EditorStylesX.Box); { GUI.color = oldColor; EditorGUILayout.HelpBox(errorMessage, messageType); if (buttonTexts != null) { for (int i = 0; i < buttonTexts.Length; ++i) { if ( buttonTexts[i] != null && EditorGUIX.DisplayButton(buttonTexts[i], controlId: controlIds == null ? 0 : controlIds[i]) ) { result = i; } } } } EditorGUILayout.EndVertical(); return(result); }
/// <summary> /// Displays the bug report button. /// </summary> /// <param name="product">Product.</param> private static void DisplayBugReportButton(AssetStoreProduct product) { if (EditorGUIX.DisplayButton(string.Format("Report a Problem with {0}", product.ToString().ToWords()))) { OpenUrl( string.Format( "mailto:{0}?subject={1} Bug Report&body=1) What happened?\n\n2) How often does it happen?\n\n" + "3) How can I reproduce it using the example you attached?", s_BugReportEmailAddress, product.ToString().ToWords() ), "Error Creating Bug Report", "Please ensure an application is associated with email links." ); } }
/// <summary> /// Raises the inspector GUI event. /// </summary> public override void OnInspectorGUI() { // early out if the target is null, e.g., if it was destroyed in an earlier callback this frame if (this.target == null) { return; } if (this.ImplementsSceneGUIOverlay || this.ImplementsSceneGUIHandles) { if (EditorGUIX.BeginSceneGUIControlsArea()) { m_DisplayHandlePreferencesMethod.Invoke(null, null); } EditorGUIX.EndSceneGUIControlsArea(); } DisplayInspector(); }
public static void DisplayPreferenceGUI() { GUILayout.BeginArea(new Rect(134f, 39f, 352f, 352f)); // the rect in the preference window is bizarre... { #if IS_CANDLELIGHT_SCENE_GUI_AVAILABLE EditorGUIX.DisplaySceneGUIToggle(); #endif EditorGUILayout.BeginVertical(TabAreaStyle, GUILayout.ExpandWidth(false)); { Instance.m_CurrentTab = EditorGUIX.DisplayTabGroup( Instance.m_CurrentTab, s_FeatureGroupLabels, s_TabPages, 4 ); } EditorGUILayout.EndVertical(); } GUILayout.EndArea(); }
public static void DisplayPreferenceGUI() { #if !UNITY_5_6_OR_NEWER GUILayout.BeginArea(new Rect(134f, 39f, 352f, 352f)); // the rect in the preference window is bizarre... #endif { if (s_DisplaySceneGUIToggle != null) { s_DisplaySceneGUIToggle.Invoke(null, null); } UnityFeatureDefineSymbols.ShouldAutoRegisterProductSymbols = EditorGUIX.DisplayOnOffToggle( s_AutoSymbolLabel, UnityFeatureDefineSymbols.ShouldAutoRegisterProductSymbols ); EditorGUILayout.BeginVertical(TabAreaStyle, GUILayout.ExpandWidth(false)); { if (s_ProductTabIndices.Count > 0) { int tab = 0; if (!s_ProductTabIndices.ContainsKey(Instance.m_CurrentTab)) { Instance.m_CurrentTab = s_ProductTabIndices.FirstOrDefault().Key; } EditorGUI.BeginChangeCheck(); { tab = EditorGUIX.DisplayTabGroup( s_ProductTabIndices[Instance.m_CurrentTab], s_ProductTabLabels, s_TabPages, 4 ); } if (EditorGUI.EndChangeCheck()) { Instance.m_CurrentTab = s_ProductTabIndices.Where(kv => kv.Value == tab).FirstOrDefault().Key; } } } EditorGUILayout.EndVertical(); } #if !UNITY_5_6_OR_NEWER GUILayout.EndArea(); #endif }
public static void DisplayPreferenceGUI() { Dictionary <int, System.Action> tabPages = new Dictionary <int, System.Action>(); for (int i = 0; i < featureGroups.Count; ++i) { tabPages.Add(i, () => Instance.DisplayPreferences(featureGroups[Instance.currentTab])); } GUILayout.BeginArea(new Rect(134f, 39f, 352f, 352f)); // the rect in the preference window is bizarre... { #if IS_CANDLELIGHT_SCENE_GUI_AVAILABLE EditorGUIX.DisplaySceneGUIToggle(); #endif EditorGUILayout.BeginVertical(TabAreaStyle, GUILayout.ExpandWidth(false)); { Instance.currentTab = DisplayTabGroup(Instance.currentTab, featureGroups.ToArray(), tabPages); } EditorGUILayout.EndVertical(); } GUILayout.EndArea(); }
/// <summary> /// Raises the draw word form event. /// </summary> /// <param name="position">Position.</param> /// <param name="wordFormProperty">Word form property.</param> /// <param name="synonymCount">Synonym count, if e.g., the word is a main form.</param> private void OnDrawWordForm( Rect position, SerializedProperty wordFormProperty, int synonymCount = -1 ) { float countLabelWidth = 30f; position.width -= EditorGUIUtility.singleLineHeight + (synonymCount < 0 ? 0 : countLabelWidth); position.height = EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(position, wordFormProperty); position.x += position.width; position.width = EditorGUIUtility.singleLineHeight; EditorGUIX.DisplayValidationStatusIcon( position, m_WordFormStatuses[wordFormProperty.propertyPath].Status, m_WordFormStatuses[wordFormProperty.propertyPath].Tooltip ); if (synonymCount >= 0) { position.x += position.width; position.width = countLabelWidth; EditorGUI.LabelField(position, string.Format("({0})", synonymCount), EditorStylesX.LabelRight); } }
/// <summary> /// Raises the GUI event. /// </summary> /// <param name="position">Position.</param> /// <param name="property">Property.</param> /// <param name="label">Label.</param> public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { ValidationStatus status = ValidationStatus.None; bool canDraw = true; object value = property.GetValue(); if (value is IValidatable) { status = GetStatus(property.serializedObject.targetObject, value as IValidatable); } else { switch (property.propertyType) { case SerializedPropertyType.Generic: canDraw = false; break; case SerializedPropertyType.AnimationCurve: canDraw = Attribute.ValidationMethod != null; if (canDraw) { status = GetStatus(property.serializedObject.targetObject, property.animationCurveValue); } break; case SerializedPropertyType.Gradient: canDraw = false; break; case SerializedPropertyType.ArraySize: case SerializedPropertyType.Character: case SerializedPropertyType.Enum: case SerializedPropertyType.Float: case SerializedPropertyType.Integer: case SerializedPropertyType.String: status = GetStatus(property.serializedObject.targetObject, (System.IComparable)property.GetValue()); break; case SerializedPropertyType.Boolean: case SerializedPropertyType.Bounds: case SerializedPropertyType.Color: case SerializedPropertyType.LayerMask: case SerializedPropertyType.ObjectReference: case SerializedPropertyType.Quaternion: case SerializedPropertyType.Rect: case SerializedPropertyType.Vector2: case SerializedPropertyType.Vector3: case SerializedPropertyType.Vector4: status = GetStatus(property.serializedObject.targetObject, property.GetValue()); break; } } if (!canDraw) { Color oldColor = GUI.color; GUI.color = Color.red; EditorGUI.LabelField( position, label, new GUIContent( string.Format( "Unable to perform comparison of SerializedPropertyType.{0} ({1}.{2}).", property.propertyType, property.serializedObject.targetObject.name, property.propertyPath ) ) ); GUI.color = oldColor; } else { EditorGUIX.DisplayPropertyFieldWithStatus( position, property, status, label, true, m_CurrentStatusTooltip ); } }
/// <summary> /// Displays the popup. /// </summary> /// <param name="position">Position.</param> /// <param name="property">Property.</param> /// <param name="label">Label.</param> protected virtual void DisplayPopup(Rect position, SerializedProperty property, GUIContent label) { FieldInfo field; object provider = property.GetProvider(out field); string key = property.propertyPath; if (!m_PopupData.ContainsKey(key)) { m_PopupData[key] = new PopupData(); } PopupData popupData = m_PopupData[key]; // initialize the contents getter method if (popupData.GetContentsCallback == null) { MethodInfo method = provider.GetType().GetInstanceMethod(this.Attribute.PopupContentsGetter, s_ContentsGetterParams); if (method != null) { popupData.GetContentsCallback = System.Delegate.CreateDelegate( typeof(PopupAttribute.GetPopupContentsCallback), provider, method ) as PopupAttribute.GetPopupContentsCallback; } } // if method cannot be found, display error icon if (popupData.GetContentsCallback == null) { EditorGUIX.DisplayPropertyFieldWithStatus( position, property, ValidationStatus.Error, label, true, string.Format( "Unabled to find method: int {0}.{1} (List<GUIContent> labels, List<object> values)", provider.GetType(), this.Attribute.PopupContentsGetter ) ); return; } else if ( property.propertyType == SerializedPropertyType.Generic || property.propertyType == SerializedPropertyType.Gradient ) { EditorGUIX.DisplayPropertyFieldWithStatus( position, property, ValidationStatus.Error, label, true, string.Format( "SerializedPropertyType.{0} not supported for popup drawer.", property.propertyType ) ); return; } EditorGUI.BeginProperty(position, label, property); { int index = popupData.GetContentsCallback(popupData.Labels, popupData.Values); EditorGUI.BeginChangeCheck(); { index = EditorGUI.Popup(position, label, index, popupData.Labels.ToArray()); } if (EditorGUI.EndChangeCheck() && index > -1 && index < popupData.Values.Count) { property.SetValue(popupData.Values[index]); popupData.GetContentsCallback = null; } } EditorGUI.EndProperty(); }
/// <summary> /// Displays a field for a property in the scene GUI. /// </summary> /// <param name="propertyPath">Property path.</param> protected void DisplaySceneGUIPropertyField(string propertyPath) { EditorGUI.BeginChangeCheck(); { EditorGUIX.DisplayPropertyField(m_InspectedObjects[this.target].FindProperty(propertyPath)); } if (EditorGUI.EndChangeCheck()) { SerializedObject so = new SerializedObject(m_InspectedObjects.Keys.ToArray()); switch (so.FindProperty(propertyPath).propertyType) { case SerializedPropertyType.AnimationCurve: so.FindProperty(propertyPath).animationCurveValue = m_InspectedObjects[this.target].FindProperty(propertyPath).animationCurveValue; break; case SerializedPropertyType.ArraySize: case SerializedPropertyType.Integer: case SerializedPropertyType.LayerMask: case SerializedPropertyType.Character: so.FindProperty(propertyPath).intValue = m_InspectedObjects[this.target].FindProperty(propertyPath).intValue; break; case SerializedPropertyType.Boolean: so.FindProperty(propertyPath).boolValue = m_InspectedObjects[this.target].FindProperty(propertyPath).boolValue; break; case SerializedPropertyType.Bounds: so.FindProperty(propertyPath).boundsValue = m_InspectedObjects[this.target].FindProperty(propertyPath).boundsValue; break; case SerializedPropertyType.Color: so.FindProperty(propertyPath).colorValue = m_InspectedObjects[this.target].FindProperty(propertyPath).colorValue; break; case SerializedPropertyType.Enum: so.FindProperty(propertyPath).enumValueIndex = m_InspectedObjects[this.target].FindProperty(propertyPath).enumValueIndex; break; case SerializedPropertyType.Float: so.FindProperty(propertyPath).floatValue = m_InspectedObjects[this.target].FindProperty(propertyPath).floatValue; break; case SerializedPropertyType.Generic: Debug.LogError("Generic properties not implemented."); break; case SerializedPropertyType.Gradient: Debug.LogError("Gradient properties not implemented"); break; case SerializedPropertyType.ObjectReference: so.FindProperty(propertyPath).objectReferenceValue = m_InspectedObjects[this.target].FindProperty(propertyPath).objectReferenceValue; break; case SerializedPropertyType.Quaternion: so.FindProperty(propertyPath).quaternionValue = m_InspectedObjects[this.target].FindProperty(propertyPath).quaternionValue; break; case SerializedPropertyType.Rect: so.FindProperty(propertyPath).rectValue = m_InspectedObjects[this.target].FindProperty(propertyPath).rectValue; break; case SerializedPropertyType.String: so.FindProperty(propertyPath).stringValue = m_InspectedObjects[this.target].FindProperty(propertyPath).stringValue; break; case SerializedPropertyType.Vector2: so.FindProperty(propertyPath).vector2Value = m_InspectedObjects[this.target].FindProperty(propertyPath).vector2Value; break; case SerializedPropertyType.Vector3: so.FindProperty(propertyPath).vector3Value = m_InspectedObjects[this.target].FindProperty(propertyPath).vector3Value; break; case SerializedPropertyType.Vector4: so.FindProperty(propertyPath).vector4Value = m_InspectedObjects[this.target].FindProperty(propertyPath).vector4Value; break; } so.ApplyModifiedProperties(); } }
/// <summary> /// Executes any registered scene GUI callbacks. /// </summary> /// <param name="ctx">Object from whose context this method is called.</param> /// <param name="width">Desired width of scene GUI area. 281 is minimum width for sliders to appear.</param> /// <param name="anchor">Corner of the viewport to which the controls should be anchored.</param> public static void Display(ISceneGUIContext ctx, float width = 281f, GUIAnchor anchor = GUIAnchor.TopLeft) { // early out if scene gui is disabled or there are no valid registered contexts if ( !IsEnabled || s_RegisteredContexts.Count == 0 || s_RegisteredContexts.Count(k => k.Target != null && k.Callback != null) == 0 ) { return; } // ensure only the first context invoking this method during a layout phase will display the GUI if (Event.current.type == EventType.Layout) { s_DisplayInvoker = ctx.SceneGUIContext.target; } if (s_DisplayInvoker != ctx.SceneGUIContext.target) { return; } if (Event.current.type != EventType.Layout) { s_DisplayInvoker = null; } // begin gui matrix Handles.BeginGUI(); // begin the area width = Mathf.Min(width, Screen.width - 2f * s_ViewportPadding); float height = Screen.height - 2f * s_ViewportPadding - SceneGUI.SceneViewTabHeight; GUISkin oldSkin = GUI.skin; GUI.skin = Skin; GUILayout.BeginArea( new Rect( (anchor == GUIAnchor.LowerLeft || anchor == GUIAnchor.TopLeft) ? s_ViewportPadding : Screen.width - s_ViewportPadding - width, (anchor == GUIAnchor.TopLeft || anchor == GUIAnchor.TopRight) ? s_ViewportPadding : Screen.height - s_ViewportPadding - height, width, height ) ); { Color oldColor = GUI.color; GUI.color = new Color(oldColor.r, oldColor.g, oldColor.b, oldColor.a * 0.65f); EditorGUILayout.BeginVertical(EditorStylesX.SceneBox); { GUI.color = oldColor; s_ScrollPosition = EditorGUILayout.BeginScrollView(s_ScrollPosition, GUILayout.ExpandHeight(false)); { for (int i = 0; i < s_RegisteredContexts.Count; ++i) { if (s_RegisteredContexts[i].Target == null || s_RegisteredContexts[i].Callback == null) { continue; } FontStyle fontStyle = GUI.skin.label.fontStyle; GUI.skin.label.fontStyle = FontStyle.Bold; EditorGUILayout.LabelField( s_RegisteredContexts[i].Target.GetType().Name.ToWords(), GUI.skin.label ); GUI.skin.label.fontStyle = fontStyle; EditorGUIX.DisplayHorizontalLine(); ++EditorGUI.indentLevel; s_RegisteredContexts[i].Callback.Invoke(); --EditorGUI.indentLevel; } } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); } GUILayout.EndArea(); GUI.skin = oldSkin; Handles.EndGUI(); }
/// <summary> /// Raises the inspector GUI event. /// </summary> public override void OnInspectorGUI() { this.serializedObject.Update(); DrawDefaultInspector(); EditorGUI.BeginChangeCheck(); { EditorGUI.BeginDisabledGroup(Selection.objects.Length > 1); { if (EditorGUIX.DisplayButton("Sort Alphabetically")) { Undo.RecordObjects(this.targets, "Sort Alphabetically"); List <KeywordsGlossary.Entry> entries = this.target.GetFieldValue <List <KeywordsGlossary.Entry> >("m_Entries"); foreach (KeywordsGlossary.Entry entry in entries) { ( entry.GetFieldValue <List <KeywordsGlossary.InflectedForm> >("m_OtherForms") ).Sort((f1, f2) => f1.Word.CompareTo(f2.Word)); } entries.Sort((e1, e2) => e1.MainForm.Word.CompareTo(e2.MainForm.Word)); m_Entries.list = entries; EditorUtility.SetDirty(this.target); this.serializedObject.Update(); } } EditorGUI.EndDisabledGroup(); m_Entries.DoLayoutList(); if (m_Entries.count > 0) { EditorGUILayout.BeginVertical(EditorStylesX.Box); { m_CurrentEntry = m_Entries.serializedProperty.GetArrayElementAtIndex(m_Entries.index); m_CurrentWord = m_CurrentEntry.FindPropertyRelative( "m_MainForm" ).FindPropertyRelative("m_Word").stringValue; EditorGUILayout.LabelField(m_CurrentWord, EditorStylesX.BoldTitleBar); EditorGUILayout.PropertyField(m_CurrentEntry.FindPropertyRelative("m_Definition")); if (!m_InflectedForms.ContainsKey(m_CurrentEntry.propertyPath)) { ReorderableList newList = new ReorderableList( this.serializedObject, m_CurrentEntry.FindPropertyRelative("m_OtherForms") ); newList.drawHeaderCallback = (rect) => EditorGUI.LabelField(rect, "Inflected Forms"); newList.drawElementCallback = OnDrawInflectedForm; newList.onAddCallback = OnAddNewInflectedForm; m_InflectedForms.Add(m_CurrentEntry.propertyPath, newList); } m_InflectedForms[m_CurrentEntry.propertyPath].DoLayoutList(); } EditorGUILayout.EndVertical(); } } if (EditorGUI.EndChangeCheck()) { this.serializedObject.ApplyModifiedProperties(); this.serializedObject.Update(); UpdateGUIContents(); s_RebuildKeywordsMethod.Invoke(this.target, null); } DisplayKeywordList(); }