/// <summary> /// Draws the specified view type. /// </summary> private void DrawSelectedViewType(int index) { var viewType = m_CameraController.ViewTypes[index]; InspectorUtility.DrawObject(viewType, true, true, target, true, SerializeViewTypes); if (Shared.Editor.Inspectors.Utility.InspectorUtility.Foldout(viewType, new GUIContent("States"), false)) { // The View Type class derives from system.object at the base level and reorderable lists can only operate on Unity objects. To get around this restriction // create a dummy array within a Unity object that corresponds to the number of elements within the view type's state list. When the reorderable list is drawn // the view type object will be used so it's like the dummy object never existed. var selectedViewType = viewType as ViewType; var gameObject = new GameObject(); var stateIndexHelper = gameObject.AddComponent <StateInspectorHelper>(); stateIndexHelper.StateIndexData = new int[selectedViewType.States.Length]; for (int i = 0; i < stateIndexHelper.StateIndexData.Length; ++i) { stateIndexHelper.StateIndexData[i] = i; } var stateIndexSerializedObject = new SerializedObject(stateIndexHelper); m_ReorderableViewTypeStateList = StateInspector.DrawStates(m_ReorderableViewTypeStateList, serializedObject, stateIndexSerializedObject.FindProperty("m_StateIndexData"), GetSelectedViewTypeStateIndexKey(selectedViewType), OnViewTypeStateListDraw, OnViewTypeStateListAdd, OnViewTypeStateListReorder, OnViewTypeStateListRemove); DestroyImmediate(gameObject); } }
/// <summary> /// Draws the specified item set. /// </summary> private void DrawSelectedPickupSet(ItemPickupBase.PickupSet pickupSet, int index) { GUILayout.Label("Pickup Set " + index, Shared.Editor.Inspectors.Utility.InspectorStyles.CenterBoldLabel); pickupSet.Item = (GameObject)EditorGUILayout.ObjectField("Item", pickupSet.Item, typeof(GameObject), false); if (pickupSet.Item != null) { // Automatically fill in the ItemDefinition for the specified item. var item = pickupSet.Item.GetComponent <Item>(); if (item != null && item.SlotID < pickupSet.ItemSet.Slots.Length && pickupSet.ItemSet.Slots[item.SlotID] != item.ItemDefinition) { pickupSet.ItemSet.Slots[item.SlotID] = item.ItemDefinition; EditorUtility.SetDirty(target); } } GUI.enabled = pickupSet.Item == null && !Application.isPlaying; DrawAvailableCategories(pickupSet, new Rect()); GUI.enabled = !Application.isPlaying; pickupSet.ItemSet.State = EditorGUILayout.TextField(new GUIContent("State", "Optionally specify a state that the character should switch to when the Item Set is active."), pickupSet.ItemSet.State); // Draws all of the slots ItemIdentifiers. for (int i = 0; i < m_SlotCount; ++i) { pickupSet.ItemSet.Slots[i] = (ItemDefinitionBase)EditorGUILayout.ObjectField("Slot " + i, pickupSet.ItemSet.Slots[i], typeof(ItemDefinitionBase), false); } pickupSet.Default = EditorGUILayout.Toggle(new GUIContent("Default", "True if the ItemSet is the default Item Set."), pickupSet.Default); pickupSet.ItemSet.Enabled = EditorGUILayout.Toggle(new GUIContent("Enabled", "True if the ItemSet can be equipped."), pickupSet.ItemSet.Enabled); pickupSet.ItemSet.CanSwitchTo = EditorGUILayout.Toggle(new GUIContent("Can Switch To", "True if the ItemSet can be switched to by the EquipNext/EquipPrevious abilities."), pickupSet.ItemSet.CanSwitchTo); pickupSet.ItemSet.DisabledIndex = EditorGUILayout.IntField(new GUIContent("Disabled Index", "The ItemSet that should be activated if the current ItemSet is disabled."), pickupSet.ItemSet.DisabledIndex); if (Shared.Editor.Inspectors.Utility.InspectorUtility.Foldout(pickupSet, new GUIContent("States"), false)) { // The MovementType class derives from system.object at the base level and reorderable lists can only operate on Unity objects. To get around this restriction // create a dummy array within a Unity object that corresponds to the number of elements within the ability's state list. When the reorderable list is drawn // the ability object will be used so it's like the dummy object never existed. var gameObject = new GameObject(); try { var stateIndexHelper = gameObject.AddComponent <StateInspectorHelper>(); stateIndexHelper.StateIndexData = new int[pickupSet.ItemSet.States.Length]; for (int i = 0; i < stateIndexHelper.StateIndexData.Length; ++i) { stateIndexHelper.StateIndexData[i] = i; } var stateIndexSerializedObject = new SerializedObject(stateIndexHelper); m_ReorderablePickupSetStateList = StateInspector.DrawStates(m_ReorderablePickupSetStateList, serializedObject, stateIndexSerializedObject.FindProperty("m_StateIndexData"), GetSelectedPickupSetStateIndexKey(index), OnPickupSetStateListDraw, OnPickupSetStateListAdd, OnPickupSetStateListReorder, OnPickupSetStateListRemove); } catch (System.Exception /*e*/) { } DestroyImmediate(gameObject); } }
/// <summary> /// Draws the AnimatorAudioStateSet. /// </summary> public static void DrawAnimatorAudioStateSet(UnityEngine.Object target, AnimatorAudioStateSet animatorAudioStateSet, string animatorAudioStateSetFieldName, bool randomDefaultSelector, ref ReorderableList reorderableList, ReorderableList.ElementCallbackDelegate drawCallback, ReorderableList.SelectCallbackDelegate selectCallback, ReorderableList.AddCallbackDelegate addCallback, ReorderableList.RemoveCallbackDelegate removeCallback, string preferencesKey, ref ReorderableList reorderableAudioList, ReorderableList.ElementCallbackDelegate drawAudioElementCallback, ReorderableList.AddCallbackDelegate addAudioCallback, ReorderableList.RemoveCallbackDelegate removeAudioCallback, ref ReorderableList reorderableStateList, ReorderableList.ElementCallbackDelegate stateDrawElementCallback, ReorderableList.AddCallbackDelegate stateAddCallback, ReorderableList.ReorderCallbackDelegate stateReorderCallback, ReorderableList.RemoveCallbackDelegate stateRemoveCallback, string statePreferencesKey) { PopulateAnimatorAudioStateSelectorTypes(); if (s_SelectorTypeNameCache != null) { var selected = 0; var forceUpdate = true; if (animatorAudioStateSet.AnimatorAudioStateSelectorData != null && !string.IsNullOrEmpty(animatorAudioStateSet.AnimatorAudioStateSelectorData.ObjectType)) { for (int i = 0; i < s_SelectorTypeCache.Count; ++i) { if (s_SelectorTypeCache[i].FullName == animatorAudioStateSet.AnimatorAudioStateSelectorData.ObjectType) { selected = i; forceUpdate = false; break; } } } var newSelected = EditorGUILayout.Popup("Selector", selected, s_SelectorTypeNameCache.ToArray()); if (newSelected != selected || forceUpdate) { // Use the Sequence selector as the default (or recoil in the case of a melee weapon). if (forceUpdate) { for (int i = 0; i < s_SelectorTypeCache.Count; ++i) { if ((randomDefaultSelector && s_SelectorTypeCache[i].FullName == "Opsive.UltimateCharacterController.Items.AnimatorAudioStates.Sequence") || (!randomDefaultSelector && s_SelectorTypeCache[i].FullName == "Opsive.UltimateCharacterController.Items.AnimatorAudioStates.ConstantRecoil")) { newSelected = i; break; } } } var animatorAudioOutputSelector = Activator.CreateInstance(s_SelectorTypeCache[newSelected]) as AnimatorAudioStateSelector; animatorAudioStateSet.AnimatorAudioStateSelectorData = Serialization.Serialize(animatorAudioOutputSelector); InspectorUtility.SetDirty(target); } } if (animatorAudioStateSet.AnimatorAudioStateSelector != null) { EditorGUI.indentLevel++; InspectorUtility.DrawObject(animatorAudioStateSet.AnimatorAudioStateSelector, false, true, target, false, () => { animatorAudioStateSet.AnimatorAudioStateSelectorData = Serialization.Serialize(animatorAudioStateSet.AnimatorAudioStateSelector); InspectorUtility.SetDirty(target); }); EditorGUI.indentLevel--; } if (animatorAudioStateSet.States == null || animatorAudioStateSet.States.Length == 0) { animatorAudioStateSet.States = new AnimatorAudioStateSet.AnimatorAudioState[] { new AnimatorAudioStateSet.AnimatorAudioState() }; } var serializedObject = new SerializedObject(target); var serializedProperty = serializedObject.FindProperty(animatorAudioStateSetFieldName).FindPropertyRelative("m_States"); if (reorderableList == null) { reorderableList = new ReorderableList(animatorAudioStateSet.States, typeof(AnimatorAudioStateSet.AnimatorAudioState), false, true, true, animatorAudioStateSet.States.Length > 1); reorderableList.drawHeaderCallback = OnAnimatorAudioStateListHeaderDraw; reorderableList.drawElementCallback = drawCallback; reorderableList.onSelectCallback = selectCallback; reorderableList.onAddCallback = addCallback; reorderableList.onRemoveCallback = removeCallback; reorderableList.serializedProperty = serializedProperty; if (EditorPrefs.GetInt(preferencesKey, -1) != -1) { reorderableList.index = EditorPrefs.GetInt(preferencesKey, -1); } } // ReorderableLists do not like indentation. var indentLevel = EditorGUI.indentLevel; while (EditorGUI.indentLevel > 0) { EditorGUI.indentLevel--; } var listRect = GUILayoutUtility.GetRect(0, reorderableList.GetHeight()); // Indent the list so it lines up with the rest of the content. listRect.x += InspectorUtility.IndentWidth * indentLevel; listRect.xMax -= InspectorUtility.IndentWidth * indentLevel; EditorGUI.BeginChangeCheck(); var prevPref = EditorPrefs.GetInt(preferencesKey, 0); reorderableList.DoList(listRect); while (EditorGUI.indentLevel < indentLevel) { EditorGUI.indentLevel++; } if (EditorGUI.EndChangeCheck() || prevPref != EditorPrefs.GetInt(preferencesKey, 0)) { reorderableList = null; reorderableAudioList = null; reorderableStateList = null; return; } if (EditorPrefs.GetInt(preferencesKey, 0) >= animatorAudioStateSet.States.Length) { EditorPrefs.SetInt(preferencesKey, 0); } serializedProperty = serializedProperty.GetArrayElementAtIndex(EditorPrefs.GetInt(preferencesKey, 0)); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(serializedProperty.FindPropertyRelative("m_AllowDuringMovement")); EditorGUILayout.PropertyField(serializedProperty.FindPropertyRelative("m_RequireGrounded")); EditorGUILayout.PropertyField(serializedProperty.FindPropertyRelative("m_StateName")); EditorGUILayout.PropertyField(serializedProperty.FindPropertyRelative("m_ItemSubstateIndex")); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } var animatorAudioState = animatorAudioStateSet.States[EditorPrefs.GetInt(preferencesKey, 0)]; AudioClipSetInspector.DrawAudioClipSet(animatorAudioState.AudioClipSet, serializedProperty.FindPropertyRelative("m_AudioClipSet"), ref reorderableAudioList, drawAudioElementCallback, addAudioCallback, removeAudioCallback); if (InspectorUtility.Foldout(animatorAudioState, new GUIContent("States"), false)) { EditorGUI.indentLevel--; // The MovementType class derives from system.object at the base level and reorderable lists can only operate on Unity objects. To get around this restriction // create a dummy array within a Unity object that corresponds to the number of elements within the ability's state list. When the reorderable list is drawn // the ability object will be used so it's like the dummy object never existed. var gameObject = new GameObject(); var stateIndexHelper = gameObject.AddComponent <StateInspectorHelper>(); stateIndexHelper.StateIndexData = new int[animatorAudioState.States.Length]; for (int i = 0; i < stateIndexHelper.StateIndexData.Length; ++i) { stateIndexHelper.StateIndexData[i] = i; } var stateIndexSerializedObject = new SerializedObject(stateIndexHelper); reorderableStateList = StateInspector.DrawStates(reorderableStateList, new SerializedObject(target), stateIndexSerializedObject.FindProperty("m_StateIndexData"), statePreferencesKey, stateDrawElementCallback, stateAddCallback, stateReorderCallback, stateRemoveCallback); GameObject.DestroyImmediate(gameObject); EditorGUI.indentLevel++; } GUILayout.Space(5); }
/// <summary> /// Draws the specified item set. /// </summary> private void DrawSelectedItemSet(ItemSet itemSet, int index) { GUILayout.Label("Item Set " + index, Shared.Editor.Inspectors.Utility.InspectorStyles.CenterBoldLabel); itemSet.State = EditorGUILayout.TextField(new GUIContent("State", "Optionally specify a state that the character should switch to when the Item Set is active."), itemSet.State); // Draws all of the slots ItemDefinitions. for (int i = 0; i < m_InventoryBase.SlotCount; ++i) { var itemDefinition = (ItemDefinitionBase)EditorGUILayout.ObjectField("Slot " + i, itemSet.Slots[i], typeof(ItemDefinitionBase), false); // The ItemIdentifier must belong to the parent category. if (itemDefinition != null && m_ItemSetManager.IsCategoryMember(itemDefinition, m_ItemSetListIndex)) { itemSet.Slots[i] = itemDefinition; if (Application.isPlaying) { EditorGUI.indentLevel++; EditorGUILayout.LabelField("Item Identifier", itemSet.ItemIdentifiers[i] == null ? "(none)" : itemSet.ItemIdentifiers[i].ToString()); EditorGUI.indentLevel--; } } else { itemSet.Slots[i] = null; if (itemDefinition != null) { Debug.LogError($"Error: Unable to add ItemDefinition {itemDefinition.name}. The ItemDefinition category doesn't match the parent category."); } } } var isDefaultIndex = m_ItemSetManager.CategoryItemSets[m_ItemSetListIndex].DefaultItemSetIndex == index; var isDefaultIndexToggle = EditorGUILayout.Toggle(new GUIContent("Default", "True if the Item Set is the default Item Set."), isDefaultIndex); if (isDefaultIndex != isDefaultIndexToggle) { m_ItemSetManager.CategoryItemSets[m_ItemSetListIndex].DefaultItemSetIndex = isDefaultIndexToggle ? index : -1; } itemSet.Enabled = EditorGUILayout.Toggle(new GUIContent("Enabled", "True if the Item Set can be equipped."), itemSet.Enabled); itemSet.CanSwitchTo = EditorGUILayout.Toggle(new GUIContent("Can Switch To", "True if the ItemSet can be switched to by the EquipNext/EquipPrevious abilities."), itemSet.CanSwitchTo); itemSet.DisabledIndex = EditorGUILayout.IntField(new GUIContent("Disabled Index", "The ItemSet that should be activated if the current ItemSet is disabled."), itemSet.DisabledIndex); if (Shared.Editor.Inspectors.Utility.InspectorUtility.Foldout(itemSet, new GUIContent("States"), false)) { // The MovementType class derives from system.object at the base level and reorderable lists can only operate on Unity objects. To get around this restriction // create a dummy array within a Unity object that corresponds to the number of elements within the ability's state list. When the reorderable list is drawn // the ability object will be used so it's like the dummy object never existed. var gameObject = new GameObject(); var stateIndexHelper = gameObject.AddComponent <StateInspectorHelper>(); stateIndexHelper.StateIndexData = new int[itemSet.States.Length]; for (int i = 0; i < stateIndexHelper.StateIndexData.Length; ++i) { stateIndexHelper.StateIndexData[i] = i; } var stateIndexSerializedObject = new SerializedObject(stateIndexHelper); m_ReorderableItemSetStateList[m_ItemSetListIndex] = StateInspector.DrawStates(m_ReorderableItemSetStateList[m_ItemSetListIndex], serializedObject, stateIndexSerializedObject.FindProperty("m_StateIndexData"), GetSelectedItemSetStateIndexKey(index), OnItemSetStateListDraw, OnItemSetStateListAdd, OnItemSetStateListReorder, OnItemSetStateListRemove); if (!m_ReorderableListCategoryMap.ContainsKey(m_ReorderableItemSetStateList[m_ItemSetListIndex])) { m_ReorderableListCategoryMap.Add(m_ReorderableItemSetStateList[m_ItemSetListIndex], m_ItemSetListIndex); } DestroyImmediate(gameObject); } }
/// <summary> /// Draws the specified attribute. /// </summary> private void DrawSelectedAttribute(int index) { EditorGUI.BeginChangeCheck(); var attributesProperty = PropertyFromName("m_Attributes"); var attributeProperty = attributesProperty.GetArrayElementAtIndex(index); if (attributeProperty == null) { return; } // The name must be unique. var name = attributeProperty.FindPropertyRelative("m_Name"); var desiredName = EditorGUILayout.TextField(new GUIContent("Name", "The name of the attribute."), name.stringValue); if (name.stringValue != desiredName && IsUniqueName(m_AttributeManager.Attributes, desiredName)) { name.stringValue = desiredName; } var minValue = attributeProperty.FindPropertyRelative("m_MinValue"); var maxValue = attributeProperty.FindPropertyRelative("m_MaxValue"); EditorGUILayout.PropertyField(minValue); if (minValue.floatValue > maxValue.floatValue) { maxValue.floatValue = minValue.floatValue; } EditorGUILayout.PropertyField(maxValue); if (maxValue.floatValue < minValue.floatValue) { minValue.floatValue = maxValue.floatValue; } var value = attributeProperty.FindPropertyRelative("m_Value"); EditorGUILayout.PropertyField(value); if (maxValue.floatValue < value.floatValue) { value.floatValue = maxValue.floatValue; } else if (minValue.floatValue > value.floatValue) { value.floatValue = minValue.floatValue; } if (value.floatValue > maxValue.floatValue) { maxValue.floatValue = value.floatValue; } else if (value.floatValue < minValue.floatValue) { minValue.floatValue = value.floatValue; } var autoUpdateValueType = attributeProperty.FindPropertyRelative("m_AutoUpdateValueType"); EditorGUILayout.PropertyField(autoUpdateValueType); if (autoUpdateValueType.intValue != (int)Attribute.AutoUpdateValue.None) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(attributeProperty.FindPropertyRelative("m_AutoUpdateStartDelay")); EditorGUILayout.PropertyField(attributeProperty.FindPropertyRelative("m_AutoUpdateInterval")); EditorGUILayout.PropertyField(attributeProperty.FindPropertyRelative("m_AutoUpdateAmount")); EditorGUI.indentLevel--; } if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); InspectorUtility.RecordUndoDirtyObject(target, "Change Value"); } var attribute = m_AttributeManager.Attributes[index]; if (InspectorUtility.Foldout(attribute, new GUIContent("States"), false)) { // The Attribute class derives from system.object at the base level and reorderable lists can only operate on Unity objects. To get around this restriction // create a dummy array within a Unity object that corresponds to the number of elements within the view type's state list. When the reorderable list is drawn // the view type object will be used so it's like the dummy object never existed. var selectedAttribute = attribute as Attribute; var gameObject = new GameObject(); var stateIndexHelper = gameObject.AddComponent <StateInspectorHelper>(); stateIndexHelper.StateIndexData = new int[selectedAttribute.States.Length]; for (int i = 0; i < stateIndexHelper.StateIndexData.Length; ++i) { stateIndexHelper.StateIndexData[i] = i; } var stateIndexSerializedObject = new SerializedObject(stateIndexHelper); m_ReorderableAttributeStateList = StateInspector.DrawStates(m_ReorderableAttributeStateList, serializedObject, stateIndexSerializedObject.FindProperty("m_StateIndexData"), GetSelectedAttributeStateIndexKey(selectedAttribute), OnAttributeStateListDraw, OnAttributeStateListAdd, OnAttributeStateListReorder, OnAttributeStateListRemove); DestroyImmediate(gameObject); } }