public override void OnGUI(SerializedNodeProperty property, BehaviourMachine.ActionNode node, GUIContent guiContent) { // Now draw the property as a Slider or an IntSlider based on whether it’s a float or integer. if ( property.type != typeof(MinMaxRangeSO) ) Debug.LogWarning( "Use only with MinMaxRange type" ); else { var range = attribute as MinMaxRangeSAttribute; var so=(MinMaxRangeSO)property.value; //set or reset to default full range if(so.rangeStart==so.rangeEnd){ so.rangeStart=range.minLimit; so.rangeEnd=range.maxLimit; } var newMin =so.rangeStart; var newMax = so.rangeEnd; Rect position= GUILayoutUtility.GetRect(Screen.width-32f,32f); var xDivision = position.width * 0.33f; var yDivision = position.height * 0.5f; EditorGUI.LabelField( new Rect( position.x, position.y, xDivision, yDivision ) , guiContent ); EditorGUI.LabelField( new Rect( position.x, position.y + yDivision, position.width, yDivision ) , range.minLimit.ToString( "0.##" ) ); EditorGUI.LabelField( new Rect( position.x + position.width -28f, position.y + yDivision, position.width, yDivision ) , range.maxLimit.ToString( "0.##" ) ); EditorGUI.MinMaxSlider( new Rect( position.x + 24f, position.y + yDivision, position.width -48f, yDivision ) , ref newMin, ref newMax, range.minLimit, range.maxLimit ); EditorGUI.LabelField( new Rect( position.x + xDivision, position.y, xDivision, yDivision ) , "From: " ); newMin = Mathf.Clamp( EditorGUI.FloatField( new Rect( position.x + xDivision + 30, position.y, xDivision -30, yDivision ) , newMin ) , range.minLimit, newMax ); EditorGUI.LabelField( new Rect( position.x + xDivision * 2f, position.y, xDivision, yDivision ) , "To: " ); newMax = Mathf.Clamp( EditorGUI.FloatField( new Rect( position.x + xDivision * 2f + 24, position.y, xDivision -24, yDivision ) , newMax ) , newMin, range.maxLimit ); so.rangeStart = newMin; so.rangeEnd = newMax; property.ValueChanged(); property.ApplyModifiedValue(); property.serializedNode.ApplyModifiedProperties(); } }
// // Methods // /// <summary> /// Handles the onGUI event. /// </summary> /// <param name="property">Property.</param> /// <param name="node">Node.</param> /// <param name="guiContent">GUI content.</param> public override void OnGUI(SerializedNodeProperty property, ActionNode node, GUIContent guiContent) { //if (animatorSerialized == null || aniController == null) { if(aniController == null) { //!!! Serialization never serialized Animator cos its initialized in Reset after // NodePropertyIterator iter= property.serializedNode.GetIterator(); // iter.Find(attribute.animatorFieldName); // animatorSerialized=iter.current; // // if(animatorSerialized==null || animatorSerialized.value==null){ // Debug.LogError("AnimatorStateNodePropertyDrawer> No Animator component set on node parent GameObject"); // return; // } //runtimeContoller =( (Animator)animatorSerialized.value).runtimeAnimatorController; Animator animator = node.GetType ().GetField (attribute.animatorFieldName).GetValue (node) as Animator; RuntimeAnimatorController runtimeContoller; runtimeContoller = animator.runtimeAnimatorController; if (runtimeContoller is AnimatorOverrideController) aniController = ((AnimatorOverrideController)runtimeContoller).runtimeAnimatorController as UnityEditor.Animations.AnimatorController; else aniController = runtimeContoller as UnityEditor.Animations.AnimatorController; } animatorStateDisplayOptions = MecanimUtility.GetDisplayOptions (aniController); animatorStateValues = MecanimUtility.GetAnimatorStates (aniController); if(property.value!=null){ if(animatorStateValues.Length>0){ animatorStateSelectedPrev=animatorStateSelected=animatorStateValues.FirstOrDefault((itm)=>itm.nameHash==((ws.winx.unity.AnimatorState)property.value).nameHash); } } animatorStateSelected = EditorGUILayoutEx.CustomObjectPopup (guiContent, animatorStateSelected, animatorStateDisplayOptions, animatorStateValues);//,compare); //TODO try Begin/End Check if (animatorStateSelectedPrev != animatorStateSelected) { NodePropertyIterator iter = property.serializedNode.GetIterator (); iter.Find (attribute.layerIndexFieldName); SerializedNodeProperty layerIndexSerialized = iter.current; layerIndexSerialized.value = MecanimUtility.GetLayerIndex (aniController, animatorStateSelected); layerIndexSerialized.ApplyModifiedValue (); ws.winx.unity.AnimatorState state=property.value as ws.winx.unity.AnimatorState; if(state==null) state=ScriptableObject.CreateInstance<ws.winx.unity.AnimatorState>(); state.motion=animatorStateSelected.motion; state.nameHash=animatorStateSelected.nameHash; state.layer=(int)layerIndexSerialized.value; if(state.motion is UnityEditor.Animations.BlendTree){ BlendTree tree =(BlendTree)state.motion; int blendParamsNum= tree.GetRecursiveBlendParamCount(); state.blendParamsHashes=new int[blendParamsNum]; for(int i=0;i<blendParamsNum;i++) state.blendParamsHashes[i]=Animator.StringToHash(tree.GetRecursiveBlendParam(i)); }else{ state.blendParamsHashes=null; } //property.value=state; property.ValueChanged(); property.ApplyModifiedValue (); animatorStateSelectedPrev = animatorStateSelected; } if (animatorStateSelected.motion == null) Debug.LogError ("Selected state doesn't have Motion set"); }
/// <summary> /// Draw the TextArea. /// </summary> public override void OnGUI (SerializedNodeProperty property, ActionNode node, GUIContent guiContent) { // The text to display string text; // string if (property.propertyType == NodePropertyType.String) { // Get the text text = property.value as string ?? string.Empty; } // StringVar else if (property.propertyType == NodePropertyType.Variable && property.type == typeof(StringVar)) { // Get the text var stringVar = property.value as StringVar; if (stringVar != null) text = stringVar.Value as string ?? string.Empty; else text = string.Empty; } // Not supported else { EditorGUILayout.LabelField(guiContent, new GUIContent("Use TextAreaAttribute with string or StringVar.")); return; } // Create style? if (s_Styles == null) s_Styles = new NodeTextAreaDrawer.Styles(); // Get the text area var textAreaAttr = (NodeTextAreaAttribute) attribute; // Store the current content color Color contentColor = GUI.contentColor; // The text is empty? if (string.IsNullOrEmpty(text)) { text = textAreaAttr.hint; Color textColor = EditorStyles.label.normal.textColor; textColor.a = .5f; GUI.contentColor = textColor; } // Draw the text area. EditorGUI.BeginChangeCheck (); #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 string value = EditorGUILayout.TextArea (text, s_Styles.textArea, GUILayout.Height(16f * textAreaAttr.lines)); #else string value = EditorGUILayout.TextArea (text, s_Styles.textArea, GUILayout.Height(EditorGUIUtility.singleLineHeight * textAreaAttr.lines)); #endif // Check for changes if (EditorGUI.EndChangeCheck ()) { if (property.propertyType == NodePropertyType.String) property.value = value; else { // Get the text var stringVar = property.value as StringVar; if (stringVar != null) { stringVar.Value = value; property.ValueChanged(); } } } // Restore content color GUI.contentColor = contentColor; }
/// <summary> /// Draws a variable field on the GUI. /// <param name= "guiContent">The GUI content to draw the property.</param> /// <param name= "property">The variable property.</param> /// <param name= "node">The node that owns the variable to be drawn.</param> /// </summary> public static void VariableField(GUIContent guiContent, SerializedNodeProperty property, ActionNode node) { var variable = property.value as Variable; var isNone = variable == null || variable.isNone; var isConstant = !isNone && variable.isConstant; VariableInfoAttribute variableInfo = property.variableInfo; string popupName = string.Empty; Texture popupTexture = null; #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 var rect = GUILayoutUtility.GetRect(guiContent, EditorStyles.popup); #else var rect = EditorGUILayout.GetControlRect(); #endif var id = GUIUtility.GetControlID(FocusType.Keyboard); // Set label color if (isNone && variableInfo.requiredField) { EditorStyles.label.normal.textColor = Color.red; } // Draw label rect = EditorGUI.PrefixLabel(rect, id, guiContent); // Restore label color EditorStyles.label.normal.textColor = s_Styles.labelTextColor; if (isNone) { popupName = variableInfo.nullLabel; popupTexture = s_Styles.noneTexture; } else if (isConstant) { if (property.isConcreteVariable) { popupName = "Constant"; popupTexture = s_Styles.constantTexture; } else { popupName = variable.GetType().Name; popupTexture = IconUtility.GetIcon(variable.GetType()); } } else { popupName = variable.name; // Its a global var? popupTexture = variable.isGlobal ? s_Styles.globalBlackboardTexture : popupTexture = s_Styles.blackboardTexture;; } // Popup button if (GUIHelper.EditorButton(rect, id, new GUIContent(popupName, popupTexture), s_Styles.popup)) { // Set keyboard focus to the label GUIUtility.keyboardControl = id; // Create the menu and the list of unique names var menu = new GenericMenu(); var names = new List <string>() { }; // None names.Add(variableInfo.nullLabel); menu.AddItem(new GUIContent(variableInfo.nullLabel), isNone, delegate { if (isConstant && property.isConcreteVariable) { variable.SetAsNone(); property.ValueChanged(); } else if (!isNone) { object noneVariable; if (property.type == typeof(GameObjectVar)) { noneVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(property.type), new object[] { node.self }); } else if (property.type.IsAbstract) { noneVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(property.type)); } else { noneVariable = Activator.CreateInstance(property.type); } property.value = noneVariable; } }); // Create the anonymous function to set constants GenericMenu.MenuFunction2 createConstant = delegate(object userData) { // Get the desired variable type var type = userData as System.Type; // its not a constant or its an "ex global" var (an ex global var does not have a GlobalBlackboard)? if (variable == null || variable.isInvalid || property.type == typeof(BehaviourMachine.Variable)) { // Create a constant Variable newVariable; if (property.type == typeof(GameObjectVar)) { newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type), new object[] { node.self }) as Variable; } else if (type.IsAbstract) { newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type)) as Variable; } else { newVariable = Activator.CreateInstance(type) as Variable; } newVariable.SetAsConstant(); property.value = newVariable; property.ValueChanged(); } else if (isNone) { variable.SetAsConstant(); property.ValueChanged(); } else if ((isConstant && !property.isConcreteVariable) || !isConstant) { // Create a concrete variable type and update the field value! Variable newVariable; if (type == typeof(GameObjectVar)) { newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type), new object[] { node.self }) as Variable; } else if (type.IsAbstract) { newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type)) as Variable; } else { newVariable = Activator.CreateInstance(type) as Variable; } newVariable.SetAsConstant(); property.value = newVariable; } }; // Add the Constant name to the list names.Add("Constant"); // Can be constant? if (variableInfo.canBeConstant && property.type != typeof(BehaviourMachine.FsmEvent) && property.type != typeof(BehaviourMachine.DynamicList)) { if (property.type != typeof(BehaviourMachine.Variable)) { menu.AddItem(new GUIContent("Constant"), isConstant && property.isConcreteVariable, createConstant, property.type); } else { bool variableNotNull = variable != null; // If its a Variable type then add options for all concrete variables if (!variableInfo.fixedType) { menu.AddItem(new GUIContent("Constant/Variable"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.Variable), createConstant, typeof(BehaviourMachine.Variable)); menu.AddItem(new GUIContent("Constant/FloatVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteFloatVar), createConstant, typeof(BehaviourMachine.ConcreteFloatVar)); menu.AddItem(new GUIContent("Constant/IntVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteIntVar), createConstant, typeof(BehaviourMachine.ConcreteIntVar)); menu.AddItem(new GUIContent("Constant/BoolVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteBoolVar), createConstant, typeof(BehaviourMachine.ConcreteBoolVar)); menu.AddItem(new GUIContent("Constant/StringVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteStringVar), createConstant, typeof(BehaviourMachine.ConcreteStringVar)); menu.AddItem(new GUIContent("Constant/Vector3Var"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteVector3Var), createConstant, typeof(BehaviourMachine.ConcreteVector3Var)); menu.AddItem(new GUIContent("Constant/RectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteRectVar), createConstant, typeof(BehaviourMachine.ConcreteRectVar)); menu.AddItem(new GUIContent("Constant/ColorVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteColorVar), createConstant, typeof(BehaviourMachine.ConcreteColorVar)); menu.AddItem(new GUIContent("Constant/QuaternionVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteQuaternionVar), createConstant, typeof(BehaviourMachine.ConcreteQuaternionVar)); menu.AddItem(new GUIContent("Constant/GameObjectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteGameObjectVar), createConstant, typeof(BehaviourMachine.ConcreteGameObjectVar)); menu.AddItem(new GUIContent("Constant/MaterialVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteMaterialVar), createConstant, typeof(BehaviourMachine.ConcreteMaterialVar)); menu.AddItem(new GUIContent("Constant/TextureVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteTextureVar), createConstant, typeof(BehaviourMachine.ConcreteTextureVar)); menu.AddItem(new GUIContent("Constant/ObjectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteObjectVar), createConstant, typeof(BehaviourMachine.ConcreteObjectVar)); } else if (variable != null) { // Get the base type System.Type baseType = BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()); if (baseType == typeof(Variable)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.Variable), createConstant, typeof(BehaviourMachine.Variable)); } else if (baseType == typeof(FloatVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteFloatVar), createConstant, typeof(BehaviourMachine.ConcreteFloatVar)); } else if (baseType == typeof(IntVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteIntVar), createConstant, typeof(BehaviourMachine.ConcreteIntVar)); } else if (baseType == typeof(BoolVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteBoolVar), createConstant, typeof(BehaviourMachine.ConcreteBoolVar)); } else if (baseType == typeof(StringVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteStringVar), createConstant, typeof(BehaviourMachine.ConcreteStringVar)); } else if (baseType == typeof(Vector3Var)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteVector3Var), createConstant, typeof(BehaviourMachine.ConcreteVector3Var)); } else if (baseType == typeof(RectVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteRectVar), createConstant, typeof(BehaviourMachine.ConcreteRectVar)); } else if (baseType == typeof(ColorVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteColorVar), createConstant, typeof(BehaviourMachine.ConcreteColorVar)); } else if (baseType == typeof(QuaternionVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteQuaternionVar), createConstant, typeof(BehaviourMachine.ConcreteQuaternionVar)); } else if (baseType == typeof(GameObjectVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteGameObjectVar), createConstant, typeof(BehaviourMachine.ConcreteGameObjectVar)); } else if (baseType == typeof(MaterialVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteMaterialVar), createConstant, typeof(BehaviourMachine.ConcreteMaterialVar)); } else if (baseType == typeof(TextureVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteTextureVar), createConstant, typeof(BehaviourMachine.ConcreteTextureVar)); } else if (baseType == typeof(ObjectVar)) { menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteObjectVar), createConstant, typeof(BehaviourMachine.ConcreteObjectVar)); } } } } else { menu.AddDisabledItem(new GUIContent("Constant")); } // Custom variables if (property.type != null) { System.Type[] customVars = CustomVariableUtility.GetCustomVariables(variableInfo.fixedType && variable != null ? BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()) : property.type); // if (customVars.Length > 0) { // menu.AddSeparator(string.Empty); // } for (int i = 0; i < customVars.Length; i++) { // Get the type of the custom variable System.Type customVarType = customVars[i]; // Get a unique name string uniqueName = StringHelper.GetUniqueNameInList(names, "Custom/" + customVarType.Name); names.Add(uniqueName); // Add to the menu menu.AddItem(new GUIContent(uniqueName), isConstant && variable != null && variable.GetType() == customVarType, delegate { try { var newVariable = Activator.CreateInstance(customVarType, new object[] { node.self }) as Variable; if (newVariable != null) { newVariable.SetAsConstant(); property.value = newVariable; } } catch (Exception e) { Print.LogError(e.ToString()); } }); } } // Boolean used to know if the variables separator was already added to the menu. bool separatorAdded = false; // Blackboard variables var variables = node.self.GetComponent <InternalBlackboard>().GetVariables(variable != null && variableInfo.fixedType ? BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()) : property.type); // Add separator? if (variables.Count > 0) { menu.AddSeparator(string.Empty); separatorAdded = true; } // Blackboard variables for (int i = 0; i < variables.Count; i++) { var v = variables[i]; var name = StringHelper.GetUniqueNameInList(names, v.name); names.Add(name); menu.AddItem(new GUIContent(name), variable == v, delegate { property.value = v; }); } // Global variables if (InternalGlobalBlackboard.Instance != null) { var globalVariables = InternalGlobalBlackboard.Instance.GetVariables(property.type); // Add separator? if (!separatorAdded && globalVariables.Count > 0) { menu.AddSeparator(string.Empty); separatorAdded = true; } for (int i = 0; i < globalVariables.Count; i++) { var v = globalVariables[i]; var name = StringHelper.GetUniqueNameInList(names, "Global/" + v.name); names.Add(name); menu.AddItem(new GUIContent(name), variable == v, delegate { property.value = v; }); } } // Show menu menu.DropDown(rect); // Set GUI as not changed GUI.changed = false; } // Draw constant properties if (isConstant) { // Get children var children = property.children; // The variable is an ObjectVar? var objectVar = variable as ObjectVar; System.Type objType = objectVar != null ? objectVar.ObjectType : null; // Draw properties if (children.Length > 0) { EditorGUI.indentLevel++; if (property.isConcreteVariable) { for (int i = 0; i < children.Length; i++) { SerializedNodeProperty childProperty = children[i]; if (!childProperty.hideInInspector) { if (childProperty.propertyType == NodePropertyType.Vector3 || childProperty.propertyType == NodePropertyType.Quaternion || childProperty.propertyType == NodePropertyType.Vector2) { #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 GUILayout.Space(-20f); EditorGUI.indentLevel--; #endif DrawNodeProperty(GUIContent.none, childProperty, node, objType); #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 EditorGUI.indentLevel++; #endif } else if (childProperty.propertyType == NodePropertyType.Rect) { #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 GUILayout.Space(-20f); EditorGUI.indentLevel--; #endif DrawNodeProperty(GUIContent.none, childProperty, node, objType); #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 GUILayout.Space(20f); EditorGUI.indentLevel++; #endif } else { DrawNodeProperty(new GUIContent(childProperty.label, childProperty.tooltip), childProperty, node, objType); } } } } else { for (int i = 0; i < children.Length; i++) { SerializedNodeProperty childProperty = children[i]; if (!childProperty.hideInInspector) { DrawNodeProperty(new GUIContent(childProperty.label, childProperty.tooltip), childProperty, node, objType); } } } EditorGUI.indentLevel--; } } }
/// <summary> /// Draw the TextArea. /// </summary> public override void OnGUI(SerializedNodeProperty property, ActionNode node, GUIContent guiContent) { // The text to display string text; // string if (property.propertyType == NodePropertyType.String) { // Get the text text = property.value as string ?? string.Empty; } // StringVar else if (property.propertyType == NodePropertyType.Variable && property.type == typeof(StringVar)) { // Get the text var stringVar = property.value as StringVar; if (stringVar != null) { text = stringVar.Value as string ?? string.Empty; } else { text = string.Empty; } } // Not supported else { EditorGUILayout.LabelField(guiContent, new GUIContent("Use TextAreaAttribute with string or StringVar.")); return; } // Create style? if (s_Styles == null) { s_Styles = new NodeTextAreaDrawer.Styles(); } // Get the text area var textAreaAttr = (NodeTextAreaAttribute)attribute; // Store the current content color Color contentColor = GUI.contentColor; // The text is empty? if (string.IsNullOrEmpty(text)) { text = textAreaAttr.hint; Color textColor = EditorStyles.label.normal.textColor; textColor.a = .5f; GUI.contentColor = textColor; } // Draw the text area. EditorGUI.BeginChangeCheck(); #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 string value = EditorGUILayout.TextArea(text, s_Styles.textArea, GUILayout.Height(16f * textAreaAttr.lines)); #else string value = EditorGUILayout.TextArea(text, s_Styles.textArea, GUILayout.Height(EditorGUIUtility.singleLineHeight * textAreaAttr.lines)); #endif // Check for changes if (EditorGUI.EndChangeCheck()) { if (property.propertyType == NodePropertyType.String) { property.value = value; } else { // Get the text var stringVar = property.value as StringVar; if (stringVar != null) { stringVar.Value = value; property.ValueChanged(); } } } // Restore content color GUI.contentColor = contentColor; }
/// <summary> /// Draws a variable field on the GUI. /// <param name= "guiContent">The GUI content to draw the property.</param> /// <param name= "property">The variable property.</param> /// <param name= "node">The node that owns the variable to be drawn.</param> /// </summary> public static void VariableField (GUIContent guiContent, SerializedNodeProperty property, ActionNode node) { var variable = property.value as Variable; var isNone = variable == null || variable.isNone; var isConstant = !isNone && variable.isConstant; VariableInfoAttribute variableInfo = property.variableInfo; string popupName = string.Empty; Texture popupTexture = null; #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 var rect = GUILayoutUtility.GetRect(guiContent, EditorStyles.popup); #else var rect = EditorGUILayout.GetControlRect(); #endif var id = GUIUtility.GetControlID(FocusType.Keyboard); // Set label color if (isNone && variableInfo.requiredField) EditorStyles.label.normal.textColor = Color.red; // Draw label rect = EditorGUI.PrefixLabel(rect, id, guiContent); // Restore label color EditorStyles.label.normal.textColor = s_Styles.labelTextColor; if (isNone) { popupName = variableInfo.nullLabel; popupTexture = s_Styles.noneTexture; } else if (isConstant) { if (property.isConcreteVariable) { popupName = "Constant"; popupTexture = s_Styles.constantTexture; } else { popupName = variable.GetType().Name; popupTexture = IconUtility.GetIcon(variable.GetType()); } } else { popupName = variable.name; // Its a global var? popupTexture = variable.isGlobal ? s_Styles.globalBlackboardTexture : popupTexture = s_Styles.blackboardTexture;; } // Popup button if (GUIHelper.EditorButton(rect, id, new GUIContent(popupName, popupTexture), s_Styles.popup)) { // Set keyboard focus to the label GUIUtility.keyboardControl = id; // Create the menu and the list of unique names var menu = new GenericMenu(); var names = new List<string>() {}; // None names.Add(variableInfo.nullLabel); menu.AddItem(new GUIContent(variableInfo.nullLabel), isNone , delegate { if (isConstant && property.isConcreteVariable) { variable.SetAsNone(); property.ValueChanged(); } else if (!isNone) { object noneVariable; if (property.type == typeof(GameObjectVar)) noneVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(property.type), new object[] {node.self}); else if (property.type.IsAbstract) noneVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(property.type)); else noneVariable = Activator.CreateInstance(property.type); property.value = noneVariable; } }); // Create the anonymous function to set constants GenericMenu.MenuFunction2 createConstant = delegate (object userData) { // Get the desired variable type var type = userData as System.Type; // its not a constant or its an "ex global" var (an ex global var does not have a GlobalBlackboard)? if (variable == null || variable.isInvalid || property.type == typeof(BehaviourMachine.Variable)) { // Create a constant Variable newVariable; if (property.type == typeof(GameObjectVar)) newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type), new object[] {node.self}) as Variable; else if (type.IsAbstract) newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type)) as Variable; else newVariable = Activator.CreateInstance(type) as Variable; newVariable.SetAsConstant(); property.value = newVariable; property.ValueChanged(); } else if (isNone) { variable.SetAsConstant(); property.ValueChanged(); } else if ((isConstant && !property.isConcreteVariable) || !isConstant) { // Create a concrete variable type and update the field value! Variable newVariable; if (type == typeof(GameObjectVar)) newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type), new object[] {node.self}) as Variable; else if (type.IsAbstract) newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type)) as Variable; else newVariable = Activator.CreateInstance(type) as Variable; newVariable.SetAsConstant(); property.value = newVariable; } }; // Add the Constant name to the list names.Add("Constant"); // Can be constant? if (variableInfo.canBeConstant && property.type != typeof(BehaviourMachine.FsmEvent) && property.type != typeof(BehaviourMachine.DynamicList)) { if (property.type != typeof(BehaviourMachine.Variable)) { menu.AddItem(new GUIContent("Constant"), isConstant && property.isConcreteVariable, createConstant, property.type); } else { bool variableNotNull = variable != null; // If its a Variable type then add options for all concrete variables if (!variableInfo.fixedType) { menu.AddItem(new GUIContent("Constant/Variable"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.Variable), createConstant, typeof(BehaviourMachine.Variable)); menu.AddItem(new GUIContent("Constant/FloatVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteFloatVar), createConstant, typeof(BehaviourMachine.ConcreteFloatVar)); menu.AddItem(new GUIContent("Constant/IntVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteIntVar), createConstant, typeof(BehaviourMachine.ConcreteIntVar)); menu.AddItem(new GUIContent("Constant/BoolVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteBoolVar), createConstant, typeof(BehaviourMachine.ConcreteBoolVar)); menu.AddItem(new GUIContent("Constant/StringVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteStringVar), createConstant, typeof(BehaviourMachine.ConcreteStringVar)); menu.AddItem(new GUIContent("Constant/Vector3Var"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteVector3Var), createConstant, typeof(BehaviourMachine.ConcreteVector3Var)); menu.AddItem(new GUIContent("Constant/RectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteRectVar), createConstant, typeof(BehaviourMachine.ConcreteRectVar)); menu.AddItem(new GUIContent("Constant/ColorVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteColorVar), createConstant, typeof(BehaviourMachine.ConcreteColorVar)); menu.AddItem(new GUIContent("Constant/QuaternionVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteQuaternionVar), createConstant, typeof(BehaviourMachine.ConcreteQuaternionVar)); menu.AddItem(new GUIContent("Constant/GameObjectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteGameObjectVar), createConstant, typeof(BehaviourMachine.ConcreteGameObjectVar)); menu.AddItem(new GUIContent("Constant/MaterialVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteMaterialVar), createConstant, typeof(BehaviourMachine.ConcreteMaterialVar)); menu.AddItem(new GUIContent("Constant/TextureVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteTextureVar), createConstant, typeof(BehaviourMachine.ConcreteTextureVar)); menu.AddItem(new GUIContent("Constant/ObjectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteObjectVar), createConstant, typeof(BehaviourMachine.ConcreteObjectVar)); } else if (variable != null) { // Get the base type System.Type baseType = BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()); if (baseType == typeof(Variable)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.Variable), createConstant, typeof(BehaviourMachine.Variable)); else if (baseType == typeof(FloatVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteFloatVar), createConstant, typeof(BehaviourMachine.ConcreteFloatVar)); else if (baseType == typeof(IntVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteIntVar), createConstant, typeof(BehaviourMachine.ConcreteIntVar)); else if (baseType == typeof(BoolVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteBoolVar), createConstant, typeof(BehaviourMachine.ConcreteBoolVar)); else if (baseType == typeof(StringVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteStringVar), createConstant, typeof(BehaviourMachine.ConcreteStringVar)); else if (baseType == typeof(Vector3Var)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteVector3Var), createConstant, typeof(BehaviourMachine.ConcreteVector3Var)); else if (baseType == typeof(RectVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteRectVar), createConstant, typeof(BehaviourMachine.ConcreteRectVar)); else if (baseType == typeof(ColorVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteColorVar), createConstant, typeof(BehaviourMachine.ConcreteColorVar)); else if (baseType == typeof(QuaternionVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteQuaternionVar), createConstant, typeof(BehaviourMachine.ConcreteQuaternionVar)); else if (baseType == typeof(GameObjectVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteGameObjectVar), createConstant, typeof(BehaviourMachine.ConcreteGameObjectVar)); else if (baseType == typeof(MaterialVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteMaterialVar), createConstant, typeof(BehaviourMachine.ConcreteMaterialVar)); else if (baseType == typeof (TextureVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteTextureVar), createConstant, typeof(BehaviourMachine.ConcreteTextureVar)); else if (baseType == typeof (ObjectVar)) menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteObjectVar), createConstant, typeof(BehaviourMachine.ConcreteObjectVar)); } } } else { menu.AddDisabledItem(new GUIContent("Constant")); } // Custom variables if (property.type != null) { System.Type[] customVars = CustomVariableUtility.GetCustomVariables(variableInfo.fixedType && variable != null ? BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()) : property.type); // if (customVars.Length > 0) { // menu.AddSeparator(string.Empty); // } for (int i = 0; i < customVars.Length; i++) { // Get the type of the custom variable System.Type customVarType = customVars[i]; // Get a unique name string uniqueName = StringHelper.GetUniqueNameInList(names, "Custom/" + customVarType.Name); names.Add(uniqueName); // Add to the menu menu.AddItem(new GUIContent(uniqueName), isConstant && variable != null && variable.GetType() == customVarType, delegate { try { var newVariable = Activator.CreateInstance(customVarType, new object[] {node.self}) as Variable; if (newVariable != null) { newVariable.SetAsConstant(); property.value = newVariable; } } catch (Exception e) { Print.LogError(e.ToString()); } }); } } // Boolean used to know if the variables separator was already added to the menu. bool separatorAdded = false; // Blackboard variables var variables = node.self.GetComponent<InternalBlackboard>().GetVariables(variable != null && variableInfo.fixedType ? BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()) : property.type); // Add separator? if (variables.Count > 0) { menu.AddSeparator(string.Empty); separatorAdded = true; } // Blackboard variables for (int i = 0; i < variables.Count; i++) { var v = variables[i]; var name = StringHelper.GetUniqueNameInList(names, v.name); names.Add(name); menu.AddItem(new GUIContent(name), variable == v , delegate {property.value = v;}); } // Global variables if (InternalGlobalBlackboard.Instance != null) { var globalVariables = InternalGlobalBlackboard.Instance.GetVariables(property.type); // Add separator? if (!separatorAdded && globalVariables.Count > 0) { menu.AddSeparator(string.Empty); separatorAdded = true; } for (int i = 0; i < globalVariables.Count; i++) { var v = globalVariables[i]; var name = StringHelper.GetUniqueNameInList(names, "Global/" + v.name); names.Add(name); menu.AddItem(new GUIContent(name), variable == v , delegate {property.value = v;}); } } // Show menu menu.DropDown(rect); // Set GUI as not changed GUI.changed = false; } // Draw constant properties if (isConstant) { // Get children var children = property.children; // The variable is an ObjectVar? var objectVar = variable as ObjectVar; System.Type objType = objectVar != null ? objectVar.ObjectType : null; // Draw properties if (children.Length > 0) { EditorGUI.indentLevel++; if (property.isConcreteVariable) { for (int i = 0; i < children.Length; i++) { SerializedNodeProperty childProperty = children[i]; if (!childProperty.hideInInspector) { if (childProperty.propertyType == NodePropertyType.Vector3 || childProperty.propertyType == NodePropertyType.Quaternion || childProperty.propertyType == NodePropertyType.Vector2) { #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 GUILayout.Space(-20f); EditorGUI.indentLevel--; #endif DrawNodeProperty(GUIContent.none, childProperty, node, objType); #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 EditorGUI.indentLevel++; #endif } else if (childProperty.propertyType == NodePropertyType.Rect) { #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 GUILayout.Space(-20f); EditorGUI.indentLevel--; #endif DrawNodeProperty(GUIContent.none, childProperty, node, objType); #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 GUILayout.Space(20f); EditorGUI.indentLevel++; #endif } else DrawNodeProperty(new GUIContent(childProperty.label, childProperty.tooltip), childProperty, node, objType); } } } else { for (int i = 0; i < children.Length; i++) { SerializedNodeProperty childProperty = children[i]; if (!childProperty.hideInInspector) DrawNodeProperty(new GUIContent(childProperty.label, childProperty.tooltip), childProperty, node, objType); } } EditorGUI.indentLevel--; } } }