public static void OnGUI(UnitEntityData ch, IEnumerable <BlueprintScriptableObject> blueprints, float indent = 0, float remainingWidth = 0, Func <String, String> titleFormater = null, NamedTypeFilter typeFilter = null ) { if (titleFormater == null) { titleFormater = (t) => t.orange().bold(); } int index = 0; if (needsLayout) { foreach (BlueprintScriptableObject blueprint in blueprints) { var actions = blueprint.GetActions(); if (actions.Any(a => a.isRepeatable)) { hasRepeatableAction = true; } int actionCount = actions.Sum(action => action.canPerform(blueprint, ch) ? 1 : 0); maxActions = Math.Max(actionCount, maxActions); } needsLayout = false; } if (hasRepeatableAction) { UI.BeginHorizontal(); UI.Space(553); UI.ActionIntTextField( ref repeatCount, "repeatCount", (limit) => { }, () => { }, UI.Width(160)); UI.Space(40); UI.Label("Parameter".cyan() + ": " + $"{repeatCount}".orange(), UI.ExpandWidth(false)); repeatCount = Math.Max(1, repeatCount); repeatCount = Math.Min(100, repeatCount); UI.EndHorizontal(); } UI.Div(indent); foreach (BlueprintScriptableObject blueprint in blueprints) { UI.BeginHorizontal(); UI.Space(indent); var actions = blueprint.GetActions().Where(action => action.canPerform(blueprint, ch)).ToArray(); var titles = actions.Select(a => a.name); var title = blueprint.name; if (titles.Contains("Remove")) { title = title.cyan().bold(); } else { title = titleFormater(title); } UI.Label(title, UI.Width(550 - indent)); int actionCount = actions != null?actions.Count() : 0; for (int ii = 0; ii < maxActions; ii++) { if (ii < actionCount) { BlueprintAction action = actions[ii]; // TODO -don't show increase or decrease actions until we redo actions into a proper value editor that gives us Add/Remove and numeric item with the ability to show values. For now users can edit ranks in the Facts Editor if (action.name == "<" || action.name == ">") { UI.Space(164); continue; } var actionName = action.name; float extraSpace = 0; if (action.isRepeatable) { actionName += (action.isRepeatable ? $" {repeatCount}" : ""); extraSpace = 20 * (float)Math.Ceiling(Math.Log10((double)repeatCount)); } UI.ActionButton(actionName, () => { action.action(blueprint, ch, repeatCount); }, UI.Width(160 + extraSpace)); UI.Space(10); } else { UI.Space(174); } } UI.Space(30); String typeString = blueprint.GetType().Name; if (typeFilter?.collator != null) { var collatorString = typeFilter.collator(blueprint); if (!typeString.Contains(collatorString)) { typeString += $" : {collatorString}".yellow(); } } Rect rect = GUILayoutUtility.GetLastRect(); var description = blueprint.GetDescription(); if (description != null && description.Length > 0) { description = $"\n{description.green()}"; } else { description = ""; } if (settings.showComponents && blueprint.ComponentsArray != null) { String componentStr = String.Join <object>(" ", blueprint.ComponentsArray).grey(); if (description.Length == 0) { description = componentStr; } else { description = componentStr + description; } } if (settings.showElements && blueprint.ElementsArray != null) { String elementsStr = String.Join <object>(" ", blueprint.ElementsArray).yellow(); if (description.Length == 0) { description = elementsStr; } else { description = elementsStr + "\n" + description; } } if (settings.showAssetIDs) { UI.Label(typeString.cyan()); GUILayout.TextField(blueprint.AssetGuid, UI.Width(450)); UI.EndHorizontal(); if (description.Length > 0) { UI.BeginHorizontal(); UI.Label("", UI.Width(rect.x)); UI.Label(blueprint.GetDescription().green()); //, UI.EndHorizontal(); } } else { float width = remainingWidth - rect.xMax; UI.Label(typeString.cyan() + " " + description, UI.Width(800)); //UI.Label($"{remainingWidth} - {rect.xMax} = {width}" + typeString + " " + description, UI.Width(800)); UI.EndHorizontal(); } #if false String description = blueprint.GetDescription(); if (description.Length > 0) { UI.BeginHorizontal(); UI.Space(684 + maxActions * 154); UI.Label($"{description.green()}"); UI.EndHorizontal(); } #endif UI.Div(indent); index++; } }
static public void OnGUI <T>(String callerKey, UnitEntityData unit, List <T> facts, Func <T, BlueprintScriptableObject> blueprint, IEnumerable <BlueprintScriptableObject> blueprints, Func <T, String> title, Func <T, String> description = null, Func <T, int> value = null, IEnumerable <BlueprintAction> actions = null ) { bool searchChanged = false; if (actions == null) { actions = new List <BlueprintAction>(); } if (callerKey != prevCallerKey) { searchChanged = true; showAll = false; } prevCallerKey = callerKey; var mutatorLookup = actions.Distinct().ToDictionary(a => a.name, a => a); UI.BeginHorizontal(); UI.Space(100); UI.ActionTextField(ref searchText, "searhText", null, () => { searchChanged = true; }, UI.Width(320)); UI.Space(25); UI.Label("Limit", UI.ExpandWidth(false)); UI.ActionIntTextField(ref searchLimit, "searchLimit", null, () => { searchChanged = true; }, UI.Width(175)); if (searchLimit > 1000) { searchLimit = 1000; } UI.Space(25); UI.Toggle("Show GUIDs", ref Main.settings.showAssetIDs); UI.Space(25); UI.Toggle("Dividers", ref Main.settings.showDivisions); UI.Space(25); searchChanged |= UI.DisclosureToggle("Show All".orange().bold(), ref showAll); UI.EndHorizontal(); UI.BeginHorizontal(); UI.Space(100); UI.ActionButton("Search", () => { searchChanged = true; }, UI.AutoWidth()); UI.Space(25); if (matchCount > 0 && searchText.Length > 0) { String matchesText = "Matches: ".green().bold() + $"{matchCount}".orange().bold(); if (matchCount > searchLimit) { matchesText += " => ".cyan() + $"{searchLimit}".cyan().bold(); } UI.Label(matchesText, UI.ExpandWidth(false)); } #if false UI.Label("Repeat Count", UI.ExpandWidth(false)); UI.ActionIntTextField( ref repeatCount, "repeatCount", (limit) => { }, () => { }, UI.Width(200)); #endif UI.EndHorizontal(); if (showAll) { // TODO - do we need this logic or can we make blueprint filtering fast enough to do keys by key searching? //if (filteredBPs == null || searchChanged) { UpdateSearchResults(searchText, searchLimit, blueprints); //} BlueprintListUI.OnGUI(unit, filteredBPs, 100); return; } var terms = searchText.Split(' ').Select(s => s.ToLower()).ToHashSet(); BlueprintAction add = mutatorLookup.GetValueOrDefault("Add", null); BlueprintAction remove = mutatorLookup.GetValueOrDefault("Remove", null); BlueprintAction decrease = mutatorLookup.GetValueOrDefault("<", null); BlueprintAction increase = mutatorLookup.GetValueOrDefault(">", null); mutatorLookup.Remove("Add"); mutatorLookup.Remove("Remove"); mutatorLookup.Remove("<"); mutatorLookup.Remove(">"); BlueprintScriptableObject toAdd = null; BlueprintScriptableObject toRemove = null; BlueprintScriptableObject toIncrease = null; BlueprintScriptableObject toDecrease = null; var toValues = new Dictionary <String, BlueprintScriptableObject>(); var sorted = facts.OrderBy((f) => title(f)); matchCount = 0; UI.Div(100); foreach (var fact in sorted) { if (fact == null) { continue; } var bp = blueprint(fact); String name = title(fact); String nameLower = name.ToLower(); if (name != null && name.Length > 0 && (searchText.Length == 0 || terms.All(term => nameLower.Contains(term)))) { matchCount++; UI.BeginHorizontal(); UI.Space(100); UI.Label($"{name}".cyan().bold(), UI.Width(400)); UI.Space(30); if (value != null) { var v = value(fact); decrease.BlueprintActionButton(unit, bp, () => { toDecrease = bp; }, 50); UI.Space(10f); UI.Label($"{v}".orange().bold(), UI.Width(30)); increase.BlueprintActionButton(unit, bp, () => { toIncrease = bp; }, 50); } #if false UI.Space(30); add.BlueprintActionButton(unit, bp, () => { toAdd = bp; }, 150); #endif UI.Space(30); remove.BlueprintActionButton(unit, bp, () => { toRemove = bp; }, 150); #if false foreach (var action in actions) { action.MutatorButton(unit, bp, () => { toValues[action.name] = bp; }, 150); } #endif if (description != null) { UI.Space(30); var assetID = Main.settings.showAssetIDs ? blueprint(fact).AssetGuid.magenta() + " " : ""; UI.Label(assetID + description(fact).green(), UI.AutoWidth()); } UI.EndHorizontal(); UI.Div(100); } } if (toAdd != null) { add.action(toAdd, unit, repeatCount); toAdd = null; } if (toRemove != null) { remove.action(toRemove, unit, repeatCount); toRemove = null; } if (toDecrease != null) { decrease.action(toDecrease, unit, repeatCount); toDecrease = null; } if (toIncrease != null) { increase.action(toIncrease, unit, repeatCount); toIncrease = null; } foreach (var item in toValues) { var muator = mutatorLookup[item.Key]; if (muator != null) { muator.action(item.Value, unit, repeatCount); } } toValues.Clear(); }