diff --git a/JanitorsCloset/EditorWindows/EditorWindows.cs b/JanitorsCloset/EditorWindows/EditorWindows.cs deleted file mode 100644 index 269bdb1..0000000 --- a/JanitorsCloset/EditorWindows/EditorWindows.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JanitorsCloset.EditorWindows -{ - class EditorWindows - { - } -} diff --git a/JanitorsCloset/EditorWindows/ModFilterWindow.cs b/JanitorsCloset/EditorWindows/ModFilterWindow.cs deleted file mode 100644 index 2e42394..0000000 --- a/JanitorsCloset/EditorWindows/ModFilterWindow.cs +++ /dev/null @@ -1,1576 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using KSP.UI.Screens; -using ClickThroughFix; - -using static JanitorsCloset.JanitorsClosetLoader; - -namespace JanitorsCloset -{ - class ModFilterWindow : MonoBehaviour - { - internal static ModFilterWindow instance; - - const string INVERSE = "-inverse"; - - public class PartSizeDescr - { - public string bulkheadProfile; - public string descr; - - public PartSizeDescr(string size, string descr) - { - this.bulkheadProfile = size; - this.descr = descr; - } - } - static SortedDictionary partSizeDict = null; - public class PartInfo : IComparable - { - string partName; - //static string[] partSizeDescr = new string[] { "Size 0 (0.625m)", "Size 1 (1.25m)", "Size 1.5 /(1.875m)", "Size 2 (2.5m)", "Size 3 (3.75m)", "Size 4 (5m)", "Size 5 (7.5m)" }; - - // Implement IComparable CompareTo method - provide default sort order. - public int CompareTo(object obj1) - { - return String.Compare(this.partName, ((PartInfo)obj1).partName); - } - //---------------- --------------------------------------------------------------------------------------------------------------- - public string RemoveWhiteSpace(string input) - { - return new string(input.ToCharArray() - .Where(c => !Char.IsWhiteSpace(c)) - .ToArray()); - } - - public PartInfo(AvailablePart part) - { - string key = ""; - this.partName = part.name; - if (partSizeDict == null) - Log.Error("partSizeDict is null in PartInfo"); - - Log.Info("Part: " + part.name + ", PartSizeDescrDict.Count: " + partSizeDict.Count); - - // Log.Info("partSizeDescr.Length: " + partSizeDescr.Length.ToString()); - - if (part.bulkheadProfiles != null && part.bulkheadProfiles != "" - && part.bulkheadProfiles != "srf") - { - //bool srf = false; - - List bulkheads = part.bulkheadProfiles.Split(',').ToList(); - for (int i = bulkheads.Count - 1; i >= 0; i--) - { - bulkheads[i] = bulkheads[i].Trim().ToLower(); - if (bulkheads[i].Contains("srf")) - { - Log.Info("Part: " + part.name + ", i: " + i + ", removing bulkhead: " + bulkheads[i]); - bulkheads.RemoveAt(i); - } - } - - if (bulkheads.Count > 1) - { - bulkheads = bulkheads.OrderBy(x => x).ToList(); - } - if (bulkheads.Count > 0) - { - string smallSizeStr = bulkheads[0]; - string largeSizeStr = bulkheads[bulkheads.Count - 1]; - if (smallSizeStr == largeSizeStr) - { - partSize = BestGuessReadableName(smallSizeStr, capitalize: true); - key = smallSizeStr; - } - else - { - partSize = "Adapter: " + BestGuessReadableName(smallSizeStr, capitalize: true) + " to " + BestGuessReadableName(largeSizeStr, capitalize: true); - key = smallSizeStr + "-" + largeSizeStr; - } - } - //if (srf) - // partSize += ", Srf"; - - //Log.Info("part: " + part.name + ", partSize: " + partSize + ", bulkheads[0]: [" + bulkheads[0] + "], bulkheads.Count: " + bulkheads.Count + ", bulkheads[bulkheads.Count - 1]: [" + bulkheads[bulkheads.Count - 1] + "]"); - } - else - { - partSize = "Srf"; - key = "srf"; - } - if (partSizeDict.ContainsKey(key)) - partSize = partSizeDict[key].descr; - else - { - if (!part.name.Contains("kerbalEVA") && part.name != "flag") - Log.Error("Unknown BulkheadProfiles: part: " + part.name + ", bulkheadProfiles: " + part.bulkheadProfiles); - } -#if false - try - { Log.Info("PartInfo, Part: " + part.name + ", partSize: " + key + " = " + partSize); } - catch (Exception ex) { Log.Error("Error: " + ex.Message); } -#endif - } - - //------------------------------------------------------------------------------------------------------------------------------- - public string partSize; - //public double sortSize; - - - public int defaultPos; - - }; - - - static Rect modWindowRect = new Rect(0, 0, 0, 0); - - private const int MOD_WINDOW_ID = 94; - private const int SIZE_WINDOW_ID = 95; - - private struct ToggleState - { - public bool enabledState; - public bool latched; - public bool inverse; - } - - private static SortedDictionary modButtons = new SortedDictionary(); - private static SortedDictionary sizeButtons = new SortedDictionary(); - private static SortedDictionary resourceButtons = new SortedDictionary(); - private static SortedDictionary partModuleButtons = new SortedDictionary(); - - private static SortedDictionary partInfos = new SortedDictionary(); - - private static SortedDictionary> modHash = new SortedDictionary>(); - private static SortedDictionary> sizeHash = new SortedDictionary>(); - private static SortedDictionary> resourceHash = new SortedDictionary>(); - private static SortedDictionary> partModuleHash = new SortedDictionary>(); - - public int ModFilteredCount = 0; - public int ModInverseCount = 0; - public int SizeFilteredCount = 0; - public int ResourceFilteredCount = 0; - public int ModuleFilteredCount = 0; - public int ModuleInverseCount = 0; - bool hideUnpurchased = false; - - private static UrlDir.UrlConfig[] configs = null; - - int selectedFilterList = 1; - - //------------------------------------------------------------------------------------------------------------------------------------------- - bool PartIsPurchased(AvailablePart info) - { - if (PartLoader.Instance == null) return false; - return HighLogic.CurrentGame.Mode == Game.Modes.SANDBOX || ResearchAndDevelopment.PartModelPurchased(info); - } - - static public string FindPartMod(AvailablePart part) - { - if (configs == null) - configs = GameDatabase.Instance.GetConfigs("PART"); - - Log.Info("ModFilterWindow.FindPartMod, part.name: " + part.name); - UrlDir.UrlConfig config = Array.Find(configs, (c => (part.name == c.name.Replace('_', '.').Replace(' ', '.')))); - if (config == null) - { - config = Array.Find(configs, (c => (part.name == c.name))); - if (config == null) - return ""; - } - var id = new UrlDir.UrlIdentifier(config.url); - return id[0]; - } - - public void Show() - { - this.enabled = true; - - modWindowRect = FilterWindowRect("Mods", Math.Max(modButtons.Count, Math.Max(sizeButtons.Count, Math.Max(resourceButtons.Count, partModuleButtons.Count)))); - - if (JanitorsCloset.GetModFilterWin != null) - { - var r = (Rect)JanitorsCloset.GetModFilterWin; - modWindowRect.x = r.x; - modWindowRect.y = r.y; - - } - } - - public void Hide() { this.enabled = false; } - - static string UsefulModuleName(string longName) - { - Log.Info("ModFilterWindow.UsefulModuleName"); - - if (longName.StartsWith("Module")) - return longName.Substring(6); - if (longName.StartsWith("FXModule")) - return "FX" + longName.Substring(8); - return longName; - } - - - void InitialPartsScan(List loadedParts) - { - Log.Info("ModFilterWindow.InitialPartsScan"); - - int index = 1; - foreach (var part in loadedParts) - { - if (part == null) - continue; - Log.Info(string.Format("PROCESS {0}", part.name)); - - PartInfo partInfo = new PartInfo(part); - if (!partInfos.ContainsKey(part.name)) - partInfos.Add(part.name, partInfo); - else - Log.Error("Part already loaded: " + part.name); - - partInfo.defaultPos = index++; - - // add the size to the list of all sizes known if it's the first time we've seen this part size - - try - { - if (!sizeButtons.ContainsKey(partInfo.partSize)) - { - Log.Info(string.Format("define new size filter key {0}", partInfo.partSize)); - sizeButtons.Add(partInfo.partSize, new ToggleState() { enabledState = true, latched = false, inverse = false }); - sizeHash.Add(partInfo.partSize, new HashSet()); - } - Log.Info(string.Format("add {0} to sizeHash for {1}", part.name, partInfo.partSize)); - sizeHash[partInfo.partSize].Add(part); - } - catch (Exception ex) - { - Log.Error("Exception caught (1), message: " + ex.Message); - } - - // Add any resources the part has listed - if (part.resourceInfos.Count > 0) - { - foreach (var res in part.resourceInfos) - { - - try - { - if (!resourceButtons.ContainsKey(res.resourceName)) - { - Log.Info(string.Format("define new resource filter key {0}", res.resourceName)); - resourceButtons.Add(res.resourceName, new ToggleState() { enabledState = true, latched = false, inverse = false }); - resourceHash.Add(res.resourceName, new HashSet()); - } - Log.Info(string.Format("add {0} to resourceHash for {1}", part.name, res.resourceName)); - resourceHash[res.resourceName].Add(part); - } - catch (Exception ex) - { - Log.Error("Exception caught (2), message: " + ex.Message); - } - } - } - else - { - string resname = "None"; - - try - { - if (!resourceButtons.ContainsKey(resname)) - { - resourceButtons.Add(resname, new ToggleState() { enabledState = true, latched = false, inverse = false }); - resourceHash.Add(resname, new HashSet()); - } - Log.Info(string.Format("add {0} to resourceHash for {1}", part.name, resname)); - resourceHash[resname].Add(part); - } - catch (Exception ex) - { - Log.Error("Exception caught (3), message: " + ex.Message); - } - } - - if (part.partPrefab.Modules.Count == 0) - { - string moduleName = "None"; - try - { - if (!partModuleButtons.ContainsKey(moduleName)) - { - Log.Info(string.Format("define new module.moduleName filter key {0}", moduleName)); - partModuleButtons.Add(moduleName, new ToggleState() { enabledState = true, latched = false, inverse = false }); - partModuleHash.Add(moduleName, new HashSet()); - } - Log.Info(string.Format("add {0} to partModuleHash for moduleName: {1}", part.name, moduleName)); - partModuleHash[moduleName].Add(part); - } - catch (Exception ex) - { - Log.Error("Exception caught (6), message: " + ex.Message); - } - } - else - { - foreach (var module in part.partPrefab.Modules) - { - // First get all the part modules here - - Log.Info("module: part name: " + part.name + ", moduleName: " + module.moduleName); - - try - { - if (!partModuleButtons.ContainsKey(module.moduleName)) - { - - Log.Info(string.Format("define new module.moduleName filter key {0}", module.moduleName)); - partModuleButtons.Add(module.moduleName, new ToggleState() { enabledState = true, latched = false, inverse = false }); - partModuleHash.Add(module.moduleName, new HashSet()); - } - Log.Info(string.Format("add {0} to partModuleHash for moduleName: {1}", part.name, module.moduleName)); - partModuleHash[module.moduleName].Add(part); - } - catch (Exception ex) - { - Log.Error("Exception caught (4), message: " + ex.Message); - } - - // Now get the resources used by the modules - - foreach (var res in module.resHandler.inputResources) - { - - try - { - if (!resourceButtons.ContainsKey(res.name)) - { - Log.Info(string.Format("define new res.inputResource filter key {0}", res.name)); - resourceButtons.Add(res.name, new ToggleState() { enabledState = true, latched = false, inverse = false }); - resourceHash.Add(res.name, new HashSet()); - } - Log.Info(string.Format("add {0} to resourceHash for inputResource: {1}", part.name, res.name)); - resourceHash[res.name].Add(part); - } - catch (Exception ex) - { - Log.Error("Exception caught (5), message: " + ex.Message); - } - - } - for (int i = 0; i < module.resHandler.outputResources.Count; i++) - { - var res = module.resHandler.outputResources[i]; - //} - //foreach (var res in module.resHandler.outputResources) - //{ - try - { - if (!resourceButtons.ContainsKey(res.name)) - { - Log.Info(string.Format("define new res.outputResources filter key {0}", res.name)); - resourceButtons.Add(res.name, new ToggleState() { enabledState = true, latched = false, inverse = false }); - resourceHash.Add(res.name, new HashSet()); - } - Log.Info(string.Format("add {0} to resourceHash for outputResources: {1}", part.name, res.name)); - resourceHash[res.name].Add(part); - } - catch (Exception ex) - { - Log.Error("Exception caught (6), message: " + ex.Message); - } - - } - switch (module.moduleName) - { - case "ModuleEngines": - { - Log.Info("ModuleEngines"); - ModuleEngines me = module as ModuleEngines; - for (int i = me.propellants.Count - 1; i >= 0; i--) - { - Propellant propellant = me.propellants[i]; - - try - { - if (!resourceButtons.ContainsKey(propellant.name)) - { - Log.Info(string.Format("define new propellant filter key {0}", propellant.name)); - resourceButtons.Add(propellant.name, new ToggleState() { enabledState = true, latched = false, inverse = false }); - resourceHash.Add(propellant.name, new HashSet()); - } - Log.Info(string.Format("add {0} to resourceHash for outputResources: {1}", part.name, propellant.name)); - resourceHash[propellant.name].Add(part); - } - catch (Exception ex) - { - Log.Error("Exception caught (7), message: " + ex.Message); - } - - } - break; - } - case "ModuleEnginesFX": - { - Log.Info("ModuleEnginesFX"); - - ModuleEngines me = module as ModuleEnginesFX; - for (int i = me.propellants.Count - 1; i >= 0; i--) - { - Propellant propellant = me.propellants[i]; - - try - { - if (!resourceButtons.ContainsKey(propellant.name)) - { - Log.Info(string.Format("define new propellant filter key {0}", propellant.name)); - resourceButtons.Add(propellant.name, new ToggleState() { enabledState = true, latched = false, inverse = false }); - resourceHash.Add(propellant.name, new HashSet()); - } - Log.Info(string.Format("add {0} to resourceHash for outputResources: {1}", part.name, propellant.name)); - resourceHash[propellant.name].Add(part); - } - catch (Exception ex) - { - Log.Error("Exception caught (8), message: " + ex.Message); - } - - } - break; - } - case "ModuleRCS": - { - Log.Info("ModuleRCS"); - - ModuleRCS me = module as ModuleRCS; - for (int i = me.propellants.Count - 1; i >= 0; i--) - { - Propellant propellant = me.propellants[i]; - - try - { - if (!resourceButtons.ContainsKey(propellant.name)) - { - Log.Info(string.Format("define new propellant filter key {0}", propellant.name)); - resourceButtons.Add(propellant.name, new ToggleState() { enabledState = true, latched = false, inverse = false }); - resourceHash.Add(propellant.name, new HashSet()); - } - Log.Info(string.Format("add {0} to resourceHash for propellant: {1}", part.name, propellant.name)); - if (!resourceHash[propellant.name].Contains(part)) - resourceHash[propellant.name].Add(part); - else - Log.Error("Part: " + part.name + " already added to hash: " + propellant.name); - } - catch (Exception ex) - { - Log.Error("Exception caught (9), message: " + ex.Message); - } - - } - break; - } - case "ModuleRCSFX": - { - Log.Info("ModuleRCSFX"); - - ModuleRCSFX me = module as ModuleRCSFX; - - for (int i = me.propellants.Count - 1; i >= 0; i--) - { - Propellant propellant = me.propellants[i]; - - try - { - if (!resourceButtons.ContainsKey(propellant.name)) - { - Log.Info(string.Format("define new propellant filter key {0}", propellant.name)); - resourceButtons.Add(propellant.name, new ToggleState() { enabledState = true, latched = false, inverse = false }); - resourceHash.Add(propellant.name, new HashSet()); - } - Log.Info(string.Format("add {0} to resourceHash for propellant: {1}", part.name, propellant.name)); - if (!resourceHash[propellant.name].Contains(part)) - resourceHash[propellant.name].Add(part); - else - Log.Error("Part: " + part.name + " already added to hash: " + propellant.name); - } - catch (Exception ex) - { - Log.Error("Exception caught (10), message: " + ex.Message); - } - - - } - - break; - } - } - } - } - - - // the part's base directory name is used to filter entire mods in and out - string partModName = FindPartMod(part); - Log.Info("partModName: " + partModName); - if (partModName != "") - { - - try - { - if (!modButtons.ContainsKey(partModName)) - { - Log.Info(string.Format("define new mod filter key {0}", partModName)); - modButtons.Add(partModName, new ToggleState() { enabledState = true, latched = false, inverse = false }); - modHash.Add(partModName, new HashSet()); - } - Log.Info(string.Format("add {0} to modHash for {1}", part.name, partModName)); - if (!modHash[partModName].Contains(part)) - modHash[partModName].Add(part); - else - Log.Error("Part: " + part.name + " already added to hash: " + partModName); - } - catch (Exception ex) - { - Log.Error("Exception caught (11), message: " + ex.Message); - } - - - // save all the module names that are anywhere in this part - if (part.partPrefab == null) - continue; - if (part.partPrefab.Modules == null) - continue; - - foreach (PartModule module in part.partPrefab.Modules) - { - string fullName = module.moduleName; - if (fullName == null) - { - Log.Info(string.Format("{0} has a null moduleName, skipping it", part.name)); - continue; - } - Log.Info(string.Format("scan part '{0}' module [{2}]'{1}'", part.name, fullName, fullName.Length)); - string moduleName = UsefulModuleName(fullName); - - } - } - } - } - - Rect FilterWindowRect(string name, int buttons) - { - var lineHeight = (int)HighLogic.Skin.GetStyle("Toggle").CalcHeight(new GUIContent("XXQ"), 20); - - if (buttons > 20) - buttons = 20; - if (buttons < 10) - buttons = 10; - - float height = lineHeight * buttons; - - Rect answer = new Rect(300, 200, 350, height); - - //Log.Info( string.Format("defining window {4} at ({0},{1},{2},{3})", answer.xMin, answer.yMin, answer.width, answer.height, name)); - return answer; - } - - List GetPartsList() - { - List loadedParts = new List(); - loadedParts.AddRange(PartLoader.LoadedPartsList); // make a copy we can manipulate - - // these two parts are internal and just serve to mess up our lists and stuff - //AvailablePart kerbalEVA = null; - //AvailablePart flag = null; - for (int i = loadedParts.Count - 1; i >= 0; i--) - { - var part = loadedParts[i]; - if (part.name.Contains("kerbalEVA")) - { - //kerbalEVA = part; - loadedParts.Remove(part); - partInfos.Add(part.name, new PartInfo(part)); - } - else if (part.name == "flag") - { - //flag = part; - loadedParts.Remove(part); - partInfos.Add(part.name, new PartInfo(part)); - } - } -#if false - // still need to prevent errors with null refs when looking up these parts though - if (kerbalEVA != null) - { - //loadedParts.Remove(kerbalEVA); - partInfos.Add(kerbalEVA, new PartInfo(kerbalEVA)); - } - if (flag != null) - { - //loadedParts.Remove(flag); - partInfos.Add(flag, new PartInfo(flag)); - } -#endif - return loadedParts; - } - - bool PartInResourceFilteredButtons(string filter, AvailablePart part, SortedDictionary buttons, SortedDictionary> filterHash) - { - Log.Info("part: " + part.name); - foreach (KeyValuePair entry in buttons) - { - if (!entry.Value.enabledState || !filterHash.ContainsKey(entry.Key)) - continue; - try - { - if (filterHash[entry.Key].Contains(part)) - { - Log.Info("part: " + part.name + " has resource: " + entry.Key); - return true; - } - } - catch - { - Log.Error("PartInResourceFilteredButtons, filter: " + filter + " entry.Key not in filterHash: " + entry.Key + ", part: " + part.name); - - } - - } - return false; - } - - bool PartInFilteredButtons(string filter, AvailablePart part, SortedDictionary buttons, SortedDictionary> filterHash) - { - foreach (KeyValuePair entry in buttons) - { - if (!entry.Value.enabledState || !filterHash.ContainsKey(entry.Key)) - continue; - try - { - if (filterHash[entry.Key].Contains(part)) - return true; - } - catch - { - Log.Error("PartInFilteredButtons, filter: " + filter + " entry.Key not in filterHash: " + entry.Key + ", part: " + part.name); - } - } - return false; - } - - bool PartInResourseExcludeButtons(string filter, AvailablePart part, SortedDictionary buttons, SortedDictionary> filterHash) - { - foreach (KeyValuePair entry in buttons) - { - if (!entry.Value.inverse) - continue; - if (!filterHash.ContainsKey(entry.Key)) - { - Log.Error("PartInResourseExcludeButtons, filter: " + filter + ", filterHash does not contain key: " + entry.Key); - } - else - { - if (filterHash[entry.Key].Contains(part)) - return false; - } - } - return true; - } - - bool PartInUnpurchasedButtons(string filter, AvailablePart part, SortedDictionary buttons, SortedDictionary> filterHash) - { - if (!hideUnpurchased) - return true; - return PartIsPurchased(part); - } - - - bool PartInModuleButtons(string filter, AvailablePart part, SortedDictionary buttons, SortedDictionary> filterHash) - { - foreach (KeyValuePair entry in buttons) - { - if (!entry.Value.enabledState || !filterHash.ContainsKey(entry.Key)) - continue; - try - { - if (filterHash[entry.Key].Contains(part)) - { - return true; - } - } - catch - { - Log.Error("PartInModuleButtons, filter: " + filter + ", entry.Key not in filterHash: " + entry.Key + ", part: " + part.name); - } - } - return false; - } - - bool PartInModuleExcludeButtons(string filter, AvailablePart part, SortedDictionary buttons, SortedDictionary> filterHash) - { - foreach (KeyValuePair entry in buttons) - { - if (!entry.Value.inverse) - continue; - - if (!filterHash.ContainsKey(entry.Key)) - { - Log.Error("PartInModuleExcludeButtons, filter: " + filter + ", filterHash does not contain key: " + entry.Key); - } - else - { - if (filterHash[entry.Key].Contains(part)) - return false; - } - } - return true; - } - - void DefineFilters() - { - Log.Info("DefineFilters"); - if (configs == null) - configs = GameDatabase.Instance.GetConfigs("PART"); - - EditorPartList.Instance.ExcludeFilters.AddFilter(new EditorPartListFilter("Mod Filter", (part => PartInFilteredButtons("Mod Filter", part, modButtons, modHash)))); - - EditorPartList.Instance.ExcludeFilters.AddFilter(new EditorPartListFilter("Size Filter", (part => PartInFilteredButtons("Size Filter", part, sizeButtons, sizeHash)))); - - EditorPartList.Instance.ExcludeFilters.AddFilter(new EditorPartListFilter("Resource Filter", (part => PartInResourceFilteredButtons("Resource Filter", part, resourceButtons, resourceHash)))); - - EditorPartList.Instance.ExcludeFilters.AddFilter(new EditorPartListFilter("Resource Exclude Filter", (part => PartInResourseExcludeButtons("Resource Exclude Filter", part, resourceButtons, resourceHash)))); - - EditorPartList.Instance.ExcludeFilters.AddFilter(new EditorPartListFilter("Unpurchased Filter", (part => PartInUnpurchasedButtons("Unpurchased Filter", part, sizeButtons, sizeHash)))); -#if true - EditorPartList.Instance.ExcludeFilters.AddFilter(new EditorPartListFilter("Module Filter", (part => PartInModuleButtons("Module Filter", part, partModuleButtons, partModuleHash)))); - EditorPartList.Instance.ExcludeFilters.AddFilter(new EditorPartListFilter("Module Exclude Filter", (part => PartInModuleExcludeButtons("Module Exclude Filter", part, partModuleButtons, partModuleHash)))); -#endif - //EditorPartList.Instance.ExcludeFilters.AddFilter(new EditorPartListFilter("Modules Filter", (part => !PartInFilteredButtons(part, moduleButtons, moduleHash)))); - EditorPartList.Instance.Refresh(); - } - - static GUIStyle styleButton = null; - static GUIStyle styleButtonSettings; - - static Color origBackgroundColor; - static GUIStyle styleButtonLeftAligned; - - static bool initted = false; - void InitData() - { - if (!initted) - { - CONFIG_BASE_FOLDER = KSPUtil.ApplicationRootPath + "GameData/"; - JC_BASE_FOLDER = CONFIG_BASE_FOLDER + "JanitorsCloset/"; - JC_NODE = "JANITORSCLOSET"; - JC_CFG_FILE = JC_BASE_FOLDER + "PluginData/JCModfilter-v2-"; - JC_FILTER_CONFIG_FILE = JC_BASE_FOLDER + "PluginData/FiltersConfig.cfg"; - //JS_WINPOS_FILE = JC_BASE_FOLDER + "PluginData/WinPos.cfg"; - JC_READABLE_NAMES_NODE = "READABLENAMES"; - JC_BULKHEADPROFILES = "BULKHEADPROFILES"; - JC_BLACKLIST_NODE = "MODULE_BLACKLIST"; -#if false - JC_MERGELIST_NODE = "MERGELIST"; -#endif - - initted = true; - if (configs == null) - configs = GameDatabase.Instance.GetConfigs("PART"); - LoadFiltersConfig(); - - List loadedParts = GetPartsList(); - InitialPartsScan(loadedParts); - LoadValuesFromConfig(selectedFilterList); - } - } - public void Start() - { - Log.Info("ModFilterWindow.Start"); - InitData(); - // DefineFilters(); - - modwindowRectID = JanitorsCloset.getNextID(); - modFilterHelpWindowID = JanitorsCloset.getNextID(); - enabled = false; - instance = this; - - } - - bool filtersDefined = false; - public void FixedUpdate() - { - if (filtersDefined) - return; - filtersDefined = true; - DefineFilters(); - } - - void InitStyles() - { - Log.Info("InitStyles"); - styleButton = new GUIStyle(GUI.skin.button); - styleButton.name = "ButtonGeneral"; - styleButton.normal.background = GUI.skin.button.normal.background; - styleButton.hover.background = GUI.skin.button.hover.background; - styleButton.normal.textColor = new Color(207, 207, 207); - styleButton.fontStyle = FontStyle.Normal; - styleButton.fixedHeight = 20; - styleButton.padding.top = 2; - - styleButtonSettings = new GUIStyle(styleButton); - styleButtonSettings.name = "ButtonSettings"; - styleButtonSettings.padding = new RectOffset(1, 1, 1, 1); - styleButtonSettings.onNormal.background = styleButtonSettings.active.background; - styleButtonSettings.alignment = TextAnchor.MiddleCenter; - styleButtonSettings.normal.textColor = new Color32(177, 193, 205, 255); - styleButtonSettings.fontStyle = FontStyle.Bold; - - origBackgroundColor = GUI.backgroundColor; // store value. - styleButtonLeftAligned = new GUIStyle(GUI.skin.button); - styleButtonLeftAligned.alignment = TextAnchor.MiddleLeft; - } - - - string _windowTitle = string.Empty; - int modwindowRectID; - int modFilterHelpWindowID; - - //bool showFilterHelpWindow = false; - - public void OnGUI() - { - if (!enabled) - return; - if (Event.current.type == EventType.Repaint) - GUI.skin = HighLogic.Skin; - if (styleButton == null) - InitStyles(); - - _windowTitle = string.Format("Mod Filter"); - var tstyle = new GUIStyle(GUI.skin.window); - - var newModWindowRect = ClickThruBlocker.GUILayoutWindow(modwindowRectID, modWindowRect, FilterChildWindowHandler, _windowTitle, tstyle); - - if (helpPopup != null) - helpPopup.draw(); - - if (newModWindowRect != modWindowRect) - { - modWindowRect = newModWindowRect; - JanitorsCloset.SetModFilterWin = modWindowRect; - } - } - - int CompareEntries(string lft, string rght) - { - string left = GetReadableName(lft); - string right = GetReadableName(rght); - if (left == right) - return 0; - if (left == "None") - return -1; - if (right == "None") - return 1; - - // use of "larger" now discontinued due to using bulkhead profiles instead of nodes -#if false - // Special cases for adapters so they are in height order, from smaller to larger - if (left.Contains("Adapter") && right.Contains("larger")) - return 1; - if (right.Contains("Adapter") && left.Contains("larger")) - return -1; - if (left.Contains("larger")) - return 1; - if (right.Contains("larger")) - return -1; -#endif - if (left.Contains("Adapter") && !right.Contains("Adapter")) - return 1; - if (right.Contains("Adapter") && !left.Contains("Adapter")) - return -1; - - return String.Compare(left, right); - } - - void resetAll() - { - var names = new List(modButtons.Keys); - SortedDictionary states = modButtons; - foreach (string name in names) - { - ToggleState state = states[name]; - state.enabledState = true; - state.inverse = false; - states[name] = state; - } - names = new List(sizeButtons.Keys); - states = sizeButtons; - foreach (string name in names) - { - ToggleState state = states[name]; - state.enabledState = true; - state.inverse = false; - states[name] = state; - } - names = new List(resourceButtons.Keys); - states = resourceButtons; - foreach (string name in names) - { - ToggleState state = states[name]; - state.enabledState = true; - state.inverse = false; - states[name] = state; - } - - names = new List(partModuleButtons.Keys); - states = partModuleButtons; - foreach (string name in names) - { - ToggleState state = states[name]; - state.enabledState = true; - state.inverse = false; - states[name] = state; - } - } - - HelpPopup helpPopup = null; - private void FilterHelpWindow(int id) - { - if (helpPopup == null) - { - helpPopup = new HelpPopup( - "Mod Filter", "Mod Name - filter mods by name\n" + - "Module Size - filter mods by size\nResources - filter mods by resource\n" + - "Modules - filter mods by modules\n\n" + - "Resource filter can filter by two methods:\n" + - "\t1. The green toggle says that the resource must be contained in the part or\n" + - "\t (if an engine module) used by the part\n" + - "\t2. The red toggle says that shown parts must NOT have or use the specified\n" + - "\t resource. Clicking the button with the resource name will cycle\n" + - "\t through the three modes of filtering for that resource.\n\n" + - - "Modules refers to the part modules which provide the functionality in each\n" + - "part. Like the resources, you can either filter by requiring one or more specific\n" + - "part modules to be present (the green toggle), or you can filter by excluding\n" + - "part which have specific part modules (the red toggle)\n\n" + - "In essense, the filters work by requiring all values with Green toggles be present\n" + - "AND that all values with Red toggles be excluded.\n\n" + - - "The Invert button will invert all the toggles and is only available on the Resources and Modules windows" - , JanitorsCloset.getNextID()); - } - - helpPopup.showMenu = true; - helpPopup.SetWinName("FilterHelpWindow"); - - //showFilterHelpWindow = false; - } - - Vector2 scrollPosition; - string[] filterType = new string[] { "Mod Name", "Module Size", "Resources", "Modules" }; - int selFilter = 0; - - private void FilterChildWindowHandler(int id) - { - SortedDictionary states = modButtons; - if (GUI.Button(new Rect(12, 2, 30, 20), "?", styleButtonSettings)) - { - // showFilterHelpWindow = !showFilterHelpWindow; - FilterHelpWindow(modFilterHelpWindowID); - } - if (GUI.Button(new Rect(modWindowRect.width - 32, 2, 30, 20), "X", styleButtonSettings)) - { - enabled = false; - // Visible = false; - } - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); - selFilter = GUILayout.SelectionGrid(selFilter, filterType, filterType.Length); - switch (selFilter) - { - case 0: - states = modButtons; - break; - case 1: - states = sizeButtons; - break; - case 2: - states = resourceButtons; - break; - case 3: - states = partModuleButtons; - break; - } - - GUILayout.EndHorizontal(); - bool updateNeeded = false; - GUILayout.BeginHorizontal(); - if (HighLogic.CurrentGame.Mode != Game.Modes.SANDBOX) - { - string s = " Hide Unpurchased "; - if (hideUnpurchased) - s = " Show Unpurchased "; - if (GUILayout.Button(s)) - { - hideUnpurchased = !hideUnpurchased; - updateNeeded = true; - } - } - if (GUILayout.Button("Show All")) - { - var names = new List(states.Keys); - foreach (string name in names) - { - ToggleState state = states[name]; - state.enabledState = true; - states[name] = state; - } - updateNeeded = true; - } - if (GUILayout.Button("Hide All")) - { - var names = new List(states.Keys); - foreach (string name in names) - { - ToggleState state = states[name]; - state.enabledState = false; - states[name] = state; - } - updateNeeded = true; - } - if (selFilter == 2 || selFilter == 3) - { - if (GUILayout.Button("Invert")) - { - var names = new List(states.Keys); - foreach (string name in names) - { - ToggleState state = states[name]; - state.inverse = !state.inverse; - state.enabledState = !state.inverse; - states[name] = state; - } - updateNeeded = true; - } - } - if (GUILayout.Button("Reset All")) - { - resetAll(); - updateNeeded = true; - } - GUILayout.EndHorizontal(); - - // saved filter lists - var oldColor = GUI.backgroundColor; - GUILayout.BeginHorizontal(); - for (int cnt = 1; cnt <= 10; cnt++) - { - if (selectedFilterList == cnt) - { - GUI.backgroundColor = Color.green; - } - if (GUILayout.Button(cnt.ToString(), GUILayout.Width(30))) - { - selectedFilterList = cnt; - LoadValuesFromConfig(selectedFilterList); - updateNeeded = true; - } - GUI.backgroundColor = oldColor; - } - GUILayout.EndHorizontal(); - if (updateNeeded) - { - EditorPartList.Instance.Refresh(); - SaveConfig(selectedFilterList); - } - - // This will hide the horizontal scrollbar - scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, false, GUIStyle.none, GUI.skin.verticalScrollbar); - - foreach (string name in states.Keys) - { - ToggleState state = states[name]; - //string truncatedName = (name.Length > 35) ? name.Remove(34) : name; - bool before = state.enabledState; - bool beforeInverse = state.inverse; - - string readableName = GetReadableName(name); - - if (readableName != "" && readableName != "None") - { - GUILayout.BeginHorizontal(); - GUILayout.Space(5); - - if (selFilter != 2 && selFilter != 3) - { - state.enabledState = GUILayout.Toggle(state.enabledState, readableName); - GUILayout.Space(20); - if (state.enabledState && state.enabledState != before) - state.inverse = false; - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - else - { - //Log.Info("FilterChildWindowHandler 3"); - state.enabledState = GUILayout.Toggle(state.enabledState, ""); - GUILayout.Space(20); - if (state.enabledState && state.enabledState != before) - state.inverse = false; - - GUI.backgroundColor = Color.red; - state.inverse = GUILayout.Toggle(state.inverse, ""); - GUI.backgroundColor = origBackgroundColor; // reset to old value. - if (state.inverse && state.inverse != beforeInverse) - state.enabledState = false; - GUILayout.Space(20); - - if (GUILayout.Button(readableName, styleButtonLeftAligned, GUILayout.Width(300))) - { - if (state.enabledState) - { - state.enabledState = false; - state.inverse = true; - } - else - { - if (state.inverse) - { - state.inverse = false; - } - else - state.enabledState = true; - } - } - - //Log.Info("FilterChildWindowHandler 4"); - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - GUILayout.Space(5); - //Log.Info("FilterChildWindowHandler 5"); - - } - - if (before != state.enabledState || beforeInverse != state.inverse) - { - states[name] = state; - EditorPartList.Instance.Refresh(); - SaveConfig(selectedFilterList); - // Break here to avoid an error: Collection was modified at the foreach - // since the state was updated. Nothing visible on screen when - // this happens - break; - //before = state.enabledState; - //beforeInverse = state.inverse; - } - } - } - GUILayout.EndScrollView(); - GUI.DragWindow(); - ModFilteredCount = modButtons.Where(p => p.Value.enabledState == false).Count(); - ModInverseCount = modButtons.Where(p => p.Value.inverse == true).Count(); - SizeFilteredCount = sizeButtons.Where(p => p.Value.enabledState == false).Count(); - ResourceFilteredCount = resourceButtons.Where(p => p.Value.enabledState == false).Count(); - ModuleFilteredCount = partModuleButtons.Where(p => p.Value.enabledState == false).Count(); - ModuleInverseCount = partModuleButtons.Where(p => p.Value.inverse == true).Count(); - - } - - private static String CONFIG_BASE_FOLDER; - private static String JC_BASE_FOLDER; - private static String JC_NODE; - private static String JC_READABLE_NAMES_NODE; - private static string JC_BULKHEADPROFILES; - private static String JC_BLACKLIST_NODE; -#if false - private static String JC_MERGELIST_NODE; -#endif - private static String JC_CFG_FILE; - private static String JC_FILTER_CONFIG_FILE; - //private static string JS_WINPOS_FILE; - - private static ConfigNode configFile = null; - private static ConfigNode configFileNode = null; - private static ConfigNode configSectionNode = null; - - - //------------------------------------------------------------------------------------------------------------------------------------------- - void SaveSelectType(string prefix, SortedDictionary buttonList, string NodeName, ConfigNode fileNode) - { - configSectionNode = new ConfigNode(NodeName); - - foreach (var mod in buttonList) - { - configSectionNode.SetValue(mod.Key, mod.Value.enabledState, true); - configSectionNode.SetValue(mod.Key + INVERSE, mod.Value.inverse, true); - } - configFileNode.SetNode(NodeName, configSectionNode, true); - - } - - void SaveConfig(int selectedCfg) //string sorting = null) - { - Log.Info("SaveConfig"); - configFile = new ConfigNode(); - configFileNode = new ConfigNode(); - - SaveSelectType("Mod", modButtons, "MOD", configFileNode); - SaveSelectType("Size", sizeButtons, "SIZE", configFileNode); - SaveSelectType("Res", resourceButtons, "RESOURCE", configFileNode); - SaveSelectType("Module", partModuleButtons, "MODULES", configFileNode); - - //config.save(); - configFile.SetNode(JC_NODE, configFileNode, true); - //configFile.AddNode (KRASH_CUSTOM_NODE, configFileNode); - configFile.Save(JC_CFG_FILE + selectedCfg.ToString() + ".cfg"); - } - //------------------------------------------------------------------------------------------------------------------------------------------- - - void LoadValuesFromSectionNode(string NodeName, SortedDictionary buttonList, ConfigNode configFileNode, string prefix) - { - configSectionNode = configFileNode.GetNode(NodeName); - if (configSectionNode != null) - LoadConfigSection(NodeName, configSectionNode, prefix, buttonList); - } - - private void LoadValuesFromConfig(int selectedCfg) - { - Log.Info("LoadValuesFromConfig, selectedCfg: " + selectedCfg); - resetAll(); - if (System.IO.File.Exists(JC_CFG_FILE + selectedCfg.ToString() + ".cfg")) - { - configFile = ConfigNode.Load(JC_CFG_FILE + selectedCfg.ToString() + ".cfg"); - configFileNode = configFile.GetNode(JC_NODE); - if (configFileNode != null) - { - //PluginConfiguration config = PluginConfiguration.CreateForType(); - //config.load(); - //LoadConfigSection(config, "Module", moduleButtons); - LoadValuesFromSectionNode("MOD", modButtons, configFileNode, "Mod"); - LoadValuesFromSectionNode("SIZE", sizeButtons, configFileNode, "Size"); - LoadValuesFromSectionNode("RESOURCE", resourceButtons, configFileNode, "Res"); - LoadValuesFromSectionNode("MODULES", partModuleButtons, configFileNode, "Module"); - - ModFilteredCount = modButtons.Where(p => p.Value.enabledState == false).Count(); - ModInverseCount = modButtons.Where(p => p.Value.inverse == true).Count(); - SizeFilteredCount = sizeButtons.Where(p => p.Value.enabledState == false).Count(); - ResourceFilteredCount = resourceButtons.Where(p => p.Value.enabledState == false).Count(); - ModuleFilteredCount = partModuleButtons.Where(p => p.Value.enabledState == false).Count(); - ModuleInverseCount = partModuleButtons.Where(p => p.Value.inverse == true).Count(); - - } - } - } - - //------------------------------------------------------------------------------------------------------------------------------------------- - void LoadConfigSection(string NodeName, ConfigNode cfgNode, string prefix, SortedDictionary buttons) - { - for (int i = 0; i < cfgNode.CountValues; i++) - { - bool inverse = false; - var e = cfgNode.values[i].name; - if (e.EndsWith(INVERSE)) - { - inverse = true; - e = cfgNode.values[i].name.Substring(0, cfgNode.values[i].name.Length - 8); - } - ToggleState s; - if (!buttons.ContainsKey(e)) - { - s = new ToggleState(); - s.inverse = false; - s.enabledState = true; - } - else - { - s = buttons[e]; - } - - if (!inverse) - s.enabledState = bool.Parse(cfgNode.values[i].value); - else - s.inverse = bool.Parse(cfgNode.values[i].value); - - buttons[e] = s; - } - - } - - - /// - /// Get a readable name from the dictionary. If not there, create it - /// - /// - /// - string GetReadableName(string name, bool add = true) - { - string s; - try - { - s = readableNamesDict[name]; - //Log.Info("GetReadableName, name: [" + name + "], readableName: [" + s + "]"); - return s; - } - catch - { -#if false // for future use - if (mergeListDict.ContainsKey(name)) - { - name = mergeListDict[name]; - if (readableNamesDict.ContainsKey(name)) - return ""; // readableNamesDict[name]; - } -#endif - - s = BestGuessReadableName(name); - - if (s != "" && add) - { - readableNamesDict.Add(name, s); - //Log.Info("GetReadableName, adding to readableNamesDict, name: [" + name + "], readableName: [" + s + "]"); - SaveReadableNames(); - } - - return s; - } - } - - - static string[] deleteLeading = new string[] { "Module", "CModule" }; - - /// - /// Given the input string, create a readable name from it using the specified rules - /// - /// - /// - static string BestGuessReadableName(string inputString, bool allowSpaces = false, bool capitalize = false) - { - //bool mk1 = (inputString == "mk1square"); - StringBuilder outputStr = new StringBuilder("", 25); - - // string outputString = ""; - // No change if any spaces in string - // lower followed by upper = word break - // numeric digit followed by upper = insert a dash - // Delete leading words: - // Module - // CModule - // - // Exclude the names in the blacklist - - if (blacklistNames.Contains(inputString)) - return ""; - - if (!allowSpaces && inputString.Contains(" ")) - { - return inputString; - } - for (int i = 0; i < 2; i++) - { - if (inputString.Length >= deleteLeading[i].Length && inputString.Substring(0, deleteLeading[i].Length) == deleteLeading[i]) - { - inputString = inputString.Remove(0, deleteLeading[i].Length); - } - } - - while (inputString.Length > 0 && - (!Char.IsDigit(inputString[0]) || - (inputString.Length > 1 && char.IsDigit(inputString[0]) && - ((!capitalize && char.IsUpper(inputString[1])) || (capitalize && char.IsLetter(inputString[1]))) - ) - ) - ) - { - // Capitalize the 2nd character if the first char is numeric - if (inputString.Length > 1 && - capitalize && - char.IsDigit(inputString[0]) && - char.IsLower(inputString[1])) - { - //if (mk1) Log.Info("mk1Debug 1: " + inputString); - - string tmp = inputString.Substring(0, 1); - tmp += Char.ToUpper(inputString[1]); - if (inputString.Length > 2) - tmp += inputString.Substring(2); - inputString = tmp; - //if (mk1) Log.Info("mk1Debug 2: " + inputString); - } - - // Capiutalize first char if requested - if (capitalize && outputStr.Length == 0) - outputStr.Append(Char.ToUpper(inputString[0])); - else - outputStr.Append(inputString[0]); - if (inputString.Length > 1) - { - if (Char.IsLower(inputString[0]) && char.IsUpper(inputString[1])) - { - outputStr.Append(" "); - } - if (char.IsDigit(inputString[0]) && char.IsUpper(inputString[1])) - { - outputStr.Append(" "); - } - } - inputString = inputString.Remove(0, 1); - } - if (capitalize && inputString.Length > 0) - return outputStr.ToString() + "-" + inputString; - else - return outputStr.ToString() + inputString; - } - - static List blacklistNames = new List(); -#if false - static private Dictionary mergeListDict; -#endif - static private SortedDictionary readableNamesDict; - static bool filtersConfigInitted = false; - - /// - /// Load data from the file:FiltersConfig.cfg - /// - void LoadFiltersConfig() - { - if (!filtersConfigInitted) - { - filtersConfigInitted = true; - readableNamesDict = new SortedDictionary(); -#if false - mergeListDict = new Dictionary(); -#endif - if (System.IO.File.Exists(JC_FILTER_CONFIG_FILE)) - { - configFile = ConfigNode.Load(JC_FILTER_CONFIG_FILE); - ConfigNode janitorsClosetNode = configFile.GetNode(JC_NODE); - if (janitorsClosetNode != null) - { - // - // Load the READABLENAMES node - // - configFileNode = janitorsClosetNode.GetNode(JC_READABLE_NAMES_NODE); - if (configFileNode != null) - { - for (int i = 0; i < configFileNode.CountValues; i++) - { - readableNamesDict[configFileNode.values[i].name] = configFileNode.values[i].value; - } - } - - - // - // - // Load the MODULE_BLACKLIST node - // - configFileNode = janitorsClosetNode.GetNode(JC_BLACKLIST_NODE); - if (configFileNode != null) - { - blacklistNames = configFileNode.GetValues("ignore").ToList(); - } - - // - // Now all the bulkhead profiles - // - if (partSizeDict == null) - { - partSizeDict = new SortedDictionary(); - - configFileNode = janitorsClosetNode.GetNode(JC_BULKHEADPROFILES); - if (configFileNode != null) - { - Log.Info(JC_BULKHEADPROFILES + " loaded: " + configFileNode.CountValues); - for (int i = 0; i < configFileNode.CountValues; i++) - { - PartSizeDescr psd = new PartSizeDescr(configFileNode.values[i].name, configFileNode.values[i].value); - - partSizeDict[configFileNode.values[i].name] = psd; - } - } - } - -#if false // Disabled for possible future update - // - // Load the MERGLIST node - // - configFileNode = janitorsClosetNode.GetNode(JC_MERGELIST_NODE); - if (configFileNode != null) - { - Log.Info("configFileNode is not null 3"); - - for (int i = 0; i < configFileNode.CountValues; i++) - { - mergeListDict[configFileNode.values[i].name] = configFileNode.values[i].value; - } - } -#endif - } - } - } - } - - /// - /// Write the updated data to the file FiltersConfig.cfg - /// - void SaveReadableNames() - { - Log.Info("SaveReadableNames"); - ConfigNode configFile = new ConfigNode(JC_NODE); - ConfigNode configJCnode = new ConfigNode(JC_NODE); - ConfigNode configFileNode = new ConfigNode(JC_READABLE_NAMES_NODE); - ConfigNode configBulkheadProfileNode = new ConfigNode(JC_BULKHEADPROFILES); - - if (blacklistNames != null) - { - ConfigNode configBLNode = new ConfigNode(JC_BLACKLIST_NODE); - foreach (var s in blacklistNames) - { - configBLNode.AddValue("ignore", s); - } - configJCnode.AddNode(JC_BLACKLIST_NODE, configBLNode); - } -#if false // disabled for possible future update - if (mergeListDict != null) - { - ConfigNode mergeListNode = new ConfigNode(JC_MERGELIST_NODE); - foreach (var s in mergeListDict) - { - mergeListNode.AddValue(s.Key, s.Value); - } - - configJCnode.AddNode(JC_MERGELIST_NODE, mergeListNode); - } -#endif - if (readableNamesDict != null) - { - foreach (var s in readableNamesDict) - { - configFileNode.AddValue(s.Key, s.Value); - } - configJCnode.SetNode(JC_READABLE_NAMES_NODE, configFileNode, true); - } - - - // - // Now all the bulkhead profiles - // - if (partSizeDict != null) - { - foreach (var s in partSizeDict) - { - configBulkheadProfileNode.AddValue(s.Key, s.Value.descr); - } - configJCnode.SetNode(JC_BULKHEADPROFILES, configBulkheadProfileNode, true); - } - - - configFile.SetNode(JC_NODE, configJCnode, true); - configFile.Save(JC_FILTER_CONFIG_FILE); - } - } -} \ No newline at end of file diff --git a/JanitorsCloset/EditorWindows/PermaPrune.cs b/JanitorsCloset/EditorWindows/PermaPrune.cs deleted file mode 100644 index 8265da6..0000000 --- a/JanitorsCloset/EditorWindows/PermaPrune.cs +++ /dev/null @@ -1,554 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Collections; -using System.Linq; -using System.Text; - -using UnityEngine; -using KSP.UI; -using KSP.UI.Screens; -using ClickThroughFix; - -using static JanitorsCloset.JanitorsClosetLoader; - - -namespace JanitorsCloset -{ - class PermaPruneWindow : MonoBehaviour - { - Rect _windowRect = new Rect() - { - xMin = Screen.width - 325, - xMax = Screen.width - 175, - yMin = Screen.height - 300, - yMax = 50 //0 height, GUILayout resizes it - }; - - public bool permapruneInProgress = false; - string _windowTitle = string.Empty; - - public static PermaPruneWindow Instance { get; private set; } - - void Awake() - { - Log.Info("PermaPruneWindow Awake()"); - this.enabled = false; - Instance = this; - } - - void Start() - { - - } - - void OnEnable() - { - Log.Info("PermaPruneWindow OnEnable()"); - - } - - public bool isEnabled() - { - return this.enabled; - } - - void CloseWindow() - { - this.enabled = false; - winState = winContent.menu; - Log.Info("PermaPruneWindow.CloseWindow enabled: " + this.enabled.ToString()); - } - - void OnDisable() - { - - } - - enum winContent - { - menu, - permaprune, - undo, - dialog, - close - } - - - int windowContentID = 0; - - winContent winState = winContent.menu; - MultiOptionDialog dialog; - void OnGUI() - { - - if (isEnabled()) - { - switch (winState) - { - case winContent.menu: - if (windowContentID == 0) - windowContentID = JanitorsCloset.getNextID(); - _windowTitle = string.Format("PermaPrune"); - var tstyle = new GUIStyle(GUI.skin.window); - - _windowRect.yMax = _windowRect.yMin; - _windowRect = ClickThruBlocker.GUILayoutWindow(windowContentID, _windowRect, WindowContent, _windowTitle, tstyle); - break; - - case winContent.permaprune: - dialog = new MultiOptionDialog("janitorsToolbar3", - "This will permanently rename files to prevent them from being loaded", "Permanent Prune", HighLogic.UISkin, new DialogGUIBase[] { - new DialogGUIButton ("OK", () => { - winState = winContent.close; - startPruner(); - // pruner(); - - }), - new DialogGUIButton ("Cancel", () => { - winState = winContent.close; - }) - }); - PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), dialog, false, HighLogic.UISkin, true); - winState = winContent.dialog; - break; - - case winContent.undo: - dialog = new MultiOptionDialog("janitorsToolbar4", - "This will permanently rename pruned files to allow them to be loaded", "Unprune (restore)", HighLogic.UISkin, new DialogGUIBase[] { - new DialogGUIButton ("OK", () => { - unpruner(); - winState = winContent.close; - }), - new DialogGUIButton ("Cancel", () => { - winState = winContent.close; - }) - }); - PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), dialog, false, HighLogic.UISkin, true); - winState = winContent.dialog; - break; - - case winContent.close: - CloseWindow(); - break; - } - - } - } - - List renamedFilesList = null; - public void RenameFile(string path, string name) - { - Log.Info("RenameFile, path: " + path + " name: " + name); -#if false - Log.Info("RenameFile, path: " + path + " name: " + name); - if (File.Exists(FileOperations.CONFIG_BASE_FOLDER + path)) - { - if (File.Exists(FileOperations.CONFIG_BASE_FOLDER + path + PRUNED)) - { - System.IO.File.Delete(FileOperations.CONFIG_BASE_FOLDER + path + PRUNED); - } - - Log.Info("Renaming: " + path + " to " + path + PRUNED); - ShowRenamed.Instance.addLine("Renaming: " + path + " to " + path + PRUNED); - System.IO.File.Move(FileOperations.CONFIG_BASE_FOLDER + path, FileOperations.CONFIG_BASE_FOLDER + path + PRUNED); - prunedPart pp = new prunedPart(); - pp.path = path + PRUNED; - pp.partName = name; - renamedFilesList.Add(pp); - } -#endif - prunedPart pp = FileOperations.Instance.RenameFile(path, name); - if (pp != null) - renamedFilesList.Add(pp); - } - - - public void stopPruner() - { - permapruneInProgress = false; - //StopCoroutine(pruning()); - } - - private void startPruner() - { - Log.Info("startPruner"); - - StartCoroutine(pruning()); - } - - /// - /// Get the partURL for the mesh - /// - /// - /// string - string GetMeshURL(AvailablePart pSearch) - { - if (pSearch == null) - { - Log.Info("GetMeshURL, pSearch is null"); - return ""; - } - if (pSearch.partConfig == null) - { - Log.Info("GetMeshURL, pSearch.partConfig is null"); - return ""; - } - string s = pSearch.partConfig.GetValue("mesh"); - - if (s != null && s != "") - { - string partUrl = pSearch.partUrlConfig.parent.url.Substring(0, pSearch.partUrlConfig.parent.url.LastIndexOf('/')); - s = partUrl + "/" + s.Substring(0, s.Length - 3); - } - return s; - } - - /// - /// Get the partURL for the part - /// - /// - /// - /// string - string GetModelURL(AvailablePart part, ConfigNode modelNode) - { - string model = modelNode.GetValue("model"); - - return model; - } - - const string PRUNED = ".prune"; - public IEnumerator pruning() - { - permapruneInProgress = true; - - Log.Info("PermaPrune.pruner"); - renamedFilesList = FileOperations.Instance.loadRenamedFiles(); - Log.Info("sizeof renamedFilesList: " + renamedFilesList.Count.ToString()); - Log.Info("pruner, sizeof blacklist:" + JanitorsCloset.blackList.Count.ToString()); - ShowRenamed.Instance.ShowRenamedWin(); - - List prunedParts = new List(); - foreach (blackListPart blp in JanitorsCloset.blackList.Values) - { - - yield return 0; - Log.Info("permapruneInProgress: " + permapruneInProgress.ToString()); - if (!permapruneInProgress) - break; - if (blp.where != blackListType.ALL || blp.permapruned) - continue; - Log.Info("pruned part: " + blp.modName); - - //AvailablePart part = PartLoader.Instance.parts.Find(item => item.name.Equals(blp.modName)); - AvailablePart part = PartLoader.getPartInfoByName(blp.modName); - if (part == null) - continue; - prunedParts.Add(blp.modName); - - // Rename cfg file - - string s1 = part.configFileFullName.Substring(part.configFileFullName.IndexOf("GameData") + 9); - - RenameFile(s1, part.name); - - string partPath = part.partUrl; - - for (int x = 0; x < 1; x++) - { - int backslash = partPath.LastIndexOf('\\'); - int slash = partPath.LastIndexOf('/'); - int i = Math.Max(backslash, slash); - partPath = partPath.Substring(0, i); - } - partPath += "/"; - - // rename resource file - // Look for model = - // model has complete path - // Look for mesh = - // with mesh, get patch from cfg file path - - Log.Info("searching for model"); - Log.Info("Part: " + part.name); - - ConfigNode[] nodes = part.partConfig.GetNodes("MODEL"); - ConfigNode[] nodes2; - bool b; -#if true - if (nodes != null) - { - Log.Info("Nodes count: " + nodes.Length.ToString()); - foreach (ConfigNode modelNode in nodes) - { - - b = false; - if (modelNode != null) - { - Log.Info("modelNode: " + modelNode.name); - string model = GetModelURL(part, modelNode); - Log.Info("ModelUrl: " + GetModelURL(part, modelNode)); - if (model != null) - { - Log.Info("model: " + model); - // Make sure it isn't being used in another part - b = false; - Log.Info("Part count: " + PartLoader.LoadedPartsList.Count.ToString()); - - string s; - foreach (AvailablePart pSearch in PartLoader.LoadedPartsList) - { - Log.Info("pSearch: " + pSearch.name); - if (part != pSearch && pSearch.partConfig != null) - { - nodes2 = pSearch.partConfig.GetNodes("MODEL"); - if (nodes2 != null) - { - Log.Info("nodes2"); - foreach (ConfigNode searchNode in nodes2) - { - if (searchNode != null) - { - Log.Info("searchNode"); - if (model == GetModelURL(pSearch, searchNode)) - { - b = true; - break; - } - } - } - } - - s = GetMeshURL(pSearch); - Log.Info("Mesh URL: " + GetMeshURL(pSearch) + " ModelUrl: " + GetModelURL(part, modelNode)); - - if (GetMeshURL(pSearch) == model) - { - b = true; - break; - } - } - if (b) - break; - } - } - - if (!b) - { - Log.Info("MODEL: " + model); - string mURL = FindTexturePathFromModel.getModelURL(model); - Log.Info("MODEL URL: " + mURL); - model = model + ".mu"; - - RenameFile(model, part.name); - } - } - } - } -#endif - yield return 0; - if (!permapruneInProgress) - break; - Log.Info("searching for meshes"); - string mesh = GetMeshURL(part); - if (mesh != null && mesh != "") - { - // Make sure it isn't being used in another part - b = false; - foreach (AvailablePart pSearch in PartLoader.LoadedPartsList) - { - if (part != pSearch) - { - string searchMesh = GetMeshURL(pSearch); - - if (searchMesh == mesh) - { - b = true; - break; - } - - - if (pSearch.partConfig != null) - { - nodes2 = pSearch.partConfig.GetNodes("MODEL"); - if (nodes2 != null) - { - foreach (ConfigNode searchNode in nodes2) - { - if (searchNode != null) - { - string model = GetModelURL(pSearch, searchNode); - - if (mesh == model) - { - b = true; - break; - } - - } - } - } - } - } - } - if (!b) - { - Log.Info("Renaming mesh: " + mesh + " partPath: " + partPath); - - string mURL = FindTexturePathFromModel.getModelURL(mesh); - partPath = partPath.Substring(0, partPath.LastIndexOf("/")) + "/"; - if (!(mesh.Contains("/") || mesh.Contains("\\"))) - mesh = partPath + mesh; - - RenameFile(mesh, part.name); - } - } - - // this gets the model - Log.Info("searching for model (INTERNAL)"); - nodes = part.partConfig.GetNodes("INTERNAL"); - if (nodes != null) - foreach (ConfigNode internalNode in nodes) - { - if (internalNode != null) - { - UrlDir.UrlConfig config; - if (GetInternalSpaceConfigUrl.FindInternalSpaceConfigByName(internalNode.GetValue("name"), out config)) - { - // Make sure it isn't being used in another part - b = false; - foreach (AvailablePart pSearch in PartLoader.Instance.parts) - { - if (part != pSearch) - { - nodes2 = part.partConfig.GetNodes("INTERNAL"); - if (nodes2 != null) - foreach (ConfigNode internalNodeSearch in nodes2) - { - UrlDir.UrlConfig configSearch; - if (GetInternalSpaceConfigUrl.FindInternalSpaceConfigByName(internalNode.GetValue("name"), out configSearch)) - { - if (configSearch.url == config.url) - { - b = true; - break; - } - } - if (b) break; - } - } - if (b) break; - } - if (!b) - { - string s = config.url.Substring(0, config.url.LastIndexOf("/")) + ".cfg"; - RenameFile(s, part.name); - } - } - - // - // We aren't going to check to see if the different models inside the space are - // used elsewhere. An assumption that the same model won't be used by multiple spaces - // - Log.Info("searching for internal space nodes"); - ConfigNode cfgNode; - bool b1 = GetInternalSpaceConfigUrl.FindInternalSpaceConfigNode(config.name, out cfgNode); - if (b1) - { - nodes = cfgNode.GetNodes("MODEL"); - if (nodes != null) - foreach (ConfigNode modelNode in nodes) - { - string model = modelNode.GetValue("model"); - //Log.Info("MODEL: " + model); - string mURL = FindTexturePathFromModel.getModelURL(model); - // Log.Info("MODEL URL: " + mURL); - model = model + ".mu"; - RenameFile(model, part.name); - } - - } - } - } - } - foreach (var s in prunedParts) - { - blackListPart blp = JanitorsCloset.blackList[s]; - blp.permapruned = true; - JanitorsCloset.blackList[s] = blp; - } - - Log.Info("before saveRenamedFiles"); - FileOperations.Instance.saveRenamedFiles(renamedFilesList); - permapruneInProgress = false; - - yield break; - //JanitorsCloset.Instance.clearBlackList(); - } - - void unpruner() - { - ShowRenamed.Instance.ShowRenamedWin(); - renamedFilesList = FileOperations.Instance.loadRenamedFiles(); - foreach (prunedPart l in renamedFilesList) - { - l.path = FileOperations.CONFIG_BASE_FOLDER + l.path; - Log.Info("Renaming " + l.path + " to " + l.path.Substring(0, l.path.Length - PRUNED.Length)); - if (File.Exists(l.path)) - { - Log.Info("Renaming " + l.path + " to " + l.path.Substring(0, l.path.Length - PRUNED.Length)); - ShowRenamed.Instance.addLineToRenamedList("Renaming " + l.path + " to " + l.path.Substring(0, l.path.Length - PRUNED.Length)); - if (!File.Exists(l.path.Substring(0, l.path.Length - PRUNED.Length))) - System.IO.File.Move(l.path, l.path.Substring(0, l.path.Length - PRUNED.Length)); - else - System.IO.File.Delete(l.path); - } - if (JanitorsCloset.blackList.ContainsKey(l.partName)) - { - blackListPart blp; - JanitorsCloset.blackList.TryGetValue(l.partName, out blp); - blp.permapruned = false; - - } - } - FileOperations.Instance.delRenamedFilesList(); - } - - - void WindowContent(int windowID) - { - GUILayout.BeginVertical(); - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Permanent Prune")) - { - winState = winContent.permaprune; - // pruner(); - // CloseWindow(); - } - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Undo Permanent Prune")) - { - winState = winContent.undo; - //unpruner(); - //CloseWindow(); - } - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Cancel")) - { - CloseWindow(); - } - - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - GUI.DragWindow(); - } - - public void Show() - { - Log.Info("PermaPrune Show()"); - this.enabled = true; - } - } -} diff --git a/JanitorsCloset/EditorWindows/ShowBlocked.cs b/JanitorsCloset/EditorWindows/ShowBlocked.cs deleted file mode 100644 index 39cbae0..0000000 --- a/JanitorsCloset/EditorWindows/ShowBlocked.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.UI; -using KSP.UI; -using KSP.UI.Screens; -using ClickThroughFix; - -using static JanitorsCloset.JanitorsClosetLoader; - -namespace JanitorsCloset -{ - class ShowBlocked : MonoBehaviour - { - const int WIDTH = 400; - const int HEIGHT = 500; - - List blpList; - - Rect _windowRect = new Rect() - { - xMin = 0, - xMax = WIDTH, - yMin = 0, - yMax = HEIGHT - }; - - - public static ShowBlocked Instance { get; private set; } - - void Awake() - { - Log.Info("ShowBlocked Awake()"); - this.enabled = false; - Instance = this; - _windowRect.center = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f); - } - - public void Show() - { - enabled = true; - //blpList.AddRange(JanitorsCloset.blackList.values); - blpList = new List(JanitorsCloset.blackList.Values); - blpList.Sort((x, y) => x.modName.CompareTo(y.modName)); - - } - - public bool isEnabled() - { - return this.enabled; - } - - void CloseWindow() - { - this.enabled = false; - - Log.Info("ShowBlocked.CloseWindow enabled: " + this.enabled.ToString()); - } - - int blockedWindowContentID = 0; - - void OnGUI() - { - if (isEnabled()) - { - if (blockedWindowContentID == 0) - blockedWindowContentID = JanitorsCloset.getNextID(); - var tstyle = new GUIStyle(GUI.skin.window); - - _windowRect = ClickThruBlocker.GUILayoutWindow(blockedWindowContentID, _windowRect, BlockedWindowContent, "Show Blocked Parts", tstyle); - } - } - - - public void clearBlackList() - { - JanitorsCloset.blackList.Clear(); - EditorPartList.Instance.Refresh(); - FileOperations.Instance.saveBlackListData(JanitorsCloset.blackList); - } - - Vector2 sitesScrollPosition; - const int LINEHEIGHT = 30; - - const int MODNAMEWIDTH = 225; - const int WHEREWIDTH = 55; - - bool sortAscending = true; - string lastSort = ""; - - void BlockedWindowContent(int windowID) - { - string unblock = ""; - blackListPart unblockBlp = null; - - GUILayout.BeginVertical(); - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Mod Name", GUILayout.Width(MODNAMEWIDTH))) - { - if (lastSort != "modname") - sortAscending = true; - else - sortAscending = !sortAscending; - if (sortAscending) - blpList.Sort((x, y) => x.title.CompareTo(y.title)); - else - blpList.Sort((y, x) => x.title.CompareTo(y.title)); - lastSort = "modname"; - } - if (GUILayout.Button("Where", GUILayout.Width(WHEREWIDTH))) - { - if (lastSort != "where") - sortAscending = true; - else - sortAscending = !sortAscending; - if (sortAscending) - blpList.Sort((x, y) => x.where.CompareTo(y.where)); - else - blpList.Sort((y, x) => x.where.CompareTo(y.where)); - lastSort = "where"; - } - if (GUILayout.Button("Unblock All")) - { - clearBlackList(); - CloseWindow(); - } - GUILayout.EndHorizontal(); - sitesScrollPosition = GUILayout.BeginScrollView(sitesScrollPosition, false, true, GUILayout.Height(HEIGHT - LINEHEIGHT)); - - // foreach (var blp in JanitorsCloset.blackList) - foreach (var blp in blpList) - { - GUILayout.BeginHorizontal(); - GUILayout.Label(blp.title, GUILayout.Width(MODNAMEWIDTH)); - GUILayout.Label(blp.where.ToString(), GUILayout.Width(WHEREWIDTH)); - - GUILayout.FlexibleSpace(); - //AvailablePart p = PartLoader.Instance.parts.Find(item => item.name.Equals(blp.modName)); - AvailablePart p = PartLoader.getPartInfoByName(blp.modName); - - - if (p == null || blp.permapruned) - GUI.enabled = false; - if (GUILayout.Button("Unblock", GUILayout.ExpandWidth(true))) - { - unblock = blp.modName; - unblockBlp = blp; - } - GUI.enabled = true; - GUILayout.EndHorizontal(); - } - - GUILayout.EndScrollView(); - - - GUILayout.BeginHorizontal(); - if (GUILayout.Button("OK")) - { - CloseWindow(); - } - GUILayout.EndHorizontal(); - - GUILayout.EndVertical(); - GUI.DragWindow(); - - if (unblock != "") - { - JanitorsCloset.blackList.Remove(unblock); - EditorPartList.Instance.Refresh(); - blpList.Remove(unblockBlp); - - } - - } - } -} diff --git a/JanitorsCloset/EditorWindows/ShowRenamed.cs b/JanitorsCloset/EditorWindows/ShowRenamed.cs deleted file mode 100644 index 348fc94..0000000 --- a/JanitorsCloset/EditorWindows/ShowRenamed.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; -using ClickThroughFix; - -using static JanitorsCloset.JanitorsClosetLoader; - - -namespace JanitorsCloset -{ - class ShowRenamed : MonoBehaviour - { - //const int WIDTH = Screen.width - 200; - const int RENAMED_WIN_HEIGHT = 500; - - List renamedList; - - Rect renamedWindowRect = new Rect() - { - xMin = 0, - xMax = UnityEngine.Screen.width - 300, - yMin = 0, - yMax = RENAMED_WIN_HEIGHT - }; - - - public static ShowRenamed Instance { get; private set; } - - void Awake() - { - Log.Info("ShowRenamed Awake()"); - this.enabled = false; - Instance = this; - renamedWindowRect.center = new Vector2(UnityEngine.Screen.width * 0.5f, UnityEngine.Screen.height * 0.5f); - } - - public void ShowRenamedWin() - { - enabled = true; - renamedList = new List(); - } - - public void addLineToRenamedList(string str) - { - renamedList.Add(str); - } - - public bool isEnabled() - { - return this.enabled; - } - - void CloseRenamedWindow() - { - this.enabled = false; - - Log.Info("ShowRenamed.CloseWindow enabled: " + this.enabled.ToString()); - } - - int renamedWindowContentID = 0; - void OnGUI() - { - if (isEnabled()) - { - if (renamedWindowContentID == 0) - renamedWindowContentID = JanitorsCloset.getNextID(); - var tstyle = new GUIStyle(GUI.skin.window); - renamedWindowRect = ClickThruBlocker.GUILayoutWindow(renamedWindowContentID, renamedWindowRect, ShowRenamedWindowContent, "Show PermaPruned Parts", tstyle); - } - } - - Vector2 sitesScrollPosition; - const int LINEHEIGHT = 30; - - const int MODNAMEWIDTH = 225; - const int WHEREWIDTH = 55; - - private Rect innerCoords; - - void ShowRenamedWindowContent(int windowID) - { - innerCoords = new Rect(0, LINEHEIGHT, UnityEngine.Screen.width - 300, RENAMED_WIN_HEIGHT - 2 * LINEHEIGHT); - - GUILayout.BeginVertical(); - -#if false - sitesScrollPosition = GUILayout.BeginScrollView(sitesScrollPosition, false, true, GUILayout.Height(HEIGHT - LINEHEIGHT)); - foreach (var blp in renamedList) - { - GUILayout.BeginHorizontal(); - GUILayout.Label(blp); - - GUILayout.EndHorizontal(); - } - - GUILayout.EndScrollView(); -#endif - string t = ""; - foreach (var blp in renamedList) - t += blp + "\n"; -// GUILayout.BeginArea(innerCoords); - sitesScrollPosition = GUILayout.BeginScrollView(sitesScrollPosition, false, true, GUILayout.Height(RENAMED_WIN_HEIGHT - LINEHEIGHT)); - //GUI.enabled = false; - GUILayout.Label(t); - //GUI.enabled = true; - GUILayout.EndScrollView(); - // GUILayout.EndArea(); - - GUILayout.FlexibleSpace(); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (!PermaPruneWindow.Instance.permapruneInProgress) - { - if (GUILayout.Button(" Close ")) - { - CloseRenamedWindow(); - } - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Copy to clipboard")) - { - GUIUtility.systemCopyBuffer = t; - } - } - else - { - if (GUILayout.Button(" Cancel ")) - { - PermaPruneWindow.Instance.stopPruner(); - } - - } - - GUILayout.EndHorizontal(); - - GUILayout.EndVertical(); - GUI.DragWindow(); - } - } -} diff --git a/JanitorsCloset/PermaPrune.cs b/JanitorsCloset/PermaPrune.cs index c7be6ab..d23c466 100644 --- a/JanitorsCloset/PermaPrune.cs +++ b/JanitorsCloset/PermaPrune.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Collections.Generic; using System.Collections; @@ -6,6 +6,7 @@ using System.Text; using UnityEngine; +using EdyCommonTools; using KSP.UI; using KSP.UI.Screens; using ClickThroughFix; @@ -217,7 +218,7 @@ string GetModelURL(AvailablePart part, ConfigNode modelNode) return model; } - const string PRUNED = ".prune"; + private const string PRUNED = ".prune"; public IEnumerator pruning() { permapruneInProgress = true; @@ -482,10 +483,47 @@ public IEnumerator pruning() FileOperations.Instance.saveRenamedFiles(renamedFilesList); permapruneInProgress = false; + UpdateCKANFilters(Path.Combine(KSPUtil.ApplicationRootPath, + "CKAN", + "install_filters.json"), + renamedFilesList); + yield break; //JanitorsCloset.Instance.clearBlackList(); } + private void UpdateCKANFilters(string filterPath, + IEnumerable pruned) + { + try + { + // Create or overwrite if parent directory exists + if (Directory.Exists(Path.GetDirectoryName(filterPath))) + { + File.WriteAllText(filterPath, + MiniJSON.jsonEncode( + GetCKANFilters(filterPath) + .Concat(pruned.Select(OriginalGameDataRelativePath)) + .Distinct() + .ToArray())); + } + } + catch + { + // Never disrupt the outer program with exceptions + } + } + + private IEnumerable GetCKANFilters(string path) + => File.Exists(path) + ? MiniJsonExtensions.arrayListFromJson(File.ReadAllText(path)) + .OfType() + : Enumerable.Empty(); + + private static string OriginalGameDataRelativePath(prunedPart pp) + => Path.Combine("GameData", pp.path.Replace("\\", "/") + .Replace(PRUNED, "")); + void unpruner() { ShowRenamed.Instance.Show();