public void UnHighlightAll() { highLight = false; for (int i = 0; i < stages.Count; i++) //foreach (EditorStatItem stage in stages) { EditorStatItem stage = stages[i]; stage.UnHighlight(); } }
public void HighlightAll() { highLight = true; for (int i = 0; i < stages.Count; i++) //foreach (EditorStatItem stage in stages) { EditorStatItem stage = stages[i]; stage.Highlight(tanksDry); } }
public void BreakShipIntoStages() { stages.Clear(); //loop through the part tree and try to break it into stages List <Part> parts = EditorLogic.fetch.ship.parts; EditorStatItem current = new EditorStatItem(); int stageNum = 0; StageParts stage = new StageParts(); List <Part> RemainingDecouplers = null; // = new List<Part>() { parts[0] }; foreach (var p in parts) { if (p.parent == null) { RemainingDecouplers = new List <Part>() { p }; break; } } if (RemainingDecouplers == null) { Log.Error("No parent part found"); return; } while (RemainingDecouplers.Count > 0) { //determine stages from the decouplers Part parent = RemainingDecouplers[0]; RemainingDecouplers.RemoveAt(0); stage = DetermineStage(parent); current = new EditorStatItem { stageNumber = stageNum++, parts = stage.parts }; RemainingDecouplers.AddRange(stage.decouplers); //compute properties double dryMass = 0; double wetMass = 0; stage.parts.ForEach(p => { dryMass += p.mass; wetMass += p.mass + p.GetResourceMass(); }); current.dryMass = dryMass; current.mass = wetMass; current.chuteArea = StageRecovery.GetChuteArea(stage.parts); stages.Add(current); } ConsolidateStages(); Log.Info("[SR] Found " + stages.Count + " stages!"); }
public void ConsolidateStages() { //finds identical (and adjacent) stages in the list and merges them into a single master stage //must find all identical stages first, then merge EditorStatItem compareItem = null; for (int i = 0; i < stages.Count; i++) { EditorStatItem stage = stages[i]; // if (compareItem == null) compareItem = stage; int j = i + 1; while (j < stages.Count) { if (stages[j].parts.Count != compareItem.parts.Count || stages[j].mass != compareItem.mass || stages[j].chuteArea != compareItem.chuteArea) { //probably not the same stage setup break; } j++; } if (j > i + 1) { Log.Info("[SR] Found " + (j - i) + " identical stages"); //some stages are the same (up to j) //merge the stages for (int k = j - 1; k > i; k--) { //add the parts from k to i stages[i].parts.AddRange(stages[k].parts); stages.RemoveAt(k); } stages[i].ForceRecalculate(); } } }
public void DrawEditorGUI(int windowID) { GUILayout.BeginVertical(); //provide toggles to turn highlighting on/off if (GUILayout.Button("Toggle Vessel Highlighting")) { highLight = !highLight; if (highLight) { HighlightAll(); } else { UnHighlightAll(); } } if (GUILayout.Button("Tanks: " + (tanksDry ? "Empty" : "Full"))) { tanksDry = !tanksDry; if (highLight) { HighlightAll(); } } //list each stage, with info for each for (int i = 0; i < stages.Count; i++) //foreach (EditorStatItem stage in stages) { EditorStatItem stage = stages[i]; GUILayout.BeginHorizontal(); GUILayout.Label("Stage " + stage.stageNumber); double vel = tanksDry ? stage.EmptyVelocity : stage.FullVelocity; GUILayout.Label(vel.ToString("N1") + " m/s"); GUILayout.Label(stage.GetRecoveryPercent(tanksDry) + "%"); // GUILayout.Label("("+stage.FullVelocity.ToString("N1") + ")"); if (GUILayout.Button("Highlight")) { //highlight this stage and unhighlight all others bool status = stage.Highlighted; if (highLight) { status = false; } UnHighlightAll(); stage.SetHighlight(!status, tanksDry); } GUILayout.EndHorizontal(); } if (GUILayout.Button("Recalculate")) { Recalculate(); #if false BreakShipIntoStages(); if (highLight) { HighlightAll(); } EditorGUIRect.height = 1; //reset the height so it is the smallest size it needs to be #endif } GUILayout.EndVertical(); /* if (GUI.Button(new Rect(EditorGUIRect.xMax-10, EditorGUIRect.yMin, 10, 10), "X")) * { * UnHighlightAll(); * showEditorGUI = false; * }*/ //Make it draggable if (!Input.GetMouseButtonDown(1) && !Input.GetMouseButtonDown(2)) { GUI.DragWindow(); } }
public void BreakShipIntoStages() { stages.Clear(); //loop through the part tree and try to break it into stages List <Part> parts = EditorLogic.fetch.ship.parts; EditorStatItem current = new EditorStatItem(); int stageNum = 0; bool realChuteInUse = false; StageParts stage = new StageParts(); List <Part> RemainingDecouplers = new List <Part>() { parts[0] }; while (RemainingDecouplers.Count > 0) { //determine stages from the decouplers Part parent = RemainingDecouplers[0]; RemainingDecouplers.RemoveAt(0); stage = DetermineStage(parent); current = new EditorStatItem(); current.stageNumber = stageNum++; current.parts = stage.parts; RemainingDecouplers.AddRange(stage.decouplers); //compute properties foreach (Part part in stage.parts) { current.dryMass += part.mass; current.mass += part.mass + part.GetResourceMass(); double pChutes = 0; if (part.Modules.Contains("RealChuteModule")) { PartModule realChute = part.Modules["RealChuteModule"]; ConfigNode rcNode = new ConfigNode(); realChute.Save(rcNode); //This is where the Reflection starts. We need to access the material library that RealChute has, so we first grab it's Type Type matLibraryType = AssemblyLoader.loadedAssemblies .SelectMany(a => a.assembly.GetExportedTypes()) .SingleOrDefault(t => t.FullName == "RealChute.Libraries.MaterialsLibrary.MaterialsLibrary"); //We make a list of ConfigNodes containing the parachutes (usually 1, but now there can be any number of them) //We get that from the PPMS ConfigNode[] parachutes = rcNode.GetNodes("PARACHUTE"); //We then act on each individual parachute in the module foreach (ConfigNode chute in parachutes) { //First off, the diameter of the parachute. From that we can (later) determine the Vt, assuming a circular chute float diameter = float.Parse(chute.GetValue("deployedDiameter")); //The name of the material the chute is made of. We need this to get the actual material object and then the drag coefficient string mat = chute.GetValue("material"); //This grabs the method that RealChute uses to get the material. We will invoke that with the name of the material from before. System.Reflection.MethodInfo matMethod = matLibraryType.GetMethod("GetMaterial", new Type[] { mat.GetType() }); //In order to invoke the method, we need to grab the active instance of the material library object MatLibraryInstance = matLibraryType.GetProperty("Instance").GetValue(null, null); //With the library instance we can invoke the GetMaterial method (passing the name of the material as a parameter) to receive an object that is the material object materialObject = matMethod.Invoke(MatLibraryInstance, new object[] { mat }); //With that material object we can extract the dragCoefficient using the helper function above. float dragC = (float)StageRecovery.GetMemberInfoValue(materialObject.GetType().GetMember("DragCoefficient")[0], materialObject); //Now we calculate the RCParameter. Simple addition of this doesn't result in perfect results for Vt with parachutes with different diameter or drag coefficients //But it works perfectly for mutiple identical parachutes (the normal case) pChutes += dragC * (float)Math.Pow(diameter, 2); } realChuteInUse = true; } else if (part.Modules.Contains("RealChuteFAR")) //RealChute Lite for FAR { PartModule realChute = part.Modules["RealChuteFAR"]; float diameter = (float)realChute.Fields.GetValue("deployedDiameter"); // = float.Parse(realChute.moduleValues.GetValue("deployedDiameter")); float dragC = 1.0f; //float.Parse(realChute.moduleValues.GetValue("staticCd")); pChutes += dragC * (float)Math.Pow(diameter, 2); realChuteInUse = true; } else if (!realChuteInUse && part.Modules.Contains("ModuleParachute")) { double scale = 1.0; //check for Tweakscale and modify the area appropriately if (part.Modules.Contains("TweakScale")) { PartModule tweakScale = part.Modules["TweakScale"]; double currentScale = 100, defaultScale = 100; double.TryParse(tweakScale.Fields.GetValue("currentScale").ToString(), out currentScale); double.TryParse(tweakScale.Fields.GetValue("defaultScale").ToString(), out defaultScale); scale = currentScale / defaultScale; } ModuleParachute mp = (ModuleParachute)part.Modules["ModuleParachute"]; //dragCoeff += part.mass * mp.fullyDeployedDrag; pChutes += mp.areaDeployed * Math.Pow(scale, 2); } current.chuteArea += pChutes; } stages.Add(current); } ConsolidateStages(); Debug.Log("[SR] Found " + stages.Count + " stages!"); }
public void DrawEditorGUI(int windowID) { GUILayout.BeginVertical(); //provide toggles to turn highlighting on/off if (GUILayout.Button(Localizer.Format("#StageRecovery_Highlight")))//"Toggle Vessel Highlighting" { highLight = !highLight; if (highLight) { HighlightAll(); } else { UnHighlightAll(); } } if (GUILayout.Button(Localizer.Format("#StageRecovery_TanksDry", (tanksDry ? Localizer.Format("#StageRecovery_TanksEmpty") :Localizer.Format("#StageRecovery_TanksFull")))))//"Tanks: " + "Empty" : "Full" { tanksDry = !tanksDry; if (highLight) { HighlightAll(); } } //list each stage, with info for each for (int i = 0; i < stages.Count; i++) //foreach (EditorStatItem stage in stages) { EditorStatItem stage = stages[i]; GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("", stage.stageNumber));//"Stage " + double vel = tanksDry ? stage.EmptyVelocity : stage.FullVelocity; GUILayout.Label(vel.ToString("N1") + " m/s"); GUILayout.Label(stage.GetRecoveryPercent(tanksDry) + "%"); // GUILayout.Label("("+stage.FullVelocity.ToString("N1") + ")"); if (GUILayout.Button(Localizer.Format("#StageRecovery_Highlight2")))//"Highlight" { //highlight this stage and unhighlight all others bool status = stage.Highlighted; if (highLight) { status = false; } UnHighlightAll(); stage.SetHighlight(!status, tanksDry); } GUILayout.EndHorizontal(); } if (GUILayout.Button(Localizer.Format("#StageRecovery_Recalculate")))//"Recalculate" { Recalculate(); } GUILayout.EndVertical(); /* if (GUI.Button(new Rect(EditorGUIRect.xMax-10, EditorGUIRect.yMin, 10, 10), "X")) * { * UnHighlightAll(); * showEditorGUI = false; * }*/ //Make it draggable if (!Input.GetMouseButtonDown(1) && !Input.GetMouseButtonDown(2)) { GUI.DragWindow(); } }
public void BreakShipIntoStages() { //loop through the part tree and try to break it into stages List <Part> parts = EditorLogic.fetch.ship.parts; EditorStatItem current = new EditorStatItem(); int stageNum = 0; StageParts stage = new StageParts(); List <Part> RemainingDecouplers = null; // = new List<Part>() { parts[0] }; for (int i = 0; i < parts.Count; i++) { Part p = parts[i]; if (p.parent == null) { RemainingDecouplers = new List <Part>() { p }; break; } } if (RemainingDecouplers == null) { stages.Clear(); Log.Error("No parent part found"); return; } var stageList = new List <EditorStatItem>(); while (RemainingDecouplers.Count > 0) { //determine stages from the decouplers Part parent = RemainingDecouplers[0]; RemainingDecouplers.RemoveAt(0); stage = DetermineStage(parent); current = new EditorStatItem { stageNumber = stageNum++, parts = stage.parts }; #if DEBUG Log.Info("Parent part: " + parent.partInfo.title); foreach (var d in stage.decouplers) { Log.Info("Child decouplers: " + d.partInfo.title); } #endif RemainingDecouplers.AddRange(stage.decouplers); //compute properties double dryMass = 0; double wetMass = 0; stage.parts.ForEach(p => { dryMass += p.mass; wetMass += p.mass + p.GetResourceMass(); }); current.dryMass = dryMass; current.mass = wetMass; current.chuteArea = StageRecovery.GetChuteArea(stage.parts); stageList.Add(current); } ConsolidateStages(ref stageList); stages.Clear(); // wait until we have a full stages collection before we clear it stages.AddRange(stageList); Log.Info("[SR] Found " + stages.Count + " stages!"); }
public void BreakShipIntoStages() { stages.Clear(); //loop through the part tree and try to break it into stages List<Part> parts = EditorLogic.fetch.ship.parts; EditorStatItem current = new EditorStatItem(); int stageNum = 0; bool realChuteInUse = false; StageParts stage = new StageParts(); List<Part> RemainingDecouplers = new List<Part>() { parts[0] }; while (RemainingDecouplers.Count > 0) { //determine stages from the decouplers Part parent = RemainingDecouplers[0]; RemainingDecouplers.RemoveAt(0); stage = DetermineStage(parent); current = new EditorStatItem(); current.stageNumber = stageNum++; current.parts = stage.parts; RemainingDecouplers.AddRange(stage.decouplers); //compute properties foreach (Part part in stage.parts) { current.dryMass += part.mass; current.mass += part.mass + part.GetResourceMass(); double pChutes = 0; if (part.Modules.Contains("RealChuteModule")) { PartModule realChute = part.Modules["RealChuteModule"]; ConfigNode rcNode = new ConfigNode(); realChute.Save(rcNode); //This is where the Reflection starts. We need to access the material library that RealChute has, so we first grab it's Type Type matLibraryType = AssemblyLoader.loadedAssemblies .SelectMany(a => a.assembly.GetExportedTypes()) .SingleOrDefault(t => t.FullName == "RealChute.Libraries.MaterialsLibrary.MaterialsLibrary"); //We make a list of ConfigNodes containing the parachutes (usually 1, but now there can be any number of them) //We get that from the PPMS ConfigNode[] parachutes = rcNode.GetNodes("PARACHUTE"); //We then act on each individual parachute in the module foreach (ConfigNode chute in parachutes) { //First off, the diameter of the parachute. From that we can (later) determine the Vt, assuming a circular chute float diameter = float.Parse(chute.GetValue("deployedDiameter")); //The name of the material the chute is made of. We need this to get the actual material object and then the drag coefficient string mat = chute.GetValue("material"); //This grabs the method that RealChute uses to get the material. We will invoke that with the name of the material from before. System.Reflection.MethodInfo matMethod = matLibraryType.GetMethod("GetMaterial", new Type[] { mat.GetType() }); //In order to invoke the method, we need to grab the active instance of the material library object MatLibraryInstance = matLibraryType.GetProperty("Instance").GetValue(null, null); //With the library instance we can invoke the GetMaterial method (passing the name of the material as a parameter) to receive an object that is the material object materialObject = matMethod.Invoke(MatLibraryInstance, new object[] { mat }); //With that material object we can extract the dragCoefficient using the helper function above. float dragC = (float)StageRecovery.GetMemberInfoValue(materialObject.GetType().GetMember("DragCoefficient")[0], materialObject); //Now we calculate the RCParameter. Simple addition of this doesn't result in perfect results for Vt with parachutes with different diameter or drag coefficients //But it works perfectly for mutiple identical parachutes (the normal case) pChutes += dragC * (float)Math.Pow(diameter, 2); } realChuteInUse = true; } else if (part.Modules.Contains("RealChuteFAR")) //RealChute Lite for FAR { PartModule realChute = part.Modules["RealChuteFAR"]; float diameter = (float)realChute.Fields.GetValue("deployedDiameter"); // = float.Parse(realChute.moduleValues.GetValue("deployedDiameter")); float dragC = 1.0f; //float.Parse(realChute.moduleValues.GetValue("staticCd")); pChutes += dragC * (float)Math.Pow(diameter, 2); realChuteInUse = true; } else if (!realChuteInUse && part.Modules.Contains("ModuleParachute")) { double scale = 1.0; //check for Tweakscale and modify the area appropriately if (part.Modules.Contains("TweakScale")) { PartModule tweakScale = part.Modules["TweakScale"]; double currentScale = 100, defaultScale = 100; double.TryParse(tweakScale.Fields.GetValue("currentScale").ToString(), out currentScale); double.TryParse(tweakScale.Fields.GetValue("defaultScale").ToString(), out defaultScale); scale = currentScale / defaultScale; } ModuleParachute mp = (ModuleParachute)part.Modules["ModuleParachute"]; //dragCoeff += part.mass * mp.fullyDeployedDrag; pChutes += mp.areaDeployed * Math.Pow(scale, 2); } current.chuteArea += pChutes; } stages.Add(current); } ConsolidateStages(); Debug.Log("[SR] Found " + stages.Count + " stages!"); }