//Retreives an "apparent" diameter from a DragCube private float GetApparentDiameter(DragCube cube) { float area = 0; for (int i = 0; i < 6; i++) { area += cube.Area[i] * cube.Drag[i] * PhysicsGlobals.DragCurveValue((Vector3.Dot(Vector3.up, DragCubeList.GetFaceDirection((DragCube.DragFace)i)) + 1f) * 0.5f, 0); } return (float)(Math.Max(Math.Round(Math.Sqrt((area * PhysicsGlobals.DragCubeMultiplier * PhysicsGlobals.DragMultiplier) / Math.PI) * 2d, 1, MidpointRounding.AwayFromZero), 0.1)); }
protected void CopyDragCubesList(DragCubeList source, DragCubeList dest) { dest.ClearCubes(); dest.SetPart(source.Part); dest.None = source.None; // Procedural need access to part so things gets bad quick. dest.Procedural = false; for (int i = 0; i < source.Cubes.Count; i++) { DragCube c = DragCubePool.Instance.Borrow(); CopyDragCube(source.Cubes[i], c); dest.Cubes.Add(c); } dest.SetDragWeights(); for (int i = 0; i < 6; i++) { dest.WeightedArea[i] = source.WeightedArea[i]; dest.WeightedDrag[i] = source.WeightedDrag[i]; dest.AreaOccluded[i] = source.AreaOccluded[i]; dest.WeightedDepth[i] = source.WeightedDepth[i]; } dest.SetDragWeights(); dest.DragCurveCd = simCurves.DragCurveCd; dest.DragCurveCdPower = simCurves.DragCurveCdPower; dest.DragCurveMultiplier = simCurves.DragCurveMultiplier; dest.BodyLiftCurve.liftCurve = simCurves.LiftCurve; dest.BodyLiftCurve.dragCurve = simCurves.DragCurve; dest.BodyLiftCurve.dragMachCurve = simCurves.DragMachCurve; dest.BodyLiftCurve.liftMachCurve = simCurves.LiftMachCurve; dest.SurfaceCurves.dragCurveMultiplier = simCurves.DragCurveMultiplier; dest.SurfaceCurves.dragCurveSurface = simCurves.DragCurveSurface; dest.SurfaceCurves.dragCurveTail = simCurves.DragCurveTail; dest.SurfaceCurves.dragCurveTip = simCurves.DragCurveTip; }
/// <summary> /// Handle all the really expensive stuff once we are no longer actively modifying the wing. Doing it continuously causes lag spikes for lots of people /// </summary> /// <returns></returns> private IEnumerator UpdateAeroDelayed() { bool running = updateTimeDelay > 0; updateTimeDelay = 0.5f; if (running) { yield break; } while (updateTimeDelay > 0) { updateTimeDelay -= TimeWarp.deltaTime; yield return(null); } if (FARactive) { if (part.Modules.Contains("FARWingAerodynamicModel")) { PartModule FARmodule = part.Modules["FARWingAerodynamicModel"]; Type FARtype = FARmodule.GetType(); FARtype.GetMethod("StartInitialization").Invoke(FARmodule, null); } part.SendMessage("GeometryPartModuleRebuildMeshData"); // notify FAR that geometry has changed } else { DragCube DragCube = DragCubeSystem.Instance.RenderProceduralDragCube(part); part.DragCubes.ClearCubes(); part.DragCubes.Cubes.Add(DragCube); part.DragCubes.ResetCubeWeights(); } FuelUpdateVolume(); if (HighLogic.LoadedSceneIsEditor) { GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship); } updateTimeDelay = 0; }
private void Start() { foreach (AvailablePart part in PartLoader.Instance.parts) { Part prefab = part.partPrefab; if (prefab != null && prefab.Modules.Contains("RealChuteFAR")) { //Updates the part's GetInfo. RealChuteFAR module = prefab.Modules["RealChuteFAR"] as RealChuteFAR; DragCubeSystem.Instance.LoadDragCubes(prefab); DragCube semi = prefab.DragCubes.Cubes.Find(c => c.Name == "SEMIDEPLOYED"), deployed = prefab.DragCubes.Cubes.Find(c => c.Name == "DEPLOYED"); if (semi == null || deployed == null) { Debug.Log(part.title + " cannot find drag cube for RealChuteLite"); } module.preDeployedDiameter = GetApparentDiameter(semi); module.deployedDiameter = GetApparentDiameter(deployed); part.moduleInfos.Find(m => m.moduleName == "RealChute").info = module.GetInfo(); } } }
private void Start() { FARLogger.Info("Initiating RealChuteLite Chute Property Calculation"); foreach (AvailablePart part in PartLoader.Instance.loadedParts) { Part prefab = part.partPrefab; if (prefab != null && prefab.Modules.Contains <RealChuteFAR>()) { //Updates the part's GetInfo. RealChuteFAR module = prefab.Modules.GetModule <RealChuteFAR>(); DragCubeSystem.Instance.LoadDragCubes(prefab); DragCube semi = prefab.DragCubes.Cubes.Find(c => c.Name == "SEMIDEPLOYED"), deployed = prefab.DragCubes.Cubes.Find(c => c.Name == "DEPLOYED"); if (semi == null || deployed == null) { FARLogger.Info("" + part.title + " cannot find drag cube for RealChuteLite"); } module.preDeployedDiameter = GetApparentDiameter(semi); module.deployedDiameter = GetApparentDiameter(deployed); part.moduleInfos.Find(m => m.moduleName == "RealChute").info = module.GetInfo(); } } }
private void recreateDragCubes() { if (!HighLogic.LoadedSceneIsFlight && !HighLogic.LoadedSceneIsEditor) { return; } //don't touch them in the prefab if (part.partInfo == null) { return; } setPanelRotations(deployedRotation); this.openCube = DragCubeSystem.Instance.RenderProceduralDragCube(part); setPanelRotations(0); this.closedCube = DragCubeSystem.Instance.RenderProceduralDragCube(part); this.closedCube.Name = "Closed"; this.openCube.Name = "Open"; part.DragCubes.ClearCubes(); part.DragCubes.Cubes.Add(closedCube); part.DragCubes.Cubes.Add(openCube); part.DragCubes.ResetCubeWeights(); updateDragCube(); }
//Retrieves an "apparent" diameter from a DragCube private static float GetApparentDiameter(DragCube cube) { float area = 0; for (int i = 0; i < 6; i++) { // TODO 1.2: according to API docs this method should have only 2 arguments but it has 3 area += cube.Area[i] * cube.Drag[i] * PhysicsGlobals.DragCurveValue(PhysicsGlobals.SurfaceCurves, (Vector3.Dot(Vector3.up, DragCubeList .GetFaceDirection((DragCube.DragFace)i)) + 1) * 0.5f, 0); } return((float)Math.Max(Math.Round(Math.Sqrt(area * 0.1f * PhysicsGlobals.DragMultiplier / Math.PI) * 2, 1, MidpointRounding.AwayFromZero), 0.1)); }
private void scaleDragCubes() { /* This causes SIGSEGV crashes, so for now it's not called. * DRVeyl says to do what https://github.com/KSP-RO/ProceduralParts/blob/3466a39/Source/ProceduralPart.cs#L698-L725 does instead, maybe we'll try that later. * For now, we just live with potentially-incorrect drag cubes. */ float factor = scaleFactor / oldScale; int len = part.DragCubes.Cubes.Count; for (int ic = 0; ic < len; ic++) { DragCube dragCube = part.DragCubes.Cubes[ic]; dragCube.Size *= factor; for (int i = 0; i < dragCube.Area.Length; i++) { dragCube.Area[i] *= factor * factor; } for (int i = 0; i < dragCube.Depth.Length; i++) { dragCube.Depth[i] *= factor; } } part.DragCubes.ForceUpdate(true, true); }
private void recreateDragCubes() { setPanelRotations(deployedRotation); this.openCube = DragCubeSystem.Instance.RenderProceduralDragCube (part); setPanelRotations(0); this.closedCube = DragCubeSystem.Instance.RenderProceduralDragCube (part); this.closedCube.Name = "Closed"; this.openCube.Name = "Open"; part.DragCubes.ClearCubes (); part.DragCubes.Cubes.Add (closedCube); part.DragCubes.Cubes.Add (openCube); part.DragCubes.ResetCubeWeights (); updateDragCube(); }
protected static void CopyDragCube(DragCube source, DragCube dest) { dest.Name = source.Name; dest.Weight = source.Weight; dest.Center = source.Center; dest.Size = source.Size; for (int i = 0; i < source.Drag.Length; i++) { dest.Drag[i] = source.Drag[i]; dest.Area[i] = source.Area[i]; dest.Depth[i] = source.Depth[i]; dest.DragModifiers[i] = source.DragModifiers[i]; } }
//TODO : rewrite the cube calls to only store and update the minimum needed data ( AreaOccluded + WeightedDrag ?) protected static void CopyDragCubesList(DragCubeList source, DragCubeList dest) { dest.ClearCubes(); dest.None = source.None; // Procedural need access to part so things gets bad quick. dest.Procedural = false; for (int i = 0; i < source.Cubes.Count; i++) { DragCube c = new DragCube(); CopyDragCube(source.Cubes[i], c); dest.Cubes.Add(c); } dest.SetDragWeights(); for (int i=0; i<6; i++) { dest.WeightedArea[i] = source.WeightedArea[i]; dest.WeightedDrag[i] = source.WeightedDrag[i]; dest.AreaOccluded[i] = source.AreaOccluded[i]; dest.WeightedDepth[i] = source.WeightedDepth[i]; } dest.SetDragWeights(); // We are missing PostOcclusionArea but it seems to be used in Thermal only }
// Need to check and then simplify this, some operations are just redundant. protected void SetCubeWeight(string name, float newWeight) { float[] WeightedDragOrig = new float[6]; int count = cubes.Cubes.Count; if (count == 0) { return; } bool noChange = true; for (int i = count - 1; i >= 0; i--) { if (cubes.Cubes[i].Name == name && cubes.Cubes[i].Weight != newWeight) { cubes.Cubes[i].Weight = newWeight; noChange = false; } } if (noChange) { return; } ResetCubeArray(cubes.WeightedArea); ResetCubeArray(cubes.WeightedDrag); ResetCubeArray(WeightedDragOrig); float weight = 0f; for (int i = count - 1; i >= 0; i--) { DragCube dc = cubes.Cubes[i]; if (dc.Weight != 0f) { weight = weight + dc.Weight; AddCubeArray(cubes.WeightedArea, dc.Area, dc.Weight); AddCubeArray(cubes.WeightedDrag, dc.Drag, dc.Weight); AddCubeArray(WeightedDragOrig, dc.Drag, dc.Weight); } } if (weight != 0f) { float invWeight = 1f / weight; MultiplyCubeArray(cubes.WeightedArea, invWeight); MultiplyCubeArray(cubes.WeightedDrag, invWeight); MultiplyCubeArray(WeightedDragOrig, invWeight); } else { ResetCubeArray(cubes.WeightedArea); ResetCubeArray(cubes.WeightedDrag); ResetCubeArray(WeightedDragOrig); } SetCubeArray(cubes.AreaOccluded, cubes.WeightedArea); SetCubeArray(cubes.WeightedDrag, WeightedDragOrig); }
public override string GetInfo() { StringBuilder stringBuilder = new StringBuilder(); if (this.resHandler.inputResources.Count > 0) { stringBuilder.Append(this.resHandler.PrintModuleResources(1.0)); } stringBuilder.Append("\n<b><color=#99ff00ff>" + ModuleRealActiveRadiator.cacheAutoLOC_232036 + "</color></b>\n"); double num = this.maxEnergyTransfer; stringBuilder.AppendFormat(Localizer.Format("#autoLOC_232038", new object[] { num }), new object[0]); double num2 = 0.0; int count = base.part.DragCubes.Cubes.Count; while (count-- > 0) { DragCube dragCube = base.part.DragCubes.Cubes[count]; double num3 = (double)(dragCube.Area[0] + dragCube.Area[1] + dragCube.Area[2] + dragCube.Area[3] + dragCube.Area[4] + dragCube.Area[5]); if (num3 > num2) { num2 = num3; } } if (num2 != 0.0) { double num4 = base.part.skinMaxTemp * base.part.radiatorHeadroom; num4 *= num4; num4 *= num4; stringBuilder.Append(Localizer.Format("#autoLOC_232057", new string[] { (num2 * base.part.emissiveConstant * num4 * PhysicsGlobals.StefanBoltzmanConstant * 0.001).ToString("F0") })); } StringBuilder stringBuilder2 = new StringBuilder(); stringBuilder2.AppendFormat("{0:0.00}", this.energyTransferScale * 100.0); stringBuilder.Append(Localizer.Format("#autoLOC_232060", new string[] { stringBuilder2.ToString() })); { stringBuilder.Append(ModuleRealActiveRadiator.cacheAutoLOC_232067); } if (this.parentCoolingOnly) { stringBuilder.Append(ModuleRealActiveRadiator.cacheAutoLOC_232071); } if (maxCryoElectricCost > 0) { stringBuilder.Append("\n<b><color=#99ff00ff>Max Cryogenic Cooling</color></b>\n"); stringBuilder.Append(" <b><color=#00C3FFff>@20K = " + (CoolingEfficiency(20, 300) * maxCryoElectricCost).ToString("F2") + "kW" + "</color>\n"); stringBuilder.Append(" <b><color=#00C3FFff>@90K = " + (CoolingEfficiency(90, 300) * maxCryoElectricCost).ToString("F2") + "kW" + "</color>\n"); } else { stringBuilder.Append("No cryogenic cooling capacity.\n"); } return(stringBuilder.ToString()); }
private void UpdateSubtype(bool fillTanks) { CurrentSubtype.ActivateObjects(); if (HighLogic.LoadedSceneIsEditor) { CurrentSubtype.ActivateNodes(); } UpdateTankSetup(fillTanks); if (CurrentSubtype.maxTemp > 0) { part.maxTemp = CurrentSubtype.maxTemp; } else { part.maxTemp = part.GetPrefab().maxTemp; } if (CurrentSubtype.skinMaxTemp > 0) { part.skinMaxTemp = CurrentSubtype.skinMaxTemp; } else { part.skinMaxTemp = part.GetPrefab().skinMaxTemp; } if (AttachNodeManaged && part.attachRules.allowSrfAttach && part.srfAttachNode != null) { var referenceNode = CurrentSubtype.attachNode ?? part.GetPrefab().srfAttachNode; part.srfAttachNode.position = referenceNode.position; part.srfAttachNode.orientation = referenceNode.orientation; part.srfAttachNode.size = referenceNode.size; } if (FARWrapper.FARLoaded && affectFARVoxels && managedTransformNames.Count > 0) { part.SendMessage("GeometryPartModuleRebuildMeshData"); } if (affectDragCubes && managedTransformNames.Count > 0) { DragCube newCube = DragCubeSystem.Instance.RenderProceduralDragCube(part); part.DragCubes.ClearCubes(); part.DragCubes.Cubes.Add(newCube); part.DragCubes.ResetCubeWeights(); } var window = FindObjectsOfType <UIPartActionWindow>().FirstOrDefault(w => w.part == part); if (window.IsNotNull()) { window.displayDirty = true; } if (HighLogic.LoadedSceneIsEditor) { GameEvents.onEditorPartEvent.Fire(ConstructionEventType.PartTweaked, part); GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship); } else if (HighLogic.LoadedSceneIsFlight) { GameEvents.onVesselWasModified.Fire(this.vessel); } LogInfo("Switched subtype to " + CurrentSubtype.Name); }
private void recreateDragCubes() { if (!HighLogic.LoadedSceneIsFlight && !HighLogic.LoadedSceneIsEditor) { return; }//don't touch them in the prefab if (part.partInfo == null) { return; } setPanelRotations(deployedRotation); this.openCube = DragCubeSystem.Instance.RenderProceduralDragCube(part); setPanelRotations(0); this.closedCube = DragCubeSystem.Instance.RenderProceduralDragCube(part); this.closedCube.Name = "Closed"; this.openCube.Name = "Open"; part.DragCubes.ClearCubes(); part.DragCubes.Cubes.Add(closedCube); part.DragCubes.Cubes.Add(openCube); part.DragCubes.ResetCubeWeights(); updateDragCube(); }