private static void SaveThreeStateItemContainer <T>(XContainer xRoot, string containerName, string entryName, ThreeStateItemContainer <T> container) where T : Def { if (container.IsInDefaultState()) { return; } var xContainerElement = new XElement(containerName); xRoot.Add(xContainerElement); xContainerElement.Add(new XElement("FilterBooleanState", container.FilterBooleanState)); xContainerElement.Add(new XElement("OffPartialNoSelect", container.OffPartialNoSelect)); foreach (var entry in container) { var xEntry = new XElement(entryName); xEntry.Add(new XElement(DefNameNode, entry.Key.defName)); xEntry.Add(new XElement(StateNode, entry.Value.State)); xContainerElement.Add(xEntry); } }
protected void FilterAnd <T>(IEnumerable <int> inputList, ThreeStateItemContainer <T> container) where T : Def { // get a list of Defs that *must not* be present var selectedDefOff = (from entry in container where entry.Value.State == MultiCheckboxState.Off select entry.Key).ToList(); // get a list of Defs that *must* be present var selectedDefOn = (from entry in container where entry.Value.State == MultiCheckboxState.On select entry.Key).ToList(); // get a list of Defs that may or may not be present var selectedDefPartial = (from entry in container where entry.Value.State == MultiCheckboxState.Partial select entry.Key).ToList(); // foreach each tile in the input list foreach (var tileId in inputList) { // get the tile and check if it has any of the Def type var tile = Find.World.grid[tileId]; var tileHasDefs = TileHasDef(tile); // get the Defs in the tile (or an empty list if no Defs) var tileDefs = TileDefs <T>(tile); if (tileHasDefs) { // if we have more "absolutely wanted" (ON) defs than there are defs in the tile, then we know it can't match if (selectedDefOn.Count > tileDefs.Count) { continue; } // No Def contained in the tile should be in the 'Off' selected state if (selectedDefOff.Intersect(tileDefs).Any()) { continue; } // all the selected On defs must be in the tile if (!tileDefs.ContainsAll(selectedDefOn)) { continue; } // tile might contains defs that are in partial state if (selectedDefPartial.Count > 0 && selectedDefOn.Count > 0) { if (!tileDefs.ContainsAll(selectedDefOn)) { var doNotAddTile = Enumerable.Any(selectedDefPartial, currentDefPartial => !tileDefs.Contains(currentDefPartial)); if (doNotAddTile) { continue; } } } // add the tile _filteredTiles.Add(tileId); } else // tile has no road { // if any Def is in 'On' selected state, then it can't match if (selectedDefOn.Count > 0) { continue; } // Partial of Off state is ok, add it. _filteredTiles.Add(tileId); } } }
protected void FilterOr <T>(IEnumerable <int> inputList, ThreeStateItemContainer <T> container, bool offNoSelect) where T : Def { // foreach each tile in the input list foreach (var tileId in inputList) { // get the tile and check if it has any road var tile = Find.World.grid[tileId]; var tileHasDef = TileHasDef(tile); // get the Defs in the tile (or an empty list if no Defs) var tileDefs = TileDefs <T>(tile); // loop through user selection items (key value pair) : // - key -> current item road def // - value -> user choice state: either ON / OFF / PARTIAL foreach (var threeStateItemKvp in container) { var currentSelectedDef = threeStateItemKvp.Key; // current def var currentSelectionState = threeStateItemKvp.Value; // current user choice for this def if (tileHasDef) { switch (currentSelectionState.State) { // user wants this type of defs case MultiCheckboxState.On: if (tileDefs.Contains(currentSelectedDef)) { _filteredTiles.Add(tileId); } break; // user doesn't want this type of defs case MultiCheckboxState.Off: if (!tileDefs.Contains(currentSelectedDef) && !offNoSelect) { _filteredTiles.Add(tileId); } break; // user don't care if it's present or not case MultiCheckboxState.Partial: if (!offNoSelect) { _filteredTiles.Add(tileId); } else { if (tileDefs.Contains(currentSelectedDef)) { _filteredTiles.Add(tileId); } } break; default: throw new ArgumentOutOfRangeException(); } } else // current tile has no defs { switch (currentSelectionState.State) { case MultiCheckboxState.On: break; case MultiCheckboxState.Off: if (container.IsAllOff()) { _filteredTiles.Add(tileId); } else { if (!offNoSelect) { _filteredTiles.Add(tileId); } } break; case MultiCheckboxState.Partial: if (!offNoSelect) { _filteredTiles.Add(tileId); } break; default: throw new ArgumentOutOfRangeException(); } } if (_filteredTiles.Count > 0 && _filteredTiles.Last() == tileId) { break; } } } }
private void LoadThreeStateItemContainer <T>(XContainer xParent, string elementName, string subElementName, ThreeStateItemContainer <T> container) where T : Def { var xFoundElement = xParent.Element(elementName); if (xFoundElement == null) { // set everything in default state foreach (var value in container.Values) { value.State = MultiCheckboxState.Partial; } return; } container.FilterBooleanState = LoadEnum <FilterBoolean>(xFoundElement, "FilterBooleanState"); LoadBoolean(xFoundElement, "OffPartialNoSelect", b => container.OffPartialNoSelect = b); foreach (var xSubElement in xFoundElement.Elements()) { if (xSubElement.Name != subElementName) { continue; } var def = LoadDef <T>(xSubElement, DefNameNode) as T; if (def == null) { continue; } var xState = xSubElement.Element(StateNode); if (xState == null) { continue; } if (!container.TryGetValue(def, out var threeStateItem)) { continue; } var state = LoadEnum <MultiCheckboxState>(xSubElement, StateNode); threeStateItem.State = state; } }