/************************************************************************************************************************/ private static void AddCallClipboardItems(GenericMenu menu, SerializedProperty property, SerializedPropertyAccessor accessor) { menu.AddItem(new GUIContent("Copy Listener %C"), false, () => { Clipboard.CopyCall(property); }); AddMenuItem(menu, "Paste Listener (Overwrite) %V", Clipboard.HasCall, () => Clipboard.PasteCall(property)); }
/************************************************************************************************************************/ private static void AddEventClipboardItems(GenericMenu menu, SerializedProperty property, SerializedPropertyAccessor accessor) { // Copy Event. menu.AddItem(new GUIContent("Copy Event"), false, () => { Clipboard.CopyEvent(property); }); // Paste Event. AddMenuItem(menu, "Paste Event (Overwrite)", Clipboard.HasEvent, () => { SerializedPropertyAccessor.ModifyValues <UltEventBase>(property, (e) => { Clipboard.Paste(e); }, "Paste Event"); }); // Paste Listener. AddMenuItem(menu, "Paste Listener (New) %#V", Clipboard.HasCall, () => { SerializedPropertyAccessor.ModifyValues <UltEventBase>(property, (e) => { var call = new PersistentCall(); Clipboard.PasteCall(call); if (e._PersistentCalls == null) { e._PersistentCalls = new List <PersistentCall>(); } e._PersistentCalls.Add(call); }, "Paste PersistentCall"); }); }
private static void OnPropertyContextMenu() { EditorApplication.contextualPropertyMenu += (menu, property) => { if (property.propertyType != SerializedPropertyType.Generic) { return; } var accessor = SerializedPropertyAccessor.GetAccessor(property); if (accessor == null) { return; } if (typeof(UltEventBase).IsAssignableFrom(accessor.FieldType)) { AddEventFunctions(menu, property, accessor); BoolPref.AddDisplayOptions(menu); } else if (accessor.FieldType == typeof(PersistentCall)) { AddCallClipboardItems(menu, property, accessor); BoolPref.AddDisplayOptions(menu); } }; }
/************************************************************************************************************************/ #region Enum /************************************************************************************************************************/ private static void DoEnumGUI(Rect area, SerializedProperty argumentProperty, GUIContent label) { var enumType = SerializedPropertyAccessor.GetValue<PersistentArgument>(argumentProperty).SystemType; if (enumType == null) { DoErrorMessageGUI(area, argumentProperty, label, "Error: enum type not set"); return; } var i = argumentProperty.FindPropertyRelative(Names.PersistentArgument.Int); label = EditorGUI.BeginProperty(area, label, argumentProperty); EditorGUI.BeginChangeCheck(); int value; if (enumType.IsDefined(typeof(FlagsAttribute), true)) { value = DrawEnumMaskField(area, label, i.intValue, enumType); } else { value = Convert.ToInt32(EditorGUI.EnumPopup(area, label, (Enum)Enum.ToObject(enumType, i.intValue))); } if (EditorGUI.EndChangeCheck()) { i.intValue = value; } EditorGUI.EndProperty(); }
/// <summary>Overwrites the call contained in the specified property with the copied details.</summary> public static void PasteCall(SerializedProperty property) { SerializedPropertyAccessor.ModifyValues <PersistentCall>(property, (call) => { PasteCall(call); }, "Paste PersistentCall"); }
/// <summary>Stores the details of the event contained in the specified property.</summary> public static void CopyEvent(SerializedProperty property) { var accessor = SerializedPropertyAccessor.GetAccessor(property); if (accessor == null) { return; } CopyEvent(accessor, property.serializedObject.targetObject); }
/************************************************************************************************************************/ public static void SetMethod(MethodInfo methodInfo) { SerializedPropertyAccessor.ModifyValues <PersistentCall>(DrawerState.Current.CallProperty, (call) => { if (call != null) { call.SetMethod(methodInfo, DrawerState.Current.TargetProperty.objectReferenceValue); } }, "Set Method"); }
/************************************************************************************************************************/ public static void AddEventFunctions(GenericMenu menu, SerializedProperty property, SerializedPropertyAccessor accessor) { property = property.Copy(); if (accessor.FieldType == typeof(UltEvent)) { menu.AddItem(new GUIContent("Invoke Event"), false, () => { var events = SerializedPropertyAccessor.GetValues <UltEvent>(property); for (int i = 0; i < events.Length; i++) { var e = events[i] as UltEvent; if (e != null) { e.Invoke(); } } SerializedPropertyAccessor.OnPropertyChanged(property); }); } AddEventClipboardItems(menu, property, accessor); menu.AddItem(new GUIContent("Clear Event"), false, () => { SerializedPropertyAccessor.ModifyValues <UltEventBase>(property, (e) => { if (e != null) { e.Clear(); } }, "Clear Event"); }); menu.AddItem(new GUIContent("Log Description"), false, () => { var targets = property.serializedObject.targetObjects; var events = SerializedPropertyAccessor.GetValues <UltEventBase>(property); for (int i = 0; i < events.Length; i++) { Debug.Log(events[i], targets[i]); } }); }
/************************************************************************************************************************/ private static void DoObjectGUI(Rect area, SerializedProperty argumentProperty, GUIContent label) { var o = argumentProperty.FindPropertyRelative(Names.PersistentArgument.Object); label = EditorGUI.BeginProperty(area, label, o); EditorGUI.BeginChangeCheck(); var type = SerializedPropertyAccessor.GetValue<PersistentArgument>(argumentProperty).SystemType ?? typeof(UnityEngine.Object); var value = EditorGUI.ObjectField(area, label, o.objectReferenceValue, type, true); if (EditorGUI.EndChangeCheck()) { o.objectReferenceValue = value; } EditorGUI.EndProperty(); }
/************************************************************************************************************************/ private static void AddSetCallItem(string label, MethodBase method, Object[] targets) { _Menu.AddItem( new GUIContent(label), method == _CurrentMethod, (userData) => { DrawerState.Current.CopyFrom(CachedState); var i = 0; SerializedPropertyAccessor.ModifyValues <PersistentCall>(CachedState.CallProperty, (call) => { var target = targets != null ? targets[i % targets.Length] : null; call.SetMethod(method, target); i++; }, "Set Persistent Call"); DrawerState.Current.Clear(); }, null); }
/// <summary>Stores the details of the call contained in the specified property.</summary> public static void CopyCall(SerializedPropertyAccessor accessor, Object target) { var call = (PersistentCall)accessor.GetValue(target); CopyCall(call); }
/// <summary>Stores the details of the event contained in the specified property.</summary> public static void CopyEvent(SerializedPropertyAccessor accessor, Object target) { var e = (UltEventBase)accessor.GetValue(target); CopyEvent(e); }
/************************************************************************************************************************/ /// <summary>Caches the event from the specified property.</summary> public void BeginEvent(SerializedProperty eventProperty) { EventProperty = eventProperty; Event = SerializedPropertyAccessor.GetValue <UltEventBase>(eventProperty); }
/// <summary>Returns the call encapsulated by the specified property.</summary> public static PersistentCall GetCall(SerializedProperty callProperty) { return(SerializedPropertyAccessor.GetValue <PersistentCall>(callProperty)); }
private static void DoLinkModeToggleGUI(Rect area, SerializedProperty argumentProperty, int linkIndex, PersistentArgumentType linkType) { if (linkIndex < 0) return; if (_LinkToggleStyle == null) { _LinkToggleStyle = new GUIStyle(EditorStyles.miniButton) { padding = new RectOffset(0, 0, 0, 1), fontSize = 12, }; } area.x += area.width + 2; area.width = SpecialModeToggleWidth - 2; var currentArgument = DrawerState.Current.call._PersistentArguments[DrawerState.Current.parameterIndex]; var wasLink = currentArgument.Type == PersistentArgumentType.Parameter || currentArgument.Type == PersistentArgumentType.ReturnValue; if (wasLink != GUI.Toggle(area, wasLink, _LinkToggleContent, _LinkToggleStyle)) { SerializedPropertyAccessor.ModifyValues<PersistentArgument>(argumentProperty, (argument) => { if (wasLink) { // Revert to normal mode. argument.SystemType = argument.SystemType; var parameter = DrawerState.Current.CurrentParameter; if ((parameter.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault) argument.Value = parameter.DefaultValue; } else { // Link to the specified return value. var argumentType = argument.Type; argument.Type = linkType; argument._Int = linkIndex; switch (argumentType) { case PersistentArgumentType.Bool: case PersistentArgumentType.String: case PersistentArgumentType.Int: case PersistentArgumentType.Float: case PersistentArgumentType.Vector2: case PersistentArgumentType.Vector3: case PersistentArgumentType.Vector4: case PersistentArgumentType.Quaternion: case PersistentArgumentType.Color: case PersistentArgumentType.Color32: case PersistentArgumentType.Rect: argument._X = (float)argumentType; break; case PersistentArgumentType.Enum: case PersistentArgumentType.Object: argument._String = DrawerState.Current.CurrentParameter.ParameterType.AssemblyQualifiedName; break; case PersistentArgumentType.Parameter: case PersistentArgumentType.ReturnValue: throw new InvalidOperationException(Names.PersistentArgument.Class + " was already linked."); default: throw new InvalidOperationException("Invalid " + Names.PersistentArgument.Full.Type + ": " + argumentType); } } }, wasLink ? "Unlink Argument" : "Link Argument"); } }
/************************************************************************************************************************/ private static void DoLinkedValueGUI(Rect area, SerializedProperty argumentProperty, GUIContent label) { var color = GUI.color; label = EditorGUI.BeginProperty(area, label, argumentProperty); EditorGUI.PrefixLabel(area, label); area.xMin += EditorGUIUtility.labelWidth; var argument = SerializedPropertyAccessor.GetValue<PersistentArgument>(argumentProperty); var callIndex = argument._Int; var argumentType = argument.SystemType; if (argumentType == null) { GUI.color = PersistentCallDrawer.ErrorFieldColor; GUI.Label(area, "Unable to determine argument type"); } else if (DrawerState.Current.Event != null) { switch (argument.Type) { case PersistentArgumentType.Parameter: label.text = "Parameter " + callIndex; var parameterTypes = DrawerState.Current.Event.ParameterTypes; var parameters = DrawerState.Current.Event.Parameters; if (callIndex < 0 || callIndex >= parameterTypes.Length) { GUI.color = PersistentCallDrawer.ErrorFieldColor; label.tooltip = "Parameter link index out of range"; } else { var parameterType = parameterTypes[callIndex]; label.text += " (" + parameterType.GetNameCS(false); if (parameters != null) label.text += " " + parameters[callIndex].Name; label.text += ")"; if (!argumentType.IsAssignableFrom(parameterType)) { GUI.color = PersistentCallDrawer.ErrorFieldColor; label.tooltip = "Incompatible parameter type"; } } break; case PersistentArgumentType.ReturnValue: label.text = "Return Value " + callIndex + ": "; var linkedMethod = DrawerState.Current.GetLinkedMethod(callIndex); if (linkedMethod == null) { label.text += "(no method set)"; GUI.color = PersistentCallDrawer.ErrorFieldColor; } else { label.text += MethodSelectionMenu.GetMethodSignature(linkedMethod, true); if (DrawerState.Current.callIndex >= 0 && DrawerState.Current.callIndex <= callIndex) { GUI.color = PersistentCallDrawer.ErrorFieldColor; label.tooltip = "The linked method must be called before this argument can retrieve its return value"; } else if (!argumentType.IsAssignableFrom(linkedMethod.GetReturnType())) { GUI.color = PersistentCallDrawer.ErrorFieldColor; label.tooltip = "Return type is incompatible with argument type"; } } break; } if (GUI.Button(area, label, PersistentCallDrawer.PopupButtonStyle)) { if (Event.current.button == 0) ShowLinkMenu(area, argumentProperty, argumentType, callIndex, argument.Type); } } EditorGUI.EndProperty(); GUI.color = color; }