Esempio n. 1
0
        /// <summary>
        /// Draws the fields related to the inspector drawer.
        /// </summary>
        /// <param name="target">The object that is being drawn.</param>
        /// <param name="parent">The Unity Object that the object belongs to.</param>
        protected override void DrawInspectorDrawerFields(object target, Object parent)
        {
            m_Jump = target as Jump;

            InspectorUtility.DrawField(target, "m_MinCeilingJumpHeight");
            InspectorUtility.DrawField(target, "m_GroundedGracePeriod");
            InspectorUtility.DrawField(target, "m_Force");
            InspectorUtility.DrawField(target, "m_SidewaysForceMultiplier");
            InspectorUtility.DrawField(target, "m_BackwardsForceMultiplier");
            InspectorUtility.DrawField(target, "m_Frames");
            InspectorUtility.DrawField(target, "m_JumpEvent");
            InspectorUtility.DrawField(target, "m_JumpSurfaceImpact");
            InspectorUtility.DrawField(target, "m_ForceHold");
            InspectorUtility.DrawField(target, "m_ForceDampingHold");
            InspectorUtility.DrawField(target, "m_MaxRepeatedJumpCount");
            if (m_Jump.MaxRepeatedJumpCount > 0)
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_RepeatedJumpForce");
                InspectorUtility.DrawField(target, "m_RepeatedJumpFrames");
                if (InspectorUtility.Foldout(target, "Repeated Jump Audio"))
                {
                    EditorGUI.indentLevel++;
                    m_ReorderableRepeatedJumpAudioClipsList = AudioClipSetInspector.DrawAudioClipSet(m_Jump.RepeatedJumpAudioClipSet, null, m_ReorderableRepeatedJumpAudioClipsList, OnRepeatedJumpAudioClipDraw, OnRepeatedJumpAudioClipListAdd, OnRepeatedJumpAudioClipListRemove);
                    EditorGUI.indentLevel--;
                }
                EditorGUI.indentLevel--;
            }
            InspectorUtility.DrawField(target, "m_VerticalVelocityStopThreshold");
            InspectorUtility.DrawField(target, "m_RecurrenceDelay");
        }
        /// <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 (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);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Called when the object should be drawn to the inspector.
        /// </summary>
        /// <param name="target">The object that is being drawn.</param>
        /// <param name="parent">The Unity Object that the object belongs to.</param>
        public override void OnInspectorGUI(object target, Object parent)
        {
            base.OnInspectorGUI(target, parent);

            if (InspectorUtility.Foldout(target, "RPG"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_YawSnapDamping");
                InspectorUtility.DrawField(target, "m_AllowFreeMovement");
                InspectorUtility.DrawField(target, "m_CameraFreeMovementInputName");
                EditorGUI.indentLevel--;
            }
        }
        /// <summary>
        /// Draws the specified item set.
        /// </summary>
        private void DrawSelectedPickupSet(ItemPickupBase.PickupSet pickupSet, int index)
        {
            GUILayout.Label("Pickup Set " + index, 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 (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();
                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);
                DestroyImmediate(gameObject);
            }
        }
        /// <summary>
        /// Called when the object should be drawn to the inspector.
        /// </summary>
        /// <param name="target">The object that is being drawn.</param>
        /// <param name="parent">The Unity Object that the object belongs to.</param>
        public override void OnInspectorGUI(object target, Object parent)
        {
            InspectorUtility.DrawField(target, "m_LookDirectionDistance");
            InspectorUtility.DrawField(target, "m_ForwardAxis");
            InspectorUtility.DrawField(target, "m_LookOffset");
            InspectorUtility.DrawField(target, "m_LookOffsetSmoothing");
            InspectorUtility.DrawField(target, "m_PositionSmoothing");
            InspectorUtility.DrawField(target, "m_ObstructionPositionSmoothing");
            InspectorUtility.DrawFieldSlider(target, "m_AlignToGroundRotationSpeed", 0, 1);
            InspectorUtility.DrawFieldSlider(target, "m_FieldOfView", 1, 179);
            InspectorUtility.DrawFieldSlider(target, "m_FieldOfViewDamping", 0, 5);
            InspectorUtility.DrawField(target, "m_CollisionRadius");
            InspectorUtility.DrawField(target, "m_CollisionAnchorOffset");
            if (InspectorUtility.Foldout(target, "Primary Spring"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawSpring(target, "Position Spring", "m_PositionSpring");
                InspectorUtility.DrawSpring(target, "Rotation Spring", "m_RotationSpring");
                EditorGUI.indentLevel--;
            }

            if (InspectorUtility.Foldout(target, "Secondary Spring"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawSpring(target, "Position Spring", "m_SecondaryPositionSpring");
                InspectorUtility.DrawSpring(target, "Rotation Spring", "m_SecondaryRotationSpring");
                EditorGUI.indentLevel--;
            }

            if (InspectorUtility.Foldout(target, "Step Zoom"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_StepZoomInputName");
                InspectorUtility.DrawField(target, "m_StepZoomSensitivity");
                InspectorUtility.DrawField(target, "m_MinStepZoom");
                InspectorUtility.DrawField(target, "m_MaxStepZoom");
                EditorGUI.indentLevel--;
            }

            if (InspectorUtility.Foldout(target, "Limits"))
            {
                EditorGUI.indentLevel++;
                OnDrawLimits(target);
                EditorGUI.indentLevel--;
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Called when the object should be drawn to the inspector.
        /// </summary>
        /// <param name="target">The object that is being drawn.</param>
        /// <param name="parent">The Unity Object that the object belongs to.</param>
        public override void OnInspectorGUI(object target, Object parent)
        {
            base.OnInspectorGUI(target, parent);

            if (!InspectorUtility.GetFieldValue <bool>(target, "m_RestrictPitch") && InspectorUtility.Foldout(target, "Limits"))
            {
                EditorGUI.indentLevel++;
                var minPitchLimit = InspectorUtility.GetFieldValue <float>(target, "m_MinPitchLimit");
                var maxPitchLimit = InspectorUtility.GetFieldValue <float>(target, "m_MaxPitchLimit");
                var minValue      = Mathf.Round(minPitchLimit * 100f) / 100f;
                var maxValue      = Mathf.Round(maxPitchLimit * 100f) / 100f;
                InspectorUtility.MinMaxSlider(ref minValue, ref maxValue, -90, 90, new GUIContent("Pitch Limit", "The min and max limit of the pitch angle (in degrees)."));
                if (minValue != minPitchLimit)
                {
                    InspectorUtility.SetFieldValue(target, "m_MinPitchLimit", minValue);
                }
                if (minValue != maxPitchLimit)
                {
                    InspectorUtility.SetFieldValue(target, "m_MaxPitchLimit", maxValue);
                }
                EditorGUI.indentLevel--;
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Returns the actions to draw before the State list is drawn.
        /// </summary>
        /// <returns>The actions to draw before the State list is drawn.</returns>
        protected override Action GetDrawCallback()
        {
            var baseCallback = base.GetDrawCallback();

            baseCallback += () =>
            {
                EditorGUILayout.PropertyField(PropertyFromName("m_Invincible"));
                EditorGUILayout.PropertyField(PropertyFromName("m_TimeInvincibleAfterSpawn"));

                // The names will be retrieved by the Attribute Manager.
                var attributeNames = new string[m_AttributeManager.Attributes.Length + 1];
                attributeNames[0] = "(None)";
                var healthNameIndex = 0;
                var shieldNameIndex = 0;
                for (int i = 0; i < m_AttributeManager.Attributes.Length; ++i)
                {
                    attributeNames[i + 1] = m_AttributeManager.Attributes[i].Name;
                    if (m_Health.HealthAttributeName == attributeNames[i + 1])
                    {
                        healthNameIndex = i + 1;
                    }
                    if (m_Health.ShieldAttributeName == attributeNames[i + 1])
                    {
                        shieldNameIndex = i + 1;
                    }
                }

                var selectedHealthNameIndex = EditorGUILayout.Popup("Health Attribute", healthNameIndex, attributeNames);
                if (healthNameIndex != selectedHealthNameIndex)
                {
                    m_Health.HealthAttributeName = (selectedHealthNameIndex == 0 ? string.Empty : m_AttributeManager.Attributes[selectedHealthNameIndex - 1].Name);
                    InspectorUtility.SetDirty(target);
                }
                // Show the current health value.
                if (Application.isPlaying && !string.IsNullOrEmpty(m_Health.HealthAttributeName) && selectedHealthNameIndex > 0 && selectedHealthNameIndex - 1 < m_AttributeManager.Attributes.Length)
                {
                    EditorGUI.indentLevel++;
                    GUI.enabled = false;
                    EditorGUILayout.TextField("Value", m_AttributeManager.Attributes[selectedHealthNameIndex - 1].Value.ToString());
                    GUI.enabled = true;
                    EditorGUI.indentLevel--;
                }

                var selectedShieldNameIndex = EditorGUILayout.Popup("Shield Attribute", shieldNameIndex, attributeNames);
                if (shieldNameIndex != selectedShieldNameIndex)
                {
                    m_Health.ShieldAttributeName = (selectedShieldNameIndex == 0 ? string.Empty : m_AttributeManager.Attributes[selectedShieldNameIndex - 1].Name);
                    InspectorUtility.SetDirty(target);
                }
                // Show the current shield value.
                if (Application.isPlaying && !string.IsNullOrEmpty(m_Health.ShieldAttributeName) && selectedShieldNameIndex > 0 && selectedShieldNameIndex - 1 < m_AttributeManager.Attributes.Length)
                {
                    EditorGUI.indentLevel++;
                    GUI.enabled = false;
                    EditorGUILayout.TextField("Value", m_AttributeManager.Attributes[selectedShieldNameIndex - 1].Value.ToString());
                    GUI.enabled = true;
                    EditorGUI.indentLevel--;
                }

                if (Foldout("Hitboxes"))
                {
                    EditorGUI.indentLevel++;
                    HitboxInspector.DrawHitbox(ref m_ReorderableHitboxList, serializedObject, PropertyFromName("m_Hitboxes"), OnHitboxElementDraw);
                    EditorGUILayout.PropertyField(PropertyFromName("m_MaxHitboxCollisionCount"));
                    EditorGUI.indentLevel--;
                }

                var healthCallback = GetHealthDrawCallback();
                if (healthCallback != null)
                {
                    healthCallback();
                }

                if (Foldout("Audio"))
                {
                    EditorGUI.indentLevel++;
                    if (InspectorUtility.Foldout(target, "Take Damage"))
                    {
                        EditorGUI.indentLevel++;
                        AudioClipSetInspector.DrawAudioClipSet(m_Health.TakeDamageAudioClipSet, PropertyFromName("m_TakeDamageAudioClipSet"), ref m_ReorderableTakeDamageAudioClipsList, OnTakeDamageAudioClipDraw, OnTakeDamageAudioClipListAdd, OnTakeDamageAudioClipListRemove);
                        EditorGUI.indentLevel--;
                    }
                    if (InspectorUtility.Foldout(target, "Heal"))
                    {
                        EditorGUI.indentLevel++;
                        AudioClipSetInspector.DrawAudioClipSet(m_Health.HealAudioClipSet, PropertyFromName("m_HealAudioClipSet"), ref m_ReorderableHealAudioClipsList, OnHealAudioClipDraw, OnHealAudioClipListAdd, OnHealAudioClipListRemove);
                        EditorGUI.indentLevel--;
                    }
                    if (InspectorUtility.Foldout(target, "Death"))
                    {
                        EditorGUI.indentLevel++;
                        AudioClipSetInspector.DrawAudioClipSet(m_Health.DeathAudioClipSet, PropertyFromName("m_DeathAudioClipSet"), ref m_ReorderableDeathAudioClipsList, OnDeathAudioClipDraw, OnDeathAudioClipListAdd, OnDeathAudioClipListRemove);
                        EditorGUI.indentLevel--;
                    }
                    EditorGUI.indentLevel--;
                }

                if (Foldout("Death"))
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(PropertyFromName("m_SpawnedObjectsOnDeath"), true);
                    EditorGUILayout.PropertyField(PropertyFromName("m_DestroyedObjectsOnDeath"), true);
                    var deactivateOnDeath = PropertyFromName("m_DeactivateOnDeath");
                    EditorGUILayout.PropertyField(deactivateOnDeath);
                    if (deactivateOnDeath.boolValue)
                    {
                        EditorGUI.indentLevel++;
                        EditorGUILayout.PropertyField(PropertyFromName("m_DeactivateOnDeathDelay"));
                        EditorGUI.indentLevel--;
                    }
                    var deathLayerProperty = PropertyFromName("m_DeathLayer");
                    deathLayerProperty.intValue = EditorGUILayout.LayerField("Death Layer", deathLayerProperty.intValue);
                    EditorGUI.indentLevel--;
                }

                if (Foldout("Events"))
                {
                    EditorGUI.indentLevel++;
                    InspectorUtility.UnityEventPropertyField(PropertyFromName("m_OnDamageEvent"));
                    InspectorUtility.UnityEventPropertyField(PropertyFromName("m_OnHealEvent"));
                    InspectorUtility.UnityEventPropertyField(PropertyFromName("m_OnDeathEvent"));
                    EditorGUI.indentLevel--;
                }
            };

            return(baseCallback);
        }
Esempio n. 8
0
        /// <summary>
        /// Called when the object should be drawn to the inspector.
        /// </summary>
        /// <param name="target">The object that is being drawn.</param>
        /// <param name="parent">The Unity Object that the object belongs to.</param>
        public override void OnInspectorGUI(object target, Object parent)
        {
            m_Ability = (target as Ability);

            DrawInputFieldsFields(target, parent);

            InspectorUtility.DrawAttributeModifier((parent as Component).GetComponent <AttributeManager>(), (target as Ability).AttributeModifier, "Attribute Name");

            EditorGUILayout.BeginHorizontal();
            InspectorUtility.DrawField(target, "m_State");
            GUI.enabled = !string.IsNullOrEmpty(InspectorUtility.GetFieldValue <string>(target, "m_State"));
            // The InspectorUtility doesn't support a toggle with the text on the right.
            var field = InspectorUtility.GetField(target, "m_StateAppendItemIdentifierName");

            GUILayout.Space(-5);
            var value = EditorGUILayout.ToggleLeft(new GUIContent("Append Item", InspectorUtility.GetFieldTooltip(field)), (bool)field.GetValue(target), GUILayout.Width(110));

            InspectorUtility.SetFieldValue(target, "m_StateAppendItemIdentifierName", value);
            GUI.enabled = true;
            EditorGUILayout.EndHorizontal();
            InspectorUtility.DrawField(target, "m_AbilityIndexParameter");

            DrawInspectorDrawerFields(target, parent);

            if (InspectorUtility.Foldout(target, "Audio"))
            {
                EditorGUI.indentLevel++;
                if (InspectorUtility.Foldout(target, "Start"))
                {
                    EditorGUI.indentLevel++;
                    m_ReorderableStartAudioClipsList = AudioClipSetInspector.DrawAudioClipSet(m_Ability.StartAudioClipSet, null, m_ReorderableStartAudioClipsList, OnStartAudioClipDraw, OnStartAudioClipListAdd, OnStartAudioClipListRemove);
                    EditorGUI.indentLevel--;
                }
                DrawAudioFields();
                if (InspectorUtility.Foldout(target, "Stop"))
                {
                    EditorGUI.indentLevel++;
                    m_ReorderableStopAudioClipsList = AudioClipSetInspector.DrawAudioClipSet(m_Ability.StopAudioClipSet, null, m_ReorderableStopAudioClipsList, OnStopAudioClipDraw, OnStopAudioClipListAdd, OnStopAudioClipListRemove);
                    EditorGUI.indentLevel--;
                }
                EditorGUI.indentLevel--;
            }

            var startEffectValue    = InspectorUtility.GetFieldValue <string>(target, "m_StartEffectName");
            var newStartEffectValue = InspectorUtility.DrawTypePopup(typeof(UltimateCharacterController.Character.Effects.Effect), startEffectValue, "Start Effect", true);

            if (startEffectValue != newStartEffectValue)
            {
                InspectorUtility.SetFieldValue(target, "m_StartEffectName", newStartEffectValue);
                InspectorUtility.SetDirty(parent);
            }

            if (!string.IsNullOrEmpty(newStartEffectValue))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_StartEffectIndex");
                EditorGUI.indentLevel--;
            }

            if (InspectorUtility.Foldout(target, "General"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_InspectorDescription");
                GUI.enabled = !(target is MoveTowards);
                InspectorUtility.DrawField(target, "m_AllowPositionalInput");
                InspectorUtility.DrawField(target, "m_AllowRotationalInput");
                GUI.enabled = true;
                InspectorUtility.DrawField(target, "m_UseGravity");
                InspectorUtility.DrawField(target, "m_UseRootMotionPosition");
                InspectorUtility.DrawField(target, "m_UseRootMotionRotation");
                InspectorUtility.DrawField(target, "m_DetectHorizontalCollisions");
                InspectorUtility.DrawField(target, "m_DetectVerticalCollisions");
                InspectorUtility.DrawField(target, "m_AnimatorMotion");
                var itemAbilityMoveTowards = (target is MoveTowards) || (target is UltimateCharacterController.Character.Abilities.Items.ItemAbility);
                GUI.enabled = !itemAbilityMoveTowards;
                var inventory = (parent as Component).GetComponent <UltimateCharacterController.Inventory.InventoryBase>();
                if (inventory != null && (parent as Component).GetComponent <UltimateCharacterController.Inventory.ItemSetManagerBase>() != null)
                {
                    var slotCount = inventory.SlotCount;
                    if (InspectorUtility.Foldout(target, "Allow Equipped Items"))
                    {
                        EditorGUI.indentLevel++;
                        var mask    = InspectorUtility.GetFieldValue <int>(target, "m_AllowEquippedSlotsMask");
                        var newMask = 0;
                        for (int i = 0; i < slotCount; ++i)
                        {
                            var enabled = (mask & (1 << i)) == (1 << i);
                            if (EditorGUILayout.Toggle("Slot " + i, enabled))
                            {
                                newMask |= 1 << i;
                            }
                        }
                        // If all of the slots are enabled then use -1.
                        if (newMask == (1 << slotCount) - 1 || itemAbilityMoveTowards)
                        {
                            newMask = -1;
                        }
                        if (mask != newMask)
                        {
                            InspectorUtility.SetFieldValue(target, "m_AllowEquippedSlotsMask", newMask);
                        }
                        InspectorUtility.DrawField(target, "m_AllowItemDefinitions");
                        InspectorUtility.DrawField(target, "m_ImmediateUnequip");
                        InspectorUtility.DrawField(target, "m_ReequipSlots");
                        if (itemAbilityMoveTowards && InspectorUtility.GetFieldValue <bool>(target, "m_ReequipSlots"))
                        {
                            InspectorUtility.SetFieldValue(target, "m_ReequipSlots", false);
                            GUI.changed = true;
                        }
                        EditorGUI.indentLevel--;
                    }
                }
                GUI.enabled = true;
                EditorGUI.indentLevel--;
            }

            if (InspectorUtility.Foldout(target, "UI"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_AbilityMessageText");
                InspectorUtility.DrawField(target, "m_AbilityMessageIcon");
                EditorGUI.indentLevel--;
            }
        }
Esempio n. 9
0
        /// <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);
        }
Esempio n. 10
0
        /// <summary>
        /// Returns the actions to draw before the State list is drawn.
        /// </summary>
        /// <returns>The actions to draw before the State list is drawn.</returns>
        protected override Action GetDrawCallback()
        {
            var baseCallback = base.GetDrawCallback();

            baseCallback += () =>
            {
                if (Foldout("Firing"))
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(PropertyFromName("m_ConsumableItemType"));
                    var fireMode = PropertyFromName("m_FireMode");
                    EditorGUILayout.PropertyField(fireMode);
                    if (fireMode.enumValueIndex == (int)ShootableWeapon.FireMode.Burst)
                    {
                        EditorGUI.indentLevel++;
                        EditorGUILayout.PropertyField(PropertyFromName("m_BurstCount"));
                        EditorGUILayout.PropertyField(PropertyFromName("m_BurstDelay"));
                        EditorGUI.indentLevel--;
                    }
                    var fireType = PropertyFromName("m_FireType");
                    EditorGUILayout.PropertyField(fireType);
                    if (fireType.enumValueIndex != (int)ShootableWeapon.FireType.Instant)
                    {
                        EditorGUI.indentLevel++;
                        EditorGUILayout.PropertyField(PropertyFromName("m_MinChargeLength"));
                        EditorGUILayout.PropertyField(PropertyFromName("m_FullChargeLength"));
                        EditorGUILayout.PropertyField(PropertyFromName("m_ChargeItemSubstateParameterValue"));
                        EditorGUILayout.PropertyField(PropertyFromName("m_MinChargeStrength"));
                        if (Foldout("Charge Audio"))
                        {
                            EditorGUI.indentLevel++;
                            AudioClipSetInspector.DrawAudioClipSet(m_ShootableWeapon.ChargeAudioClipSet, PropertyFromName("m_ChargeAudioClipSet"), ref m_ReorderableChargeAudioClipsList, OnChargeAudioClipDraw, OnChargeAudioClipListAdd, OnChargeAudioClipListRemove);
                            EditorGUI.indentLevel--;
                        }
                        EditorGUI.indentLevel--;
                    }
                    EditorGUILayout.PropertyField(PropertyFromName("m_FireCount"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_Spread"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_FireInLookSourceDirection"));
                    EditorGUILayout.HelpBox("If a projectile prefab is specified then this projectile will be fired from the weapon. If no projectile is specified then a hitscan will be used.", MessageType.Info);
                    var projectile = PropertyFromName("m_Projectile");
                    EditorGUILayout.PropertyField(projectile);
                    if (projectile.objectReferenceValue == null)
                    {
                        EditorGUILayout.PropertyField(PropertyFromName("m_HitscanFireRange"));
                        EditorGUILayout.PropertyField(PropertyFromName("m_MaxHitscanCollisionCount"));
                        InspectorUtility.UnityEventPropertyField(PropertyFromName("m_OnHitscanImpactEvent"));
                    }
                    else
                    {
                        if ((projectile.objectReferenceValue as GameObject).GetComponent <UltimateCharacterController.Objects.Projectile>() == null)
                        {
                            EditorGUILayout.HelpBox("The projectile must have the Projectile component attached to it.", MessageType.Error);
                        }
                        EditorGUI.indentLevel++;
                        EditorGUILayout.PropertyField(PropertyFromName("m_ProjectileFireVelocityMagnitude"));
                        EditorGUILayout.PropertyField(PropertyFromName("m_ProjectileVisibility"));
                        var shootableWeapon = target as ShootableWeapon;
                        shootableWeapon.ProjectileStartLayer = EditorGUILayout.LayerField(new GUIContent("Projectile Start Layer",
                                                                                                         "The layer that the projectile should occupy when initially spawned."), shootableWeapon.ProjectileStartLayer);
                        shootableWeapon.ProjectileFiredLayer = EditorGUILayout.LayerField(new GUIContent("Projectile Fired Layer",
                                                                                                         "The layer that the projectile object should change to after being fired."), shootableWeapon.ProjectileFiredLayer);
                        EditorGUILayout.PropertyField(PropertyFromName("m_LayerChangeDelay"));
                        EditorGUILayout.PropertyField(PropertyFromName("m_ProjectileEnableDelayAfterOtherUse"));
                        EditorGUI.indentLevel--;
                    }
                    EditorGUILayout.PropertyField(PropertyFromName("m_DryFireItemSubstateParameterValue"));
                    if (InspectorUtility.Foldout(target, "Dry Fire Audio"))
                    {
                        EditorGUI.indentLevel++;
                        AudioClipSetInspector.DrawAudioClipSet(m_ShootableWeapon.DryFireAudioClipSet, PropertyFromName("m_DryFireAudioClipSet"), ref m_ReorderableDryFireAudioClipsList, OnDryFireAudioClipDraw, OnDryFireAudioClipListAdd, OnDryFireAudioClipListRemove);
                        EditorGUI.indentLevel--;
                    }
                    EditorGUI.indentLevel--;
                }

                if (Foldout("Impact"))
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(PropertyFromName("m_ImpactLayers"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_DamageAmount"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_ImpactForce"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_ImpactForceFrames"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_ImpactStateName"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_ImpactStateDisableTimer"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_SurfaceImpact"));
                    EditorGUI.indentLevel--;
                }

                if (Foldout("Reload"))
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(PropertyFromName("m_ClipSize"));
                    var autoReloadProperty = PropertyFromName("m_AutoReload");
                    var autoReloadString   = Enum.GetNames(typeof(UltimateCharacterController.Character.Abilities.Items.Reload.AutoReloadType));
                    autoReloadProperty.intValue = EditorGUILayout.MaskField(new GUIContent("Auto Reload", autoReloadProperty.tooltip), (int)autoReloadProperty.intValue, autoReloadString);
                    EditorGUILayout.PropertyField(PropertyFromName("m_ReloadType"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_ReloadCanCameraZoom"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_ReloadCrosshairsSpread"));
                    InspectorUtility.DrawAnimationEventTrigger(target, "Reload Event", PropertyFromName("m_ReloadEvent"));
                    InspectorUtility.DrawAnimationEventTrigger(target, "Reload Complete Event", PropertyFromName("m_ReloadCompleteEvent"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_ReloadDetachAttachClip"));
                    InspectorUtility.DrawAnimationEventTrigger(target, "Reload Detach Clip Event", PropertyFromName("m_ReloadDetachClipEvent"));
                    InspectorUtility.DrawAnimationEventTrigger(target, "Reload Show Projectile Event", PropertyFromName("m_ReloadShowProjectileEvent"));
                    InspectorUtility.DrawAnimationEventTrigger(target, "Reload Attach Projectile Event", PropertyFromName("m_ReloadAttachProjectileEvent"));
                    var reloadClipProperty = PropertyFromName("m_ReloadDropClip");
                    EditorGUILayout.PropertyField(reloadClipProperty);
                    if (reloadClipProperty.objectReferenceValue != null)
                    {
                        EditorGUI.indentLevel++;
                        var shootableWeapon = target as ShootableWeapon;
                        shootableWeapon.ReloadClipTargetLayer = EditorGUILayout.LayerField(new GUIContent("Reload Clip Target Layer",
                                                                                                          "The layer that the clip object should change to after being reloaded."), shootableWeapon.ReloadClipTargetLayer);
                        EditorGUILayout.PropertyField(PropertyFromName("m_ReloadClipLayerChangeDelay"));
                        InspectorUtility.DrawAnimationEventTrigger(target, "Reload Drop Clip Event", PropertyFromName("m_ReloadDropClipEvent"));
                        EditorGUI.indentLevel--;
                    }
                    InspectorUtility.DrawAnimationEventTrigger(target, "Reload Attach Clip Event", PropertyFromName("m_ReloadAttachClipEvent"));
                    if (Foldout("Animator Audio"))
                    {
                        EditorGUI.indentLevel++;
                        AnimatorAudioStateSetInspector.DrawAnimatorAudioStateSet(m_ShootableWeapon, m_ShootableWeapon.ReloadAnimatorAudioStateSet, "m_ReloadAnimatorAudioStateSet", true,
                                                                                 ref m_ReorderableReloadAnimatorAudioStateSetList, OnAnimatorAudioStateListDraw, OnAnimatorAudioStateListSelect,
                                                                                 OnAnimatorAudioStateListAdd, OnAnimatorAudioStateListRemove, SelectedReloadAnimatorAudioStateSetIndexKey,
                                                                                 ref m_ReorderableReloadAnimatorAudioStateSetAudioList, OnReloadAudioListElementDraw, OnReloadAudioListAdd, OnReloadAudioListRemove,
                                                                                 ref m_ReorderableReloadAnimatorAudioStateSetStateList,
                                                                                 OnAnimatorAudioStateSetStateListDraw, OnAnimatorAudioStateSetStateListAdd, OnAnimatorAudioStateSetStateListReorder, OnAnimatorAudioStateSetStateListRemove,
                                                                                 GetSelectedAnimatorAudioStateSetStateIndexKey(EditorPrefs.GetInt(SelectedReloadAnimatorAudioStateSetIndexKey)));
                        EditorGUI.indentLevel--;
                    }
                    if (InspectorUtility.Foldout(target, "Reload Complete Audio"))
                    {
                        EditorGUI.indentLevel++;
                        AudioClipSetInspector.DrawAudioClipSet(m_ShootableWeapon.ReloadCompleteAudioClipSet, PropertyFromName("m_ReloadCompleteAudioClipSet"), ref m_ReorderableReloadCompleteAudioClipsList, OnReloadCompleteAudioClipDraw, OnReloadCompleteAudioClipListAdd, OnReloadCompleteAudioClipListRemove);
                        EditorGUI.indentLevel--;
                    }
                }
                if (Foldout("Recoil"))
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(PropertyFromName("m_PositionRecoil"), true);
                    EditorGUILayout.PropertyField(PropertyFromName("m_RotationRecoil"), true);
                    EditorGUILayout.PropertyField(PropertyFromName("m_PositionCameraRecoil"), true);
                    EditorGUILayout.PropertyField(PropertyFromName("m_RotationCameraRecoil"), true);
                    EditorGUILayout.PropertyField(PropertyFromName("m_CameraRecoilAccumulation"));
                    EditorGUILayout.PropertyField(PropertyFromName("m_LocalizeRecoilForce"));
                    EditorGUI.indentLevel--;
                }
                if (Foldout("Muzzle Flash"))
                {
                    EditorGUI.indentLevel++;
                    var muzzleFlash = PropertyFromName("m_MuzzleFlash");
                    EditorGUILayout.PropertyField(muzzleFlash);
                    if (muzzleFlash.objectReferenceValue != null)
                    {
                        EditorGUILayout.PropertyField(PropertyFromName("m_PoolMuzzleFlash"));
                    }
                    EditorGUI.indentLevel--;
                }
                if (Foldout("Shell"))
                {
                    EditorGUI.indentLevel++;
                    var shell = PropertyFromName("m_Shell");
                    EditorGUILayout.PropertyField(shell);
                    if (shell.objectReferenceValue != null)
                    {
                        EditorGUILayout.PropertyField(PropertyFromName("m_ShellVelocity"), true);
                        EditorGUILayout.PropertyField(PropertyFromName("m_ShellTorque"), true);
                        EditorGUILayout.PropertyField(PropertyFromName("m_ShellEjectDelay"));
                    }
                    EditorGUI.indentLevel--;
                }
                if (Foldout("Smoke"))
                {
                    EditorGUI.indentLevel++;
                    var smoke = PropertyFromName("m_Smoke");
                    EditorGUILayout.PropertyField(smoke);
                    if (smoke.objectReferenceValue != null)
                    {
                        EditorGUILayout.PropertyField(PropertyFromName("m_SmokeSpawnDelay"));
                    }
                    EditorGUI.indentLevel--;
                }
                if (Foldout("Tracer"))
                {
                    EditorGUI.indentLevel++;
                    if (PropertyFromName("m_Projectile").objectReferenceValue == null)
                    {
                        var tracer = PropertyFromName("m_Tracer");
                        EditorGUILayout.PropertyField(tracer);
                        if (tracer.objectReferenceValue != null)
                        {
                            EditorGUILayout.PropertyField(PropertyFromName("m_TracerDefaultLength"));
                            EditorGUILayout.PropertyField(PropertyFromName("m_TracerSpawnDelay"));
                        }
                    }
                    else
                    {
                        EditorGUILayout.HelpBox("A tracer can only be applied to hitscan weapons.", MessageType.Info);
                    }
                    EditorGUI.indentLevel--;
                }
                if (Foldout("Attachments"))
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(PropertyFromName("m_DisableScopeCameraOnNoAim"));
                    EditorGUI.indentLevel--;
                }
            };

            return(baseCallback);
        }
        /// <summary>
        /// Called when the object should be drawn to the inspector.
        /// </summary>
        /// <param name="target">The object that is being drawn.</param>
        /// <param name="parent">The Unity Object that the object belongs to.</param>
        public override void OnInspectorGUI(object target, Object parent)
        {
            // Draw the fields related to rendering.
            if (InspectorUtility.Foldout(target, "Rendering"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_LookDirectionDistance");
                var lookOffsetValue = InspectorUtility.GetFieldValue <Vector3>(target, "m_LookOffset");
                var lookOffset      = EditorGUILayout.Vector3Field(new GUIContent(InspectorUtility.SplitCamelCase("m_LookOffset"), InspectorUtility.GetFieldTooltip(target, "m_LookOffset")), lookOffsetValue);
                // Set the property if the game is playing so the camera will update.
                if (lookOffsetValue != lookOffset)
                {
                    (target as FirstPerson).LookOffset = lookOffset;
                    InspectorUtility.SetFieldValue(target, "m_LookOffset", lookOffset);
                }
                InspectorUtility.DrawField(target, "m_LookDownOffset");
                InspectorUtility.DrawField(target, "m_CullingMask");
                InspectorUtility.DrawFieldSlider(target, "m_FieldOfView", 1, 179);
                InspectorUtility.DrawFieldSlider(target, "m_FieldOfViewDamping", 0, 5);
#if ULTIMATE_CHARACTER_CONTROLLER_LWRP || ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP
                var prevRenderType = InspectorUtility.GetFieldValue <FirstPerson.ObjectOverlayRenderType>(target, "m_OverlayRenderType");
                InspectorUtility.DrawField(target, "m_OverlayRenderType");
                var renderType = InspectorUtility.GetFieldValue <FirstPerson.ObjectOverlayRenderType>(target, "m_OverlayRenderType");
                // Ensure the render type has been switched for all first person view types.
                if (prevRenderType != renderType)
                {
                    if (renderType == FirstPerson.ObjectOverlayRenderType.SecondCamera)
                    {
                        UltimateCharacterController.Utility.Builders.ViewTypeBuilder.AddFirstPersonCamera(parent as CameraController, target as FirstPerson);
                    }
                    else if (prevRenderType == FirstPerson.ObjectOverlayRenderType.SecondCamera)
                    {
                        var firstPersonCamera = InspectorUtility.GetFieldValue <UnityEngine.Camera>(target, "m_FirstPersonCamera");
                        if (firstPersonCamera != null)
                        {
                            if (PrefabUtility.IsPartOfPrefabInstance(firstPersonCamera.gameObject))
                            {
                                PrefabUtility.UnpackPrefabInstance(PrefabUtility.GetOutermostPrefabInstanceRoot(firstPersonCamera.gameObject), PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
                            }
                            GameObject.DestroyImmediate(firstPersonCamera.gameObject, true);
                            (target as FirstPerson).FirstPersonCamera = null;
                        }
                    }
                    // All first person view types need to be switched to the currently active render type.
                    var viewTypes = (parent as CameraController).ViewTypes;
                    for (int i = 0; i < viewTypes.Length; ++i)
                    {
                        var firstPersonViewType = viewTypes[i] as FirstPerson;
                        if (firstPersonViewType == null)
                        {
                            continue;
                        }

                        if (renderType == FirstPerson.ObjectOverlayRenderType.RenderPipeline && firstPersonViewType.OverlayRenderType == FirstPerson.ObjectOverlayRenderType.SecondCamera)
                        {
                            firstPersonViewType.FirstPersonCamera = null;
                            firstPersonViewType.OverlayRenderType = renderType;
                        }
                        else if (renderType == FirstPerson.ObjectOverlayRenderType.SecondCamera && firstPersonViewType.OverlayRenderType == FirstPerson.ObjectOverlayRenderType.RenderPipeline)
                        {
                            firstPersonViewType.FirstPersonCamera = (target as FirstPerson).FirstPersonCamera;
                            firstPersonViewType.OverlayRenderType = renderType;
                        }
                    }
                    UltimateCharacterController.Utility.Builders.ViewTypeBuilder.SerializeViewTypes(parent as CameraController);
                }
                var drawFirstPersonCamera = renderType == FirstPerson.ObjectOverlayRenderType.SecondCamera;
#else
                InspectorUtility.DrawField(target, "m_UseFirstPersonCamera");
                var drawFirstPersonCamera = InspectorUtility.GetFieldValue <bool>(target, "m_UseFirstPersonCamera");
#endif
                if (drawFirstPersonCamera && InspectorUtility.Foldout(target, "First Person Camera"))
                {
                    EditorGUI.indentLevel++;
                    InspectorUtility.DrawField(target, "m_FirstPersonCamera");
                    InspectorUtility.DrawField(target, "m_FirstPersonCullingMask");
                    InspectorUtility.DrawField(target, "m_SynchronizeFieldOfView");
                    var synchronizeFieldOfView = InspectorUtility.GetFieldValue <bool>(target, "m_SynchronizeFieldOfView");
                    if (!synchronizeFieldOfView)
                    {
                        InspectorUtility.DrawFieldSlider(target, "m_FirstPersonFieldOfView", 1, 179);
                        InspectorUtility.DrawFieldSlider(target, "m_FirstPersonFieldOfViewDamping", 0, 5);
                    }
                    var positionOffsetValue = InspectorUtility.GetFieldValue <Vector3>(target, "m_FirstPersonPositionOffset");
                    var positionOffset      = EditorGUILayout.Vector3Field(new GUIContent(InspectorUtility.SplitCamelCase("m_FirstPersonPositionOffset"), InspectorUtility.GetFieldTooltip(target, "m_FirstPersonPositionOffset")), positionOffsetValue);
                    // Set the property if the game is playing so the camera will update.
                    if (positionOffsetValue != positionOffset)
                    {
                        (target as FirstPerson).FirstPersonPositionOffset = positionOffset;
                        InspectorUtility.SetFieldValue(target, "m_FirstPersonPositionOffset", positionOffset);
                    }
                    var rotationOffsetValue = InspectorUtility.GetFieldValue <Vector3>(target, "m_FirstPersonRotationOffset");
                    var rotationOffset      = EditorGUILayout.Vector3Field(new GUIContent(InspectorUtility.SplitCamelCase("m_FirstPersonRotationOffset"), InspectorUtility.GetFieldTooltip(target, "m_FirstPersonRotationOffset")), rotationOffsetValue);
                    // Set the property so the camera will update.
                    if (rotationOffsetValue != rotationOffset)
                    {
                        (target as FirstPerson).FirstPersonRotationOffset = rotationOffset;
                        InspectorUtility.SetFieldValue(target, "m_FirstPersonRotationOffset", rotationOffset);
                    }
                    EditorGUI.indentLevel--;
                }
#if ULTIMATE_CHARACTER_CONTROLLER_LWRP || ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP
                else if (renderType == FirstPerson.ObjectOverlayRenderType.RenderPipeline)
                {
                    EditorGUI.indentLevel++;
                    InspectorUtility.DrawField(target, "m_FirstPersonCullingMask");
                    EditorGUI.indentLevel--;
                }
#endif
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Primary Spring"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawSpring(target, "Position Spring", "m_PositionSpring");
                var lowerLimit      = InspectorUtility.GetFieldValue <float>(target, "m_PositionLowerVerticalLimit");
                var lowerLimitValue = EditorGUILayout.Slider(new GUIContent(InspectorUtility.SplitCamelCase("m_PositionLowerVerticalLimit"),
                                                                            InspectorUtility.GetFieldTooltip(target, "m_PositionLowerVerticalLimit")), lowerLimit, 0, 5);
                // Set the property if the game is playing so the camera will update.
                if (lowerLimitValue != lowerLimit)
                {
                    (target as FirstPerson).PositionLowerVerticalLimit = lowerLimit;
                    InspectorUtility.SetFieldValue(target, "m_PositionLowerVerticalLimit", lowerLimitValue);
                }
                InspectorUtility.DrawFieldSlider(target, "m_PositionFallImpact", 0, 5);
                InspectorUtility.DrawFieldIntSlider(target, "m_PositionFallImpactSoftness", 1, 30);
                InspectorUtility.DrawFieldSlider(target, "m_RotationStrafeRoll", -5, 5);
                InspectorUtility.DrawSpring(target, "Rotation Spring", "m_RotationSpring");
                InspectorUtility.DrawFieldSlider(target, "m_RotationFallImpact", 0, 5);
                InspectorUtility.DrawFieldIntSlider(target, "m_RotationFallImpactSoftness", 1, 30);
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Secondary Spring"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawSpring(target, "Secondary Position Spring", "m_SecondaryPositionSpring");
                InspectorUtility.DrawSpring(target, "Secondary Rotation Spring", "m_SecondaryRotationSpring");
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Shake"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawFieldSlider(target, "m_ShakeSpeed", 0, 10);
                InspectorUtility.DrawField(target, "m_ShakeAmplitude");
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Bob"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_BobPositionalRate");
                InspectorUtility.DrawField(target, "m_BobPositionalAmplitude");
                InspectorUtility.DrawField(target, "m_BobRollRate");
                InspectorUtility.DrawField(target, "m_BobRollAmplitude");
                InspectorUtility.DrawFieldSlider(target, "m_BobInputVelocityScale", 0, 10);
                InspectorUtility.DrawField(target, "m_BobMaxInputVelocity");
                InspectorUtility.DrawField(target, "m_BobMinTroughVerticalOffset");
                InspectorUtility.DrawField(target, "m_BobTroughForce");
                InspectorUtility.DrawField(target, "m_BobRequireGroundContact");
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Limits"))
            {
                EditorGUI.indentLevel++;
                var minPitchLimit = InspectorUtility.GetFieldValue <float>(target, "m_MinPitchLimit");
                var maxPitchLimit = InspectorUtility.GetFieldValue <float>(target, "m_MaxPitchLimit");
                var minValue      = Mathf.Round(minPitchLimit * 100f) / 100f;
                var maxValue      = Mathf.Round(maxPitchLimit * 100f) / 100f;
                InspectorUtility.MinMaxSlider(ref minValue, ref maxValue, -90, 90, new GUIContent("Pitch Limit", "The min and max limit of the pitch angle (in degrees)."));
                if (minValue != minPitchLimit)
                {
                    InspectorUtility.SetFieldValue(target, "m_MinPitchLimit", minValue);
                }
                if (minValue != maxPitchLimit)
                {
                    InspectorUtility.SetFieldValue(target, "m_MaxPitchLimit", maxValue);
                }

                if (target is FreeLook)
                {
                    var minYawLimit = InspectorUtility.GetFieldValue <float>(target, "m_MinYawLimit");
                    var maxYawLimit = InspectorUtility.GetFieldValue <float>(target, "m_MaxYawLimit");
                    minValue = Mathf.Round(minYawLimit * 100f) / 100f;
                    maxValue = Mathf.Round(maxYawLimit * 100f) / 100f;
                    InspectorUtility.MinMaxSlider(ref minValue, ref maxValue, -180, 180, new GUIContent("Yaw Limit", "The min and max limit of the yaw angle (in degrees)."));
                    if (minValue != minYawLimit)
                    {
                        InspectorUtility.SetFieldValue(target, "m_MinYawLimit", minValue);
                    }
                    if (minValue != maxYawLimit)
                    {
                        InspectorUtility.SetFieldValue(target, "m_MaxYawLimit", maxValue);
                    }
                    InspectorUtility.DrawField(target, "m_YawLimitLerpSpeed");
                    InspectorUtility.DrawField(target, "m_RotateWithCharacter");
                }
                InspectorUtility.DrawField(target, "m_LookDirectionDistance");
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Head Tracking"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_SmoothHeadOffsetSteps");
                InspectorUtility.DrawField(target, "m_CollisionRadius");
                InspectorUtility.DrawField(target, "m_RotateWithHead");
                EditorGUI.indentLevel--;
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Draws the specified item set.
        /// </summary>
        private void DrawSelectedItemSet(ItemSet itemSet, int index)
        {
            GUILayout.Label("Item Set " + index, 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 (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);
            }
        }
Esempio n. 13
0
 /// <summary>
 /// Shortcut for drawing a foldout on the current target.
 /// </summary>
 /// <param name="name">The name of the foldout.</param>
 /// <param name="defaultExpanded">The default value if the foldout is expanded.</param>
 /// <param name="identifyingString">A string that can be used to help identify the foldout key.</param>
 /// <returns>True if the foldout is expanded.</returns></param>
 protected bool Foldout(string name, bool defaultExpanded, string identifyingString)
 {
     return(InspectorUtility.Foldout(target, new GUIContent(name), defaultExpanded, identifyingString));
 }
        /// <summary>
        /// Called when the object should be drawn to the inspector.
        /// </summary>
        /// <param name="target">The object that is being drawn.</param>
        /// <param name="parent">The Unity Object that the object belongs to.</param>
        public override void OnInspectorGUI(object target, Object parent)
        {
            // Draw the fields related to rendering.
            if (InspectorUtility.Foldout(target, "Rendering"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_LookDirectionDistance");
                var lookOffsetValue = InspectorUtility.GetFieldValue <Vector3>(target, "m_LookOffset");
                var lookOffset      = EditorGUILayout.Vector3Field(new GUIContent(InspectorUtility.SplitCamelCase("m_LookOffset"), InspectorUtility.GetFieldTooltip(target, "m_LookOffset")), lookOffsetValue);
                // Set the property if the game is playing so the camera will update.
                if (lookOffsetValue != lookOffset)
                {
                    (target as FirstPerson).LookOffset = lookOffset;
                    InspectorUtility.SetFieldValue(target, "m_LookOffset", lookOffset);
                }
                InspectorUtility.DrawField(target, "m_LookDownOffset");
                InspectorUtility.DrawField(target, "m_CullingMask");
                InspectorUtility.DrawFieldSlider(target, "m_FieldOfView", 1, 179);
                InspectorUtility.DrawFieldSlider(target, "m_FieldOfViewDamping", 0, 5);
                if (InspectorUtility.Foldout(target, "First Person Camera"))
                {
                    EditorGUI.indentLevel++;
                    InspectorUtility.DrawField(target, "m_UseFirstPersonCamera");
                    InspectorUtility.DrawField(target, "m_FirstPersonCamera");
                    InspectorUtility.DrawField(target, "m_FirstPersonCullingMask");
                    InspectorUtility.DrawField(target, "m_SynchronizeFieldOfView");
                    var synchronizeFieldOfView = InspectorUtility.GetFieldValue <bool>(target, "m_SynchronizeFieldOfView");
                    if (!synchronizeFieldOfView)
                    {
                        InspectorUtility.DrawFieldSlider(target, "m_FirstPersonFieldOfView", 1, 179);
                        InspectorUtility.DrawFieldSlider(target, "m_FirstPersonFieldOfViewDamping", 0, 5);
                    }
                    var positionOffsetValue = InspectorUtility.GetFieldValue <Vector3>(target, "m_FirstPersonPositionOffset");
                    var positionOffset      = EditorGUILayout.Vector3Field(new GUIContent(InspectorUtility.SplitCamelCase("m_FirstPersonPositionOffset"), InspectorUtility.GetFieldTooltip(target, "m_FirstPersonPositionOffset")), positionOffsetValue);
                    // Set the property if the game is playing so the camera will update.
                    if (positionOffsetValue != positionOffset)
                    {
                        (target as FirstPerson).FirstPersonPositionOffset = positionOffset;
                        InspectorUtility.SetFieldValue(target, "m_FirstPersonPositionOffset", positionOffset);
                    }
                    var rotationOffsetValue = InspectorUtility.GetFieldValue <Vector3>(target, "m_FirstPersonRotationOffset");
                    var rotationOffset      = EditorGUILayout.Vector3Field(new GUIContent(InspectorUtility.SplitCamelCase("m_FirstPersonRotationOffset"), InspectorUtility.GetFieldTooltip(target, "m_FirstPersonRotationOffset")), rotationOffsetValue);
                    // Set the property so the camera will update.
                    if (rotationOffsetValue != rotationOffset)
                    {
                        (target as FirstPerson).FirstPersonRotationOffset = rotationOffset;
                        InspectorUtility.SetFieldValue(target, "m_FirstPersonRotationOffset", rotationOffset);
                    }
                    EditorGUI.indentLevel--;
                }
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Primary Spring"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawSpring(target, "Position Spring", "m_PositionSpring");
                var lowerLimit      = InspectorUtility.GetFieldValue <float>(target, "m_PositionLowerVerticalLimit");
                var lowerLimitValue = EditorGUILayout.Slider(new GUIContent(InspectorUtility.SplitCamelCase("m_PositionLowerVerticalLimit"),
                                                                            InspectorUtility.GetFieldTooltip(target, "m_PositionLowerVerticalLimit")), lowerLimit, 0, 5);
                // Set the property if the game is playing so the camera will update.
                if (lowerLimitValue != lowerLimit)
                {
                    (target as FirstPerson).PositionLowerVerticalLimit = lowerLimit;
                    InspectorUtility.SetFieldValue(target, "m_PositionLowerVerticalLimit", lowerLimitValue);
                }
                InspectorUtility.DrawFieldSlider(target, "m_PositionFallImpact", 0, 5);
                InspectorUtility.DrawFieldIntSlider(target, "m_PositionFallImpactSoftness", 1, 30);
                InspectorUtility.DrawFieldSlider(target, "m_RotationStrafeRoll", -5, 5);
                InspectorUtility.DrawSpring(target, "Rotation Spring", "m_RotationSpring");
                InspectorUtility.DrawFieldSlider(target, "m_RotationFallImpact", 0, 5);
                InspectorUtility.DrawFieldIntSlider(target, "m_RotationFallImpactSoftness", 1, 30);
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Secondary Spring"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawSpring(target, "Secondary Position Spring", "m_SecondaryPositionSpring");
                InspectorUtility.DrawSpring(target, "Secondary Rotation Spring", "m_SecondaryRotationSpring");
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Shake"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawFieldSlider(target, "m_ShakeSpeed", 0, 10);
                InspectorUtility.DrawField(target, "m_ShakeAmplitude");
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Bob"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_BobPositionalRate");
                InspectorUtility.DrawField(target, "m_BobPositionalAmplitude");
                InspectorUtility.DrawField(target, "m_BobRollRate");
                InspectorUtility.DrawField(target, "m_BobRollAmplitude");
                InspectorUtility.DrawFieldSlider(target, "m_BobInputVelocityScale", 0, 10);
                InspectorUtility.DrawField(target, "m_BobMaxInputVelocity");
                InspectorUtility.DrawField(target, "m_BobMinTroughVerticalOffset");
                InspectorUtility.DrawField(target, "m_BobTroughForce");
                InspectorUtility.DrawField(target, "m_BobRequireGroundContact");
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Limits"))
            {
                EditorGUI.indentLevel++;
                var minPitchLimit = InspectorUtility.GetFieldValue <float>(target, "m_MinPitchLimit");
                var maxPitchLimit = InspectorUtility.GetFieldValue <float>(target, "m_MaxPitchLimit");
                var minValue      = Mathf.Round(minPitchLimit * 100f) / 100f;
                var maxValue      = Mathf.Round(maxPitchLimit * 100f) / 100f;
                InspectorUtility.MinMaxSlider(ref minValue, ref maxValue, -90, 90, new GUIContent("Pitch Limit", "The min and max limit of the pitch angle (in degrees)."));
                if (minValue != minPitchLimit)
                {
                    InspectorUtility.SetFieldValue(target, "m_MinPitchLimit", minValue);
                }
                if (minValue != maxPitchLimit)
                {
                    InspectorUtility.SetFieldValue(target, "m_MaxPitchLimit", maxValue);
                }

                if (target is FreeLook)
                {
                    var minYawLimit = InspectorUtility.GetFieldValue <float>(target, "m_MinYawLimit");
                    var maxYawLimit = InspectorUtility.GetFieldValue <float>(target, "m_MaxYawLimit");
                    minValue = Mathf.Round(minYawLimit * 100f) / 100f;
                    maxValue = Mathf.Round(maxYawLimit * 100f) / 100f;
                    InspectorUtility.MinMaxSlider(ref minValue, ref maxValue, -180, 180, new GUIContent("Yaw Limit", "The min and max limit of the yaw angle (in degrees)."));
                    if (minValue != minYawLimit)
                    {
                        InspectorUtility.SetFieldValue(target, "m_MinYawLimit", minValue);
                    }
                    if (minValue != maxYawLimit)
                    {
                        InspectorUtility.SetFieldValue(target, "m_MaxYawLimit", maxValue);
                    }
                    InspectorUtility.DrawField(target, "m_YawLimitLerpSpeed");
                }
                InspectorUtility.DrawField(target, "m_LookDirectionDistance");
                EditorGUI.indentLevel--;
            }
            if (InspectorUtility.Foldout(target, "Head Tracking"))
            {
                EditorGUI.indentLevel++;
                InspectorUtility.DrawField(target, "m_SmoothHeadOffsetSteps");
                InspectorUtility.DrawField(target, "m_CollisionRadius");
                InspectorUtility.DrawField(target, "m_RotateWithHead");
                EditorGUI.indentLevel--;
            }
        }
Esempio n. 15
0
        /// <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);
            }
        }
        public override void OnInspectorGUI()
        {
            //base.OnInspectorGUI();
            serializedObject.Update();

            InspectorUtility.PropertyField(serializedObject.FindProperty("m_Script"));

            //  -----
            //  Character Movement
            //  -----

            SetGUIContent(ref motorGUIContent, k_motorHeader, k_motorTooltip);
            SetGUIContent(ref physicsGUIContent, k_physicsContentHeader, k_physicsTooltip);
            SetGUIContent(ref collisionsGUIContent, k_collisionsHeader, k_collisionsTooltip);
            SetGUIContent(ref animationGUIContent, k_animationHeader, k_animationTooltip);
            SetGUIContent(ref advanceGUIContent, k_advanceHeader, k_advanceTooltip);

            DrawProperties(m_motorSettings, motorGUIContent);
            DrawProperties(m_physicsSettings, physicsGUIContent);
            DrawProperties(m_collisionSettings, collisionsGUIContent);
            DrawProperties(m_animationSettings, animationGUIContent);
            DrawProperties(m_advanceSettings, advanceGUIContent);


            //  -----
            //  Character Actions
            //  -----

            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            {
                EditorGUI.indentLevel++;
                displayActions.boolValue = m_useCustomeHeader ? InspectorUtility.Foldout(displayActions.boolValue, ActionsFoldoutHeader) : EditorGUILayout.Foldout(displayActions.boolValue, ActionsFoldoutHeader);
                //displayActions.boolValue = EditorGUILayout.Foldout(displayActions.boolValue, ActionsFoldoutHeader);
                if (displayActions.boolValue)
                {
                    //GUILayout.BeginVertical("box");
                    DrawReorderableList(m_ActionsList);
                    //GUILayout.EndVertical();

                    //  Draw Selected Action Inspector.
                    //EditorGUI.indentLevel++;
                    if (m_SelectedAction != null)
                    {
                        GUILayout.BeginVertical(EditorStyles.helpBox);

                        GUILayout.Space(12);
                        m_ActionEditor = CreateEditor(m_SelectedAction);
                        //m_ActionEditor.DrawDefaultInspector();
                        m_ActionEditor.OnInspectorGUI();

                        GUILayout.Space(12);

                        GUILayout.EndVertical();
                    }
                    //EditorGUI.indentLevel--;
                    //EditorGUI.indentLevel--;
                }
                EditorGUI.indentLevel--;
            }
            EditorGUILayout.EndVertical();


            if (m_spaceBetweenSections)
            {
                EditorGUILayout.Space();
            }

            //  -----
            //  Debugging
            //  -----

            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            {
                EditorGUI.indentLevel++;
                if (debugger.isExpanded)
                {
                    InspectorUtility.PropertyField(debugger, true);
                }
                else
                {
                    EditorGUILayout.BeginVertical(InspectorUtility.HeaderStyleBlue);
                    {
                        InspectorUtility.PropertyField(debugger, true);
                    }
                    EditorGUILayout.EndVertical();
                }
                EditorGUI.indentLevel--;
            }
            EditorGUILayout.EndVertical();



            EditorGUILayout.Space();
            serializedObject.ApplyModifiedProperties();
        }