public override void OnStart(PartModule.StartState state) { base.OnStart(state); _scale = this.Fields["tweakScale"]; _name = this.Fields["tweakName"]; _type = this.Fields["scaleTypeId"]; _scaleEdit = (UI_FloatEdit)_scale.uiControlEditor; _nameEdit = (UI_ChooseOption)_name.uiControlEditor; _typeEdit = (UI_ChooseOption)_type.uiControlEditor; _typeEdit.options = ScaleType.AllScaleTypes.Select(a => a.Name).ToArray(); scaleInfo = ScaleDatabase.Lookup(part.partInfo.name); }
public override void UpdateTechConstraints() { if (!HighLogic.LoadedSceneIsEditor) return; // ReSharper disable CompareOfFloatsByEqualityOperator if (PPart.lengthMin == PPart.lengthMax) Fields["length"].guiActiveEditor = false; else { UI_FloatEdit lengthEdit = (UI_FloatEdit)Fields["length"].uiControlEditor; lengthEdit.maxValue = PPart.lengthMax; lengthEdit.minValue = PPart.lengthMin; lengthEdit.incrementLarge = PPart.lengthLargeStep; lengthEdit.incrementSmall = PPart.lengthSmallStep; length = Mathf.Clamp(length, PPart.lengthMin, PPart.lengthMax); } UI_FloatEdit diameterEdit = (UI_FloatEdit)Fields["diameter"].uiControlEditor; if (PPart.diameterMin == PPart.diameterMax) Fields["diameter"].guiActiveEditor = false; else { diameterEdit.maxValue = PPart.diameterMax; diameterEdit.minValue = PPart.diameterMin; diameterEdit.incrementLarge = PPart.diameterLargeStep; diameterEdit.incrementSmall = PPart.diameterSmallStep; diameter = Mathf.Clamp(diameter, PPart.diameterMin, PPart.diameterMax); } if (!PPart.allowCurveTweaking) { Fields["fillet"].guiActiveEditor = false; diameterEdit.maxValue = PPart.diameterMax - fillet; } else { filletEdit = (UI_FloatEdit)Fields["fillet"].uiControlEditor; filletEdit.maxValue = Mathf.Min(length, useEndDiameter ? PPart.diameterMax : diameter); filletEdit.minValue = 0; filletEdit.incrementLarge = PPart.diameterLargeStep; filletEdit.incrementSmall = PPart.diameterSmallStep; fillet = Mathf.Clamp(fillet, filletEdit.minValue, filletEdit.maxValue); } // ReSharper restore CompareOfFloatsByEqualityOperator }
public override void OnStart(StartState state) { if (!HighLogic.LoadedSceneIsEditor) return; if (pPart.lengthMin == pPart.lengthMax) Fields["length"].guiActiveEditor = false; else { UI_FloatEdit lengthEdit = (UI_FloatEdit)Fields["length"].uiControlEditor; lengthEdit.maxValue = pPart.lengthMax; lengthEdit.minValue = pPart.lengthMin; lengthEdit.incrementLarge = pPart.lengthLargeStep; lengthEdit.incrementSmall = pPart.lengthSmallStep; } UI_FloatEdit diameterEdit = (UI_FloatEdit)Fields["diameter"].uiControlEditor; if (pPart.diameterMin == pPart.diameterMax) Fields["diameter"].guiActiveEditor = false; else { diameterEdit.maxValue = pPart.diameterMax; diameterEdit.minValue = useEndDiameter ? 0 : pPart.diameterMin; diameterEdit.incrementLarge = pPart.diameterLargeStep; diameterEdit.incrementSmall = pPart.diameterSmallStep; } if (!pPart.allowCurveTweaking) { Fields["fillet"].guiActiveEditor = false; diameterEdit.maxValue = pPart.diameterMax - fillet; } else { filletEdit = (UI_FloatEdit)Fields["fillet"].uiControlEditor; filletEdit.maxValue = Mathf.Min(length, useEndDiameter ? pPart.diameterMax : diameter); filletEdit.minValue = 0; filletEdit.incrementLarge = pPart.diameterLargeStep; filletEdit.incrementSmall = pPart.diameterSmallStep; } }
protected override void UpdateShape(bool force) { // ReSharper disable CompareOfFloatsByEqualityOperator if (!force && oldDiameter == diameter && oldLength == length && oldFillet == fillet) return; if (HighLogic.LoadedSceneIsFlight) { Volume = CalcVolume(); } else if (HighLogic.LoadedSceneIsEditor) { if (filletEdit == null) filletEdit = (UI_FloatEdit)Fields["fillet"].uiControlEditor; if (length != oldLength) { if (length < oldLength && fillet > length) fillet = length; float volExcess = MaxMinVolume(); if (volExcess != 0) { // Again using alpha, solve the volume equation below equation for l // v = 1/24 pi (6 d^2 l+3 (pi-4) d f^2+(10-3 pi) f^3) for l // l = (-3 (pi-4) pi d f^2+pi (3 pi-10) f^3+24 v)/(6 pi d^2) length = (-3f * (Pi - 4f) * Pi * diameter * pow(fillet, 2) + Pi * (3f * Pi - 10f) * pow(fillet, 3) + 24f * Volume) / (6f * Pi * pow(diameter, 2)); length = (float)Math.Round(length, 3); // We could iterate here with the fillet and push it back up if it's been pushed down // but it's altogether too much bother. User will just have to suck it up and not be // so darn agressive with short lengths. I mean, seriously... :) } filletEdit.maxValue = Mathf.Min(length, useEndDiameter ? PPart.diameterMax : diameter); } else if (diameter != oldDiameter) { if (useEndDiameter) { if (diameter + fillet < PPart.diameterMin) fillet = PPart.diameterMin - diameter; else if (diameter + fillet > PPart.diameterMax) fillet = PPart.diameterMax - diameter; } else { if (diameter < oldDiameter && fillet > diameter) fillet = diameter; } float volExcess = MaxMinVolume(); if (volExcess != 0) { // Unfortunatly diameter is not as easily isolated, but its still possible. // v = 1/24 pi (6 d^2 l+3 (pi-4) d f^2+(10-3 pi) f^3) for d // simplify d = ((-3 pi^2 f^2+12 pi f^2) ± sqrt(3 pi) sqrt(3 pi^3 f^4-24 pi^2 f^4+48 pi f^4+24 pi^2 f^3 l-80 pi f^3 l+192 l v))/(12 pi l) // d = (-3 (pi-4) pi f^2 ± sqrt(3 pi) sqrt(3 (pi-4)^2 pi f^4+8 pi (3 pi-10) f^3 l+192 l v)) / (12 pi l) float t1 = -3 * (Pi - 4f) * Pi * fillet * fillet; float t2 = sqrt(3f * Pi) * sqrt(3f * pow(Pi - 4f, 2) * Pi * pow(fillet, 4) + 8f * Pi * (3f * Pi - 10f) * pow(fillet, 3) * length + 192f * length * Volume); float de = (12f * Pi * length); // I'm pretty sure only the +ve value is required, but make the -ve possible too. diameter = (t1 + t2) / de; if (diameter < 0) diameter = (t1 - t2) / de; diameter = (float)Math.Round(diameter, 3); } filletEdit.maxValue = Mathf.Min(length, useEndDiameter ? PPart.diameterMax : diameter); } else if (fillet != oldFillet) { if (useEndDiameter) { // Keep diameter + fillet within range. if (diameter + fillet < PPart.diameterMin) diameter = PPart.diameterMin - fillet; else if (diameter + fillet > PPart.diameterMax) diameter = PPart.diameterMax - fillet; } // Will do an iterative process for finding the value. // The equation is far too complicated plug this into alpha and you'll see what I mean: // v = 1/24 pi (6 d^2 l+3 (pi-4) d f^2+(10-3 pi) f^3) for f float vol = CalcVolume(); float inc; if (vol < PPart.volumeMin) { Volume = PPart.volumeMin; inc = -0.001f; } else if (vol > PPart.volumeMax) { Volume = PPart.volumeMax; inc = 0.001f; } else { Volume = vol; goto goldilocks; } float lVol; float lFillet; do { lVol = vol; lFillet = fillet; fillet += inc; vol = CalcVolume(); } while (Mathf.Abs(vol - Volume) < Mathf.Abs(lVol - Volume)); fillet = (float)Math.Round(lFillet, 3); goldilocks: ; } } LinkedList<ProfilePoint> points = new LinkedList<ProfilePoint>(); if (fillet == 0) { // Reduces down to a cylinder part. points.AddLast(new ProfilePoint(diameter, -0.5f * length, 0f, new Vector2(1, 0))); points.AddLast(new ProfilePoint(diameter, 0.5f * length, 1f, new Vector2(1, 0))); } else { float bodyLength = length - fillet; float endDiameter = useEndDiameter ? diameter : (diameter - fillet); float bodyDiameter = useEndDiameter ? (fillet + diameter) : diameter; float filletLength = Mathf.PI * fillet * 0.5f; float totLength = filletLength + bodyLength; float s1 = filletLength * 0.5f / totLength; CirclePoints cp = CirclePoints.ForDiameter(fillet, MaxCircleError, MinCircleVertexes); // We need to be careful with the number of points so we don't blow the 255 point budget for colliders CirclePoints collCp = CirclePoints.ForDiameter(fillet, MaxCircleError, 0, 12); CirclePoints collEnds = CirclePoints.ForDiameter(endDiameter, MaxCircleError * 4f, 4, 12); CirclePoints collBody = CirclePoints.ForDiameter(bodyDiameter, MaxCircleError * 4f, 4, 16); points.AddLast(new ProfilePoint(endDiameter, -0.5f * length, 0f, new Vector2(0, -1), colliderCirc: collEnds)); foreach (Vector3 xzu in cp.PointsXZU(0.5f, 0.75f)) points.AddLast(new ProfilePoint(endDiameter + fillet * xzu.x, -0.5f * (bodyLength - fillet * xzu.y), s1 * Mathf.InverseLerp(0.5f, 0.75f, xzu[2]), xzu, inCollider: false)); foreach (Vector3 xzu in collCp.PointsXZU(0.5f, 0.75f)) points.AddLast(new ProfilePoint(endDiameter + fillet * xzu.x, -0.5f * (bodyLength - fillet * xzu.y), s1 * Mathf.InverseLerp(0.5f, 0.75f, xzu[2]), xzu, inRender: false, colliderCirc: collEnds)); points.AddLast(new ProfilePoint(bodyDiameter, -0.5f * bodyLength, s1, new Vector2(1, 0), colliderCirc: collBody)); if (fillet < length) points.AddLast(new ProfilePoint(bodyDiameter, 0.5f * bodyLength, 1f - s1, new Vector2(1, 0), colliderCirc: collBody)); foreach (Vector3 xzu in cp.PointsXZU(0.75f, 1)) points.AddLast(new ProfilePoint(endDiameter + fillet * xzu.x, 0.5f * (bodyLength + fillet * xzu.y), 1f - s1 * Mathf.InverseLerp(1f, 0.75f, xzu[2]), xzu, inCollider: false)); foreach (Vector3 xzu in collCp.PointsXZU(0.75f, 1)) points.AddLast(new ProfilePoint(endDiameter + fillet * xzu.x, 0.5f * (bodyLength + fillet * xzu.y), 1f - s1 * Mathf.InverseLerp(1f, 0.75f, xzu[2]), xzu, inRender: false, colliderCirc: collEnds)); points.AddLast(new ProfilePoint(endDiameter, 0.5f * length, 1f, new Vector2(0, 1), colliderCirc: collEnds)); } WriteMeshes(points); oldDiameter = diameter; oldLength = length; oldFillet = fillet; // ReSharper restore CompareOfFloatsByEqualityOperator UpdateInterops(); }