private void OnPlanetSelected(DropDownList sender, int OldIndex, int NewIndex) { CelestialBody newBody = lstPlanets[NewIndex].CB; if (newBody == body) { return; } body = newBody; graphDirty = true; graphRequested = false; this.conditionDetails = ""; if (vessel is VesselCache.SimulatedVessel releasable) { releasable.Release(); } this.vessel = VesselCache.SimulatedVessel.Borrow(EditorLogic.fetch.ship, VesselCache.SimCurves.Borrow(body)); //this.vessel = new StockAero(); Parent.UpdateHighlighting(Parent.highlightMode, this.body, this.Altitude, this.Speed, this.AoA); selectedCrossHairVect = new Vector2(-1, -1); switch (body.name.ToLower()) { case "laythe": default: case "kerbin": maxAltitude = 25000; maxSpeed = 2500; altitudeStep = 200; speedStep = 20; break; case "eve": maxAltitude = 35000; maxSpeed = 3500; altitudeStep = 200; speedStep = 28; break; case "duna": maxAltitude = 10000; maxSpeed = 1000; altitudeStep = 200; speedStep = 20; break; /*case "laythe": * maxAltitude = 20000; * maxSpeed = 2000; * break;*/ case "jool": maxAltitude = 200000; maxSpeed = 7000; altitudeStep = 2000; speedStep = 70; break; } }
private void GenerateHighlightingData(ShipConstruct ship, CelestialBody body, float altitude, float speed, float aoa) { float mach, atmDensity; lock (body) { atmDensity = (float)Extensions.KSPClassExtensions.GetDensity(body, altitude); mach = speed / (float)body.GetSpeedOfSound(body.GetPressure(altitude), atmDensity); } int count = ship.parts.Count; highlightingData = new PartAeroData[count]; Vector3 inflow = AeroPredictor.InflowVect(aoa); float pseudoReDragMult; lock (PhysicsGlobals.DragCurvePseudoReynolds) pseudoReDragMult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(atmDensity * speed); for (int i = 0; i < count; i++) { if (WindTunnelSettings.HighlightIgnoresLiftingSurfaces && ship.parts[i].HasModuleImplementing <ModuleLiftingSurface>()) { highlightingData[i] = new PartAeroData(0, 0, ship.parts[i].mass); continue; } VesselCache.SimulatedPart simPart = VesselCache.SimulatedPart.Borrow(ship.parts[i], null); Vector3 partForce = simPart.GetAero(inflow, mach, pseudoReDragMult); ModuleLiftingSurface liftingSurface = ship.parts[i].FindModuleImplementing <ModuleLiftingSurface>(); if (liftingSurface != null) { VesselCache.SimulatedLiftingSurface simLiftSurf = VesselCache.SimulatedLiftingSurface.Borrow(liftingSurface, simPart); partForce += simLiftSurf.GetForce(inflow, mach); simLiftSurf.Release(); } simPart.Release(); //Vector3 partForce = highlightingVessel.parts[i].GetAero(inflow, mach, pseudoReDragMult); //Vector3 partForce = StockAeroUtil.SimAeroForce(body, new ShipConstruct("test", "", new List<Part>() { EditorLogic.fetch.ship.parts[i] }), inflow * speed, altitude); partForce = AeroPredictor.ToFlightFrame(partForce, aoa); // (Quaternion.AngleAxis((aoa * 180 / Mathf.PI), Vector3.left) * partForce); highlightingData[i] = new PartAeroData(Math.Abs(partForce.z), Math.Abs(partForce.y), ship.parts[i].mass); } }
private void OnRootChanged(Part rootPart) { OnVesselChanged(); // TODO: Could do fancier stuff like compare angles and then adjust all AoAs appropriately. this.vessel = VesselCache.SimulatedVessel.Borrow(EditorLogic.fetch.ship, VesselCache.SimCurves.Borrow(body)); }
private void OnVesselLoaded(ShipConstruct vessel, KSP.UI.Screens.CraftBrowserDialog.LoadType loadType) { OnVesselChanged(); this.vessel = null; //this.vessel = VesselCache.SimulatedVessel.Borrow(vessel, VesselCache.SimCurves.Borrow(body)); }
private void OnNewVessel() { this.Parent.CloseWindow(); OnVesselChanged(); vessel = null; }
internal override void DrawWindow(int id) { if (GUI.Button(new Rect(this.WindowRect.width - 27, 2, 25, 25), "X", exitButton)) { WindTunnel.Instance.CloseWindow(); return; } if (GUI.Button(new Rect(this.WindowRect.width - 54, 2, 25, 25), "▲", Minimized ? downButton : HighLogic.Skin.button)) { Minimized = !Minimized; if (Minimized) { this.WindowRect.height = 100; this.WindowRect.width = 100; } } if (GUI.Button(new Rect(this.WindowRect.width - 81, 2, 25, 25), settingsTex)) { settingsDialog = SpawnDialog(); this.Visible = false; } GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.BeginVertical(GUILayout.Width(graphWidth + 55 + axisWidth)); if (!Minimized) { if (GraphGenerator.Status == CalculationManager.RunStatus.Completed) { if (GUI.Button(new Rect(12, 80 + graphHeight + 9 + 11 - (CurrentGraphMode != GraphMode.FlightEnvelope ? 28 : 0), 25, 25), saveIconTex)) { if (EditorLogic.fetch.ship != null) { grapher.WriteToFile(EditorLogic.fetch.ship.shipName); } } } CurrentGraphMode = (GraphMode)GUILayout.SelectionGrid((int)CurrentGraphMode, graphModes, 3); DrawGraph(CurrentGraphMode, CurrentGraphSelect); /*if (GUILayout.Button("Test!")) * { * Debug.Log("Testing!"); * * float atmPressure, atmDensity, mach; * bool oxygenAvailable; * lock (body) * { * atmPressure = (float)body.GetPressure(Altitude); * atmDensity = (float)Extensions.KSPClassExtensions.GetDensity(body, Altitude); * mach = (float)(Speed / body.GetSpeedOfSound(atmPressure, atmDensity)); * oxygenAvailable = body.atmosphereContainsOxygen; * } * * //Debug.Log("Aero Force (stock): " + stockVessel.GetAeroForce(body, speed, altitude, 2.847f * Mathf.PI / 180, mach)); * //Debug.Log("Lift Force (stock): " + stockVessel.GetLiftForce(body, speed, altitude, 2.847f * Mathf.PI / 180)); * * VesselCache.SimulatedVessel testVessel = VesselCache.SimulatedVessel.Borrow(EditorLogic.fetch.ship, VesselCache.SimCurves.Borrow(body)); * * float weight = (float)(testVessel.Mass * body.gravParameter / ((body.Radius + Altitude) * (body.Radius + Altitude))); // TODO: Minus centrifugal force... * Vector3 thrustForce = testVessel.GetThrustForce(mach, atmDensity, atmPressure, oxygenAvailable); * * DataGenerators.EnvelopeSurf.EnvelopePoint pt = new DataGenerators.EnvelopeSurf.EnvelopePoint(VesselCache.SimulatedVessel.Borrow(EditorLogic.fetch.ship, VesselCache.SimCurves.Borrow(body)), body, Altitude, Speed, this.rootSolver, 0); * Debug.Log("AoA Level: " + pt.AoA_level * 180 / Mathf.PI); * Debug.Log("Thrust Available: " + pt.Thrust_available); * Debug.Log("Excess Thrust: " + pt.Thrust_excess); * Debug.Log("Excess Accel: " + pt.Accel_excess); * Debug.Log("Speed: " + pt.speed); * Debug.Log("Altitude: " + pt.altitude); * Debug.Log("Force: " + pt.force); * Debug.Log("LiftForce: " + pt.liftforce); * Debug.Log(""); * AeroPredictor.Conditions conditions = new AeroPredictor.Conditions(body, Speed, Altitude); * Debug.Log("Aero Force (sim'd): " + AeroPredictor.ToFlightFrame(testVessel.GetAeroForce(conditions, pt.AoA_level, 0, out Vector3 torque), pt.AoA_level)); * Debug.Log("Lift Force (sim'd): " + AeroPredictor.ToFlightFrame(testVessel.GetLiftForce(conditions, pt.AoA_level, 0, out Vector3 lTorque), pt.AoA_level)); * Debug.Log("Aero torque: " + torque); * Debug.Log("Lift torque: " + lTorque); * Debug.Log("Aero torque1: " + testVessel.GetAeroTorque(conditions, pt.AoA_level, 1)); * Debug.Log("Aero torque-1: " + testVessel.GetAeroTorque(conditions, pt.AoA_level, -1)); * Debug.Log(""); * }//*/ CurrentGraphSelect = selectFromIndex[(int)CurrentGraphMode][GUILayout.SelectionGrid(indexFromSelect[(int)CurrentGraphMode][(int)CurrentGraphSelect], graphSelections[(int)CurrentGraphMode], 3)]; } if (Minimized || CurrentGraphMode == GraphMode.AoACurves || CurrentGraphMode == GraphMode.VelocityCurves) { GUILayout.BeginHorizontal(GUILayout.Height(25), GUILayout.ExpandHeight(false)); GUILayout.Label("Altitude: ", GUILayout.Width(62)); altitudeStr = GUILayout.TextField(altitudeStr, GUILayout.Width(105)); if (CurrentGraphMode == GraphMode.AoACurves || Minimized) { Rect toggleRect = GUILayoutUtility.GetRect(new GUIContent(""), HighLogic.Skin.label, GUILayout.Width(20)); toggleRect.position -= new Vector2(7, 3); Mach = GUI.Toggle(toggleRect, Mach, " ", new GUIStyle(HighLogic.Skin.toggle) { padding = new RectOffset(6, 2, -6, -6), contentOffset = new Vector2(6, 2) }); //Mach = GUILayout.Toggle(Mach, "", GUILayout.Width(30), GUILayout.Height(20)); if (!Mach) { GUILayout.Label("Speed (m/s): ", GUILayout.Width(101)); speedStr = GUILayout.TextField(speedStr, GUILayout.Width(132)); } else { GUILayout.Label("Speed (Mach): ", GUILayout.Width(101)); speedStr = GUILayout.TextField(speedStr, GUILayout.Width(132)); } } else { GUILayout.Label("", GUILayout.Width(20)); GUILayout.Label("", GUILayout.Width(101)); GUILayout.Label("", GUILayout.Width(132)); } if (GUILayout.Button("Apply")) { if (float.TryParse(altitudeStr, out float altitude) && (CurrentGraphMode != GraphMode.AoACurves | float.TryParse(speedStr, out float speed))) { if (this.Altitude != altitude || this.Speed != speed) { this.Altitude = altitude; if (CurrentGraphMode == GraphMode.AoACurves) { if (Mach) { lock (body) _speed *= (float)body.GetSpeedOfSound(body.GetPressure(Altitude), Extensions.KSPClassExtensions.GetDensity(body, Altitude)); } this.Speed = speed; } Cancel(); graphDirty = true; graphRequested = false; Parent.UpdateHighlighting(Parent.highlightMode, this.body, this.Altitude, this.Speed, this.AoA); } } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (!Minimized) { GUILayout.BeginVertical(GUILayout.Width(200)); ddlPlanet.DrawButton(); GUILayout.Space(2); if (GUILayout.Button("Update Vessel", GUILayout.Height(25))) { OnVesselChanged(); this.vessel = VesselCache.SimulatedVessel.Borrow(EditorLogic.fetch.ship, VesselCache.SimCurves.Borrow(body)); } // Display selected point details. GUILayout.Label(this.conditionDetails); if (CurrentGraphMode == GraphMode.AoACurves && AoACurveGenerator.Status == CalculationManager.RunStatus.Completed) { DataGenerators.AoACurve.AoAPoint zeroPoint = new DataGenerators.AoACurve.AoAPoint(vessel, body, Altitude, Speed, 0); GUILayout.Label(String.Format("CL_Alpha_0:\t{0:F3}m^2/°\nCL_Alpha_avg:\t{1:F3}m^2/°", zeroPoint.dLift / zeroPoint.dynamicPressure, AoACurveGenerator.AverageLiftSlope)); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Part Highlighting: "); WindTunnel.HighlightMode newhighlightMode = (WindTunnel.HighlightMode)GUILayout.SelectionGrid((int)WindTunnel.Instance.highlightMode, highliftModeStrings, 3); if (newhighlightMode != Parent.highlightMode) { Parent.UpdateHighlighting(newhighlightMode, this.body, this.Altitude, this.Speed, this.AoA); if (newhighlightMode == WindTunnel.HighlightMode.Off) { this.WindowRect.height = 100; } } GUILayout.EndHorizontal(); if (newhighlightMode != WindTunnel.HighlightMode.Off) { GUILayout.BeginHorizontal(); GUILayout.Label("AoA (deg): "); aoaStr = GUILayout.TextField(aoaStr, GUILayout.Width(132)); if (GUILayout.Button("Apply")) { if (float.TryParse(aoaStr, out float tempAoA)) { tempAoA *= Mathf.Deg2Rad; if (tempAoA != AoA) { AoA = tempAoA; Parent.UpdateHighlighting(Parent.highlightMode, this.body, this.Altitude, this.Speed, this.AoA); } } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); Vector2 vectMouse = Event.current.mousePosition; if (selectedCrossHairVect.x >= 0 && selectedCrossHairVect.y >= 0 && Status == CalculationManager.RunStatus.Completed) { if (graphRect.x + selectedCrossHairVect.x != vectMouse.x || !graphRect.Contains(vectMouse)) { GUI.Box(new Rect(graphRect.x + selectedCrossHairVect.x, graphRect.y, 1, graphRect.height), "", styleSelectedCrossHair); } if (CurrentGraphMode == GraphMode.FlightEnvelope) { if (graphRect.y + selectedCrossHairVect.y != vectMouse.y || !graphRect.Contains(vectMouse)) { GUI.Box(new Rect(graphRect.x, graphRect.y + selectedCrossHairVect.y, graphRect.width, 1), "", styleSelectedCrossHair); } } } if (graphRect.Contains(vectMouse) && Status == CalculationManager.RunStatus.Completed) { GUI.Box(new Rect(vectMouse.x, graphRect.y, 1, graphRect.height), "", stylePlotCrossHair); if (CurrentGraphMode == GraphMode.FlightEnvelope) { GUI.Box(new Rect(graphRect.x, vectMouse.y, graphRect.width, 1), "", stylePlotCrossHair); } float showValue = GetGraphValue((int)(vectMouse.x - graphRect.x), CurrentGraphMode == GraphMode.FlightEnvelope ? (int)(graphHeight - (vectMouse.y - graphRect.y)) : -1); //GUI.Label(new Rect(vectMouse.x + 5, vectMouse.y - 20, 80, 15), String.Format(graphUnits[(int)CurrentGraphSelect], showValue), SkinsLibrary.CurrentTooltip); GUIContent labelContent = new GUIContent(grapher.GetFormattedValueAtPixel((int)(vectMouse.x - graphRect.x), (int)(graphHeight - (vectMouse.y - graphRect.y)))); Vector2 labelSize = SkinsLibrary.CurrentTooltip.CalcSize(labelContent); if (labelSize.x < 80) { labelSize.x = 80; } if (labelSize.y < 15) { labelSize.y = 15; } GUI.Label(new Rect(vectMouse.x + 5, vectMouse.y - 20, labelSize.x, labelSize.y), labelContent, SkinsLibrary.CurrentTooltip); if (Event.current.type == EventType.MouseDown && Event.current.button == 0) { //conditionDetails = GetConditionDetails((vectMouse.x - graphRect.x) / graphWidth, CurrentGraphMode == GraphMode.FlightEnvelope ? (graphHeight - (vectMouse.y - graphRect.y)) / graphHeight : float.NaN); selectedCrossHairVect = vectMouse - graphRect.position; SetConditionsFromGraph(selectedCrossHairVect); conditionDetails = GetConditionDetails(CurrentGraphMode, this.Altitude, this.Speed, this.AoA, true); if (Parent.highlightMode != WindTunnel.HighlightMode.Off) { Parent.UpdateHighlighting(Parent.highlightMode, this.body, this.Altitude, this.Speed, this.AoA); } } } if (CurrentGraphMode == GraphMode.FlightEnvelope && cAxisRect.Contains(vectMouse) && Status == CalculationManager.RunStatus.Completed) { GUI.Box(new Rect(vectMouse.x, cAxisRect.y, 1, cAxisRect.height), "", stylePlotCrossHair); float showValue = (vectMouse.x - cAxisRect.x) / (cAxisRect.width - 1) * (grapher.colorAxis.Max - grapher.colorAxis.Min) + grapher.colorAxis.Min; //GUI.Label(new Rect(vectMouse.x + 5, cAxisRect.y - 15, 80, 15), String.Format(graphUnits[(int)CurrentGraphSelect], showValue), SkinsLibrary.CurrentTooltip); GUI.Label(new Rect(vectMouse.x + 5, cAxisRect.y - 15, 80, 15), String.Format("{0:" + ((Graphing.Graphable)(grapher[grapher.dominantColorMapIndex])).StringFormat + "}{1}", showValue, ((Graphing.Graphable3)(grapher[grapher.dominantColorMapIndex])).ZUnit), SkinsLibrary.CurrentTooltip); } }