From 5bb929a5965a6d48c2e2c71a6f6ee36ab6180d9b Mon Sep 17 00:00:00 2001 From: PapaJoesSoup Date: Mon, 14 May 2018 14:26:42 -0700 Subject: [PATCH] v1.7.3 - Add Crew selection screen to spawn feature. You can now (optionally) select one crewmember from a list of available crew. Git Issue #17 - Fixed Tab key movement mode changes to prevent positioning craft underground. Git Issue #29 - Clean up tool tips to display above window and not beyond edge of screen. - Improved control of altitude during movement mode changes. Now when changing altitudes, changes to movement mode will not alter current altitude. - Added new Movement Mode altitude reset key Throttle Cuttoff (Default is X) to allow for flexible altitude positioning. - Revised help and readme to reflect changes to hot keys. --- .../GameData/VesselMover/ChangeLog.txt | 8 +- .../VesselMover/Plugins/VesselMover.dll | Bin 40448 -> 40448 bytes Distribution/GameData/VesselMover/Readme.txt | 17 +- .../GameData/VesselMover/VesselMover.version | 4 +- Properties/AssemblyInfo.cs | 4 +- VesselMove.cs | 454 +++++++++--------- VesselMoverToolbar.cs | 60 +-- VesselSpawn.cs | 36 +- 8 files changed, 303 insertions(+), 280 deletions(-) diff --git a/Distribution/GameData/VesselMover/ChangeLog.txt b/Distribution/GameData/VesselMover/ChangeLog.txt index bb9f52a..b386434 100644 --- a/Distribution/GameData/VesselMover/ChangeLog.txt +++ b/Distribution/GameData/VesselMover/ChangeLog.txt @@ -1,6 +1,10 @@ -v1.7.2.3 - - Add Crew selection screen to spawn feature. You can select one crewmember from a list of available crew. Git Issue #17 +v1.7.3 + - Add Crew selection screen to spawn feature. You can now (optionally) select one crewmember from a list of available crew. Git Issue #17 + - Fixed Tab key movement mode changes to prevent positioning craft underground. Git Issue #29 - Clean up tool tips to display above window and not beyond edge of screen. + - Improved control of altitude during movement mode changes. Now when changing altitudes, changes to movement mode will not alter current altitude. + - Added new Movement Mode altitude reset key Throttle Cuttoff (Default is X) to allow for flexible altitude positioning. + - Revised help and readme to reflect changes to hot keys. v1.7.2.2 - Recompiled for KSP 1.4.3 Works in 1.4.x diff --git a/Distribution/GameData/VesselMover/Plugins/VesselMover.dll b/Distribution/GameData/VesselMover/Plugins/VesselMover.dll index fe05d62599d10eb91dd222845ce46279713ea019..ba15307e20dc474abf2b6e087cc5bfe8c2813185 100644 GIT binary patch literal 40448 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 literal 40448 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 placingVessels = new List(); + private MoveModes _moveMode = MoveModes.Normal; + private bool _moving = false; + private List _placingVessels = new List(); + private bool _hoverChanged; + + public float MoveHeight = 0; + private float _hoverAdjust = 0f; + private readonly float[] _hoverHeights = new float[] { 35, 15, 5, 3000 }; - public float moveHeight = 0; - float hoverAdjust = 0f; - - float[] hoverHeights = new float[] { 35, 15, 5, 3000 }; - float hoverHeight + private float HoverHeight { get { - return hoverHeights[(int)moveMode]; + return _hoverHeights[(int)_moveMode]; } } - float[] moveSpeeds = new float[] { 10, 0.5f, 0.1f, 1500 }; - float moveSpeed + private readonly float[] _moveSpeeds = new float[] { 10, 5, 1, 1500 }; + + private float MoveSpeed { get { - return moveSpeeds[(int)moveMode]; + return _moveSpeeds[(int)_moveMode]; } } - float[] moveAccels = new float[] { 10, 1, 0.5f, 750 }; - float moveAccel + private readonly float[] _moveAccels = new float[] { 10, 1, 0.5f, 750 }; + + private float MoveAccel { get { - return moveAccels[(int)moveMode]; + return _moveAccels[(int)_moveMode]; } } - float[] rotationSpeeds = new float[] { 50, 20, 10, 50 }; - float rotationSpeed + private readonly float[] _rotationSpeeds = new float[] { 50, 20, 10, 50 }; + + private float RotationSpeed { get { - return rotationSpeeds[(int)moveMode] * Time.fixedDeltaTime; + return _rotationSpeeds[(int)_moveMode] * Time.fixedDeltaTime; } } - public bool isMovingVessel = false; - public Vessel movingVessel; - Quaternion startRotation; - Quaternion currRotation; - float currMoveSpeed = 0; - Vector3 currMoveVelocity; - VesselBounds vBounds; - LineRenderer debugLr; - Vector3 up; - Vector3 startingUp; - float maxPlacementSpeed = 1050; - bool hasRotated = false; - float timeBoundsUpdated = 0; - ScreenMessage moveMessage; + public bool IsMovingVessel = false; + public Vessel MovingVessel; + private Quaternion _startRotation; + private Quaternion _currRotation; + private float _currMoveSpeed = 0; + private Vector3 _currMoveVelocity; + private VesselBounds _vBounds; + private LineRenderer _debugLr; + private Vector3 _up; + private Vector3 _startingUp; + private readonly float maxPlacementSpeed = 1050; + private bool _hasRotated = false; + private float _timeBoundsUpdated = 0; + private ScreenMessage _moveMessage; #endregion #region KSP Events - void Awake() + private void Awake() { - if (instance) + if (Instance) { - Destroy(instance); + Destroy(Instance); } - instance = this; + Instance = this; } - void Start() + private void Start() { - debugLr = new GameObject().AddComponent(); - debugLr.material = new Material(Shader.Find("KSP/Emissive/Diffuse")); - debugLr.material.SetColor("_EmissiveColor", Color.green); - debugLr.startWidth = 0.15f; - debugLr.endWidth = 0.15f; - debugLr.enabled = false; + _debugLr = new GameObject().AddComponent(); + _debugLr.material = new Material(Shader.Find("KSP/Emissive/Diffuse")); + _debugLr.material.SetColor("_EmissiveColor", Color.green); + _debugLr.startWidth = 0.15f; + _debugLr.endWidth = 0.15f; + _debugLr.enabled = false; } - void Update() + private void Update() { - if (moving) + if (_moving) { if (Input.GetKeyDown(KeyCode.Tab)) { @@ -108,29 +112,27 @@ void Update() // Changed to a GameEvents handler flag. This test was too sensitive and caused issues with display. // a latched setting will prevent misfires. - if (isMovingVessel) + if (IsMovingVessel) { - debugLr.enabled = VesselMoverToolbar.ShowUI; + _debugLr.enabled = VesselMoverToolbar.ShowUI; } } - void FixedUpdate() + private void FixedUpdate() { - if (moving) - { - movingVessel.IgnoreGForces(240); - UpdateMove(); + if (!_moving) return; + MovingVessel.IgnoreGForces(240); + UpdateMove(); - if (hasRotated && Time.time - timeBoundsUpdated > 0.2f) - { - UpdateBounds(); - } + if (_hasRotated && Time.time - _timeBoundsUpdated > 0.2f) + { + UpdateBounds(); } } - void LateUpdate() + private void LateUpdate() { - if (moving) + if (_moving) { UpdateDebugLines(); } @@ -138,30 +140,38 @@ void LateUpdate() #endregion - void UpdateBounds() + private void UpdateBounds() { - hasRotated = false; - vBounds.UpdateBounds(); - timeBoundsUpdated = Time.time; + _hasRotated = false; + _vBounds.UpdateBounds(); + _timeBoundsUpdated = Time.time; } - void UpdateMove() + private void UpdateMove() { - if (!movingVessel) + if (!MovingVessel) { EndMove(); return; } - movingVessel.IgnoreGForces(240); + MovingVessel.IgnoreGForces(240); - double alt = movingVessel.radarAltitude; - if (moveHeight < alt) moveHeight = Convert.ToSingle(alt); // Lerp is animating move from 0 to hoverheight, we do not want this going below current altitude - - moveHeight = Mathf.Lerp(moveHeight, vBounds.bottomLength + hoverHeight + hoverAdjust, 10 * Time.fixedDeltaTime); + // Lerp is animating move + if (!_hoverChanged) + MoveHeight = Mathf.Lerp(MoveHeight, _vBounds.BottomLength + HoverHeight, 10 * Time.fixedDeltaTime); + else + { + double alt = MovingVessel.radarAltitude; + // sINCE Lerp is animating move from 0 to hoverheight, we do not want this going below current altitude + if (MoveHeight < alt) MoveHeight = Convert.ToSingle(alt); - movingVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, false); + MoveHeight = MovingVessel.Splashed + ? Mathf.Lerp(MoveHeight, _vBounds.BottomLength + _hoverAdjust, 10 * Time.fixedDeltaTime) + : Mathf.Lerp(MoveHeight, _vBounds.BottomLength + (MoveHeight + _hoverAdjust < 0 ? -MoveHeight : _hoverAdjust), 10 * Time.fixedDeltaTime); + } + MovingVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, false); - up = (movingVessel.transform.position - FlightGlobals.currentMainBody.transform.position).normalized; + _up = (MovingVessel.transform.position - FlightGlobals.currentMainBody.transform.position).normalized; Vector3 forward; if (MapView.MapIsEnabled) @@ -170,112 +180,120 @@ void UpdateMove() } else { - forward = Vector3.ProjectOnPlane(movingVessel.CoM - FlightCamera.fetch.mainCamera.transform.position, up).normalized; - if (Vector3.Dot(-up, FlightCamera.fetch.mainCamera.transform.up) > 0) + forward = Vector3.ProjectOnPlane(MovingVessel.CoM - FlightCamera.fetch.mainCamera.transform.position, _up).normalized; + if (Vector3.Dot(-_up, FlightCamera.fetch.mainCamera.transform.up) > 0) { - forward = Vector3.ProjectOnPlane(FlightCamera.fetch.mainCamera.transform.up, up).normalized; + forward = Vector3.ProjectOnPlane(FlightCamera.fetch.mainCamera.transform.up, _up).normalized; } } - Vector3 right = Vector3.Cross(up, forward); + Vector3 right = Vector3.Cross(_up, forward); Vector3 offsetDirection = Vector3.zero; bool inputting = false; //Altitude Adjustment + if (GameSettings.THROTTLE_CUTOFF.GetKey()) + { + _hoverAdjust = 0f; + _hoverChanged = false; + } + if (GameSettings.THROTTLE_UP.GetKey()) { - hoverAdjust += 10f > moveSpeed ? 10f : moveSpeed * Time.fixedDeltaTime; + _hoverAdjust += MoveSpeed * Time.fixedDeltaTime; inputting = true; + _hoverChanged = true; } if (GameSettings.THROTTLE_DOWN.GetKey()) { - hoverAdjust += -(10f > moveSpeed ? 10f : moveSpeed) * Time.fixedDeltaTime; + _hoverAdjust += -(MoveSpeed * Time.fixedDeltaTime); inputting = true; + _hoverChanged = true; } if (GameSettings.PITCH_DOWN.GetKey()) { - offsetDirection += (forward * moveSpeed * Time.fixedDeltaTime); + offsetDirection += (forward * MoveSpeed * Time.fixedDeltaTime); inputting = true; } if (GameSettings.PITCH_UP.GetKey()) { - offsetDirection += (-forward * moveSpeed * Time.fixedDeltaTime); + offsetDirection += (-forward * MoveSpeed * Time.fixedDeltaTime); inputting = true; } if (GameSettings.YAW_RIGHT.GetKey()) { - offsetDirection += (right * moveSpeed * Time.fixedDeltaTime); + offsetDirection += (right * MoveSpeed * Time.fixedDeltaTime); inputting = true; } if (GameSettings.YAW_LEFT.GetKey()) { - offsetDirection += (-right * moveSpeed * Time.fixedDeltaTime); + offsetDirection += (-right * MoveSpeed * Time.fixedDeltaTime); inputting = true; } if (GameSettings.TRANSLATE_RIGHT.GetKey()) { - startRotation = Quaternion.AngleAxis(-rotationSpeed, movingVessel.ReferenceTransform.forward) * startRotation; - hasRotated = true; + _startRotation = Quaternion.AngleAxis(-RotationSpeed, MovingVessel.ReferenceTransform.forward) * _startRotation; + _hasRotated = true; } else if (GameSettings.TRANSLATE_LEFT.GetKey()) { - startRotation = Quaternion.AngleAxis(rotationSpeed, movingVessel.ReferenceTransform.forward) * startRotation; - hasRotated = true; + _startRotation = Quaternion.AngleAxis(RotationSpeed, MovingVessel.ReferenceTransform.forward) * _startRotation; + _hasRotated = true; } if (GameSettings.TRANSLATE_DOWN.GetKey()) { - startRotation = Quaternion.AngleAxis(rotationSpeed, movingVessel.ReferenceTransform.right) * startRotation; - hasRotated = true; + _startRotation = Quaternion.AngleAxis(RotationSpeed, MovingVessel.ReferenceTransform.right) * _startRotation; + _hasRotated = true; } else if (GameSettings.TRANSLATE_UP.GetKey()) { - startRotation = Quaternion.AngleAxis(-rotationSpeed, movingVessel.ReferenceTransform.right) * startRotation; - hasRotated = true; + _startRotation = Quaternion.AngleAxis(-RotationSpeed, MovingVessel.ReferenceTransform.right) * _startRotation; + _hasRotated = true; } if (GameSettings.ROLL_LEFT.GetKey()) { - startRotation = Quaternion.AngleAxis(rotationSpeed, movingVessel.ReferenceTransform.up) * startRotation; - hasRotated = true; + _startRotation = Quaternion.AngleAxis(RotationSpeed, MovingVessel.ReferenceTransform.up) * _startRotation; + _hasRotated = true; } else if (GameSettings.ROLL_RIGHT.GetKey()) { - startRotation = Quaternion.AngleAxis(-rotationSpeed, movingVessel.ReferenceTransform.up) * startRotation; - hasRotated = true; + _startRotation = Quaternion.AngleAxis(-RotationSpeed, MovingVessel.ReferenceTransform.up) * _startRotation; + _hasRotated = true; } //auto level plane if (GameSettings.TRANSLATE_FWD.GetKey()) { - Quaternion targetRot = Quaternion.LookRotation(-up, forward); - startRotation = Quaternion.RotateTowards(startRotation, targetRot, rotationSpeed * 2); - hasRotated = true; + Quaternion targetRot = Quaternion.LookRotation(-_up, forward); + _startRotation = Quaternion.RotateTowards(_startRotation, targetRot, RotationSpeed * 2); + _hasRotated = true; } else if (GameSettings.TRANSLATE_BACK.GetKey())//auto level rocket { - Quaternion targetRot = Quaternion.LookRotation(forward, up); - startRotation = Quaternion.RotateTowards(startRotation, targetRot, rotationSpeed * 2); - hasRotated = true; + Quaternion targetRot = Quaternion.LookRotation(forward, _up); + _startRotation = Quaternion.RotateTowards(_startRotation, targetRot, RotationSpeed * 2); + _hasRotated = true; } if (inputting) { - currMoveSpeed = Mathf.Clamp(Mathf.MoveTowards(currMoveSpeed, moveSpeed, moveAccel * Time.fixedDeltaTime), 0, moveSpeed); + _currMoveSpeed = Mathf.Clamp(Mathf.MoveTowards(_currMoveSpeed, MoveSpeed, MoveAccel * Time.fixedDeltaTime), 0, MoveSpeed); } else { - currMoveSpeed = 0; + _currMoveSpeed = 0; } - Vector3 offset = offsetDirection.normalized * currMoveSpeed; - currMoveVelocity = offset / Time.fixedDeltaTime; - Vector3 vSrfPt = movingVessel.CoM - (moveHeight * up); + Vector3 offset = offsetDirection.normalized * _currMoveSpeed; + _currMoveVelocity = offset / Time.fixedDeltaTime; + Vector3 vSrfPt = MovingVessel.CoM - (MoveHeight * _up); bool srfBelowWater = false; RaycastHit ringHit; @@ -289,21 +307,21 @@ void UpdateMove() srfBelowWater = true; } - Vector3 rOffset = Vector3.Project(ringHit.point - vSrfPt, up); - Vector3 mOffset = (vSrfPt + offset) - movingVessel.CoM; - finalOffset = rOffset + mOffset + (moveHeight * up); - movingVessel.Translate(finalOffset); + Vector3 rOffset = Vector3.Project(ringHit.point - vSrfPt, _up); + Vector3 mOffset = (vSrfPt + offset) - MovingVessel.CoM; + finalOffset = rOffset + mOffset + (MoveHeight * _up); + MovingVessel.Translate(finalOffset); } - PQS bodyPQS = movingVessel.mainBody.pqsController; + PQS bodyPQS = MovingVessel.mainBody.pqsController; - Vector3d geoCoords = WorldPositionToGeoCoords(movingVessel.GetWorldPos3D() + (currMoveVelocity * Time.fixedDeltaTime), movingVessel.mainBody); - double Lat = geoCoords.x; - double Lng = geoCoords.y; + Vector3d geoCoords = WorldPositionToGeoCoords(MovingVessel.GetWorldPos3D() + (_currMoveVelocity * Time.fixedDeltaTime), MovingVessel.mainBody); + double lat = geoCoords.x; + double lng = geoCoords.y; Vector3d bodyUpVector = new Vector3d(1, 0, 0); - bodyUpVector = QuaternionD.AngleAxis(Lat, Vector3d.forward/*around Z axis*/) * bodyUpVector; - bodyUpVector = QuaternionD.AngleAxis(Lng, Vector3d.down/*around -Y axis*/) * bodyUpVector; + bodyUpVector = QuaternionD.AngleAxis(lat, Vector3d.forward/*around Z axis*/) * bodyUpVector; + bodyUpVector = QuaternionD.AngleAxis(lng, Vector3d.down/*around -Y axis*/) * bodyUpVector; double srfHeight = bodyPQS.GetSurfaceHeight(bodyUpVector); @@ -316,39 +334,39 @@ void UpdateMove() if (!surfaceDetected || srfBelowWater) { - Vector3 terrainPos = movingVessel.mainBody.position + (float)srfHeight * up; - Vector3 waterSrfPoint = FlightGlobals.currentMainBody.position + ((float)FlightGlobals.currentMainBody.Radius * up); + Vector3 terrainPos = MovingVessel.mainBody.position + (float)srfHeight * _up; + Vector3 waterSrfPoint = FlightGlobals.currentMainBody.position + ((float)FlightGlobals.currentMainBody.Radius * _up); if (!surfaceDetected) { - movingVessel.SetPosition(terrainPos + (moveHeight * up) + offset); + MovingVessel.SetPosition(terrainPos + (MoveHeight * _up) + offset); } - else if (srfBelowWater) + else { - movingVessel.SetPosition(waterSrfPoint + (moveHeight * up) + offset); + MovingVessel.SetPosition(waterSrfPoint + (MoveHeight * _up) + offset); } //update vessel situation to splashed down: - movingVessel.UpdateLandedSplashed(); + MovingVessel.UpdateLandedSplashed(); } //fix surface rotation - Quaternion srfRotFix = Quaternion.FromToRotation(startingUp, up); - currRotation = srfRotFix * startRotation; - movingVessel.SetRotation(currRotation); + Quaternion srfRotFix = Quaternion.FromToRotation(_startingUp, _up); + _currRotation = srfRotFix * _startRotation; + MovingVessel.SetRotation(_currRotation); - if (Vector3.Angle(startingUp, up) > 5) + if (Vector3.Angle(_startingUp, _up) > 5) { - startRotation = currRotation; - startingUp = up; + _startRotation = _currRotation; + _startingUp = _up; } - movingVessel.SetWorldVelocity(Vector3d.zero); - movingVessel.angularVelocity = Vector3.zero; - movingVessel.angularMomentum = Vector3.zero; + MovingVessel.SetWorldVelocity(Vector3d.zero); + MovingVessel.angularVelocity = Vector3.zero; + MovingVessel.angularMomentum = Vector3.zero; } - Vector3d WorldPositionToGeoCoords(Vector3d worldPosition, CelestialBody body) + private Vector3d WorldPositionToGeoCoords(Vector3d worldPosition, CelestialBody body) { if (!body) { @@ -374,7 +392,7 @@ public void StartMove(Vessel v, bool forceReleaseClamps) return; } - if (!placingVessels.Contains(v) && v.LandedOrSplashed) + if (!_placingVessels.Contains(v) && v.LandedOrSplashed) { foreach (LaunchClamp clamp in v.FindPartModulesImplementing()) { @@ -390,38 +408,38 @@ public void StartMove(Vessel v, bool forceReleaseClamps) ShowModeMessage(); - movingVessel = v; - isMovingVessel = true; + MovingVessel = v; + IsMovingVessel = true; - up = (v.transform.position - v.mainBody.transform.position).normalized; - startingUp = up; + _up = (v.transform.position - v.mainBody.transform.position).normalized; + _startingUp = _up; - vBounds = new VesselBounds(movingVessel); - moving = true; - moveHeight = vBounds.bottomLength + 0.5f; + _vBounds = new VesselBounds(MovingVessel); + _moving = true; + MoveHeight = _vBounds.BottomLength + 0.5f; - startRotation = movingVessel.transform.rotation; - currRotation = startRotation; + _startRotation = MovingVessel.transform.rotation; + _currRotation = _startRotation; - debugLr.enabled = true; + _debugLr.enabled = true; } } public void EndMove() { - StartCoroutine(EndMoveRoutine(vBounds)); - isMovingVessel = false; - debugLr.enabled = false; + StartCoroutine(EndMoveRoutine(_vBounds)); + IsMovingVessel = false; + _debugLr.enabled = false; } public void DropMove() { - StartCoroutine(DropMoveRoutine(vBounds)); - isMovingVessel = false; - debugLr.enabled = false; + StartCoroutine(DropMoveRoutine(_vBounds)); + IsMovingVessel = false; + _debugLr.enabled = false; } - IEnumerator EndMoveRoutine(VesselBounds vesselBounds) + private IEnumerator EndMoveRoutine(VesselBounds vesselBounds) { Vessel v = vesselBounds.vessel; if (!v) yield break; @@ -431,15 +449,15 @@ IEnumerator EndMoveRoutine(VesselBounds vesselBounds) yield return new WaitForFixedUpdate(); - while (moveMode != MoveModes.Normal) + while (_moveMode != MoveModes.Normal) { ToggleMoveMode(); } - moving = false; - moveHeight = 0; - placingVessels.Add(vesselBounds.vessel); - float bottomLength = vBounds.bottomLength; + _moving = false; + MoveHeight = 0; + _placingVessels.Add(vesselBounds.vessel); + float bottomLength = _vBounds.BottomLength; //float heightOffset = GetRadarAltitude(movingVessel) - moveHeight; @@ -448,40 +466,40 @@ IEnumerator EndMoveRoutine(VesselBounds vesselBounds) while (v && !v.LandedOrSplashed) { v.IgnoreGForces(240); - movingVessel.IgnoreGForces(240); + MovingVessel.IgnoreGForces(240); - up = (v.transform.position - FlightGlobals.currentMainBody.transform.position).normalized; + _up = (v.transform.position - FlightGlobals.currentMainBody.transform.position).normalized; float placeSpeed = Mathf.Clamp(((altitude - bottomLength) * 2), 0.1f, maxPlacementSpeed); if (placeSpeed > 3) { v.SetWorldVelocity(Vector3.zero); - movingVessel.angularVelocity = Vector3.zero; - movingVessel.angularMomentum = Vector3.zero; - v.Translate(placeSpeed * Time.fixedDeltaTime * -up); + MovingVessel.angularVelocity = Vector3.zero; + MovingVessel.angularMomentum = Vector3.zero; + v.Translate(placeSpeed * Time.fixedDeltaTime * -_up); } else { - v.SetWorldVelocity(placeSpeed * -up); + v.SetWorldVelocity(placeSpeed * -_up); } altitude -= placeSpeed * Time.fixedDeltaTime; yield return new WaitForFixedUpdate(); } - placingVessels.Remove(v); - hoverAdjust = 0f; + _placingVessels.Remove(v); + _hoverAdjust = 0f; } - IEnumerator DropMoveRoutine(VesselBounds vesselBounds) + private IEnumerator DropMoveRoutine(VesselBounds vesselBounds) { Vessel v = vesselBounds.vessel; if (!v) yield break; - moving = false; - moveHeight = 0; - hoverAdjust = 0f; + _moving = false; + MoveHeight = 0; + _hoverAdjust = 0f; } - void UpdateDebugLines() + private void UpdateDebugLines() { int circleRes = 24; @@ -491,14 +509,14 @@ void UpdateDebugLines() positions[i] = GetBoundPoint(i, circleRes, 1); } positions[circleRes] = GetBoundPoint(0, circleRes, 1); - positions[circleRes + 1] = movingVessel.CoM; - positions[circleRes + 2] = movingVessel.CoM + (moveHeight * -up); + positions[circleRes + 1] = MovingVessel.CoM; + positions[circleRes + 2] = MovingVessel.CoM + (MoveHeight * -_up); - debugLr.positionCount = circleRes + 3; - debugLr.SetPositions(positions); + _debugLr.positionCount = circleRes + 3; + _debugLr.SetPositions(positions); } - Vector3 GetBoundPoint(int index, int totalPoints, float radiusFactor) + private Vector3 GetBoundPoint(int index, int totalPoints, float radiusFactor) { float angleIncrement = 360 / (float)totalPoints; @@ -506,39 +524,39 @@ Vector3 GetBoundPoint(int index, int totalPoints, float radiusFactor) Vector3 forward = North();//Vector3.ProjectOnPlane((movingVessel.CoM)-FlightCamera.fetch.mainCamera.transform.position, up).normalized; - float radius = vBounds.radius; + float radius = _vBounds.Radius; Vector3 offsetVector = (radius * radiusFactor * forward); - offsetVector = Quaternion.AngleAxis(angle, up) * offsetVector; + offsetVector = Quaternion.AngleAxis(angle, _up) * offsetVector; - Vector3 point = movingVessel.CoM + offsetVector; + Vector3 point = MovingVessel.CoM + offsetVector; return point; } - bool CapsuleCast(out RaycastHit rayHit) + private bool CapsuleCast(out RaycastHit rayHit) { //float radius = (Mathf.Max (Mathf.Max(vesselBounds.size.x, vesselBounds.size.y), vesselBounds.size.z)) + (currMoveSpeed*2); - float radius = vBounds.radius + Mathf.Clamp(currMoveSpeed, 0, 200); + float radius = _vBounds.Radius + Mathf.Clamp(_currMoveSpeed, 0, 200); - return Physics.CapsuleCast(movingVessel.CoM + (250 * up), movingVessel.CoM + (249 * up), radius, -up, out rayHit, 2000, 1 << 15); + return Physics.CapsuleCast(MovingVessel.CoM + (250 * _up), MovingVessel.CoM + (249 * _up), radius, -_up, out rayHit, 2000, 1 << 15); } - float GetRadarAltitude(Vessel vessel) + private float GetRadarAltitude(Vessel vessel) { //Not needed anymore - RadarAlt is part of vessel now float radarAlt = Mathf.Clamp((float)(vessel.mainBody.GetAltitude(vessel.CoM) - vessel.terrainAltitude), 0, (float)vessel.altitude); return radarAlt; } - float GetRaycastAltitude(VesselBounds vesselBounds) //TODO do the raycast from the bottom point of the ship, and include vessels in layer mask, so you can safely place on top of vessel + private float GetRaycastAltitude(VesselBounds vesselBounds) //TODO do the raycast from the bottom point of the ship, and include vessels in layer mask, so you can safely place on top of vessel { RaycastHit hit; //test - if (Physics.Raycast(vesselBounds.vessel.CoM - (vesselBounds.bottomLength * up), -up, out hit, (float)vesselBounds.vessel.altitude, (1 << 15) | (1 << 0))) + if (Physics.Raycast(vesselBounds.vessel.CoM - (vesselBounds.BottomLength * _up), -_up, out hit, (float)vesselBounds.vessel.altitude, (1 << 15) | (1 << 0))) { - return Vector3.Project(hit.point - vesselBounds.vessel.CoM, up).magnitude; + return Vector3.Project(hit.point - vesselBounds.vessel.CoM, _up).magnitude; } /* @@ -554,13 +572,13 @@ float GetRadarAltitude(Vessel vessel) } } - Vector3 GetRaycastPosition(VesselBounds vesselBounds) + private Vector3 GetRaycastPosition(VesselBounds vesselBounds) { Vector3 ZeroVector = new Vector3(0, 0, 0); RaycastHit hit; - if (Physics.Raycast(vesselBounds.vessel.CoM - (vesselBounds.bottomLength * up), -up, out hit, (float)vesselBounds.vessel.altitude, (1 << 15) | (1 << 0))) + if (Physics.Raycast(vesselBounds.vessel.CoM - (vesselBounds.BottomLength * _up), -_up, out hit, (float)vesselBounds.vessel.altitude, (1 << 15) | (1 << 0))) { - return Vector3.Project(hit.point - vesselBounds.vessel.CoM, up); + return Vector3.Project(hit.point - vesselBounds.vessel.CoM, _up); } else { @@ -568,65 +586,65 @@ Vector3 GetRaycastPosition(VesselBounds vesselBounds) } } - void ToggleMoveMode() + private void ToggleMoveMode() { - moveMode = (MoveModes)(int)Mathf.Repeat((float)moveMode + 1, 4); + _moveMode = (MoveModes)(int)Mathf.Repeat((float)_moveMode + 1, 4); ShowModeMessage(); - switch (moveMode) + switch (_moveMode) { case MoveModes.Normal: - debugLr.material.SetColor("_EmissiveColor", Color.green); + _debugLr.material.SetColor("_EmissiveColor", Color.green); break; case MoveModes.Slow: - debugLr.material.SetColor("_EmissiveColor", XKCDColors.Orange); + _debugLr.material.SetColor("_EmissiveColor", XKCDColors.Orange); break; case MoveModes.Fine: - debugLr.material.SetColor("_EmissiveColor", XKCDColors.BrightRed); + _debugLr.material.SetColor("_EmissiveColor", XKCDColors.BrightRed); break; case MoveModes.Ludicrous: - debugLr.material.SetColor("_EmissiveColor", XKCDColors.PurpleishBlue); + _debugLr.material.SetColor("_EmissiveColor", XKCDColors.PurpleishBlue); break; } } - void ShowModeMessage() + private void ShowModeMessage() { - if (moveMessage != null) + if (_moveMessage != null) { - ScreenMessages.RemoveMessage(moveMessage); + ScreenMessages.RemoveMessage(_moveMessage); } - moveMessage = ScreenMessages.PostScreenMessage("Mode : " + moveMode.ToString(), 3, ScreenMessageStyle.UPPER_CENTER); + _moveMessage = ScreenMessages.PostScreenMessage("Mode : " + _moveMode.ToString(), 3, ScreenMessageStyle.UPPER_CENTER); } - Vector3 North() + private Vector3 North() { - Vector3 n = movingVessel.mainBody.GetWorldSurfacePosition(movingVessel.latitude + 1, movingVessel.longitude, movingVessel.altitude) - movingVessel.GetWorldPos3D(); - n = Vector3.ProjectOnPlane(n, up); + Vector3 n = MovingVessel.mainBody.GetWorldSurfacePosition(MovingVessel.latitude + 1, MovingVessel.longitude, MovingVessel.altitude) - MovingVessel.GetWorldPos3D(); + n = Vector3.ProjectOnPlane(n, _up); return n.normalized; } public struct VesselBounds { public Vessel vessel; - public float bottomLength; - public float radius; + public float BottomLength; + public float Radius; - private Vector3 localBottomPoint; - public Vector3 bottomPoint + private Vector3 _localBottomPoint; + public Vector3 BottomPoint { get { - return vessel.transform.TransformPoint(localBottomPoint); + return vessel.transform.TransformPoint(_localBottomPoint); } } public VesselBounds(Vessel v) { vessel = v; - bottomLength = 0; - radius = 0; - localBottomPoint = Vector3.zero; + BottomLength = 0; + Radius = 0; + _localBottomPoint = Vector3.zero; UpdateBounds(); } @@ -668,8 +686,8 @@ public void UpdateBounds() foreach (MeshFilter mf in p.GetComponentsInChildren()) { - Mesh mesh = mf.mesh; - foreach (Vector3 vert in mesh.vertices) + //Mesh mesh = mf.mesh; + foreach (Vector3 vert in mf.mesh.vertices) { //bottom check Vector3 worldVertPoint = mf.transform.TransformPoint(vert); @@ -683,12 +701,9 @@ public void UpdateBounds() //radius check //float sqrDist = (vessel.CoM-worldVertPoint).sqrMagnitude; float hSqrDist = Vector3.ProjectOnPlane(vessel.CoM - worldVertPoint, up).sqrMagnitude; - if (hSqrDist > furthestSqrDist) - { - furthestSqrDist = hSqrDist; - furthestVert = worldVertPoint; - } - + if (!(hSqrDist > furthestSqrDist)) continue; + furthestSqrDist = hSqrDist; + furthestVert = worldVertPoint; } } @@ -696,10 +711,11 @@ public void UpdateBounds() } Vector3 radVector = Vector3.ProjectOnPlane(furthestVert - vessel.CoM, up); - radius = radVector.magnitude; + Radius = radVector.magnitude; + + BottomLength = Vector3.Project(closestVert - vessel.CoM, up).magnitude; + _localBottomPoint = vessel.transform.InverseTransformPoint(closestVert); - bottomLength = Vector3.Project(closestVert - vessel.CoM, up).magnitude; - localBottomPoint = vessel.transform.InverseTransformPoint(closestVert); //Debug.Log ("Vessel bottom length: "+bottomLength); /* if(furthestPart!=null) @@ -731,7 +747,7 @@ public void UpdateBounds() */ //radius *= 1.75f; //radius += 5;//15; - radius += Mathf.Clamp(radius, 2, 10); + Radius += Mathf.Clamp(Radius, 2, 10); } diff --git a/VesselMoverToolbar.cs b/VesselMoverToolbar.cs index 5e76951..19b458a 100644 --- a/VesselMoverToolbar.cs +++ b/VesselMoverToolbar.cs @@ -19,18 +19,17 @@ public class VesselMoverToolbar : MonoBehaviour // ReSharper disable once PossibleNullReferenceException internal static GUIStyle ToolTipStyle; internal static List SelectedCrewMembers = new List(); - - Rect toolbarRect; - float toolbarWidth = 280; - float toolbarHeight = 0; - float toolbarMargin = 6; - float toolbarLineHeight = 20; - float contentWidth; - Vector2 toolbarPosition; - Rect svRectScreenSpace; - Rect svCrewScreenSpace; - bool showMoveHelp = false; - float helpHeight; + private Rect toolbarRect; + private float toolbarWidth = 280; + private float toolbarHeight = 0; + private float toolbarMargin = 6; + private float toolbarLineHeight = 20; + private float contentWidth; + private Vector2 toolbarPosition; + private Rect svRectScreenSpace; + private Rect svCrewScreenSpace; + private bool showMoveHelp = false; + private float helpHeight; private Rect _crewSelectRect; private float _crewSelectWidth = 300; @@ -39,7 +38,7 @@ public class VesselMoverToolbar : MonoBehaviour private static Vector2 _displayViewerPosition = Vector2.zero; private static Rect Position; - void Start() + private void Start() { GameEvents.onHideUI.Add(OnHideUI); GameEvents.onShowUI.Add(OnShowUI); @@ -54,13 +53,13 @@ void Start() AddToolbarButton(); } - void OnDestroy() + private void OnDestroy() { GameEvents.onHideUI.Remove(OnHideUI); GameEvents.onShowUI.Remove(OnShowUI); } - void OnGUI() + private void OnGUI() { SetGuiStyles(); @@ -71,11 +70,11 @@ void OnGUI() latch = true; } - if (!ShowUI || !toolbarGuiEnabled || !VesselMove.instance || !VesselSpawn.instance || + if (!ShowUI || !toolbarGuiEnabled || !VesselMove.Instance || !VesselSpawn.instance || VesselSpawn.instance.openingCraftBrowser || VesselSpawn.IsSelectingCrew) return; toolbarRect = GUI.Window(401240, toolbarRect, ToolbarWindow, "Vessel Mover", HighLogic.Skin.window); - if (!VesselMove.instance.isMovingVessel) + if (!VesselMove.Instance.IsMovingVessel) { if (!MouseIsInRect(svRectScreenSpace)) return; Vector2 mousePos = MouseGUIPos(); @@ -89,18 +88,18 @@ void OnGUI() } - void ToolbarWindow(int windowID) + private void ToolbarWindow(int windowID) { float line = 0; line += 1.25f; - if (FlightGlobals.ActiveVessel && (FlightGlobals.ActiveVessel.LandedOrSplashed || VesselMove.instance.isMovingVessel)) + if (FlightGlobals.ActiveVessel && (FlightGlobals.ActiveVessel.LandedOrSplashed || VesselMove.Instance.IsMovingVessel)) { - if (!VesselMove.instance.isMovingVessel) + if (!VesselMove.Instance.IsMovingVessel) { if (GUI.Button(LineRect(ref line, 1.5f), "Move Vessel", HighLogic.Skin.button)) { - VesselMove.instance.StartMove(FlightGlobals.ActiveVessel, true); + VesselMove.Instance.StartMove(FlightGlobals.ActiveVessel, true); } line += 0.2f; @@ -131,14 +130,14 @@ void ToolbarWindow(int windowID) { if (GUI.Button(LineRect(ref line, 2), "Place Vessel", HighLogic.Skin.button)) { - VesselMove.instance.EndMove(); + VesselMove.Instance.EndMove(); } line += 0.3f; if (GUI.Button(LineRect(ref line, 2), "Drop Vessel", HighLogic.Skin.button)) { - VesselMove.instance.DropMove(); + VesselMove.Instance.DropMove(); } line += 0.3f; @@ -161,7 +160,7 @@ void ToolbarWindow(int windowID) VMUtils.RepositionWindow(ref toolbarRect); } - void CrewSelectionWindow(int windowID) + private void CrewSelectionWindow(int windowID) { KerbalRoster kerbalRoster = HighLogic.CurrentGame.CrewRoster; GUILayout.BeginVertical(); @@ -196,14 +195,14 @@ void CrewSelectionWindow(int windowID) GUILayout.EndVertical(); } - Rect LineRect(ref float currentLine, float heightFactor = 1) + private Rect LineRect(ref float currentLine, float heightFactor = 1) { Rect rect = new Rect(toolbarMargin, toolbarMargin + (currentLine * toolbarLineHeight), contentWidth, toolbarLineHeight * heightFactor); currentLine += heightFactor + 0.1f; return rect; } - void MoveHelp(int windowID) + private void MoveHelp(int windowID) { float line = 0; line += 1.25f; @@ -219,19 +218,20 @@ void MoveHelp(int windowID) GameSettings.TRANSLATE_RIGHT.primary.ToString(), ref line); LineLabel("Auto rotate rocket: " + GameSettings.TRANSLATE_BACK.primary.ToString(), ref line); LineLabel("Auto rotate plane: " + GameSettings.TRANSLATE_FWD.primary.ToString(), ref line); - LineLabel("Change movement speed: Tab", ref line); + LineLabel("Change movement mode: Tab", ref line); + LineLabel("Reset Altitude: " + GameSettings.THROTTLE_CUTOFF.primary.ToString(), ref line); LineLabel("Adjust Altitude: " + GameSettings.THROTTLE_UP.primary.ToString() + " " + GameSettings.THROTTLE_DOWN.primary.ToString(), ref line); helpHeight = (line * toolbarLineHeight) + (toolbarMargin * 2); } - void LineLabel(string label, ref float line) + private void LineLabel(string label, ref float line) { GUI.Label(LineRect(ref line), label, HighLogic.Skin.label); } - void AddToolbarButton() + private void AddToolbarButton() { if (HighLogic.LoadedSceneIsFlight) { @@ -254,7 +254,7 @@ public void HideToolbarGUI() VesselMoverToolbar.toolbarGuiEnabled = false; } - void Dummy() + private void Dummy() { } public static bool MouseIsInRect(Rect rect) diff --git a/VesselSpawn.cs b/VesselSpawn.cs index fa6bc93..eb8883c 100644 --- a/VesselSpawn.cs +++ b/VesselSpawn.cs @@ -20,18 +20,19 @@ public class VesselSpawn : MonoBehaviour internal static bool IsCrewSelected; internal static string FullPath; internal static List SelectedCrewData; + // End Crew Selection vars - void Awake() + private void Awake() { if (instance) Destroy(instance); instance = this; } public bool openingCraftBrowser = false; - bool loadingCraft = false; - bool choosingPosition = false; - CraftBrowserDialog craftBrowser; + private bool loadingCraft = false; + private bool choosingPosition = false; + private CraftBrowserDialog craftBrowser; //object crewBrowser; public void StartVesselSpawn() @@ -42,7 +43,7 @@ public void StartVesselSpawn() } } - IEnumerator StartVesselSpawnRoutine() + private IEnumerator StartVesselSpawnRoutine() { openingCraftBrowser = true; @@ -56,7 +57,7 @@ IEnumerator StartVesselSpawnRoutine() craftBrowser = CraftBrowserDialog.Spawn(EditorFacility.SPH, HighLogic.SaveFolder, OnSelected, OnCancelled, false); } - void OnSelected(string fullPath, CraftBrowserDialog.LoadType loadType) + private void OnSelected(string fullPath, CraftBrowserDialog.LoadType loadType) { craftBrowser = null; openingCraftBrowser = false; @@ -70,7 +71,7 @@ void OnSelected(string fullPath, CraftBrowserDialog.LoadType loadType) choosingPosition = true; } - void OnCrewSelected() + private void OnCrewSelected() { IsSelectingCrew = false; StartCoroutine(SpawnCraftRoutine(FullPath, SelectedCrewData)); @@ -78,13 +79,13 @@ void OnCrewSelected() FullPath = null; } - void OnCancelled() + private void OnCancelled() { craftBrowser = null; openingCraftBrowser = false; } - void OnGUI() + private void OnGUI() { if (craftBrowser != null) { @@ -120,7 +121,7 @@ void OnGUI() } } - void DrawShadowedMessage(string message) + private void DrawShadowedMessage(string message) { GUIStyle style = new GUIStyle(HighLogic.Skin.label); style.fontSize = 22; @@ -146,8 +147,7 @@ void DrawShadowedMessage(string message) GUI.Label(labelRect, message, style); } - - IEnumerator SpawnCraftRoutine(string craftUrl, List crewData = null) + private IEnumerator SpawnCraftRoutine(string craftUrl, List crewData = null) { yield return null; yield return null; @@ -200,7 +200,7 @@ public static Vector3d WorldPositionToGeoCoords(Vector3d worldPosition, Celestia return new Vector3d(lat, longi, alt); } - bool GetMouseWorldPoint(out Vector3 worldPos) + private bool GetMouseWorldPoint(out Vector3 worldPos) { worldPos = Vector3.zero; float maxTargetingRange = 5000; @@ -246,7 +246,7 @@ bool GetMouseWorldPoint(out Vector3 worldPos) } - void SpawnVesselFromCraftFile(string craftURL, Vector3d gpsCoords, float heading, float pitch, List crewData = null) + private void SpawnVesselFromCraftFile(string craftURL, Vector3d gpsCoords, float heading, float pitch, List crewData = null) { VesselData newData = new VesselData(); @@ -617,7 +617,7 @@ private void SpawnVessel(VesselData vesselData, List crewData = } } - IEnumerator PlaceSpawnedVessel(Vessel v, bool moveVessel) + private IEnumerator PlaceSpawnedVessel(Vessel v, bool moveVessel) { loadingCraft = true; v.isPersistent = true; @@ -642,10 +642,10 @@ IEnumerator PlaceSpawnedVessel(Vessel v, bool moveVessel) if (moveVessel) { - VesselMove.instance.StartMove(v, false); - VesselMove.instance.moveHeight = 35; + VesselMove.Instance.StartMove(v, false); + VesselMove.Instance.MoveHeight = 35; yield return null; - if (VesselMove.instance.movingVessel == v) + if (VesselMove.Instance.MovingVessel == v) { v.Landed = false; }