//Shows a button that when clicked, pops a context menu with a list of tasks deriving the base type specified. When something is selected the callback is called //On top of that it also shows a search field for Tasks public static void ShowCreateTaskSelectionButton(ITaskSystem ownerSystem, Type baseType, Action <Task> callback) { GUI.backgroundColor = Colors.lightBlue; var label = "Assign " + baseType.Name.SplitCamelCase(); if (GUILayout.Button(label)) { Action <Type> TaskTypeSelected = (t) => { var newTask = Task.Create(t, ownerSystem); UndoUtility.RecordObject(ownerSystem.contextObject, "New Task"); callback(newTask); }; var menu = EditorUtils.GetTypeSelectionMenu(baseType, TaskTypeSelected); if (CopyBuffer.TryGetCache <Task>(out Task copy) && baseType.IsAssignableFrom(copy.GetType())) { menu.AddSeparator("/"); menu.AddItem(new GUIContent(string.Format("Paste ({0})", copy.name)), false, () => { callback(copy.Duplicate(ownerSystem)); }); } menu.ShowAsBrowser(label, typeof(Task)); } GUILayout.Space(2); GUI.backgroundColor = Color.white; }
//show variable data void ShowDataFieldGUI(Variable data, int index) { //Prop Bind info if (data.isPropertyBound) { var idx = data.propertyPath.LastIndexOf('.'); var typeName = data.propertyPath.Substring(0, idx); var memberName = data.propertyPath.Substring(idx + 1); GUI.color = new Color(0.8f, 0.8f, 1); var suf = data.debugBoundValue && Application.isPlaying ? data.value.ToStringAdvanced() : typeName.Split('.').Last(); GUILayout.Label(string.Format(".{0} ({1}) {2}", memberName, suf, data.debugBoundValue ? "*" : string.Empty), Styles.leftLabel, layoutOptions); GUI.color = Color.white; return; } GUI.color = data.isExposedPublic ? GUI.color.WithAlpha(0.5f) : GUI.color; EditorGUIUtility.labelWidth = 10; var newVal = VariableField(data, contextObject, layoutOptions); EditorGUIUtility.labelWidth = 0; if (!Equals(data.value, newVal)) { UndoUtility.RecordObject(contextObject, "Variable Value Change"); data.value = newVal; UndoUtility.SetDirty(contextObject); } GUI.color = Color.white; }
///---------------------------------------------------------------------------------------------- //... public override void OnInspectorGUI() { DoPrefabRelatedGUI(); if (owner.graph == null && !owner.graphIsBound) { DoMissingGraphControls(); serializedObject.ApplyModifiedProperties(); return; } DoValidGraphControls(); DoStandardFields(); EditorGUI.BeginChangeCheck(); GUI.enabled = (!isBoundGraphOnPrefabInstance || !owner.lockBoundGraphPrefabOverrides) && !isBoundGraphOnPrefabRoot; OnPreExtraGraphOptions(); GUI.enabled = true; if (EditorGUI.EndChangeCheck() && owner.graph != null) { UndoUtility.RecordObject(owner.graph, "Sub Option Change"); owner.graph.SelfSerialize(); UndoUtility.SetDirty(owner.graph); } EditorUtils.ReflectedObjectInspector(owner, owner); DoExposedVariablesMapping(); DoRuntimeGraphControls(); OnPostExtraGraphOptions(); EditorUtils.EndOfInspector(); serializedObject.ApplyModifiedProperties(); }
///---------------------------------------------------------------------------------------------- ///<summary>Self Serialize blackboard</summary> public void SelfSerialize() { if (haltForUndo || ParadoxNotion.Services.Threader.applicationIsPlaying || Application.isPlaying) { return; } var newReferences = new List <UnityEngine.Object>(); var newSerialization = JSONSerializer.Serialize(typeof(BlackboardSource), _blackboard, newReferences); if (newSerialization != _serializedBlackboard || !newReferences.SequenceEqual(_objectReferences) || (_serializedVariables == null || _serializedVariables.Length != _blackboard.variables.Count)) { haltForUndo = true; UndoUtility.RecordObject(this, UndoUtility.GetLastOperationNameOr("Blackboard Change")); haltForUndo = false; _serializedVariables = new SerializationPair[_blackboard.variables.Count]; for (var i = 0; i < _blackboard.variables.Count; i++) { var serializedVariable = new SerializationPair(); serializedVariable._json = JSONSerializer.Serialize(typeof(Variable), _blackboard.variables.ElementAt(i).Value, serializedVariable._references); _serializedVariables[i] = serializedVariable; } _serializedBlackboard = newSerialization; _objectReferences = newReferences; } }
///Generate and return task menu GenericMenu GetMenu(Action <Task> callback) { var menu = new GenericMenu(); menu.AddItem(new GUIContent("Open Script"), false, () => { EditorUtils.OpenScriptOfType(task.GetType()); }); menu.AddItem(new GUIContent("Copy"), false, () => { CopyBuffer.SetCache <Task>(task); }); foreach (var _m in task.GetType().RTGetMethods()) { var m = _m; var att = m.RTGetAttribute <ContextMenu>(true); if (att != null) { menu.AddItem(new GUIContent(att.menuItem), false, () => { m.Invoke(task, null); }); } } menu.AddSeparator("/"); menu.AddItem(new GUIContent("Delete"), false, () => { if (callback != null) { UndoUtility.RecordObject(task.ownerSystem.contextObject, "Delete Task"); callback(null); } }); return(menu); }
///Show the sub-tasks list public void ShowListGUI() { if (ownerSystem == null) { GUILayout.Label("Owner System is null!"); return; } TaskEditor.ShowCreateTaskSelectionButton <ActionTask>(ownerSystem, AddAction); ValidateList(); if (actions.Count == 0) { EditorGUILayout.HelpBox("No Actions", MessageType.None); return; } if (actions.Count == 1) { return; } //show the actions EditorUtils.ReorderableList(actions, (i, picked) => { var action = actions[i]; GUI.color = Color.white.WithAlpha(action == currentViewAction ? 0.75f : 0.25f); EditorGUILayout.BeginHorizontal("box"); GUI.color = Color.white.WithAlpha(action.isUserEnabled ? 0.8f : 0.25f); GUI.enabled = !Application.isPlaying; action.isUserEnabled = EditorGUILayout.Toggle(action.isUserEnabled, GUILayout.Width(18)); GUI.enabled = true; GUILayout.Label((action.isPaused ? "<b>||</b> " : action.isRunning ? "► " : "") + action.summaryInfo, GUILayout.MinWidth(0), GUILayout.ExpandWidth(true)); if (!Application.isPlaying && GUILayout.Button("X", GUILayout.Width(20))) { UndoUtility.RecordObject(ownerSystem.contextObject, "List Remove Task"); actions.RemoveAt(i); } EditorGUILayout.EndHorizontal(); var lastRect = GUILayoutUtility.GetLastRect(); EditorGUIUtility.AddCursorRect(lastRect, MouseCursor.Link); if (Event.current.type == EventType.MouseDown && lastRect.Contains(Event.current.mousePosition)) { currentViewAction = action == currentViewAction ? null : action; Event.current.Use(); } GUI.color = Color.white; }); executionMode = (ActionsExecutionMode)EditorGUILayout.EnumPopup(executionMode); }
///Duplicate the task for the target ITaskSystem virtual public Task Duplicate(ITaskSystem newOwnerSystem) { var newTask = JSONSerializer.Clone <Task>(this); UndoUtility.RecordObject(newOwnerSystem.contextObject, "Duplicate Task"); BBParameter.SetBBFields(newTask, newOwnerSystem.blackboard); newTask.Validate(newOwnerSystem); return(newTask); }
//create new local graph and assign it to owner public Graph NewAsBound() { var newGraph = (Graph)ScriptableObject.CreateInstance(owner.graphType); UndoUtility.RecordObject(owner, "New Bound Graph"); owner.SetBoundGraphReference(newGraph); UndoUtility.SetDirty(owner); return(newGraph); }
//Apply bound graph public void PrefabApplyBoundGraph() { UndoUtility.RecordObject(owner, "Apply Graph To Prefab"); var prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(owner); PrefabUtility.ApplyPropertyOverride(boundGraphSerializationProp, prefabAssetPath, InteractionMode.UserAction); PrefabUtility.ApplyPropertyOverride(boundGraphReferencesProp, prefabAssetPath, InteractionMode.UserAction); UndoUtility.SetDirty(owner); }
public static Task Create(Type type, ITaskSystem newOwnerSystem) { var newTask = (Task)Activator.CreateInstance(type); UndoUtility.RecordObject(newOwnerSystem.contextObject, "New Task"); BBParameter.SetBBFields(newTask, newOwnerSystem.blackboard); newTask.Validate(newOwnerSystem); newTask.OnCreate(newOwnerSystem); return(newTask); }
///Show the sub-tasks list public void ShowListGUI() { TaskEditor.ShowCreateTaskSelectionButton <ConditionTask>(ownerSystem, AddCondition); ValidateList(); if (conditions.Count == 0) { EditorGUILayout.HelpBox("No Conditions", MessageType.None); return; } if (conditions.Count == 1) { return; } EditorUtils.ReorderableList(conditions, (i, picked) => { var condition = conditions[i]; GUI.color = Color.white.WithAlpha(condition == currentViewCondition ? 0.75f : 0.25f); GUILayout.BeginHorizontal("box"); GUI.color = Color.white.WithAlpha(condition.isUserEnabled ? 0.8f : 0.25f); GUI.enabled = !Application.isPlaying; condition.isUserEnabled = EditorGUILayout.Toggle(condition.isUserEnabled, GUILayout.Width(18)); GUI.enabled = true; GUILayout.Label(condition.summaryInfo, GUILayout.MinWidth(0), GUILayout.ExpandWidth(true)); if (!Application.isPlaying && GUILayout.Button("X", GUILayout.MaxWidth(20))) { UndoUtility.RecordObject(ownerSystem.contextObject, "List Remove Task"); conditions.RemoveAt(i); if (conditions.Count == 1) { conditions[0].isUserEnabled = true; } } GUILayout.EndHorizontal(); var lastRect = GUILayoutUtility.GetLastRect(); EditorGUIUtility.AddCursorRect(lastRect, MouseCursor.Link); if (Event.current.type == EventType.MouseDown && lastRect.Contains(Event.current.mousePosition)) { currentViewCondition = condition == currentViewCondition ? null : condition; Event.current.Use(); } GUI.color = Color.white; }); checkMode = (ConditionsCheckMode)EditorGUILayout.EnumPopup(checkMode); }
//Revert bound graph public void PrefabRevertBoundGraph() { UndoUtility.RecordObject(owner, "Revert Graph From Prefab"); var prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(owner); PrefabUtility.RevertPropertyOverride(boundGraphSerializationProp, InteractionMode.UserAction); PrefabUtility.RevertPropertyOverride(boundGraphReferencesProp, InteractionMode.UserAction); GraphEditorUtility.activeElement = null; UndoUtility.SetDirty(owner); GraphEditor.FullDrawPass(); }
//... bool DoListCheckout(List <string> options, ref List <string> selected) { var changed = false; //show potential missing first for (var i = selected.Count; i-- > 0;) { var s = selected[i]; if (!options.Contains(s)) { GUILayout.BeginHorizontal(GUI.skin.box); GUILayout.Label(s.FormatError()); if (GUILayout.Button("Remove", GUILayout.Width(75))) { changed = true; UndoUtility.RecordObject(graph, "Extractor"); selected.RemoveAt(i); UndoUtility.SetDirty(graph); } GUILayout.EndHorizontal(); } } //show expose options for (var i = 0; i < options.Count; i++) { var name = options[i]; var active = selected.Contains(name); GUI.color = Color.white.WithAlpha(active ? 1 : 0.5f); GUILayout.BeginHorizontal(GUI.skin.box); GUILayout.Label(name.SplitCamelCase()); GUILayout.Label("Expose", GUILayout.Width(50)); GUI.color = Color.white; var newActive = UnityEditor.EditorGUILayout.Toggle(active, GUILayout.Width(20)); GUILayout.EndHorizontal(); if (newActive != active) { changed = true; UndoUtility.RecordObject(graph, "Extractor"); if (newActive == true) { selected.Add(name); } if (newActive == false) { selected.Remove(name); } UndoUtility.SetDirty(graph); } } return(changed); }
//create new graph asset and assign it to owner public Graph NewAsAsset() { var newGraph = (Graph)EditorUtils.CreateAsset(owner.graphType); if (newGraph != null) { UndoUtility.RecordObject(owner, "New Asset Graph"); owner.graph = newGraph; UndoUtility.SetDirty(owner); UndoUtility.SetDirty(newGraph); AssetDatabase.SaveAssets(); } return(newGraph); }
public static Task Create(Type type, ITaskSystem newOwnerSystem) { if (type.IsGenericTypeDefinition) { type = type.MakeGenericType(type.GetFirstGenericParameterConstraintType()); } var newTask = (Task)Activator.CreateInstance(type); UndoUtility.RecordObject(newOwnerSystem.contextObject, "New Task"); BBParameter.SetBBFields(newTask, newOwnerSystem.blackboard); newTask.Validate(newOwnerSystem); newTask.OnCreate(newOwnerSystem); return(newTask); }
//Shows the agent field in case an agent type is specified through the use of the generic versions of Action or Condition Task void ShowAgentField() { if (task.agentType == null) { return; } TaskAgentParameter agentParam = agentParameterProp.value; if (Application.isPlaying && task.agentIsOverride && agentParam.value == null) { GUILayout.Label("<b>Missing Agent Reference</b>".FormatError()); return; } GUI.color = Color.white.WithAlpha(task.agentIsOverride ? 0.65f : 0.5f); GUILayout.BeginVertical(GUI.skin.box); GUILayout.BeginHorizontal(); if (task.agentIsOverride) { BBParameterEditor.ParameterField(null, agentParam, task.ownerSystem.contextObject); } else { var compInfo = task.agent == null?task.agentType.FriendlyName().FormatError() : task.agentType.FriendlyName(); var icon = TypePrefs.GetTypeIcon(task.agentType); var label = string.Format("Use Self ({0})", compInfo); var content = EditorUtils.GetTempContent(label, icon); GUILayout.Label(content, GUILayout.Height(18), GUILayout.Width(0), GUILayout.ExpandWidth(true)); } GUI.color = Color.white; if (!Application.isPlaying) { var newOverride = EditorGUILayout.Toggle(task.agentIsOverride, GUILayout.Width(18)); if (newOverride != task.agentIsOverride) { UndoUtility.RecordObject(task.ownerSystem.contextObject, "Override Agent"); task.agentIsOverride = newOverride; } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); }
public void AddAction(ActionTask action) { if (action is ActionList) { foreach (var subAction in (action as ActionList).actions) { AddAction(subAction); } return; } #if UNITY_EDITOR UndoUtility.RecordObject(ownerSystem.contextObject, "List Add Task"); currentViewAction = action; #endif actions.Add(action); action.SetOwnerSystem(this.ownerSystem); }
public void AddCondition(ConditionTask condition) { if (condition is ConditionList) { foreach (var subCondition in (condition as ConditionList).conditions) { AddCondition(subCondition); } return; } #if UNITY_EDITOR UndoUtility.RecordObject(ownerSystem.contextObject, "List Add Task"); currentViewCondition = condition; #endif conditions.Add(condition); condition.SetOwnerSystem(this.ownerSystem); }
///Create a new Node of type and assigned to the provided graph. Use this for constructor public static Node Create(Graph targetGraph, System.Type nodeType, Vector2 pos) { if (targetGraph == null) { Logger.LogError("Can't Create a Node without providing a Target Graph", LogTag.GRAPH); return(null); } var newNode = (Node)System.Activator.CreateInstance(nodeType); UndoUtility.RecordObject(targetGraph, "Create Node"); newNode.graph = targetGraph; newNode.position = pos; BBParameter.SetBBFields(newNode, targetGraph.blackboard); newNode.Validate(targetGraph); newNode.OnCreate(targetGraph); UndoUtility.SetDirty(targetGraph); return(newNode); }
public override ActionResult DoAction() { if (MeshSelection.selectedObjectCount < 2) { return(new ActionResult(ActionResult.Status.Canceled, "Must Select 2+ Objects")); } var selected = MeshSelection.top.ToArray(); ProBuilderMesh currentMesh = MeshSelection.activeMesh; UndoUtility.RecordObject(currentMesh, "Merge Objects"); List <ProBuilderMesh> res = CombineMeshes.Combine(MeshSelection.topInternal, currentMesh); if (res != null) { foreach (var mesh in res) { mesh.Optimize(); if (mesh != currentMesh) { mesh.gameObject.name = Selection.activeGameObject.name + "-Merged"; UndoUtility.RegisterCreatedObjectUndo(mesh.gameObject, "Merge Objects"); Selection.objects = res.Select(x => x.gameObject).ToArray(); } } // Delete donor objects if they are not part of the result for (int i = 0; i < selected.Length; i++) { if (selected[i] != null && res.Contains(selected[i]) == false) { UndoUtility.DestroyImmediate(selected[i].gameObject); } } } ProBuilderEditor.Refresh(); return(new ActionResult(ActionResult.Status.Success, "Merged Objects")); }
/** * \brief Duplicates and mirrors the passed pb_Object. * @param pb The donor pb_Object. * @param axe The axis to mirror the object on. * \returns The newly duplicated pb_Object. * \sa ProBuilder.Axis */ public static ProBuilderMesh Mirror(ProBuilderMesh pb, Vector3 scale, bool duplicate = true) { ProBuilderMesh mirredObject; if (duplicate) { mirredObject = Object.Instantiate(pb.gameObject, pb.transform.parent, false).GetComponent <ProBuilderMesh>(); mirredObject.MakeUnique(); mirredObject.transform.parent = pb.transform.parent; mirredObject.transform.localRotation = pb.transform.localRotation; Undo.RegisterCreatedObjectUndo(mirredObject.gameObject, "Mirror Object"); } else { UndoUtility.RecordObject(pb, "Mirror"); mirredObject = pb; } Vector3 lScale = mirredObject.gameObject.transform.localScale; mirredObject.transform.localScale = scale; // if flipping on an odd number of axes, flip winding order if ((scale.x * scale.y * scale.z) < 0) { foreach (var face in mirredObject.facesInternal) { face.Reverse(); } } mirredObject.FreezeScaleTransform(); mirredObject.transform.localScale = lScale; mirredObject.ToMesh(); mirredObject.Refresh(); mirredObject.Optimize(); return(mirredObject); }
public override INodeReference OnGUI(GUIContent content, INodeReference instance) { //we presume that INodeRefence is serialized in a Node context if (instance == null) { UnityEditor.EditorGUILayout.LabelField(content.text, "Null NodeReference Instance"); return(instance); } var contextNode = context as Node; if (contextNode == null || contextNode.graph == null) { return(instance); } var graph = contextNode.graph; var targets = graph.allNodes.Where(x => instance.type.IsAssignableFrom(x.GetType())); var current = instance.Get(graph); var newTarget = EditorUtils.Popup <Node>(content, current, targets); if (newTarget != current) { UndoUtility.RecordObject(contextUnityObject, "Set Node Reference"); instance.Set(newTarget); foreach (var callbackAtt in attributes.OfType <CallbackAttribute>()) { var m = contextNode.GetType().RTGetMethod(callbackAtt.methodName); if (m != null) { m.Invoke(contextNode, null); } } UndoUtility.SetDirty(contextUnityObject); } return(instance); }
///<summary>Generate and return task menu</summary> GenericMenu GetMenu(Action <Task> callback) { var menu = new GenericMenu(); var taskType = task.GetType(); menu.AddItem(new GUIContent("Open Script"), false, () => { EditorUtils.OpenScriptOfType(taskType); }); menu.AddItem(new GUIContent("Copy"), false, () => { CopyBuffer.SetCache <Task>(task); }); foreach (var _m in taskType.RTGetMethods()) { var m = _m; var att = m.RTGetAttribute <ContextMenu>(true); if (att != null) { menu.AddItem(new GUIContent(att.menuItem), false, () => { m.Invoke(task, null); }); } } if (taskType.IsGenericType) { menu = EditorUtils.GetPreferedTypesSelectionMenu(taskType.GetGenericTypeDefinition(), (t) => { callback(Task.Create(t, task.ownerSystem)); }, menu, "Change Generic Type"); } menu.AddSeparator("/"); menu.AddItem(new GUIContent("Delete"), false, () => { if (callback != null) { UndoUtility.RecordObject(task.ownerSystem.contextObject, "Delete Task"); callback(null); } }); return(menu); }
///Duplicate node alone assigned to the provided graph public Node Duplicate(Graph targetGraph) { if (targetGraph == null) { Logger.LogError("Can't duplicate a Node without providing a Target Graph", LogTag.GRAPH); return(null); } //deep clone var newNode = JSONSerializer.Clone <Node>(this); UndoUtility.RecordObject(targetGraph, "Duplicate Node"); targetGraph.allNodes.Add(newNode); newNode.inConnections.Clear(); newNode.outConnections.Clear(); if (targetGraph == this.graph) { newNode.position += new Vector2(50, 50); } newNode._UID = null; newNode.graph = targetGraph; BBParameter.SetBBFields(newNode, targetGraph.blackboard); foreach (var task in Graph.GetTasksInElement(newNode)) { task.Validate(targetGraph); } //-- newNode.Validate(targetGraph); UndoUtility.SetDirty(targetGraph); return(newNode); }
///<summary>Return get add variable menu</summary> GenericMenu GetAddVariableMenu(IBlackboard bb, UnityEngine.Object contextParent) { System.Action <System.Type> AddNewVariable = (t) => { UndoUtility.RecordObject(contextParent, "Variable Added"); var name = "my" + t.FriendlyName(); while (bb.GetVariable(name) != null) { name += "."; } bb.AddVariable(name, t); UndoUtility.SetDirty(contextParent); }; System.Action <PropertyInfo> AddBoundProp = (p) => { UndoUtility.RecordObject(contextParent, "Variable Added"); var newVar = bb.AddVariable(p.Name, p.PropertyType); newVar.BindProperty(p); UndoUtility.SetDirty(contextParent); }; System.Action <FieldInfo> AddBoundField = (f) => { UndoUtility.RecordObject(contextParent, "Variable Added"); var newVar = bb.AddVariable(f.Name, f.FieldType); newVar.BindProperty(f); UndoUtility.SetDirty(contextParent); }; System.Action AddSeparator = () => { UndoUtility.RecordObject(contextParent, "Separator Added"); bb.AddVariable("Separator (Double Click To Rename)", new VariableSeperator()); UndoUtility.SetDirty(contextParent); }; var menu = new GenericMenu(); menu = EditorUtils.GetPreferedTypesSelectionMenu(typeof(object), AddNewVariable, menu, "New", true); if (bb.propertiesBindTarget != null) { foreach (var comp in bb.propertiesBindTarget.GetComponents(typeof(Component)).Where(c => c.hideFlags == 0)) { menu = EditorUtils.GetInstanceFieldSelectionMenu(comp.GetType(), typeof(object), AddBoundField, menu, "Bound (Self)"); menu = EditorUtils.GetInstancePropertySelectionMenu(comp.GetType(), typeof(object), AddBoundProp, false, false, menu, "Bound (Self)"); } menu.AddSeparator("Bound (Self)/"); } foreach (var type in TypePrefs.GetPreferedTypesList()) { if (bb.propertiesBindTarget != null && typeof(UnityEngine.Component).RTIsAssignableFrom(type)) { menu = EditorUtils.GetInstanceFieldSelectionMenu(type, typeof(object), AddBoundField, menu, "Bound (Self)"); menu = EditorUtils.GetInstancePropertySelectionMenu(type, typeof(object), AddBoundProp, false, false, menu, "Bound (Self)"); } menu = EditorUtils.GetStaticFieldSelectionMenu(type, typeof(object), AddBoundField, menu, "Bound (Static)"); menu = EditorUtils.GetStaticPropertySelectionMenu(type, typeof(object), AddBoundProp, false, false, menu, "Bound (Static)"); } menu.AddSeparator("/"); menu.AddItem(new GUIContent("Add Header Separator"), false, () => { AddSeparator(); }); return(menu); }
///Show a Task's field. If task null allow add task. Multiple tasks can be added to form a list. public static void TaskFieldMulti(Task task, ITaskSystem ownerSystem, Type baseType, Action <Task> callback) { //if null simply show an assignment button if (task == null) { ShowCreateTaskSelectionButton(ownerSystem, baseType, callback); return; } //Handle Action/ActionLists so that in GUI level a list is used only when needed if (baseType == typeof(ActionTask)) { if (!(task is ActionList)) { ShowCreateTaskSelectionButton(ownerSystem, baseType, (t) => { var newList = Task.Create <ActionList>(ownerSystem); UndoUtility.RecordObject(ownerSystem.contextObject, "New Action Task"); newList.AddAction((ActionTask)task); newList.AddAction((ActionTask)t); callback(newList); }); } ShowTaskInspectorGUI(task, callback); if (task is ActionList) { var list = (ActionList)task; if (list.actions.Count == 1) { list.actions[0].isUserEnabled = true; callback(list.actions[0]); } } return; } //Handle Condition/ConditionLists so that in GUI level a list is used only when needed if (baseType == typeof(ConditionTask)) { if (!(task is ConditionList)) { ShowCreateTaskSelectionButton(ownerSystem, baseType, (t) => { var newList = Task.Create <ConditionList>(ownerSystem); UndoUtility.RecordObject(ownerSystem.contextObject, "New Condition Task"); newList.AddCondition((ConditionTask)task); newList.AddCondition((ConditionTask)t); callback(newList); }); } ShowTaskInspectorGUI(task, callback); if (task is ConditionList) { var list = (ConditionList)task; if (list.conditions.Count == 1) { list.conditions[0].isUserEnabled = true; callback(list.conditions[0]); } } return; } //in all other cases where the base type is not a base ActionTask or ConditionTask, //(thus lists can't be used unless the base type IS a list), simple show the inspector. ShowTaskInspectorGUI(task, callback); }
//static because it's also used from DialogueTreeController public static void ShowActorParameters(DialogueTree dialogue) { EditorUtils.CoolLabel("Dialogue Actor Parameters"); EditorGUILayout.HelpBox("Enter the Key-Value pair for Dialogue Actors involved in the Dialogue.\nThe reference Object must be an IDialogueActor or have an IDialogueActor component. Referencing a Dialogue Actor is optional.", MessageType.Info); GUILayout.BeginVertical(GUI.skin.box); if (GUILayout.Button("Add Actor Parameter")) { UndoUtility.RecordObject(dialogue, "New Actor Parameter"); dialogue.actorParameters.Add(new DialogueTree.ActorParameter("actor parameter name")); UndoUtility.SetDirty(dialogue); } EditorGUILayout.LabelField("INSTIGATOR --> Replaced by the Actor starting the Dialogue"); var options = new EditorUtils.ReorderableListOptions(); options.allowAdd = false; options.allowRemove = true; options.unityObjectContext = dialogue; EditorUtils.ReorderableList(dialogue.actorParameters, options, (i, picked) => { var reference = dialogue.actorParameters[i]; GUILayout.BeginHorizontal(); if (dialogue.actorParameters.Where(r => r != reference).Select(r => r.name).Contains(reference.name)) { GUI.backgroundColor = Color.red; } var newRefName = EditorGUILayout.DelayedTextField(reference.name); if (newRefName != reference.name) { UndoUtility.RecordObject(dialogue, "Actor Parameter Name Change"); reference.name = newRefName; UndoUtility.SetDirty(dialogue); } GUI.backgroundColor = Color.white; var newReference = (Object)EditorGUILayout.ObjectField(reference.actor as Object, typeof(Object), true); if (!ReferenceEquals(newReference, reference.actor)) { UndoUtility.RecordObject(dialogue, "Actor Assignment"); //all this jazz because ObjectField does not work with interfaces... if (newReference == null) { reference.actor = null; } else { if (newReference is Component) { newReference = (newReference as Component).GetComponent(typeof(IDialogueActor)); } if (newReference is GameObject) { newReference = (newReference as GameObject).GetComponent(typeof(IDialogueActor)); } if (newReference is IDialogueActor) { reference.actor = (IDialogueActor)newReference; } else { ParadoxNotion.Services.Logger.LogWarning("Object is not an IDialogueActor and none of the components attached is an IDialogueActor either."); } } UndoUtility.SetDirty(dialogue); } GUILayout.EndHorizontal(); }); GUILayout.EndVertical(); }
///---------------------------------------------------------------------------------------------- #if UNITY_EDITOR //Shows blackboard variables mapping public static void ShowVariablesMappingGUI(this IGraphAssignable assignable) { if (assignable.subGraph == null || !assignable.subGraph.allowBlackboardOverrides) { assignable.variablesMap = null; return; } ParadoxNotion.Design.EditorUtils.Separator(); ParadoxNotion.Design.EditorUtils.CoolLabel("SubGraph Variables Mapping"); var subTreeVariables = assignable.subGraph.blackboard.variables.Values; if (subTreeVariables.Count == 0 || !subTreeVariables.Any(v => v.isExposedPublic)) { UnityEditor.EditorGUILayout.HelpBox("SubGraph has no exposed public variables. You can make variables exposed public through the 'gear' menu of a variable.", UnityEditor.MessageType.Info); assignable.variablesMap = null; return; } UnityEditor.EditorGUILayout.HelpBox("Map SubGraph exposed variables to this graph variables.\nUse the arrow buttons on the right of each parameter to enable WriteIn and/or ReadOut. WriteIn takes place when the SubGraph starts. ReadOut takes place continously while the SubGraph is running.", UnityEditor.MessageType.Info); foreach (var variable in subTreeVariables) { if (variable is Variable <VariableSeperator> ) { continue; } if (!variable.isExposedPublic || variable.isPropertyBound) { continue; } if (assignable.variablesMap == null) { assignable.variablesMap = new System.Collections.Generic.List <BBMappingParameter>(); } var bbParam = assignable.variablesMap.Find(x => x.targetSubGraphVariableID == variable.ID); if (bbParam == null) { GUILayout.BeginHorizontal(); GUI.enabled = false; EditorUtils.DrawEditorFieldDirect(new GUIContent(variable.name), variable.value, variable.varType, default(InspectedFieldInfo)); GUI.enabled = true; int tmp = 0; if (GUILayout.Button(EditorUtils.GetTempContent("▽", null, "Write (In)"), Styles.centerLabel, GUILayout.Width(12))) { tmp = 1; } UnityEditor.EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), UnityEditor.MouseCursor.Link); if (GUILayout.Button(EditorUtils.GetTempContent("△", null, "Read (Out)"), Styles.centerLabel, GUILayout.Width(12))) { tmp = -1; } if (tmp != 0) { UndoUtility.RecordObject(assignable.graph, "Override Variable"); bbParam = new BBMappingParameter(variable); bbParam.canWrite = tmp == 1; bbParam.canRead = tmp == -1; bbParam.useBlackboard = tmp == -1; bbParam.value = variable.value; bbParam.bb = assignable.graph.blackboard; assignable.variablesMap.Add(bbParam); UndoUtility.SetDirty(assignable.graph); } UnityEditor.EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), UnityEditor.MouseCursor.Link); GUILayout.EndHorizontal(); continue; } if (bbParam.varType != variable.varType && (bbParam.canRead || bbParam.canWrite)) { bbParam.SetType(variable.varType); } GUILayout.BeginHorizontal(); GUI.enabled = bbParam.canRead || bbParam.canWrite; NodeCanvas.Editor.BBParameterEditor.ParameterField(variable.name, bbParam); if (bbParam.canRead && !bbParam.useBlackboard) { EditorUtils.MarkLastFieldWarning("The parameter is set to Read Out, but is not linked to any Variable."); } GUI.enabled = true; if (GUILayout.Button(EditorUtils.GetTempContent(bbParam.canWrite ? "▼" : "▽", null, "Write (In)"), Styles.centerLabel, GUILayout.Width(12))) { UndoUtility.RecordObject(assignable.graph, "Set Write In"); bbParam.canWrite = !bbParam.canWrite; UndoUtility.SetDirty(assignable.graph); } UnityEditor.EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), UnityEditor.MouseCursor.Link); if (GUILayout.Button(EditorUtils.GetTempContent(bbParam.canRead ? "▲" : "△", null, "Read (Out)"), Styles.centerLabel, GUILayout.Width(12))) { UndoUtility.RecordObject(assignable.graph, "Set Read Out"); bbParam.canRead = !bbParam.canRead; UndoUtility.SetDirty(assignable.graph); } UnityEditor.EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), UnityEditor.MouseCursor.Link); if (!bbParam.canRead && !bbParam.canWrite) { UndoUtility.RecordObject(assignable.graph, "Remove Override"); assignable.variablesMap.Remove(bbParam); UndoUtility.SetDirty(assignable.graph); } GUILayout.EndHorizontal(); } if (assignable.variablesMap != null) { for (var i = assignable.variablesMap.Count; i-- > 0;) { var bbParam = assignable.variablesMap[i]; var variable = assignable.subGraph.blackboard.GetVariableByID(bbParam.targetSubGraphVariableID); if (variable == null || !variable.isExposedPublic || variable.isPropertyBound) { assignable.variablesMap.RemoveAt(i); UndoUtility.SetDirty(assignable.graph); } } } }
//... static void ParameterDropDown(GUIContent content, BBParameter bbParam) { if (bbParam.varRef == null && !string.IsNullOrEmpty(bbParam.name)) { bbParam.name = EditorGUILayout.DelayedTextField(content, bbParam.name); GUI.backgroundColor = Color.white.WithAlpha(0.5f); if (bbParam.bb != null && GUILayout.Button(EditorUtils.GetTempContent(Icons.plusIcon, "Promote To Variable"), Styles.centerLabel, GUILayout.Width(18), GUILayout.Height(16))) { var menu = new GenericMenu(); foreach (var bb in bbParam.bb.GetAllParents(true).Reverse()) { menu.AddItem(new GUIContent($"Promote Variable in '{bb.identifier}' Blackboard"), false, () => { UndoUtility.RecordObject(bb.unityContextObject, "Promote Variable"); bbParam.PromoteToVariable(bb); UndoUtility.SetDirty(bb.unityContextObject); }); } menu.ShowAsContext(); } GUI.backgroundColor = Color.white; return; } GUI.color = new Color(0.9f, 0.9f, 1f, 1f); EditorGUILayout.PrefixLabel(content); var rect = EditorGUILayout.GetControlRect(false); rect.xMin += 2; // O.o var cachedContentTextForNew = string.IsNullOrEmpty(content.text) ? string.Format("new{0}", bbParam.varType.Name) : content.text; var displayName = bbParam.isNone ? "[NONE]" : bbParam.name; var pop = EditorGUI.DropdownButton(rect, EditorUtils.GetTempContent(displayName), FocusType.Passive); GUI.color = Color.white; if (pop) { var menu = new GenericMenu(); menu.AddItem(new GUIContent("[NONE]"), false, () => { bbParam.name = string.Empty; }); foreach (var globalBB in GlobalBlackboard.GetAll()) { var globalVars = globalBB.GetVariables(bbParam.varType); if (globalVars.Count() == 0) { menu.AddDisabledItem(new GUIContent(globalBB.identifier + "/No Assignable Variables")); continue; } foreach (var variable in globalVars) { menu.AddItem(new GUIContent(globalBB.identifier + "/" + variable.name), bbParam.targetVariableID == variable.ID, () => { bbParam.SetTargetVariable(globalBB, variable); }); } } if (bbParam.bb != null) { foreach (var actualBB in bbParam.bb.GetAllParents(true).Reverse()) { var variables = actualBB.variables.Values.Where(v => v.CanConvertTo(bbParam.varType)); if (variables.Count() == 0) { menu.AddDisabledItem(new GUIContent(actualBB.identifier + "/No Assignable Variables")); continue; } foreach (var variable in variables) { menu.AddItem(new GUIContent(actualBB.identifier + "/" + variable.name), bbParam.targetVariableID == variable.ID, () => { bbParam.SetTargetVariable(actualBB, variable); }); } } } menu.AddSeparator(string.Empty); if (bbParam.bb != null) { foreach (var targetBB in bbParam.bb.GetAllParents(true).Reverse()) { menu.AddItem(new GUIContent("(Create New)/In '" + targetBB.identifier + "' Blackboard"), false, () => { UndoUtility.RecordObject(targetBB.unityContextObject, "New Variable"); if (targetBB.AddVariable(cachedContentTextForNew, bbParam.varType) != null) { bbParam.name = cachedContentTextForNew; } else { bbParam.name = null; } UndoUtility.SetDirty(targetBB.unityContextObject); }); } } menu.AddItem(new GUIContent("(DynamicVar)"), false, () => { bbParam.name = "_"; }); menu.DropDown(rect); } }
///<summary>Get a menu for variable</summary> GenericMenu GetVariableMenu(Variable data, int index) { var menu = new GenericMenu(); if (data.varType == typeof(VariableSeperator)) { menu.AddItem(new GUIContent("Rename"), false, () => { (data.value as VariableSeperator).isEditingName = true; }); menu.AddItem(new GUIContent("Remove"), false, () => { UndoUtility.RecordObject(contextObject, "Remove Variable"); bb.RemoveVariable(data.name); UndoUtility.SetDirty(contextObject); }); return(menu); } System.Action <PropertyInfo> BindProp = (p) => { UndoUtility.RecordObject(contextObject, "Bind Variable"); data.BindProperty(p); UndoUtility.SetDirty(contextObject); }; System.Action <FieldInfo> BindField = (f) => { UndoUtility.RecordObject(contextObject, "Bind Variable"); data.BindProperty(f); UndoUtility.SetDirty(contextObject); }; menu.AddDisabledItem(new GUIContent(string.Format("Type: {0}", data.varType.FriendlyName()))); if (bb.propertiesBindTarget != null) { foreach (var comp in bb.propertiesBindTarget.GetComponents(typeof(Component)).Where(c => c != null)) { menu = EditorUtils.GetInstanceFieldSelectionMenu(comp.GetType(), data.varType, BindField, menu, "Bind (Self)"); menu = EditorUtils.GetInstancePropertySelectionMenu(comp.GetType(), data.varType, BindProp, false, false, menu, "Bind (Self)"); } menu.AddSeparator("Bind (Self)/"); } foreach (var type in TypePrefs.GetPreferedTypesList()) { if (bb.propertiesBindTarget != null && typeof(UnityEngine.Component).RTIsAssignableFrom(type)) { menu = EditorUtils.GetInstanceFieldSelectionMenu(type, typeof(object), BindField, menu, "Bind (Self)"); menu = EditorUtils.GetInstancePropertySelectionMenu(type, typeof(object), BindProp, false, false, menu, "Bind (Self)"); } menu = EditorUtils.GetStaticFieldSelectionMenu(type, data.varType, BindField, menu, "Bind (Static)"); menu = EditorUtils.GetStaticPropertySelectionMenu(type, data.varType, BindProp, false, false, menu, "Bind (Static)"); } menu.AddItem(new GUIContent("Duplicate"), false, () => { UndoUtility.RecordObject(contextObject, "Duplicate Variable"); data.Duplicate(bb); UndoUtility.SetDirty(contextObject); }); if (bb is BlackboardSource) //TODO: avoid this check (but Im too tired now) { if (!data.isPropertyBound) { menu.AddItem(new GUIContent("Exposed Public"), data.isExposedPublic, () => { UndoUtility.RecordObject(contextObject, "Modify Variable"); data.isExposedPublic = !data.isExposedPublic; UndoUtility.SetDirty(contextObject); }); } else { menu.AddDisabledItem(new GUIContent("Bound Variables Can't Be Exposed")); } } menu.AddSeparator("/"); if (data.isPropertyBound) { menu.AddItem(new GUIContent("Runtime Debug Bound Value"), data.debugBoundValue, () => { UndoUtility.RecordObject(contextObject, "Debug Bound Variable Value"); data.debugBoundValue = !data.debugBoundValue; UndoUtility.SetDirty(contextObject); }); menu.AddItem(new GUIContent("UnBind"), false, () => { UndoUtility.RecordObject(contextObject, "UnBind Variable"); data.UnBind(); UndoUtility.SetDirty(contextObject); }); } else { menu.AddDisabledItem(new GUIContent("UnBind")); } var serProp = variablesProperty?.GetArrayElementAtIndex(index); if (serProp != null && serProp.prefabOverride) { var prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(contextObject); var asset = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(prefabAssetPath); menu.AddItem(new GUIContent("Apply Prefab Modification To '" + asset.name + "'"), false, () => { UndoUtility.RecordObject(asset, "Apply Variable To Prefab"); UndoUtility.RecordObject(contextObject, "Apply Variable To Prefab"); PrefabUtility.ApplyPropertyOverride(serProp, prefabAssetPath, InteractionMode.UserAction); UndoUtility.SetDirty(contextObject); UndoUtility.SetDirty(asset); }); menu.AddItem(new GUIContent("Revert Prefab Modification"), false, () => { UndoUtility.RecordObject(contextObject, "Revert Variable From Prefab"); PrefabUtility.RevertPropertyOverride(serProp, InteractionMode.UserAction); UndoUtility.SetDirty(contextObject); }); } System.Action <System.Type> ChangeType = (t) => { UndoUtility.RecordObject(contextObject, "Change Variable Type"); bb.ChangeVariableType(data, t); UndoUtility.SetDirty(contextObject); }; menu = EditorUtils.GetPreferedTypesSelectionMenu(typeof(object), ChangeType, menu, "Change Type"); menu.AddItem(new GUIContent("Delete Variable"), false, () => { if (EditorUtility.DisplayDialog("Delete Variable '" + data.name + "'", "Are you sure?", "Yes", "No")) { UndoUtility.RecordObject(contextObject, "Delete Variable"); bb.RemoveVariable(data.name); GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; UndoUtility.SetDirty(contextObject); } }); return(menu); }