public static GUIContent BeginProperty(Rect totalPosition, GUIContent label, RuntimeSerializedProperty property) { Highlighter.HighlightIdentifier(totalPosition, property.PropertyPath); if (s_PendingPropertyKeyboardHandling != null) { DoPropertyFieldKeyboardHandling(s_PendingPropertyKeyboardHandling); } // Properties can be nested, so A BeginProperty may not be followed by its corresponding EndProperty // before there have been one or more pairs of BeginProperty/EndProperty in between. // The keyboard handling for a property (that handles duplicate and delete commands for array items) // uses EditorGUI.lastControlID so it has to be executed for a property before any possible child // properties are handled. However, it can't be done in it's own BeginProperty, because the controlID // for the property is not yet known at that point. For that reason we mark the keyboard handling as // pending and handle it either the next BeginProperty call (for the first child property) or if there's // no child properties, then in the matching EndProperty call. s_PendingPropertyKeyboardHandling = property; if (property == null) { string error = ((label != null) ? (label.text + ": ") : EmptyStr) + "RuntimeSerializedProperty is null"; EditorGUI.HelpBox(totalPosition, "null", MessageType.Error); throw new System.NullReferenceException(error); } s_PropertyFieldTempContent.text = LocalizationDatabaseHelper.GetLocalizedString((label != null) ? label.text : property.DisplayName); // no necessary to be translated. s_PropertyFieldTempContent.tooltip = EasyGUI.IsCollectingTooltips ? ((label == null) ? property.Tooltip : label.tooltip) : null; string attributeTooltip = RuntimeScriptAttributeUtility.GetHandler(property, null).Tooltip; if (attributeTooltip != null) { s_PropertyFieldTempContent.tooltip = attributeTooltip; } s_PropertyFieldTempContent.image = label != null ? label.image : null; // In inspector debug mode & when holding down alt. Show the property path of the property. if (Event.current.alt && property.RuntimeSerializedObject.SerializedObject.InspectorMode() != InspectorMode.Normal) { s_PropertyFieldTempContent.tooltip = s_PropertyFieldTempContent.text = property.PropertyPath; } bool wasBoldDefaultFont = EditorGUIUtilityHelper.GetBoldDefaultFont(); if (property.RuntimeSerializedObject.SerializedObject.targetObjects.Length == 1 && property.IsInstantiatedPrefab) { EditorGUIUtilityHelper.SetBoldDefaultFont(property.PrefabOverride); } s_PropertyStack.Push(new RuntimePropertyGUIData(property, totalPosition, wasBoldDefaultFont, GUI.enabled, GUI.backgroundColor)); GUI.enabled &= property.Editable; return(s_PropertyFieldTempContent); }
public float GetHeight(RuntimeSerializedProperty property, GUIContent label, bool includeChildren) { float height = 0; if (DecoratorDrawers != null && !IsCurrentlyNested) { foreach (var drawer in DecoratorDrawers) { height += drawer.GetHeight(); } } if (RuntimePropertyDrawer != null) { height += RuntimePropertyDrawer.GetPropertyHeightSafe(property, label ?? EditorGUIUtilityHelper.TempContent(property.DisplayName)); } else if (!includeChildren) { height += RuntimeEasyGUI.GetSinglePropertyHeight(property, label); } else { RuntimeSerializedProperty prop = property.Copy(); // First property with custom label height += RuntimeEasyGUI.GetSinglePropertyHeight(prop, label); bool childrenAreExpanded = prop.IsExpanded && RuntimeEasyGUI.HasVisibleChildFields(prop); // Loop through all child properties if (childrenAreExpanded) { RuntimeSerializedProperty endProperty = prop.GetEndProperty(); while (prop.NextVisible(childrenAreExpanded) && !RuntimeSerializedProperty.EqualContents(prop, endProperty)) { height += RuntimeScriptAttributeUtility.GetHandler(prop, null).GetHeight(prop, EditorGUIUtilityHelper.TempContent(prop.DisplayName), true); childrenAreExpanded = false; height += EasyGUI.kControlVerticalSpacing; } } } return(height); }
public void HandleDrawnType(Type drawnType, Type propertyType, FieldInfo field, PropertyAttribute attribute) { Type drawerType = RuntimeScriptAttributeUtility.GetDrawerTypeForType(drawnType); // If we found a drawer type, instantiate the drawer, cache it, and return it. if (drawerType != null) { if (typeof(RuntimePropertyDrawer).IsAssignableFrom(drawerType)) { // HACK: Here is different from the U3D setting, maybe is not a good idea! // Unity only want use PropertyDrawer on array elements, not on array itself, // But i don't like this setting, so i recode it. runtimePropertyDrawer = (RuntimePropertyDrawer)Activator.CreateInstance(drawerType); runtimePropertyDrawer.FieldInfo = field; // Will be null by design if default type drawer! runtimePropertyDrawer.Attribute = attribute; } else if (typeof(UnityEditor.DecoratorDrawer).IsAssignableFrom(drawerType)) { // Draw decorators on array itself, not on each array elements if (field != null && field.FieldType.IsArrayOrList() && !propertyType.IsArrayOrList()) { return; } UnityEditor.DecoratorDrawer decoratorDrawer = (UnityEditor.DecoratorDrawer)Activator.CreateInstance(drawerType); DecoratorDrawerHelper.SetAttribute(decoratorDrawer, attribute); if (DecoratorDrawers == null) { DecoratorDrawers = new List <UnityEditor.DecoratorDrawer>(); } DecoratorDrawers.Add(decoratorDrawer); } } }
public static bool PropertyFieldInternal(Rect position, RuntimeSerializedProperty property, GUIContent label, bool includeChildren, List <PropertyAttribute> attributes) { return(RuntimeScriptAttributeUtility.GetHandler(property, attributes).OnGUI(position, property, label, includeChildren)); }
public static GenericMenu FillPropertyContextMenu(RuntimeSerializedProperty property, RuntimeSerializedProperty linkedProperty = null) { GenericMenu popupMenu = new GenericMenu(); RuntimeSerializedProperty propertyWithPath = property.RuntimeSerializedObject.FindProperty(property.PropertyPath); RuntimeScriptAttributeUtility.GetHandler(property, null).AddMenuItems(property, popupMenu); if (property.RuntimeSerializedObject.SerializedObject.targetObjects.Length == 1 && property.IsInstantiatedPrefab) { popupMenu.AddItem(EditorGUIUtility.TrTextContent("Revert Value to Prefab"), false, RuntimeTargetChoiceHandler.RevertPrefabPropertyOverride, propertyWithPath); } // If property is an element in an array, show duplicate and delete menu options if (property.Depth > 0 && !property.PropertyPath.EndsWith("Size")) { var length = property.PropertyPath.LastIndexOf("."); var parentPath = property.PropertyPath.Substring(0, length); var prop = property.FindProperty(parentPath); if (prop != null && prop.IsArray) { if (popupMenu.GetItemCount() > 0) { popupMenu.AddSeparator(EmptyStr); } popupMenu.AddItem(EditorGUIUtility.TrTextContent("Duplicate Array Element"), false, (object a) => { RuntimeTargetChoiceHandler.DuplicateArrayElement(a); EditorGUIUtility.editingTextField = false; }, propertyWithPath); popupMenu.AddItem(EditorGUIUtility.TrTextContent("Delete Array Element"), false, (object a) => { RuntimeTargetChoiceHandler.DeleteArrayElement(a); EditorGUIUtility.editingTextField = false; }, propertyWithPath); } } // If shift is held down, show debug menu options if (Event.current.shift) { if (popupMenu.GetItemCount() > 0) { popupMenu.AddSeparator(EmptyStr); } popupMenu.AddItem(EditorGUIUtility.TrTextContent("Print Property Path"), false, e => Debug.Log(((SerializedProperty)e).propertyPath), propertyWithPath); } else { if (popupMenu.GetItemCount() > 0) { popupMenu.AddSeparator(EmptyStr); } popupMenu.AddItem(EditorGUIUtility.TrTextContent("Copy Component"), false, (object a) => { RuntimeTargetChoiceHandler.CopyComponent(a); }, propertyWithPath); if (RuntimeTargetChoiceHandler.CanPasteAsNew(propertyWithPath)) { popupMenu.AddItem(EditorGUIUtility.TrTextContent("Paste Component As New"), false, (object a) => { RuntimeTargetChoiceHandler.PasteComponentAsNew(a); }, propertyWithPath); } else { popupMenu.AddDisabledItem(EditorGUIUtility.TrTextContent("Paste Component As New")); } if (RuntimeTargetChoiceHandler.CanPaste(propertyWithPath)) { popupMenu.AddItem(EditorGUIUtility.TrTextContent("Paste Component Values"), false, (object a) => { RuntimeTargetChoiceHandler.PasteComponentValues(a); }, propertyWithPath); } else { popupMenu.AddDisabledItem(EditorGUIUtility.TrTextContent("Paste Component Values")); } } if (property.RuntimeSerializedObject.Target != null) { if (popupMenu.GetItemCount() > 0) { popupMenu.AddSeparator(EmptyStr); } var obj = propertyWithPath.RuntimeSerializedObject.Target; var methods = obj.GetType().GetAllInstanceMethods(); contextMenuIndex.Clear(); contextMenuResultIndex.Clear(); easyContextMenuResultIndex.Clear(); foreach (var method in methods) { foreach (ContextMenu contextMenu in method.GetCustomAttributes(typeof(ContextMenu), false)) { contextMenuIndex.Add(contextMenu, method); } } var orderedContextMenu = contextMenuIndex.Select(kvp => kvp.Key).OrderByDescending(menu => menu.validate).ThenBy(menu => menu.priority).ToArray(); foreach (var menu in orderedContextMenu) { if (menu.validate) { var result = (bool)contextMenuIndex[menu].Invoke(obj, null); if (contextMenuResultIndex.ContainsKey(menu.menuItem)) { if (contextMenuResultIndex[menu.menuItem] && !result) { contextMenuResultIndex[menu.menuItem] = result; } } else { contextMenuResultIndex.Add(menu.menuItem, result); } } else { if (contextMenuResultIndex.ContainsKey(menu.menuItem) && !contextMenuResultIndex[menu.menuItem]) { popupMenu.AddDisabledItem(EditorGUIUtility.TrTextContent(menu.menuItem)); } else { popupMenu.AddItem(EditorGUIUtility.TrTextContent(menu.menuItem), false, (object o) => { contextMenuIndex[menu].Invoke(o, null); }, obj); } } } } return(popupMenu); }
public static float GetPropertyHeightInternal(RuntimeSerializedProperty property, GUIContent label, bool includeChildren, List <PropertyAttribute> attributes) { return(RuntimeScriptAttributeUtility.GetHandler(property, attributes).GetHeight(property, label, includeChildren)); }
public bool OnGUI(Rect position, RuntimeSerializedProperty property, GUIContent label, bool includeChildren, Rect visibleArea) { float oldLabelWidth, oldFieldWidth; float propHeight = position.height; position.height = 0; if (DecoratorDrawers != null && !IsCurrentlyNested) { foreach (var decorator in DecoratorDrawers) { position.height = decorator.GetHeight(); oldLabelWidth = EditorGUIUtility.labelWidth; oldFieldWidth = EditorGUIUtility.fieldWidth; decorator.OnGUI(position); EditorGUIUtility.labelWidth = oldLabelWidth; EditorGUIUtility.fieldWidth = oldFieldWidth; position.y += position.height; propHeight -= position.height; } } position.height = propHeight; if (RuntimePropertyDrawer != null) { // Remember widths oldLabelWidth = EditorGUIUtility.labelWidth; oldFieldWidth = EditorGUIUtility.fieldWidth; // Draw with custom drawer RuntimePropertyDrawer.OnGUISafe(position, property, label ?? EditorGUIUtilityHelper.TempContent(property.DisplayName)); // Restore widths EditorGUIUtility.labelWidth = oldLabelWidth; EditorGUIUtility.fieldWidth = oldFieldWidth; return(false); } else { if (!includeChildren) { return(RuntimeEasyGUI.DefaultPropertyField(position, property, label)); } // Remember state Vector2 oldIconSize = EditorGUIUtility.GetIconSize(); bool wasEnabled = GUI.enabled; int origIndent = EditorGUI.indentLevel; int relIndent = origIndent - property.Depth; RuntimeSerializedProperty prop = property.Copy(); position.height = RuntimeEasyGUI.GetSinglePropertyHeight(property, label); // First property with custom label EditorGUI.indentLevel = property.Depth + relIndent; bool childrenAreExpanded = RuntimeEasyGUI.DefaultPropertyField(position, property, label) && RuntimeEasyGUI.HasVisibleChildFields(property); position.y += position.height + EasyGUI.kControlVerticalSpacing; // Loop through all child properties if (childrenAreExpanded) { RuntimeSerializedProperty endProperty = property.GetEndProperty(); while (prop.NextVisible(childrenAreExpanded) && !RuntimeSerializedProperty.EqualContents(prop, endProperty)) { var handler = RuntimeScriptAttributeUtility.GetHandler(prop, null); EditorGUI.indentLevel = prop.Depth + relIndent; position.height = handler.GetHeight(prop, null, false); if (position.Overlaps(visibleArea)) { EditorGUI.BeginChangeCheck(); childrenAreExpanded = handler.OnGUI(position, prop, null, false) && RuntimeEasyGUI.HasVisibleChildFields(prop); // Changing child properties (like array size) may invalidate the iterator, // so stop now, or we may get errors. if (EditorGUI.EndChangeCheck()) { break; } } position.y += position.height + EasyGUI.kControlVerticalSpacing; } } // Restore state GUI.enabled = wasEnabled; EditorGUIUtility.SetIconSize(oldIconSize); EditorGUI.indentLevel = origIndent; return(false); } }