/// <summary>Handles camera focus selection logic.</summary> void HandleCameraFocusSelection() { var camera = FlightCamera.fetch; var targetPart = Mouse.HoveredPart; var targetTransform = targetPart != null ? targetPart.transform : null; if (Mouse.GetAllMouseButtonsDown() != _switchMouseButton || targetTransform == camera.Target) { return; } if (targetPart != null) { _oldInfo = VesselInfo.CaptureCurrentState(); if (targetPart.vessel == FlightGlobals.ActiveVessel && targetPart.vessel.parts.Count == 1) { // When moving focus back to a single part vessel reset to the vessel mode. camera.TargetActiveVessel(); } else { camera.SetTargetPart(Mouse.HoveredPart); } _newInfo = VesselInfo.CaptureCurrentState(); StabilizeCamera(); } else { _oldInfo = VesselInfo.CaptureCurrentState(); camera.TargetActiveVessel(); _newInfo = VesselInfo.CaptureCurrentState(); StabilizeCamera(); } }
/// <summary>GameEvents callback.</summary> /// <remarks> /// Detects vessel switch and remembers old camera settings if switching from the currently active /// vessel. /// </remarks> /// <param name="fromVessel">A vessel prior the switch.</param> /// <param name="toVessel">A new active vessel.</param> void OnVesselSwitch(Vessel fromVessel, Vessel toVessel) { if (_state == SwitchEvent.Idle && _cameraStabilizationMode != CameraStabilization.None && fromVessel != null && fromVessel.isActiveVessel) { _state = SwitchEvent.VesselSwitched; DebugEx.Info("Detected switch from {0} to {1}. Request camera stabilization.", fromVessel, toVessel); _newInfo = new VesselInfo(toVessel); _oldInfo = new VesselInfo(fromVessel, FlightCamera.fetch); } }
/// <summary>GameEvents callback.</summary> /// <remarks> /// Detects vessel docking events. /// <para> /// Parts coupling is not a straightforward event. Depending on what has docked to what there may /// or may not be a vessel switch event sent. To be on a safe side just disable switch event /// handling in such case and fix camera in <c>LastUpdate</c>. /// </para> /// </remarks> void OnPartCouple(GameEvents.FromToAction <Part, Part> action) { // Only do camera fix if either the source or the destination is an active vessel. if (action.from.vessel.isActiveVessel) { _state = SwitchEvent.VesselDocked; DebugEx.Info("Active vessel docked to a station. Waiting for LateUpdate..."); _oldInfo = new VesselInfo(action.from.vessel, FlightCamera.fetch); } else if (action.to.vessel.isActiveVessel) { _state = SwitchEvent.VesselDocked; DebugEx.Info("Something has docked to the active vessel. Waiting for LateUpdate..."); _oldInfo = new VesselInfo(action.to.vessel, FlightCamera.fetch); } }
/// <summary> /// Preserves the camera-to-target rotation and the distance. It also moves the camera's focus to /// the new vessel. /// </summary> /// <remarks> /// The vessel may move while the animation is playing (e.g. on the orbit). To compensate this /// movement all the camera calculations are done relative to the original vessel position at the /// time of the switch. /// </remarks> /// <param name="target">The camera target. If it's changed then the animation will abort.</param> /// <param name="oldInfo">The previous vessel info.</param> /// <param name="newInfo">The new vessel info.</param> /// <param name="transitionDuration">The duration to play the transition animation.</param> /// <returns><c>null</c> until the animation is done or aborted.</returns> // ReSharper disable once MemberCanBeMadeStatic.Local IEnumerator AnimateCameraPositionCoroutine( Transform target, VesselInfo oldInfo, VesselInfo newInfo, float transitionDuration) { var startTime = Time.unscaledTime; float progress; do { // Calculate vessel movement compensation offset. var movementOffset = FlightGlobals.ActiveVessel.transform.position - newInfo.anchorPos; progress = (Time.unscaledTime - startTime) / transitionDuration; // Only animate the pivot position. The camera's position will be adjusted by the FlightCamera // code. FlightCamera.fetch.GetPivot().transform.position = movementOffset + Vector3.Lerp(oldInfo.cameraPivotPos, newInfo.cameraPivotPos, progress); yield return(null); } while (progress < 1.0f && FlightCamera.fetch.Target == target); }
/// <summary>Preserves fixed position of camera, and moves its focus to the new vessel.</summary> /// <remarks> /// The vessel may move while the animation is done (e.g. on the orbit). To compensate this /// movement all camera calculations are done relative to the original vessel position at the /// time of the switch. And then a difference is added given the current vessel position. /// </remarks> /// <param name="target">A camera target. If it's changed the animation will abort.</param> /// <param name="oldInfo">Previous vessel info.</param> /// <param name="newInfo">New vessel info.</param> /// <param name="transitionDuration">The duration to play the transition animation.</param> /// <returns><c>null</c> until the animation is done or aborted.</returns> IEnumerator AnimateCameraPivotCoroutine( Transform target, VesselInfo oldInfo, VesselInfo newInfo, float transitionDuration) { float startTime = Time.unscaledTime; float progress; do { // Calculate vessel movement compensation offset. var movementOffset = FlightGlobals.ActiveVessel.transform.position - newInfo.anchorPos; progress = (Time.unscaledTime - startTime) / transitionDuration; var camera = FlightCamera.fetch; camera.GetPivot().position = movementOffset + Vector3.Lerp(oldInfo.cameraPivotPos, newInfo.cameraPivotPos, progress); var newCameraPos = movementOffset + oldInfo.cameraPos; camera.SetCamCoordsFromPosition(newCameraPos); camera.GetCameraTransform().position = newCameraPos; yield return(null); } while (progress < 1.0f && FlightCamera.fetch.Target == target); }