diff --git a/FilterExtension/ConfigNodes/Filter.cs b/FilterExtension/ConfigNodes/Filter.cs index 7862a345..1e8a2ff3 100644 --- a/FilterExtension/ConfigNodes/Filter.cs +++ b/FilterExtension/ConfigNodes/Filter.cs @@ -51,17 +51,7 @@ public ConfigNode toConfigNode() return node; } - internal bool checkFilter(AvailablePart part) - { - for (int i = 0; i < checks.Count; i++) - { - if (!checks[i].checkPart(part)) - return invert ? true : false; - } - return invert ? false : true; - } - - internal bool checkFilter(AvailablePart part, int depth) + internal bool checkFilter(AvailablePart part, int depth = 0) { for (int i = 0; i < checks.Count; i++) { diff --git a/FilterExtension/ConfigNodes/customCategory.cs b/FilterExtension/ConfigNodes/customCategory.cs index 85b8c5ec..b727c37e 100644 --- a/FilterExtension/ConfigNodes/customCategory.cs +++ b/FilterExtension/ConfigNodes/customCategory.cs @@ -12,7 +12,9 @@ public enum categoryTypeAndBehaviour None, Engines, StockAdd, - StockReplace + StockReplace, + ModAdd, + ModReplace } public class customCategory : IEquatable @@ -39,14 +41,17 @@ public customCategory(ConfigNode node) bool.TryParse(node.GetValue("all"), out tmp); this.all = tmp; - ConfigNode subcategoryList = node.GetNode("SUBCATEGORIES", 0); + ConfigNode[] subcategoryList = node.GetNodes("SUBCATEGORIES"); subCategories = new List(); if (subcategoryList != null) { List unorderedSubCats = new List(); - string[] stringList = subcategoryList.GetValues(); + List stringList = new List(); + for (int i = 0; i < subcategoryList.Length; i++) + stringList.AddRange(subcategoryList[i].GetValues()); + subCategoryItem[] subs = new subCategoryItem[1000]; - for (int i = 0; i < stringList.Length; i++) + for (int i = 0; i < stringList.Count; i++) { string[] indexAndValue = stringList[i].Split(',').Select(s => s.Trim()).ToArray(); @@ -94,7 +99,7 @@ public void initialise() return; } PartCategorizer.Category category; - if (!stockCategory) + if (behaviour == categoryTypeAndBehaviour.None || behaviour == categoryTypeAndBehaviour.Engines) { RUI.Icons.Selectable.Icon icon = Core.getIcon(iconName); PartCategorizer.AddCustomFilter(categoryName, icon, colour); @@ -103,10 +108,18 @@ public void initialise() category.displayType = EditorPartList.State.PartsList; category.exclusionFilter = PartCategorizer.Instance.filterGenericNothing; } - else if (!PartCategorizer.Instance.filters.TryGetValue(c => c.button.categoryName == categoryName, out category)) + else { - Core.Log("No stock category of this name was found: " + categoryName); - return; + if (!PartCategorizer.Instance.filters.TryGetValue(c => c.button.categoryName == categoryName, out category)) + { + Core.Log("No category of this name was found to manipulate: " + categoryName); + return; + } + else + { + if (behaviour == categoryTypeAndBehaviour.StockReplace || behaviour == categoryTypeAndBehaviour.ModReplace) + category.subcategories.Clear(); + } } List subcategoryNames = new List(); @@ -171,7 +184,6 @@ public void initialise() } } - #warning Need another type which runs after other mods for editing their categories private void typeSwitch(string type, string value) { switch (type) @@ -186,6 +198,12 @@ private void typeSwitch(string type, string value) else behaviour = categoryTypeAndBehaviour.StockAdd; break; + case "mod": + if (value == "replace") + behaviour = categoryTypeAndBehaviour.ModReplace; + else + behaviour = categoryTypeAndBehaviour.ModAdd; + break; default: behaviour = categoryTypeAndBehaviour.None; break; @@ -237,9 +255,9 @@ private void makeTemplate(ConfigNode node) ConfigNode[] filtNodes = node.GetNodes("FILTER"); if (filtNodes == null) return; - this.templates = new List(); + templates = new List(); foreach (ConfigNode n in filtNodes) - this.templates.Add(new Filter(n)); + templates.Add(new Filter(n)); } public static Color convertToColor(string hex_ARGB) @@ -274,7 +292,7 @@ public static Color convertToColor(string hex_ARGB) public bool hasSubCategories() { - return (this.subCategories != null && this.subCategories.Any()); + return (subCategories != null && subCategories.Any()); } public override bool Equals(object obj) @@ -302,14 +320,6 @@ public override int GetHashCode() { return categoryName.GetHashCode(); } - - public bool stockCategory - { - get - { - return this.behaviour == categoryTypeAndBehaviour.StockAdd || this.behaviour == categoryTypeAndBehaviour.StockReplace; - } - } } public class subCategoryItem : IEquatable diff --git a/FilterExtension/ConfigNodes/customSubCategory.cs b/FilterExtension/ConfigNodes/customSubCategory.cs index 2d9c4da7..d50c8574 100644 --- a/FilterExtension/ConfigNodes/customSubCategory.cs +++ b/FilterExtension/ConfigNodes/customSubCategory.cs @@ -43,6 +43,22 @@ public customSubCategory(string name, string icon) this.iconName = icon; } + /// + /// called in the editor when creating the subcategory + /// + /// The category to add this subcategory to + public void initialise(PartCategorizer.Category cat) + { + if (cat == null) + return; + RUI.Icons.Selectable.Icon icon = Core.getIcon(iconName); + PartCategorizer.AddCustomSubcategoryFilter(cat, this.subCategoryTitle, icon, p => checkFilters(p)); + } + + /// + /// used mostly for purpose of creating a deep copy + /// + /// public ConfigNode toConfigNode() { ConfigNode node = new ConfigNode("SUBCATEGORY"); @@ -57,38 +73,21 @@ public ConfigNode toConfigNode() return node; } - public bool checkFilters(AvailablePart part) - { - if (Editor.blackListedParts != null) - { - if (part.category == PartCategories.none && Editor.blackListedParts.Contains(part.name)) - return false; - if (!unPurchasedOverride && Core.Instance.hideUnpurchased && !ResearchAndDevelopment.PartModelPurchased(part) && !ResearchAndDevelopment.IsExperimentalPart(part)) - return false; - } - foreach (Filter f in filters) - { - if (f.checkFilter(part)) - return true; - } - return false; // part passed no filter(s), not compatible with this subcategory - } - /// - /// called by subcategory check type, has depth loop protection + /// called by subcategory check type, has depth limit protection /// /// /// /// - public bool checkFilters(AvailablePart part, int depth) + public bool checkFilters(AvailablePart part, int depth = 0) { if (Editor.blackListedParts != null) { if (part.category == PartCategories.none && Editor.blackListedParts.Contains(part.name)) return false; - if (!unPurchasedOverride && Core.Instance.hideUnpurchased && !ResearchAndDevelopment.PartModelPurchased(part) && !ResearchAndDevelopment.IsExperimentalPart(part)) - return false; } + if (!unPurchasedOverride && Core.Instance.hideUnpurchased && !ResearchAndDevelopment.PartModelPurchased(part) && !ResearchAndDevelopment.IsExperimentalPart(part)) + return false; foreach (Filter f in filters) { @@ -98,19 +97,6 @@ public bool checkFilters(AvailablePart part, int depth) return false; // part passed no filter(s), not compatible with this subcategory } - public void initialise(PartCategorizer.Category cat) - { - RUI.Icons.Selectable.Icon icon = Core.getIcon(iconName); - if (hasFilters) - { - if (cat == null) - return; - PartCategorizer.AddCustomSubcategoryFilter(cat, this.subCategoryTitle, icon, p => checkFilters(p)); - } - else - Core.Log("Invalid subCategory definition"); - } - /// /// check to see if any checks in a subcategory match a given check /// diff --git a/FilterExtension/Core.cs b/FilterExtension/Core.cs index 7c47ef67..c0551ed0 100644 --- a/FilterExtension/Core.cs +++ b/FilterExtension/Core.cs @@ -59,7 +59,7 @@ void Awake() { instance = this; DontDestroyOnLoad(this); - Log("Version 2.4.0"); + Log("Version 2.4.1"); getConfigs(); getPartData(); diff --git a/FilterExtension/Editor.cs b/FilterExtension/Editor.cs index 8e1c5ccd..567d2d62 100644 --- a/FilterExtension/Editor.cs +++ b/FilterExtension/Editor.cs @@ -27,6 +27,8 @@ void Start() IEnumerator editorInit() { + ready = false; + while (PartCategorizer.Instance == null) yield return null; if (Core.Instance.debug) @@ -38,11 +40,10 @@ IEnumerator editorInit() foreach (PartCategorizer.Category C in PartCategorizer.Instance.filters) { customCategory cat; - if (Core.Instance.Categories.TryGetValue(c => c.categoryName == C.button.categoryName, out cat) && cat.hasSubCategories() && cat.stockCategory) + if (Core.Instance.Categories.TryGetValue(c => c.categoryName == C.button.categoryName, out cat)) { - if (cat.behaviour == categoryTypeAndBehaviour.StockReplace) - C.subcategories.Clear(); - cat.initialise(); + if (cat.hasSubCategories() && (cat.behaviour == categoryTypeAndBehaviour.StockReplace || cat.behaviour == categoryTypeAndBehaviour.StockAdd)) + cat.initialise(); } } // custom categories @@ -54,11 +55,11 @@ IEnumerator editorInit() for (int i = 0; i < 4; i++) yield return null; if (Core.Instance.debug) - Core.Log("Starting on other filters"); + Core.Log("Starting on general categories"); // run everything foreach (customCategory c in Core.Instance.Categories) { - if (!c.stockCategory) + if (c.behaviour == categoryTypeAndBehaviour.None || c.behaviour == categoryTypeAndBehaviour.Engines) c.initialise(); } @@ -67,33 +68,20 @@ IEnumerator editorInit() yield return null; // edit names and icons of all subcategories if (Core.Instance.debug) - Core.Log("Starting on setting names and icons"); + Core.Log("Starting on late categories"); if (blackListedParts == null) { + #warning not known until now which parts are never visible so some completely empty subcategories may be present on the first VAB entry findPartsToBlock(); - // not known until now which parts are never visible so some empty subcategories will be present - //for (int i = 0; i < PartCategorizer.Instance.filters.Count; i++) - //{ - // PartCategorizer.Category C = PartCategorizer.Instance.filters[i]; - // if (C == null) - // continue; - // int j = 0; - // while (j < C.subcategories.Count) - // { - // PartCategorizer.Category sub = C.subcategories[j]; - // if (sub == null) - // { - // j++; - // continue; - // } + } - // if (!PartLoader.Instance.parts.Any(p => sub.exclusionFilter.FilterCriteria.Invoke(p))) - // C.subcategories.RemoveAt(j); - // else - // j++; - // } - //} + // this is to be used for altering subcategories in a category added by another mod + foreach (customCategory c in Core.Instance.Categories) + { + if (c.behaviour == categoryTypeAndBehaviour.ModAdd || c.behaviour == categoryTypeAndBehaviour.ModReplace) + c.initialise(); } + foreach (PartCategorizer.Category c in PartCategorizer.Instance.filters) Core.Instance.namesAndIcons(c); @@ -146,8 +134,7 @@ void findPartsToBlock() int j = 0; while (j < partsToCheck.Count) { - AvailablePart AP = partsToCheck[j]; - if (subCat.exclusionFilter.FilterCriteria.Invoke(AP)) // if visible + if (subCat.exclusionFilter.FilterCriteria.Invoke(partsToCheck[j])) // if visible partsToCheck.RemoveAt(j); else j++; diff --git a/GameData/000_FilterExtensions/FilterExtensions.dll b/GameData/000_FilterExtensions/FilterExtensions.dll index 42b42738..e79d0453 100644 Binary files a/GameData/000_FilterExtensions/FilterExtensions.dll and b/GameData/000_FilterExtensions/FilterExtensions.dll differ