///An editor for BBParameter type to let user choose either a constant value or link to a Blackboard Variable. public static BBParameter ParameterField(string name, BBParameter bbParam, bool blackboardOnly = false, UnityEngine.Object context = null) { var info = new InspectedFieldInfo(); info.unityObjectContext = context; return(ParameterField(string.IsNullOrEmpty(name) ? GUIContent.none : EditorUtils.GetTempContent(name), bbParam, blackboardOnly, false, info)); }
///An editor for BBParameter type to let user choose either a constant value or link to a Blackboard Variable. public static BBParameter ParameterField(GUIContent content, BBParameter bbParam, bool blackboardOnly = false, bool required = false, InspectedFieldInfo info = default(InspectedFieldInfo)) { if (bbParam == null) { EditorGUILayout.LabelField(content, EditorUtils.GetTempContent("BBParameter is null")); return(null); } //ensure we use blackboard if 'blackboardOnly' if (blackboardOnly && !bbParam.useBlackboard) { bbParam.useBlackboard = true; } GUILayout.BeginVertical(); { GUILayout.BeginHorizontal(); { if (bbParam.useBlackboard) { ParameterDropDown(content, bbParam); } else { //we mutate inspected info field and parentInstance, but keep attributes and of course unity object context //this way, attributes work on internal field info.field = bbParam.GetType().RTGetField("_value"); info.wrapperInstanceContext = info.parentInstanceContext; info.parentInstanceContext = bbParam; if (info.attributes != null) { info.attributes = info.attributes.Where(a => !(a is DrawerAttribute) || !((DrawerAttribute)a).isDecorator).ToArray(); } GUILayout.BeginVertical(); bbParam.value = EditorUtils.ReflectedFieldInspector(content, bbParam.value, bbParam.varType, info); GUILayout.EndVertical(); } if (!blackboardOnly) { bbParam.useBlackboard = EditorGUILayout.Toggle(bbParam.useBlackboard, EditorStyles.radioButton, GUILayout.Width(18)); } } GUILayout.EndHorizontal(); //warn/error marks if (content != GUIContent.none) { if (bbParam.varRef == null && !string.IsNullOrEmpty(bbParam.name)) { if (!bbParam.isPresumedDynamic) { EditorUtils.MarkLastFieldError($"Missing Variable. Type of '{bbParam.varType.FriendlyName()}'"); } if (bbParam.isPresumedDynamic) { EditorUtils.MarkLastFieldWarning($"Dynamic Variable. Type of '{bbParam.varType.FriendlyName()}'"); } } else { if (required && bbParam.isNone) { EditorUtils.MarkLastFieldError("An instance is required"); } if (required && !string.IsNullOrEmpty(bbParam.name) && bbParam.isNull) { EditorUtils.MarkLastFieldWarning("An instance is required but currently resolves to null. If it is set in runtime you can ignore this warning."); } } } string textInfo = null; if (bbParam.useBlackboard) { if (bbParam.bb == null) { textInfo = "<i>No current Blackboard reference</i>"; } else if (bbParam.isNone) { textInfo = "Select a '" + bbParam.varType.FriendlyName() + "' Assignable Blackboard Variable"; } else if (bbParam.varRef != null && bbParam.varType != bbParam.refType) { var setPossible = bbParam.varRef.CanConvertFrom(bbParam.varType); textInfo = string.Format("AutoConvert: ({0} ➲ {1}){2}", bbParam.refType.FriendlyName(), bbParam.varType.FriendlyName(), setPossible ? string.Empty : " [GET ONLY]"); } } if (textInfo != null) { GUI.color = Color.white.WithAlpha(0.5f); GUILayout.BeginVertical(GUI.skin.textField); GUILayout.Label(textInfo, GUILayout.Width(0), GUILayout.ExpandWidth(true)); GUILayout.EndVertical(); GUILayout.Space(2); GUI.color = Color.white; } } GUILayout.EndVertical(); return(bbParam); }
//... void DoExposedVariablesMapping() { if (owner.graph == null) { return; } var separatorDrawn = false; var subTreeVariables = owner.graph.blackboard.variables.Values; foreach (var variable in subTreeVariables) { if (variable is Variable <VariableSeperator> ) { continue; } if (!variable.isExposedPublic || variable.isPropertyBound) { continue; } if (!separatorDrawn) { separatorDrawn = true; EditorUtils.Separator(); EditorGUILayout.HelpBox("Exposed Graph Variables. Use the arrows button to override/parametrize the variable.\nDoing this will not change the graph serialization. Prefab overrides are also supported.", MessageType.None); } if (owner.exposedParameters == null) { owner.exposedParameters = new System.Collections.Generic.List <ExposedParameter>(); } var exposedParam = owner.exposedParameters.Find(x => x.targetVariableID == variable.ID); if (exposedParam == null) { GUILayout.BeginHorizontal(); GUI.enabled = false; EditorUtils.DrawEditorFieldDirect(new GUIContent(variable.name, "This is an Exposed Public variable of the graph local blackboard. You can use the arrows button on the right side to override/parametrize the default value."), variable.value, variable.varType, default(InspectedFieldInfo)); GUI.enabled = true; if (GUILayout.Button(EditorUtils.GetTempContent("▽△", null, "Override Variable"), Styles.centerLabel, GUILayout.Width(24))) { UndoUtility.RecordObject(owner, "Add Override"); exposedParam = ExposedParameter.CreateInstance(variable); owner.exposedParameters.Add(exposedParam); exposedParam.Bind(owner.graph.blackboard); UndoUtility.SetDirty(owner); } EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link); GUILayout.EndHorizontal(); continue; } GUILayout.BeginHorizontal(); var info = new InspectedFieldInfo(); info.unityObjectContext = owner; exposedParam.valueBoxed = EditorUtils.DrawEditorFieldDirect(new GUIContent(variable.name), exposedParam.valueBoxed, variable.varType, info); if (GUILayout.Button(EditorUtils.GetTempContent("▼▲", null, "Remove Override"), Styles.centerLabel, GUILayout.Width(24))) { UndoUtility.RecordObject(owner, "Remove Override"); exposedParam.UnBind(owner.graph.blackboard); owner.exposedParameters.Remove(exposedParam); UndoUtility.SetDirty(owner); continue; } EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link); GUILayout.EndHorizontal(); var index = owner.exposedParameters.IndexOf(exposedParam); var serProp = exposeParamsProp.GetArrayElementAtIndex(index); var isPrefabOverride = serProp.prefabOverride; if (isPrefabOverride) { var rect = GUILayoutUtility.GetLastRect(); EditorUtils.MarkLastFieldOverride(); if (rect.Contains(Event.current.mousePosition) && Event.current.type == EventType.ContextClick) { var prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(owner); var asset = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(prefabAssetPath); var menu = new GenericMenu(); menu.AddItem(new GUIContent($"Apply to Prefab '{asset.name}'"), false, () => { UndoUtility.RecordObject(owner, "Apply Exposed Parameter"); UndoUtility.RecordObject(asset, "Apply Exposed Parameter"); PrefabUtility.ApplyPropertyOverride(serProp, prefabAssetPath, InteractionMode.UserAction); UndoUtility.SetDirty(owner); UndoUtility.SetDirty(asset); }); menu.AddItem(new GUIContent("Revert"), false, () => { UndoUtility.RecordObject(owner, "Revert Exposed Parameter"); PrefabUtility.RevertPropertyOverride(serProp, InteractionMode.UserAction); UndoUtility.SetDirty(owner); }); menu.ShowAsContext(); } } } if (separatorDrawn) { EditorUtils.Separator(); } //cleanup if (owner.exposedParameters != null) { for (var i = owner.exposedParameters.Count; i-- > 0;) { var exposedParam = owner.exposedParameters[i]; var variable = owner.graph.blackboard.GetVariableByID(exposedParam.targetVariableID); if (variable == null || !variable.isExposedPublic || variable.isPropertyBound) { owner.exposedParameters.RemoveAt(i); UndoUtility.SetDirty(owner); } } } }