//Lists the errors of a given type private List <string> GetErrors(string type) { if (type == "general") { List <string> general = new List <string>(); if (!RCUtils.CanParseTime(timer) || !RCUtils.CheckRange(RCUtils.ParseTime(timer), 0, 3600)) { general.Add("Deployment timer"); } if (!RCUtils.CanParseWithEmpty(spares) || !RCUtils.CheckRange(RCUtils.ParseWithEmpty(spares), -1, 10) || !RCUtils.IsWholeNumber(RCUtils.ParseWithEmpty(spares))) { general.Add("Spare chutes"); } if (!RCUtils.CanParse(cutSpeed) || !RCUtils.CheckRange(float.Parse(cutSpeed), 0.01f, 100)) { general.Add("Autocut speed"); } return(general); } else if (type == "main") { return(main.errors); } else if (type == "secondary") { return(secondary.errors); } return(new List <string>()); }
public override void OnStart(PartModule.StartState state) { if ((!HighLogic.LoadedSceneIsEditor && !HighLogic.LoadedSceneIsFlight) || !CompatibilityChecker.IsAllCompatible()) { return; } //Identification of the RealChuteModule if (this.part.Modules.Contains("RealChuteModule")) { rcModule = this.part.Modules["RealChuteModule"] as RealChuteModule; } else { return; } secondaryChute = rcModule.secondaryChute; if (textureLibrary != "none") { textureLib.TryGetConfig(textureLibrary, ref textures); } bodies = AtmoPlanets.fetch; //Initializes ChuteTemplates LoadChutes(); if (this.part.name.Contains("(Clone)(Clone)")) { if (this.part.symmetryCounterparts.Count > 0) { CopyFromOriginal(this.part.symmetryCounterparts.Find(p => !p.name.Contains("(Clone)(Clone)"))); } RCUtils.RemoveClone(this.part); } chutes.ForEach(c => c.Initialize()); if (sizes.Count <= 0) { sizes = sizeLib.GetSizes(this.part.partInfo.name); } //Creates an instance of the texture library editorGUI = new EditorGUI(this); if (textureLibrary != "none") { editorGUI.cases = textures.caseNames; editorGUI.canopies = textures.canopyNames; editorGUI.models = textures.modelNames; textures.TryGetCase(caseID, type, ref parachuteCase); lastCaseID = caseID; } if (HighLogic.LoadedSceneIsEditor) { //Windows initiation this.editorGUI.window = new Rect(5, 370, 420, Screen.height - 375); this.chutes.ForEach(c => c.materialsWindow = new Rect(editorGUI.matX, editorGUI.matY, 375, 275)); this.editorGUI.failedWindow = new Rect(Screen.width / 2 - 150, Screen.height / 2 - 150, 300, 300); this.editorGUI.successfulWindow = new Rect(Screen.width / 2 - 150, Screen.height / 2 - 25, 300, 50); this.editorGUI.presetsWindow = new Rect(Screen.width / 2 - 200, Screen.height / 2 - 250, 400, 500); this.editorGUI.presetsSaveWindow = new Rect(Screen.width / 2 - 175, Screen.height / 2 - 110, 350, 220); this.editorGUI.presetsWarningWindow = new Rect(Screen.width / 2 - 100, Screen.height / 2 - 50, 200, 100); if (!initiated) { planets = bodies.GetPlanetIndex("Kerbin"); //Gets the original part state if (textureLibrary != "none") { if (textures.TryGetCase(currentCase, ref parachuteCase)) { caseID = textures.GetCaseIndex(parachuteCase); } lastCaseID = caseID; } //Identification of the values from the RealChuteModule mustGoDown = rcModule.mustGoDown; deployOnGround = rcModule.deployOnGround; timer = rcModule.timer + "s"; cutSpeed = rcModule.cutSpeed.ToString(); if (rcModule.spareChutes != -1) { spares = rcModule.spareChutes.ToString(); } originalSize = this.part.transform.GetChild(0).localScale; initiated = true; } } if (parent == null) { parent = this.part.FindModelTransform(rcModule.parachutes[0].parachuteName).parent; } //Updates the part if (textureLibrary != "none") { UpdateCaseTexture(this.part, rcModule); } UpdateScale(this.part, rcModule); }
//Lists the errors of a given type internal List <string> GetErrors(bool general) { if (general) { List <string> errors = new List <string>(); float f = 0; if (!GUIUtils.TryParseTime(this.timer, out f) || !GUIUtils.CheckRange(f, 0, 3600)) { errors.Add("Deployment timer"); } if (!GUIUtils.TryParseWithEmpty(this.spares, out f) || !GUIUtils.CheckRange(f, -1, 10) || !RCUtils.IsWholeNumber(f)) { errors.Add("Spare chutes"); } if (!float.TryParse(this.cutSpeed, out f) || !GUIUtils.CheckRange(f, 0.01f, 100)) { errors.Add("Autocut speed"); } if (!float.TryParse(this.landingAlt, out f) || !GUIUtils.CheckRange(f, 0, (float)this.body.GetMaxAtmosphereAltitude())) { errors.Add("Landing altitude"); } return(errors); } else { return(new List <string>(this.chutes.SelectMany(c => c.templateGUI.errors))); } }
//Info window private void Window(int id) { GUI.DragWindow(new Rect(0, 0, window.width, 30)); GUILayout.BeginVertical(); StringBuilder builder = new StringBuilder("Part name: ").AppendLine(this.part.partInfo.title); builder.Append("Symmetry counterparts: ").AppendLine(this.part.symmetryCounterparts.Count.ToString()); builder.Append("Part mass: ").Append(this.part.TotalMass().ToString("0.###")).Append("t"); GUILayout.Label(builder.ToString(), skins.label); scroll = GUILayout.BeginScrollView(scroll, false, false, skins.horizontalScrollbar, skins.verticalScrollbar, skins.box); GUILayout.Space(5); GUILayout.Label("General:", RCUtils.boldLabel, GUILayout.Width(120)); builder = new StringBuilder("Autocut speed: ").Append(cutSpeed).AppendLine("m/s"); if (timer >= 60) { builder.Append("Deployment timer: ").AppendLine(RCUtils.ToMinutesSeconds(timer)); } else if (timer > 0) { builder.Append("Deployment timer: ").Append(timer.ToString("0.#")).AppendLine("s"); } if (this.mustGoDown) { builder.AppendLine("Must go downwards to deploy"); } if (this.deployOnGround) { builder.AppendLine("Automatically deploys on ground contact"); } if (this.spareChutes >= 0) { builder.Append("Spare chutes: ").Append(chuteCount); } else { builder.Append("Spare chutes: inf"); } GUILayout.Label(builder.ToString(), skins.label); for (int i = 0; i < parachutes.Count; i++) { GUILayout.Label("___________________________________________", RCUtils.boldLabel); GUILayout.Space(3); GUILayout.Label(RCUtils.ParachuteNumber(i), RCUtils.boldLabel, GUILayout.Width(120)); parachutes[i].UpdateGUI(); } GUILayout.EndScrollView(); if (HighLogic.LoadedSceneIsFlight && this.part.symmetryCounterparts.Count > 0) { GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Copy to counterparts", skins.button, GUILayout.Width(150))) { CopyToCouterparts(); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Close", skins.button, GUILayout.Width(150))) { this.visible = false; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); }
//Lists the errors of a given type internal List <string> GetErrors(string type) { if (type == "general") { List <string> general = new List <string>(); if (!RCUtils.CanParseTime(timer) || !RCUtils.CheckRange(RCUtils.ParseTime(timer), 0, 3600)) { general.Add("Deployment timer"); } if (!RCUtils.CanParseWithEmpty(spares) || !RCUtils.CheckRange(RCUtils.ParseWithEmpty(spares), -1, 10) || !RCUtils.IsWholeNumber(RCUtils.ParseWithEmpty(spares))) { general.Add("Spare chutes"); } if (!RCUtils.CanParse(cutSpeed) || !RCUtils.CheckRange(float.Parse(cutSpeed), 0.01f, 100)) { general.Add("Autocut speed"); } if (!RCUtils.CanParse(landingAlt) || !RCUtils.CheckRange(float.Parse(landingAlt), 0, (float)body.GetMaxAtmosphereAltitude())) { general.Add("Landing altitude"); } return(general); } else if (type == "main" || type == "secondary") { return(chutes.SelectMany(c => c.errors).ToList()); } return(new List <string>()); }
//Applies changes to the parachute internal void ApplyChanges(bool toSymmetryCounterparts) { parachute.material = material.name; parachute.mat = material; if (calcSelect) { float m = 0; if (getMass) { m = this.pChute.GetCraftMass(useDry); } else { m = float.Parse(mass); } double alt = typeID == 1 ? double.Parse(refDepAlt) : double.Parse(pChute.landingAlt); float density = (float)body.GetDensityAtAlt(alt); float speed = float.Parse(landingSpeed); float speed2 = speed * speed; float acc = typeID == 2 ? float.Parse(deceleration) : (float)(body.GeeASL * RCUtils.geeToAcc); Debug.Log(String.Concat("[RealChute]: ", this.part.partInfo.title, " ", RCUtils.ParachuteNumber(this.id), " - m: ", m, "t, alt: ", alt, "m, rho: ", density, "kg/m³, v²: ", speed2, "m²/s², acceleration: ", acc, "m/s²")); parachute.deployedDiameter = RCUtils.Round(Mathf.Sqrt((8000f * m * acc) / (Mathf.PI * speed2 * material.dragCoefficient * density * float.Parse(chuteCount)))); if ((this.pChute.textureLibrary != "none" || this.textures.modelNames.Length > 0) && parachute.deployedDiameter > model.maxDiam) { parachute.deployedDiameter = model.maxDiam; this.editorGUI.warning = true; } else if ((this.pChute.textureLibrary == "none" || this.textures.modelNames.Length <= 0) && parachute.deployedDiameter > 70f) { parachute.deployedDiameter = 70f; this.editorGUI.warning = true; } else { this.editorGUI.warning = false; } parachute.preDeployedDiameter = RCUtils.Round(typeID == 0 ? (parachute.deployedDiameter / 20) : (parachute.deployedDiameter / 2)); Debug.Log(String.Concat("[RealChute]: ", this.part.partInfo.title, " ", RCUtils.ParachuteNumber(this.id), " - depDiam: ", parachute.deployedDiameter, "m, preDepDiam: ", parachute.preDeployedDiameter, "m")); } else { parachute.preDeployedDiameter = RCUtils.Round(float.Parse(preDepDiam)); parachute.deployedDiameter = RCUtils.Round(float.Parse(depDiam)); } parachute.minIsPressure = isPressure; if (isPressure) { parachute.minPressure = float.Parse(predepClause); } else { parachute.minDeployment = float.Parse(predepClause); } parachute.deploymentAlt = float.Parse(deploymentAlt); parachute.cutAlt = RCUtils.ParseWithEmpty(cutAlt); parachute.preDeploymentSpeed = float.Parse(preDepSpeed); parachute.deploymentSpeed = float.Parse(depSpeed); if (toSymmetryCounterparts) { foreach (Part part in this.part.symmetryCounterparts) { Parachute sym = ((RealChuteModule)part.Modules["RealChuteModule"]).parachutes[id]; sym.material = material.name; sym.mat = material; sym.deployedDiameter = parachute.deployedDiameter; sym.preDeployedDiameter = parachute.preDeployedDiameter; sym.minIsPressure = isPressure; if (isPressure) { sym.minPressure = parachute.minPressure; } else { sym.minDeployment = parachute.minDeployment; } sym.deploymentAlt = parachute.deploymentAlt; sym.cutAlt = parachute.cutAlt; sym.preDeploymentSpeed = parachute.preDeploymentSpeed; sym.deploymentSpeed = parachute.deploymentSpeed; ChuteTemplate template = ((ProceduralChute)part.Modules["ProceduralChute"]).chutes[id]; template.chuteID = this.chuteID; template.typeID = this.typeID; template.modelID = this.modelID; template.materialsID = this.materialsID; template.isPressure = this.isPressure; template.calcSelect = this.calcSelect; template.getMass = this.getMass; template.useDry = this.useDry; template.preDepDiam = this.preDepDiam; template.depDiam = this.depDiam; template.predepClause = this.predepClause; template.mass = this.mass; template.landingSpeed = this.landingSpeed; template.deceleration = this.deceleration; template.refDepAlt = this.refDepAlt; template.chuteCount = this.chuteCount; template.deploymentAlt = this.deploymentAlt; template.cutAlt = this.cutAlt; template.preDepSpeed = this.preDepSpeed; template.depSpeed = this.depSpeed; } } }
//Gives the cost for this parachute public float GetModuleCost() { return(RCUtils.Round(this.parachutes.Sum(p => p.deployedArea * p.mat.areaCost))); }
//Main GUI window private void Window(int id) { GUILayout.BeginVertical(); #region Info labels //Header labels StringBuilder builder = new StringBuilder(); builder.Append("Selected part: ").AppendLine(this.Part.partInfo.title); builder.Append("Symmetry counterparts: ").AppendLine(this.Part.symmetryCounterparts.Count.ToString()); builder.Append("Case mass: ").Append(this.RCModule.caseMass.ToString("0.000")).Append("t"); if (this.Sizes.Count > 0) { builder.Append("\t\tCase cost: ").Append(this.Sizes[this.pChute.size].Cost.ToString("0.#")).Append("F"); } builder.Append("\nTotal part mass: ").Append(this.Part.TotalMass().ToString("0.000")).Append("t"); builder.Append("\tTotal part cost: ").Append(this.Part.TotalCost().ToString("0.#")).Append("F"); GUILayout.Label(builder.ToString()); #endregion #region Presets //Presets buttons GUILayout.BeginHorizontal(); if (GUILayout.Button("Select a preset")) { this.presetVisible = !this.presetVisible; } if (GUILayout.Button("Save as preset...")) { this.presetSaveVisible = !this.presetSaveVisible; } GUILayout.EndHorizontal(); #endregion //Scroll being this.mainScroll = GUILayout.BeginScrollView(this.mainScroll); #region Planet selector //Target planet selection GUILayout.Space(10); GUILayout.BeginHorizontal(GUILayout.Height(30)); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUILayout.Label("Target planet:"); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); this.pChute.planets = GUILayout.SelectionGrid(this.pChute.planets, AtmoPlanets.Instance.BodyNames, 4, GUILayout.Width(250)); GUILayout.EndHorizontal(); this.pChute.body = AtmoPlanets.Instance.GetBody(this.pChute.planets); #endregion #region Size cyclers //Size selection if (this.Sizes.Count > 0) { GUILayout.BeginHorizontal(GUILayout.Height(20)); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUILayout.Label("Cycle part size"); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Previous size", GUILayout.Width(125))) { this.pChute.size--; if (this.pChute.size < 0) { this.pChute.size = this.Sizes.Count - 1; } } if (GUILayout.Button("Next size", GUILayout.Width(125))) { this.pChute.size++; if (this.pChute.size > this.Sizes.Count - 1) { this.pChute.size = 0; } } GUILayout.EndHorizontal(); } #endregion GUILayout.Space(5); GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); //Main chute texture selector GUILayout.Space(5); this.Chutes[0].templateGUI.TextureSelector(); #region General //Materials editor GUILayout.Space(5); this.Chutes[0].templateGUI.MaterialsSelector(); //MustGoDown GuiUtils.CreateTwinToggle("Must go down to deploy:", ref this.pChute.mustGoDown, this.window.width); //DeployOnGround GuiUtils.CreateTwinToggle("Deploy on ground contact:", ref this.pChute.deployOnGround, this.window.width); //Timer GuiUtils.CreateTimeEntryArea("Deployment timer:", ref this.pChute.timer, 0, 3600); //Spares GuiUtils.CreateEmptyEntryArea("Spare chutes:", ref this.pChute.spares, -1, 10); //CutSpeed GuiUtils.CreateEntryArea("Autocut speed (m/s):", ref this.pChute.cutSpeed, 0.01f, 100); //LandingAlt GuiUtils.CreateEntryArea("Landing alt (m):", ref this.pChute.landingAlt, 0, (float)this.pChute.body.GetMaxAtmosphereAltitude()); #endregion #region Main //Indicator label GUILayout.Space(10); GUILayout.Label("________________________________________________", GuiUtils.BoldLabel); GUILayout.Label("Main chute:", GuiUtils.BoldLabel, GUILayout.Width(150)); GUILayout.Label("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾", GuiUtils.BoldLabel); this.Chutes[0].templateGUI.Calculations(); #endregion #region Secondary if (this.pChute.secondaryChute) { for (int i = 1; i < this.Chutes.Count; i++) { ChuteTemplate chute = this.Chutes[i]; //Indicator label GUILayout.Space(10); GUILayout.Label("________________________________________________", GuiUtils.BoldLabel); GUILayout.Label(RCUtils.ParachuteNumber(i) + ":", GuiUtils.BoldLabel, GUILayout.Width(150)); GUILayout.Label("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾", GuiUtils.BoldLabel); //Texture selector GUILayout.Space(5); chute.templateGUI.TextureSelector(); //Materials editor GUILayout.Space(5); chute.templateGUI.MaterialsSelector(); chute.templateGUI.Calculations(); } } #endregion GUILayout.EndVertical(); GUILayout.BeginVertical(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.EndScrollView(); //Scroll end #region Application GUILayout.Space(5); if (GUILayout.Button("Apply settings")) { this.pChute.Apply(false); } if (this.Part.symmetryCounterparts.Count > 0) { if (GUILayout.Button("Apply to all symmetry counterparts")) { this.pChute.Apply(true); } } #endregion GUILayout.EndVertical(); }
//Applies changes to the parachute internal void ApplyChanges(bool toSymmetryCounterparts) { this.parachute.material = this.material.name; this.parachute.mat = this.material; if (this.templateGUI.calcSelect) { double m = this.templateGUI.getMass ? this.pChute.GetCraftMass(this.templateGUI.useDry) : double.Parse(this.templateGUI.mass); double alt = 0, acc = 0; switch (this.templateGUI.type) { case ParachuteType.Main: { alt = double.Parse(this.pChute.landingAlt); acc = (this.body.GeeASL * RCUtils.geeToAcc); break; } case ParachuteType.Drogue: { alt = double.Parse(this.templateGUI.refDepAlt); acc = (this.body.GeeASL * RCUtils.geeToAcc); break; } case ParachuteType.Drag: { alt = double.Parse(this.pChute.landingAlt); acc = double.Parse(this.templateGUI.deceleration); break; } default: break; } double density = this.body.GetDensityAtAlt(alt); double speed = double.Parse(this.templateGUI.landingSpeed); speed = speed * speed; Debug.Log(String.Format("[RealChute]: {0} {1} - m: {2}t, alt: {3}m, ρ: {4}kg/m³, v²: {5}m²/s², a: {6}m/s²", this.part.partInfo.title, RCUtils.ParachuteNumber(this.id), m, alt, density, speed, acc)); this.parachute.deployedDiameter = RCUtils.Round(Math.Sqrt((8000 * m * acc) / (Math.PI * speed * material.dragCoefficient * density * double.Parse(this.templateGUI.chuteCount)))); float maxDiam = (this.textures != null || this.textures.models.Count > 0) ? this.model.maxDiam : 70; if (this.parachute.deployedDiameter > this.model.maxDiam) { this.parachute.deployedDiameter = maxDiam; this.editorGUI.warning = true; } else { this.editorGUI.warning = false; } this.parachute.preDeployedDiameter = RCUtils.Round(this.templateGUI.type == ParachuteType.Main ? (this.parachute.deployedDiameter / 20) : (this.parachute.deployedDiameter / 2)); Debug.Log(String.Format("[RealChute]: {0} {1} - depDiam: {2}m, preDepDiam: {3}m", this.part.partInfo.title, RCUtils.ParachuteNumber(this.id), this.parachute.deployedDiameter, this.parachute.preDeployedDiameter)); } else { this.parachute.preDeployedDiameter = RCUtils.Round(float.Parse(this.templateGUI.preDepDiam)); this.parachute.deployedDiameter = RCUtils.Round(float.Parse(this.templateGUI.depDiam)); Debug.Log(String.Format("[RealChute]: {0} {1} - depDiam: {2}m, preDepDiam: {3}m", this.part.partInfo.title, RCUtils.ParachuteNumber(this.id), this.parachute.deployedDiameter, this.parachute.preDeployedDiameter)); } this.parachute.minIsPressure = this.templateGUI.isPressure; if (this.templateGUI.isPressure) { this.parachute.minPressure = float.Parse(this.templateGUI.predepClause); } else { this.parachute.minDeployment = float.Parse(this.templateGUI.predepClause); } this.parachute.deploymentAlt = float.Parse(this.templateGUI.deploymentAlt); this.parachute.cutAlt = GUIUtils.ParseEmpty(this.templateGUI.cutAlt); this.parachute.preDeploymentSpeed = float.Parse(this.templateGUI.preDepSpeed); this.parachute.deploymentSpeed = float.Parse(this.templateGUI.depSpeed); if (toSymmetryCounterparts) { foreach (Part part in this.part.symmetryCounterparts) { Parachute sym = ((RealChuteModule)part.Modules["RealChuteModule"]).parachutes[id]; sym.material = this.material.name; sym.mat = this.material; sym.deployedDiameter = this.parachute.deployedDiameter; sym.preDeployedDiameter = this.parachute.preDeployedDiameter; sym.minIsPressure = this.templateGUI.isPressure; sym.minPressure = this.parachute.minPressure; sym.minDeployment = this.parachute.minDeployment; sym.deploymentAlt = this.parachute.deploymentAlt; sym.cutAlt = this.parachute.cutAlt; sym.preDeploymentSpeed = this.parachute.preDeploymentSpeed; sym.deploymentSpeed = this.parachute.deploymentSpeed; TemplateGUI template = ((ProceduralChute)part.Modules["ProceduralChute"]).chutes[id].templateGUI; template.chuteID = this.templateGUI.chuteID; template.typeID = this.templateGUI.typeID; template.modelID = this.templateGUI.modelID; template.materialsID = this.templateGUI.materialsID; template.isPressure = this.templateGUI.isPressure; template.calcSelect = this.templateGUI.calcSelect; template.getMass = this.templateGUI.getMass; template.useDry = this.templateGUI.useDry; template.preDepDiam = this.templateGUI.preDepDiam; template.depDiam = this.templateGUI.depDiam; template.predepClause = this.templateGUI.predepClause; template.mass = this.templateGUI.mass; template.landingSpeed = this.templateGUI.landingSpeed; template.deceleration = this.templateGUI.deceleration; template.refDepAlt = this.templateGUI.refDepAlt; template.chuteCount = this.templateGUI.chuteCount; template.deploymentAlt = this.templateGUI.deploymentAlt; template.cutAlt = this.templateGUI.cutAlt; template.preDepSpeed = this.templateGUI.preDepSpeed; template.depSpeed = this.templateGUI.depSpeed; } } }
//Gives the cost for this parachute public float GetModuleCost(float defaultCost, ModifierStagingSituation sit) => RCUtils.Round(this.parachutes.Sum(p => p.DeployedArea * p.mat.AreaCost));
//Info window private void Window(int id) { //Header GUI.DragWindow(this.drag); GUILayout.BeginVertical(); //Top info labels StringBuilder builder = new StringBuilder("Part name: ").AppendLine(this.part.partInfo.title); builder.Append("Symmetry counterparts: ").AppendLine(this.part.symmetryCounterparts.Count.ToString()); builder.Append("Part mass: ").Append(this.part.TotalMass().ToString("0.###")).Append("t"); GUILayout.Label(builder.ToString()); //Beginning scroll this.scroll = GUILayout.BeginScrollView(this.scroll, false, false, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.box); GUILayout.Space(5); GUILayout.Label("General:", GuiUtils.BoldLabel, GUILayout.Width(120)); //General labels builder = new StringBuilder("Autocut speed: ").Append(this.cutSpeed).AppendLine("m/s"); if (this.timer >= 60) { builder.Append("Deployment timer: ").AppendLine(RCUtils.ToMinutesSeconds(this.timer)); } else if (this.timer > 0) { builder.Append("Deployment timer: ").Append(this.timer.ToString("0.#")).AppendLine("s"); } if (this.mustGoDown) { builder.AppendLine("Must go downwards to deploy"); } if (this.deployOnGround) { builder.AppendLine("Automatically deploys on ground contact"); } if (this.spareChutes >= 0) { builder.Append("Spare chutes: ").Append(this.chuteCount); } else { builder.Append("Spare chutes: inf"); } GUILayout.Label(builder.ToString()); //Specific labels for (int i = 0; i < this.parachutes.Count; i++) { GUILayout.Label("___________________________________________", GuiUtils.BoldLabel); GUILayout.Space(3); GUILayout.Label(RCUtils.ParachuteNumber(i) + ":", GuiUtils.BoldLabel, GUILayout.Width(120)); this.parachutes[i].RenderGUI(); } //End scroll GUILayout.EndScrollView(); //Copy button if in flight if (HighLogic.LoadedSceneIsFlight && this.part.symmetryCounterparts.Count > 0) { GuiUtils.CenteredButton("Copy to others chutes", CopyToCounterparts); } //Close button GuiUtils.CenteredButton("Close", () => this.visible = false); //Closer GUILayout.EndVertical(); }
//Checks if there is a timer and/or a mustGoDown clause active public void CheckForWait() { bool timerSpent = true, goesDown = true; this.screenMessage = string.Empty; //Timer if (this.timer > 0 && this.deploymentTimer.Elapsed.TotalSeconds < this.timer) { timerSpent = false; if (!this.deploymentTimer.IsRunning) { this.deploymentTimer.Start(); } if (this.vessel.isActiveVessel) { float time = this.timer - (float)this.deploymentTimer.Elapsed.TotalSeconds; this.screenMessage = time < 60 ? $"Deployment in {time:0.0}s" : $"Deployment in {RCUtils.ToMinutesSeconds(time)}"; } } else if (this.deploymentTimer.IsRunning) { this.deploymentTimer.Stop(); } //Goes down if (this.mustGoDown && this.vessel.verticalSpeed > 0) { if (!timerSpent) { this.screenMessage += "\n"; } goesDown = false; if (this.vessel.isActiveVessel) { this.screenMessage += $"Deployment awaiting negative vertical velocity\nCurrent vertical velocity: {this.vessel.verticalSpeed:0.0}/s"; } } //Can deploy or not if (timerSpent && goesDown) { this.wait = false; this.showDisarm = false; this.deploymentTimer.Reset(); } else { this.part.stackIcon.SetIconColor(XKCDColors.LightCyan); this.wait = true; this.showDisarm = true; } }
//Applies changes to the parachute internal void ApplyChanges(bool toSymmetryCounterparts) { this.parachute.material = this.material.Name; this.parachute.mat = this.material; if (this.templateGUI.calcSelect) { double m = this.templateGUI.getMass ? this.pChute.GetCraftMass(this.templateGUI.useDry) : double.Parse(this.templateGUI.mass); double alt = 0, acc = 0; switch (this.templateGUI.Type) { case ParachuteType.MAIN: { alt = double.Parse(this.pChute.landingAlt); acc = this.Body.GeeASL * RCUtils.GeeToAcc; break; } case ParachuteType.DROGUE: { alt = double.Parse(this.templateGUI.refDepAlt); acc = this.Body.GeeASL * RCUtils.GeeToAcc; break; } case ParachuteType.DRAG: { alt = double.Parse(this.pChute.landingAlt); acc = double.Parse(this.templateGUI.deceleration); break; } } double density = this.Body.GetDensityAtAlt(alt, this.Body.GetMaxTemperatureAtAlt(alt)); double speed = double.Parse(this.templateGUI.landingSpeed); speed *= speed; Debug.Log($"[RealChute]: {this.Part.partInfo.title} {RCUtils.ParachuteNumber(this.id)} - m: {m}t, alt: {alt}m, ρ: {density}kg/m³, v²: {speed}m²/s², a: {acc}m/s²"); this.parachute.deployedDiameter = RCUtils.Round(Math.Sqrt((8000 * m * acc) / (Math.PI * speed * this.material.DragCoefficient * density * double.Parse(this.templateGUI.chuteCount)))); float maxDiam = (this.Textures != null) && (this.Textures.Models.Count > 0) ? this.model.MaxDiam : 70f; if (this.parachute.deployedDiameter > this.model.MaxDiam) { this.parachute.deployedDiameter = maxDiam; this.EditorGUI.warning = true; } else { this.EditorGUI.warning = false; } this.parachute.preDeployedDiameter = RCUtils.Round(this.templateGUI.Type == ParachuteType.MAIN ? this.parachute.deployedDiameter / 20 : this.parachute.deployedDiameter / 2); Debug.Log($"[RealChute]: {this.Part.partInfo.title} {RCUtils.ParachuteNumber(this.id)} - depDiam: {this.parachute.deployedDiameter}m, preDepDiam: {this.parachute.preDeployedDiameter}m"); } else { this.parachute.preDeployedDiameter = RCUtils.Round(float.Parse(this.templateGUI.preDepDiam)); this.parachute.deployedDiameter = RCUtils.Round(float.Parse(this.templateGUI.depDiam)); Debug.Log($"[RealChute]: {this.Part.partInfo.title} {RCUtils.ParachuteNumber(this.id)} - depDiam: {this.parachute.deployedDiameter}m, preDepDiam: {this.parachute.preDeployedDiameter}m"); } this.parachute.minIsPressure = this.templateGUI.isPressure; if (this.templateGUI.isPressure) { this.parachute.minPressure = float.Parse(this.templateGUI.predepClause); } else { this.parachute.minDeployment = float.Parse(this.templateGUI.predepClause); } this.parachute.deploymentAlt = float.Parse(this.templateGUI.deploymentAlt); this.parachute.cutAlt = GuiUtils.ParseEmpty(this.templateGUI.cutAlt); this.parachute.preDeploymentSpeed = float.Parse(this.templateGUI.preDepSpeed); this.parachute.deploymentSpeed = float.Parse(this.templateGUI.depSpeed); if (toSymmetryCounterparts) { foreach (Part part in this.Part.symmetryCounterparts) { Parachute sym = ((RealChuteModule)part.Modules["RealChuteModule"]).parachutes[this.id]; sym.material = this.material.Name; sym.mat = this.material; sym.deployedDiameter = this.parachute.deployedDiameter; sym.preDeployedDiameter = this.parachute.preDeployedDiameter; sym.minIsPressure = this.templateGUI.isPressure; sym.minPressure = this.parachute.minPressure; sym.minDeployment = this.parachute.minDeployment; sym.deploymentAlt = this.parachute.deploymentAlt; sym.cutAlt = this.parachute.cutAlt; sym.preDeploymentSpeed = this.parachute.preDeploymentSpeed; sym.deploymentSpeed = this.parachute.deploymentSpeed; TemplateGUI template = ((ProceduralChute)part.Modules["ProceduralChute"]).chutes[this.id].templateGUI; template.chuteId = this.templateGUI.chuteId; template.TypeId = this.templateGUI.TypeId; template.modelId = this.templateGUI.modelId; template.materialsId = this.templateGUI.materialsId; template.isPressure = this.templateGUI.isPressure; template.calcSelect = this.templateGUI.calcSelect; template.getMass = this.templateGUI.getMass; template.useDry = this.templateGUI.useDry; template.preDepDiam = this.templateGUI.preDepDiam; template.depDiam = this.templateGUI.depDiam; template.predepClause = this.templateGUI.predepClause; template.mass = this.templateGUI.mass; template.landingSpeed = this.templateGUI.landingSpeed; template.deceleration = this.templateGUI.deceleration; template.refDepAlt = this.templateGUI.refDepAlt; template.chuteCount = this.templateGUI.chuteCount; template.deploymentAlt = this.templateGUI.deploymentAlt; template.cutAlt = this.templateGUI.cutAlt; template.preDepSpeed = this.templateGUI.preDepSpeed; template.depSpeed = this.templateGUI.depSpeed; } } }
//Calculations GUI core internal void Calculations() { #region Calculations //Selection mode GUILayout.Space(5); GUILayout.BeginHorizontal(); GUILayout.Label("Calculations mode:", skins.label); if (GUILayout.Toggle(calcSelect, "Automatic", skins.toggle)) { calcSelect = true; } GUILayout.FlexibleSpace(); if (GUILayout.Toggle(!calcSelect, "Manual", skins.toggle)) { calcSelect = false; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(5); //Calculations parachuteScroll = GUILayout.BeginScrollView(parachuteScroll, false, false, skins.horizontalScrollbar, skins.verticalScrollbar, skins.box, GUILayout.Height(160)); #region Automatic if (calcSelect) { typeID = GUILayout.SelectionGrid(typeID, RCUtils.types, 3, skins.button); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Toggle(getMass, "Use current craft mass", skins.button, GUILayout.Width(150))) { getMass = true; } GUILayout.FlexibleSpace(); if (GUILayout.Toggle(!getMass, "Input craft mass", skins.button, GUILayout.Width(150))) { getMass = false; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); if (getMass) { GUILayout.Label("Currently using " + (useDry ? "dry mass" : "wet mass"), skins.label); if (useDry) { if (GUILayout.Button("Switch to wet mass", skins.button, GUILayout.Width(125))) { useDry = false; } } else { if (GUILayout.Button("Switch to dry mass", skins.button, GUILayout.Width(125))) { useDry = true; } } } else { string m = mass; this.editorGUI.CreateEntryArea("Mass to use (t):", ref m, 0.1f, 10000, 100); mass = m; } GUILayout.Space(5); GUILayout.BeginHorizontal(); if (typeID == 0) { if (RCUtils.CanParse(landingSpeed) && RCUtils.CheckRange(float.Parse(landingSpeed), 0.1f, 300)) { GUILayout.Label("Wanted touchdown speed (m/s):", skins.label); } else { GUILayout.Label("Wanted touchdown speed (m/s):", RCUtils.redLabel); } } else if (typeID == 1) { if (RCUtils.CanParse(landingSpeed) && RCUtils.CheckRange(float.Parse(landingSpeed), 0.1f, 5000)) { GUILayout.Label("Wanted speed at target alt (m/s):", skins.label); } else { GUILayout.Label("Wanted speed at target alt (m/s):", RCUtils.redLabel); } } else { if (RCUtils.CanParse(landingSpeed) && RCUtils.CheckRange(float.Parse(landingSpeed), 0.1f, 300)) { GUILayout.Label("Planned landing speed (m/s):", skins.label); } else { GUILayout.Label("Planned landing speed (m/s):", RCUtils.redLabel); } } GUILayout.FlexibleSpace(); landingSpeed = GUILayout.TextField(landingSpeed, 10, skins.textField, GUILayout.Width(100)); GUILayout.EndHorizontal(); if (typeID == 2) { string decel = deceleration; this.editorGUI.CreateEntryArea("Wanted deceleration (m/s²):", ref decel, 0.1f, 100, 100); deceleration = decel; } if (typeID == 1) { string depAlt = refDepAlt; this.editorGUI.CreateEntryArea("Target altitude (m):", ref depAlt, 10, (float)body.GetMaxAtmosphereAltitude(), 100); refDepAlt = depAlt; } string chutes = chuteCount; this.editorGUI.CreateEntryArea("Parachutes used (parts):", ref chutes, 1, 100, 100); chuteCount = chutes; } #endregion #region Manual else { //Predeployed diameter string preDep = preDepDiam, dep = depDiam; this.editorGUI.CreateEntryArea("Predeployed diameter (m):", ref preDep, 0.5f, model.maxDiam / 2, 100); if (RCUtils.CanParse(preDepDiam)) { GUILayout.Label("Resulting area: " + RCUtils.GetArea(float.Parse(preDepDiam)).ToString("0.00") + "m²", skins.label); } else { GUILayout.Label("Resulting predeployed area: --- m²", skins.label); } //Deployed diameter this.editorGUI.CreateEntryArea("Deployed diameter (m):", ref dep, 1, model.maxDiam, 100); if (RCUtils.CanParse(depDiam)) { GUILayout.Label("Resulting area: " + RCUtils.GetArea(float.Parse(depDiam)).ToString("0.00") + "m²", skins.label); } else { GUILayout.Label("Resulting deployed area: --- m²", skins.label); } preDepDiam = preDep; depDiam = dep; } #endregion GUILayout.EndScrollView(); #endregion #region Specific //Pressure/alt toggle GUILayout.Space(5); GUILayout.BeginHorizontal(); if (GUILayout.Toggle(isPressure, "Pressure predeployment", skins.toggle)) { if (!isPressure) { isPressure = true; this.predepClause = this.parachute.minPressure.ToString(); } } GUILayout.FlexibleSpace(); if (GUILayout.Toggle(!isPressure, "Altitude predeployment", skins.toggle)) { if (isPressure) { isPressure = false; this.predepClause = this.parachute.minDeployment.ToString(); } } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.BeginHorizontal(); if (isPressure) { if (RCUtils.CanParse(predepClause) && RCUtils.CheckRange(float.Parse(predepClause), 0.0001f, (float)body.GetPressureASL())) { GUILayout.Label("Predeployment pressure (atm):", skins.label); } else { GUILayout.Label("Predeployment pressure (atm):", RCUtils.redLabel); } } else { if (RCUtils.CanParse(predepClause) && RCUtils.CheckRange(float.Parse(predepClause), 10, (float)body.GetMaxAtmosphereAltitude())) { GUILayout.Label("Predeployment altitude (m):", skins.label); } else { GUILayout.Label("Predeployment altitude (m):", RCUtils.redLabel); } } GUILayout.FlexibleSpace(); predepClause = GUILayout.TextField(predepClause, 10, skins.textField, GUILayout.Width(150)); GUILayout.EndHorizontal(); //Deployment altitude this.editorGUI.CreateEntryArea("Deployment altitude", ref deploymentAlt, 10, (float)body.GetMaxAtmosphereAltitude()); //Cut altitude GUILayout.Space(5); GUILayout.BeginHorizontal(); if (RCUtils.CanParseWithEmpty(cutAlt) && RCUtils.CheckRange(RCUtils.ParseWithEmpty(cutAlt), -1, (float)body.GetMaxAtmosphereAltitude())) { GUILayout.Label("Autocut altitude (m):", skins.label); } else { GUILayout.Label("Autocut altitude (m):", RCUtils.redLabel); } GUILayout.FlexibleSpace(); cutAlt = GUILayout.TextField(cutAlt, 10, skins.textField, GUILayout.Width(150)); GUILayout.EndHorizontal(); //Predeployment speed this.editorGUI.CreateEntryArea("Pre deployment speed (s):", ref preDepSpeed, 0.5f, 5); //Deployment speed this.editorGUI.CreateEntryArea("Deployment speed (s):", ref depSpeed, 1, 10); #endregion }
//Main GUI window private void Window(int id) { GUILayout.BeginVertical(); #region Info labels GUILayout.Label("Selected part: " + this.part.partInfo.title, skins.label); GUILayout.Label("Symmetry counterparts: " + (this.part.symmetryCounterparts.Count), skins.label); GUILayout.Label("Case mass: " + rcModule.caseMass + "t", skins.label); GUILayout.Label("Total part mass: " + this.part.TotalMass().ToString("0.###") + "t", skins.label); #endregion #region Presets GUILayout.BeginHorizontal(); if (GUILayout.Button("Select a preset", skins.button)) { this.presetVisible = !this.presetVisible; } if (GUILayout.Button("Save as preset...", skins.button)) { this.presetSaveVisible = !this.presetSaveVisible; } GUILayout.EndHorizontal(); #endregion #region Planet selector GUILayout.Space(10); GUILayout.BeginHorizontal(GUILayout.Height(30)); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUILayout.Label("Target planet:", skins.label); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); planets = GUILayout.SelectionGrid(planets, bodies.GetNames(), 4, skins.button, GUILayout.Width(250)); GUILayout.EndHorizontal(); body = bodies.GetBody(planets); #endregion #region Size cyclers if (sizes.Count > 0) { GUILayout.BeginHorizontal(GUILayout.Height(20)); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUILayout.Label("Cycle part size", skins.label); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Previous size", skins.button, GUILayout.Width(125))) { size--; if (size < 0) { size = sizes.Count - 1; } } if (GUILayout.Button("Next size", skins.button, GUILayout.Width(125))) { size++; if (size > sizes.Count - 1) { size = 0; } } GUILayout.EndHorizontal(); } #endregion GUILayout.Space(5); mainScroll = GUILayout.BeginScrollView(mainScroll, false, false, skins.horizontalScrollbar, skins.verticalScrollbar); GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); #region Texture selectors GUILayout.Space(5); main.TextureSelector(); #endregion #region General //Materials editor GUILayout.Space(5); main.MaterialsSelector(); //MustGoDown GUILayout.Space(5); GUILayout.BeginHorizontal(GUILayout.MaxWidth(window.width)); GUILayout.Label("Must go down to deploy:", skins.label); if (GUILayout.Toggle(mustGoDown, "True", skins.toggle)) { mustGoDown = true; } GUILayout.FlexibleSpace(); if (GUILayout.Toggle(!mustGoDown, "False", skins.toggle)) { mustGoDown = false; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); //DeployOnGround GUILayout.Space(5); GUILayout.BeginHorizontal(GUILayout.MaxWidth(window.width)); GUILayout.Label("Deploy on ground contact:", skins.label); if (GUILayout.Toggle(deployOnGround, "True", skins.toggle)) { deployOnGround = true; } GUILayout.FlexibleSpace(); if (GUILayout.Toggle(!deployOnGround, "False", skins.toggle)) { deployOnGround = false; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); //Timer GUILayout.Space(5); GUILayout.BeginHorizontal(); if (RCUtils.CanParseTime(timer) && RCUtils.CheckRange(RCUtils.ParseTime(timer), 0, 3600)) { GUILayout.Label("Deployment timer:", skins.label); } else { GUILayout.Label("Deployment timer:", RCUtils.redLabel); } GUILayout.FlexibleSpace(); timer = GUILayout.TextField(timer, 10, skins.textField, GUILayout.Width(150)); GUILayout.EndHorizontal(); //Spares GUILayout.Space(5); GUILayout.BeginHorizontal(); if (RCUtils.CanParseWithEmpty(spares) && RCUtils.CheckRange(RCUtils.ParseWithEmpty(spares), -1, 10) && RCUtils.IsWholeNumber(RCUtils.ParseWithEmpty(spares))) { GUILayout.Label("Spare chutes:", skins.label); } else { GUILayout.Label("Spare chutes:", RCUtils.redLabel); } GUILayout.FlexibleSpace(); spares = GUILayout.TextField(spares, 10, skins.textField, GUILayout.Width(150)); GUILayout.EndHorizontal(); //CutSpeed CreateEntryArea("Autocut speed (m/s):", ref cutSpeed, 0.01f, 100); #endregion #region Main //Indicator label GUILayout.Space(10); GUILayout.Label("________________________________________________", RCUtils.boldLabel); GUILayout.Label("Main chute:", RCUtils.boldLabel, GUILayout.Width(150)); GUILayout.Label("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾", RCUtils.boldLabel); main.Calculations(); #endregion #region Secondary if (secondaryChute) { //Indicator label GUILayout.Space(10); GUILayout.Label("________________________________________________", RCUtils.boldLabel); GUILayout.Label("Secondary chute:", RCUtils.boldLabel, GUILayout.Width(150)); GUILayout.Label("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾", RCUtils.boldLabel); #region Texture selectors GUILayout.Space(5); secondary.TextureSelector(); #endregion //Materials editor GUILayout.Space(5); secondary.MaterialsSelector(); secondary.Calculations(); } #endregion GUILayout.EndVertical(); GUILayout.BeginVertical(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.EndScrollView(); #region Application GUILayout.Space(5); if (GUILayout.Button("Apply settings", skins.button)) { Apply(false); } if (part.symmetryCounterparts.Count > 0) { if (GUILayout.Button("Apply to all symmetry counterparts", skins.button)) { Apply(true); } } #endregion GUILayout.EndVertical(); }
//Checks if there is a timer and/or a mustGoDown clause active public void CheckForWait() { bool timerSpent = true, goesDown = true; //Timer if (timer > 0 && deploymentTimer.elapsed.TotalSeconds < timer) { timerSpent = false; if (!deploymentTimer.isRunning) { deploymentTimer.Start(); } if (this.vessel.isActiveVessel) { float time = timer - (float)deploymentTimer.elapsed.TotalSeconds; if (time < 60) { ScreenMessages.PostScreenMessage(String.Format("Deployment in {0:0.0}s", time), Time.fixedDeltaTime, ScreenMessageStyle.UPPER_CENTER); } else { ScreenMessages.PostScreenMessage(String.Format("Deployment in {0}", RCUtils.ToMinutesSeconds(time)), Time.fixedDeltaTime, ScreenMessageStyle.UPPER_CENTER); } } } else if (deploymentTimer.isRunning) { deploymentTimer.Stop(); } //Goes down if (mustGoDown && this.vessel.verticalSpeed >= 0) { goesDown = false; if (this.vessel.isActiveVessel) { ScreenMessages.PostScreenMessage("Deployment awaiting negative vertical velocity", Time.fixedDeltaTime, ScreenMessageStyle.UPPER_CENTER); ScreenMessages.PostScreenMessage(String.Format("Current vertical velocity: {0:0.0}/s", this.vessel.verticalSpeed), Time.fixedDeltaTime, ScreenMessageStyle.UPPER_CENTER); } } //Can deploy or not if (timerSpent && goesDown) { wait = false; showDisarm = false; deploymentTimer.Reset(); } else { this.part.stackIcon.SetIconColor(XKCDColors.LightCyan); wait = true; showDisarm = true; } }
//Main GUI window private void Window(int id) { GUILayout.BeginVertical(); #region Info labels StringBuilder builder = new StringBuilder(); builder.Append("Selected part: ").AppendLine(this.part.partInfo.title); builder.Append("Symmetry counterparts: ").AppendLine(this.part.symmetryCounterparts.Count.ToString()); builder.Append("Case mass: ").Append(rcModule.caseMass.ToString()).Append("t"); if (sizes.Count > 0) { builder.Append("\t\t\t\t\tCase cost: ").Append(this.sizes[pChute.size].cost.ToString()).Append("f"); } builder.Append("\nTotal part mass: ").Append(this.part.TotalMass().ToString("0.###")).Append("t"); builder.Append("\t\t\tTotal case part cost: ").Append(this.part.TotalCost().ToString("0.#")).Append("f"); GUILayout.Label(builder.ToString(), skins.label); #endregion #region Presets GUILayout.BeginHorizontal(); if (GUILayout.Button("Select a preset", skins.button)) { this.presetVisible = !this.presetVisible; } if (GUILayout.Button("Save as preset...", skins.button)) { this.presetSaveVisible = !this.presetSaveVisible; } GUILayout.EndHorizontal(); #endregion mainScroll = GUILayout.BeginScrollView(mainScroll, false, false, skins.horizontalScrollbar, skins.verticalScrollbar); #region Planet selector GUILayout.Space(10); GUILayout.BeginHorizontal(GUILayout.Height(30)); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUILayout.Label("Target planet:", skins.label); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); pChute.planets = GUILayout.SelectionGrid(pChute.planets, pChute.bodies.bodyNames, 4, skins.button, GUILayout.Width(250)); GUILayout.EndHorizontal(); pChute.body = pChute.bodies.GetBody(pChute.planets); #endregion #region Size cyclers if (sizes.Count > 0) { GUILayout.BeginHorizontal(GUILayout.Height(20)); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUILayout.Label("Cycle part size", skins.label); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Previous size", skins.button, GUILayout.Width(125))) { pChute.size--; if (pChute.size < 0) { pChute.size = sizes.Count - 1; } } if (GUILayout.Button("Next size", skins.button, GUILayout.Width(125))) { pChute.size++; if (pChute.size > sizes.Count - 1) { pChute.size = 0; } } GUILayout.EndHorizontal(); } #endregion GUILayout.Space(5); GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); #region Texture selectors GUILayout.Space(5); chutes[0].TextureSelector(); #endregion #region General //Materials editor GUILayout.Space(5); chutes[0].MaterialsSelector(); //MustGoDown GUILayout.Space(5); GUILayout.BeginHorizontal(GUILayout.MaxWidth(window.width)); GUILayout.Label("Must go down to deploy:", skins.label); if (GUILayout.Toggle(pChute.mustGoDown, "True", skins.toggle)) { pChute.mustGoDown = true; } GUILayout.FlexibleSpace(); if (GUILayout.Toggle(!pChute.mustGoDown, "False", skins.toggle)) { pChute.mustGoDown = false; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); //DeployOnGround GUILayout.Space(5); GUILayout.BeginHorizontal(GUILayout.MaxWidth(window.width)); GUILayout.Label("Deploy on ground contact:", skins.label); if (GUILayout.Toggle(pChute.deployOnGround, "True", skins.toggle)) { pChute.deployOnGround = true; } GUILayout.FlexibleSpace(); if (GUILayout.Toggle(!pChute.deployOnGround, "False", skins.toggle)) { pChute.deployOnGround = false; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); //Timer GUILayout.Space(5); GUILayout.BeginHorizontal(); if (RCUtils.CanParseTime(pChute.timer) && RCUtils.CheckRange(RCUtils.ParseTime(pChute.timer), 0, 3600)) { GUILayout.Label("Deployment timer:", skins.label); } else { GUILayout.Label("Deployment timer:", RCUtils.redLabel); } GUILayout.FlexibleSpace(); pChute.timer = GUILayout.TextField(pChute.timer, 10, skins.textField, GUILayout.Width(150)); GUILayout.EndHorizontal(); //Spares GUILayout.Space(5); GUILayout.BeginHorizontal(); if (RCUtils.CanParseWithEmpty(pChute.spares) && RCUtils.CheckRange(RCUtils.ParseWithEmpty(pChute.spares), -1, 10) && RCUtils.IsWholeNumber(RCUtils.ParseWithEmpty(pChute.spares))) { GUILayout.Label("Spare chutes:", skins.label); } else { GUILayout.Label("Spare chutes:", RCUtils.redLabel); } GUILayout.FlexibleSpace(); pChute.spares = GUILayout.TextField(pChute.spares, 10, skins.textField, GUILayout.Width(150)); GUILayout.EndHorizontal(); //CutSpeed CreateEntryArea("Autocut speed (m/s):", ref pChute.cutSpeed, 0.01f, 100); //LandingAlt CreateEntryArea("Landing alt (m):", ref pChute.landingAlt, 0, (float)pChute.body.GetMaxAtmosphereAltitude()); #endregion #region Main //Indicator label GUILayout.Space(10); GUILayout.Label("________________________________________________", RCUtils.boldLabel); GUILayout.Label("Main chute:", RCUtils.boldLabel, GUILayout.Width(150)); GUILayout.Label("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾", RCUtils.boldLabel); chutes[0].Calculations(); #endregion #region Secondary if (pChute.secondaryChute) { for (int i = 1; i < chutes.Count; i++) { ChuteTemplate chute = chutes[i]; //Indicator label GUILayout.Space(10); GUILayout.Label("________________________________________________", RCUtils.boldLabel); GUILayout.Label("Chute #" + (i + 1) + " :", RCUtils.boldLabel, GUILayout.Width(150)); GUILayout.Label("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾", RCUtils.boldLabel); #region Texture selectors GUILayout.Space(5); chute.TextureSelector(); #endregion //Materials editor GUILayout.Space(5); chute.MaterialsSelector(); chute.Calculations(); } } #endregion GUILayout.EndVertical(); GUILayout.BeginVertical(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.EndScrollView(); #region Application GUILayout.Space(5); if (GUILayout.Button("Apply settings", skins.button)) { pChute.Apply(false); } if (part.symmetryCounterparts.Count > 0) { if (GUILayout.Button("Apply to all symmetry counterparts", skins.button)) { pChute.Apply(true); } } #endregion GUILayout.EndVertical(); }
//Calculations GUI core internal void Calculations() { #region Calculations //Selection mode GuiUtils.CreateTwinToggle("Calculations mode:", ref this.calcSelect, 300, new string[] { "Automatic", "Manual" }); GUILayout.Space(5); //Calculations this.parachuteScroll = GUILayout.BeginScrollView(this.parachuteScroll, false, false, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.box, GUILayout.Height(160)); string label; float max, min; #region Automatic if (this.calcSelect) { this.TypeID = GUILayout.SelectionGrid(this.TypeID, EnumUtils.GetNames <ParachuteType>(), 3); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Toggle(this.getMass, "Use current craft mass", GUILayout.Width(150))) { this.getMass = true; } GUILayout.FlexibleSpace(); if (GUILayout.Toggle(!this.getMass, "Input craft mass", GUILayout.Width(150))) { this.getMass = false; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); if (this.getMass) { GUILayout.Label("Currently using " + (this.useDry ? "dry mass" : "wet mass")); if (GUILayout.Button("Switch to " + (this.useDry ? "wet mass" : "dry mass"), GUILayout.Width(125))) { this.useDry = !this.useDry; } } else { GuiUtils.CreateEntryArea("Mass to use (t):", ref this.mass, 0.1f, 10000, 100); } max = 300; switch (this.Type) { case ParachuteType.MAIN: label = "Wanted touchdown speed (m/s):"; break; case ParachuteType.DROGUE: label = "Wanted speed at target alt (m/s):"; max = 5000; break; case ParachuteType.DRAG: label = "Planned landing speed (m/s):"; break; default: label = string.Empty; break; } GuiUtils.CreateEntryArea(label, ref this.landingSpeed, 0.1f, max, 100); if (this.Type == ParachuteType.DROGUE) { GuiUtils.CreateEntryArea("Target altitude (m):", ref this.refDepAlt, 10, (float)this.Body.GetMaxAtmosphereAltitude(), 100); } if (this.Type == ParachuteType.DRAG) { GuiUtils.CreateEntryArea("Wanted deceleration (m/s²):", ref this.deceleration, 0.1f, 100, 100); } GuiUtils.CreateEntryArea("Parachutes used (parachutes):", ref this.chuteCount, 1, 100, 100); } #endregion #region Manual else { float p, d; if (!float.TryParse(this.preDepDiam, out p)) { p = -1; } if (!float.TryParse(this.depDiam, out d)) { d = -1; } //Predeployed diameter GuiUtils.CreateEntryArea("Predeployed diameter (m):", ref this.preDepDiam, 0.5f, d, 100); if (p != -1) { GUILayout.Label("Resulting area: " + RCUtils.GetArea(p).ToString("0.00") + "m²"); } else { GUILayout.Label("Resulting predeployed area: --- m²"); } //Deployed diameter GuiUtils.CreateEntryArea("Deployed diameter (m):", ref this.depDiam, 1, this.PChute.textures == null ? 70 : this.Model.MaxDiam, 100); if (d != 1) { GUILayout.Label("Resulting area: " + RCUtils.GetArea(d).ToString("0.00") + "m²"); } else { GUILayout.Label("Resulting deployed area: --- m²"); } } #endregion GUILayout.EndScrollView(); #endregion #region Specific //Pressure/alt toggle GUILayout.Space(5); GUILayout.BeginHorizontal(); if (GUILayout.Toggle(this.isPressure, "Pressure predeployment")) { if (!this.isPressure) { this.isPressure = true; this.predepClause = this.Parachute.minPressure.ToString(); } } GUILayout.FlexibleSpace(); if (GUILayout.Toggle(!this.isPressure, "Altitude predeployment")) { if (this.isPressure) { this.isPressure = false; this.predepClause = this.Parachute.minDeployment.ToString(); } } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); //Pressure/alt selection if (this.isPressure) { label = "Predeployment pressure (atm):"; min = 0.0001f; max = (float)this.Body.GetPressureAsl(); } else { label = "Predeployment altitude (m):"; min = 10; max = (float)this.Body.GetMaxAtmosphereAltitude(); } GuiUtils.CreateEntryArea(label, ref this.predepClause, min, max); //Deployment altitude GuiUtils.CreateEntryArea("Deployment altitude", ref this.deploymentAlt, 10, (float)this.Body.GetMaxAtmosphereAltitude()); //Cut altitude GuiUtils.CreateEmptyEntryArea("Autocut altitude (m):", ref this.cutAlt, -1, (float)this.Body.GetMaxAtmosphereAltitude()); //Predeployment speed GuiUtils.CreateEntryArea("Pre deployment speed (s):", ref this.preDepSpeed, 0.5f, 5); //Deployment speed GuiUtils.CreateEntryArea("Deployment speed (s):", ref this.depSpeed, 1, 10); #endregion }