/// <summary> /// Draws all of the states. /// </summary> public void OnStateListDraw(Rect rect, int index, bool isActive, bool isFocused) { if (rect.width < 0) { return; } var profileIndex = EditorPrefs.GetInt(SelectedProfileKey, 0); var profile = m_StateConfiguration.Profiles[profileIndex]; if (index >= profile.StateElements.Length) { return; } var stateElement = profile.StateElements[index]; // Setup the field sizings. var fieldWidth = rect.width / 3; var blockedByWidth = Mathf.Max(c_MinBlockedByWidth, Mathf.Min(c_MaxBlockedByWidth, fieldWidth)) + EditorGUI.indentLevel * InspectorUtility.IndentWidth; fieldWidth = (rect.width - blockedByWidth) / 2 - (c_WidthBuffer * 3); var presetWidth = Mathf.Min(c_MaxPresetWidth, fieldWidth) + EditorGUI.indentLevel * 30; var nameWidth = Mathf.Max(0, rect.width - presetWidth - blockedByWidth - (c_WidthBuffer * 4)) + EditorGUI.indentLevel * InspectorUtility.IndentWidth * 3; var startRectX = rect.x; GUI.enabled = !stateElement.Default; var desiredName = EditorGUI.TextField(new Rect(startRectX, rect.y + 1, nameWidth, EditorGUIUtility.singleLineHeight), stateElement.Name); if (desiredName != stateElement.Name && IsUniqueStateName(profile.StateElements, stateElement, desiredName)) { stateElement.Name = desiredName; } startRectX += nameWidth + c_WidthBuffer - EditorGUI.indentLevel * InspectorUtility.IndentWidth; var preset = EditorGUI.ObjectField(new Rect(startRectX, rect.y + 1, presetWidth, EditorGUIUtility.singleLineHeight), string.Empty, stateElement.Preset, typeof(PersistablePreset), false) as PersistablePreset; if (preset != stateElement.Preset) { // If the preset is just set then ensure the state name doesn't conflict with any other state name. stateElement.Preset = preset; var name = stateElement.Name; var count = 1; while (!IsUniqueStateName(profile.StateElements, stateElement, name)) { name = stateElement.Name + " " + count; count++; } stateElement.Name = name; m_StateConfiguration.ResetInitialization(); } startRectX += presetWidth + c_WidthBuffer - EditorGUI.indentLevel * InspectorUtility.IndentWidth; // Create a popup of the states that can block the current state. There are several conditions which would prevent a state from being able to block // another state so this popup has to first be filtered. var stateName = stateElement.Name; var blockList = stateElement.BlockList; var allStates = new List <string>(); var selected = 0; if (stateElement.Preset != null) { var objType = stateElement.Preset.Data.ObjectType; for (int i = 0; i < profile.StateElements.Length; ++i) { var currentState = profile.StateElements[i]; // The current state cannot block another object type. if (currentState.Preset == null || objType != currentState.Preset.Data.ObjectType) { continue; } string name; // The current state cannot block itself. if ((name = currentState.Name) == stateName) { continue; } // The selected state cannot block the current state if the current state blocks the selected state. var currentStateBlockList = currentState.BlockList; var canAdd = true; if (currentStateBlockList != null) { for (int j = 0; j < currentStateBlockList.Length; ++j) { if (stateName == currentStateBlockList[j]) { canAdd = false; break; } } } // canAdd will be false if the current state is blocking the selected state. if (!canAdd) { continue; } // The current state can block the selected state. Add the name to the popup and determine if the state is selected. A mask is used // to allow multiple selected states. allStates.Add(name); if (blockList != null) { for (int j = 0; j < blockList.Length; ++j) { if (allStates[allStates.Count - 1] == blockList[j]) { selected |= 1 << (allStates.Count - 1); break; } } } } } else { GUI.enabled = false; } // At least one value needs to exist. if (allStates.Count == 0) { allStates.Add("Nothing"); } // Draw the actual popup. var blockMask = EditorGUI.MaskField(new Rect(startRectX, rect.y + 1, blockedByWidth, EditorGUIUtility.singleLineHeight), string.Empty, selected, allStates.ToArray()); if (blockMask != selected) { var stateNames = new List <string>(); for (int i = 0; i < allStates.Count; ++i) { // If the state index is within the block mask then that state should be added to the list. A blockMask of -1 indicates Everything. if (((1 << i) & blockMask) != 0 || blockMask == -1) { stateNames.Add(allStates[i]); } } stateElement.BlockList = stateNames.ToArray(); } GUI.enabled = true; }