This repository has been archived by the owner on Sep 7, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Filters are precompiled at main menu, only research check active in t…
…he editor
- Loading branch information
Showing
20 changed files
with
741 additions
and
695 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
using FilterExtensions.ConfigNodes; | ||
using FilterExtensions.Utility; | ||
using KSP.Localization; | ||
using KSP.UI.Screens; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace FilterExtensions | ||
{ | ||
public class CategoryInstance | ||
{ | ||
public string Name { get; } | ||
public string Icon { get; } | ||
public UnityEngine.Color Colour { get; } | ||
public CategoryNode.CategoryType Type { get; } | ||
public CategoryNode.CategoryBehaviour Behaviour { get; } | ||
|
||
public List<SubCategoryInstance> Subcategories { get; } | ||
|
||
|
||
public CategoryInstance(CategoryNode protoC, Dictionary<string, SubcategoryNode> allSubCats) | ||
{ | ||
Name = protoC.CategoryName; | ||
Icon = protoC.IconName; | ||
Colour = protoC.Colour; | ||
Type = protoC.Type; | ||
Behaviour = protoC.Behaviour; | ||
Subcategories = new List<SubCategoryInstance>(); | ||
foreach (SubCategoryItem sci in protoC.SubCategories) | ||
{ | ||
if (allSubCats.TryGetValue(sci.SubcategoryName, out SubcategoryNode protoSC) && protoSC != null) | ||
{ | ||
SubcategoryNode node = new SubcategoryNode(protoSC, sci.ApplyTemplate ? protoC : null); | ||
SubCategoryInstance instance = new SubCategoryInstance(node, PartLoader.LoadedPartsList); | ||
if (instance.Valid) | ||
Subcategories.Add(instance); | ||
} | ||
} | ||
if (!Subcategories.Any()) | ||
throw new ArgumentException($"No subcategories valid, abandon instantiation of {Name}"); | ||
} | ||
|
||
public void Initialise() | ||
{ | ||
if (string.IsNullOrEmpty(Name)) | ||
{ | ||
LoadAndProcess.Log("Category name is null or empty", LoadAndProcess.LogLevel.Warn); | ||
return; | ||
} | ||
|
||
if (Type == CategoryNode.CategoryType.New) | ||
{ | ||
RUI.Icons.Selectable.Icon icon = LoadAndProcess.GetIcon(Icon); | ||
PartCategorizer.Category category = PartCategorizer.AddCustomFilter(Name, icon, Colour); | ||
category.displayType = EditorPartList.State.PartsList; | ||
category.exclusionFilter = PartCategorizer.Instance.filterGenericNothing; | ||
InstanceSubcategories(category); | ||
} | ||
else | ||
{ | ||
if (!PartCategorizer.Instance.filters.TryGetValue(c => string.Equals(Localization.Format(c.button.categoryName), Name, StringComparison.OrdinalIgnoreCase), | ||
out PartCategorizer.Category category)) | ||
{ | ||
LoadAndProcess.Log("No category of this name was found to manipulate: " + Name, LoadAndProcess.LogLevel.Warn); | ||
return; | ||
} | ||
else if (Behaviour == CategoryNode.CategoryBehaviour.Replace) | ||
{ | ||
if (category.button.activeButton.CurrentState == KSP.UI.UIRadioButton.State.True) | ||
{ | ||
var subcat = category.subcategories.Find(c => c.button.activeButton.CurrentState == KSP.UI.UIRadioButton.State.True); | ||
if (subcat != null) | ||
{ | ||
subcat.OnFalseSUB(subcat); | ||
} | ||
PartCategorizer.Instance.scrollListSub.Clear(false); | ||
} | ||
category.subcategories.Clear(); | ||
} | ||
InstanceSubcategories(category); | ||
} | ||
} | ||
|
||
void InstanceSubcategories(PartCategorizer.Category category) | ||
{ | ||
foreach (SubCategoryInstance sc in Subcategories) | ||
{ | ||
try | ||
{ | ||
sc.Initialise(category); | ||
} | ||
catch (Exception ex) | ||
{ | ||
LoadAndProcess.Log($"{sc} failed to initialise" | ||
+ $"\r\nCategory: {Name}" | ||
+ $"\r\nSubcategory Valid: {sc.Valid}" | ||
+ $"\r\n{ex.Message}" | ||
+ $"\r\n{ex.StackTrace}", | ||
LoadAndProcess.LogLevel.Error); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using UnityEngine; | ||
|
||
namespace FilterExtensions.ConfigNodes | ||
{ | ||
using Utility; | ||
|
||
public class CategoryNode : IEquatable<CategoryNode> | ||
{ | ||
public enum CategoryType | ||
{ | ||
New = 0, // new category | ||
Stock, // modification to stock category | ||
Mod // modification to a mod cateogry | ||
} | ||
|
||
public enum CategoryBehaviour | ||
{ | ||
Add = 1, // only add to existing categories | ||
Replace = 2, // wipe existing categories | ||
Engines = 4 // generate unique engine types | ||
} | ||
|
||
public string CategoryName { get; } | ||
public string IconName { get; } | ||
public Color Colour { get; } | ||
public CategoryType Type { get; } | ||
public CategoryBehaviour Behaviour { get; } | ||
public bool All { get; } // has an all parts subCategory | ||
public List<SubCategoryItem> SubCategories { get; } // array of subcategories | ||
public List<FilterNode> Templates { get; } // Checks to add to every Filter in a category with the template tag | ||
|
||
public CategoryNode(ConfigNode node, LoadAndProcess data) | ||
{ | ||
string tmpStr = string.Empty; | ||
|
||
CategoryName = node.GetValue("name"); | ||
IconName = node.GetValue("icon"); | ||
Colour = GUIUtils.convertToColor(node.GetValue("colour")); | ||
|
||
ConfigNode[] filtNodes = node.GetNodes("FILTER"); | ||
if (filtNodes == null) | ||
return; | ||
Templates = new List<FilterNode>(); | ||
foreach (ConfigNode n in filtNodes) | ||
Templates.Add(new FilterNode(n)); | ||
|
||
if (bool.TryParse(node.GetValue("all"), out bool tmpBool)) | ||
{ | ||
this.All = tmpBool; | ||
} | ||
|
||
ConfigNode[] subcategoryList = node.GetNodes("SUBCATEGORIES"); | ||
SubCategories = new List<SubCategoryItem>(); | ||
if (subcategoryList != null) | ||
{ | ||
List<SubCategoryItem> unorderedSubCats = new List<SubCategoryItem>(); | ||
List<string> stringList = new List<string>(); | ||
for (int i = 0; i < subcategoryList.Length; i++) | ||
stringList.AddRange(subcategoryList[i].GetValues()); | ||
|
||
SubCategoryItem[] subs = new SubCategoryItem[1000]; | ||
for (int i = 0; i < stringList.Count; i++) | ||
{ | ||
string[] indexAndValue = stringList[i].Split(',').Select(s => s.Trim()).ToArray(); | ||
|
||
SubCategoryItem newSubItem = new SubCategoryItem(); | ||
if (int.TryParse(indexAndValue[0], out int index)) // has position index | ||
{ | ||
if (indexAndValue.Length >= 2) | ||
newSubItem.SubcategoryName = indexAndValue[1]; | ||
if (string.IsNullOrEmpty(newSubItem.SubcategoryName)) | ||
continue; | ||
|
||
if (indexAndValue.Length >= 3 && string.Equals(indexAndValue[2], "dont template", StringComparison.CurrentCultureIgnoreCase)) | ||
newSubItem.ApplyTemplate = false; | ||
subs[index] = newSubItem; | ||
} | ||
else // no valid position index | ||
{ | ||
newSubItem.SubcategoryName = indexAndValue[0]; | ||
if (string.IsNullOrEmpty(newSubItem.SubcategoryName)) | ||
continue; | ||
|
||
if (indexAndValue.Length >= 2 && string.Equals(indexAndValue[1], "dont template", StringComparison.CurrentCultureIgnoreCase)) | ||
newSubItem.ApplyTemplate = false; | ||
unorderedSubCats.Add(newSubItem); | ||
} | ||
} | ||
SubCategories = subs.Distinct().ToList(); // no duplicates and no gaps in a single line. Yay | ||
SubCategories.AddUniqueRange(unorderedSubCats); // tack unordered subcats on to the end | ||
SubCategories.RemoveAll(s => s == null); | ||
} | ||
|
||
if (node.TryGetValue("type", ref tmpStr)) | ||
tmpStr = tmpStr.ToLower(); | ||
switch (tmpStr) | ||
{ | ||
case "stock": | ||
Type = CategoryType.Stock; | ||
break; | ||
|
||
case "mod": | ||
Type = CategoryType.Mod; | ||
break; | ||
|
||
case "new": | ||
default: | ||
Type = CategoryType.New; | ||
break; | ||
} | ||
if (node.TryGetValue("value", ref tmpStr)) | ||
{ | ||
if (string.Equals(tmpStr, "replace", StringComparison.OrdinalIgnoreCase)) | ||
Behaviour = CategoryBehaviour.Replace; | ||
else if (string.Equals(tmpStr, "engine", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
Behaviour = CategoryBehaviour.Engines; | ||
foreach (List<string> combo in data.propellantCombos) | ||
{ | ||
string dummy = string.Empty, subcatName = string.Join(",", combo.ToArray()); | ||
data.SetNameAndIcon(ref subcatName, ref dummy); | ||
SubCategories.AddUnique(new SubCategoryItem(subcatName)); | ||
} | ||
} | ||
else | ||
Behaviour = CategoryBehaviour.Add; | ||
} | ||
} | ||
|
||
public bool HasSubCategories() | ||
{ | ||
return (SubCategories?.Count ?? 0) > 0; | ||
} | ||
|
||
public override bool Equals(object obj) | ||
{ | ||
if (ReferenceEquals(null, obj)) | ||
return false; | ||
if (ReferenceEquals(this, obj)) | ||
return true; | ||
if (obj.GetType() != this.GetType()) | ||
return false; | ||
return Equals((CategoryNode)obj); | ||
} | ||
|
||
public bool Equals(CategoryNode C) | ||
{ | ||
if (ReferenceEquals(null, C)) | ||
return false; | ||
if (ReferenceEquals(this, C)) | ||
return true; | ||
|
||
return CategoryName.Equals(C.CategoryName); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return CategoryName.GetHashCode(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.