/// <summary> /// Performs a camera focus operation on the currently selected game objects. The /// method uses the current focs settings to perform the focus operation. /// </summary> /// <remarks> /// The method has no effect if there are no objects currently selected. /// </remarks> public void FocusOnSelection() { // Focussing on the default object is not selected in constant and smooth focus mode if (EditorObjectSelection.Instance.NumberOfSelectedObjects == 0 && (_focusSettings.FocusMode == EditorCameraFocusMode.ConstantSpeed || _focusSettings.FocusMode == EditorCameraFocusMode.Smooth) ) { return; } // Focus the camera based on the chosen focus method if (_focusSettings.FocusMode == EditorCameraFocusMode.Instant) { //Select the default focus object bool selectedDefaultFocusObject = false; if (EditorObjectSelection.Instance.NumberOfSelectedObjects == 0) { selectedDefaultFocusObject = EditorObjectSelection.Instance.AddObjectAndItsChildrenToSelection(_focusSettings.DefaultFocusObject); } //EditorObjectSelection.Instance.AddObjectToSelection(_focusSettings.DefaultFocusObject, false); // Get the focus info EditorCameraFocusOperationInfo focusOpInfo = EditorCameraFocus.GetFocusOperationInfo(Camera, _focusSettings); // Note: We will also adjust the ortho size to make sure things are all well when // switching from a perspective to orthographic camera. Camera.orthographicSize = focusOpInfo.OrthoCameraHalfVerticalSize; Camera.transform.position = focusOpInfo.CameraDestinationPosition; // The camera was focused _wasFocused = true; _lastFocusPoint = focusOpInfo.FocusPoint; CalculateOrbitOffsetAlongLook(focusOpInfo); // Deselect the default focus object if (selectedDefaultFocusObject) { /// Undo select all EditorUndoRedoSystem.Instance.OnUndo(); } } else if (_focusSettings.FocusMode == EditorCameraFocusMode.ConstantSpeed) { StopCoroutine("StartConstantFocusOnSelection"); StopCoroutine("StartSmoothZoom"); StopCoroutine("StartSmoothPan"); StartCoroutine("StartConstantFocusOnSelection"); } else if (_focusSettings.FocusMode == EditorCameraFocusMode.Smooth) { StopCoroutine("StartSmoothFocusOnSelection"); StopCoroutine("StartSmoothZoom"); StopCoroutine("StartSmoothPan"); StartCoroutine("StartSmoothFocusOnSelection"); } }
/// <summary> /// Starts a smooth focus operation on the current object selection. /// </summary> private IEnumerator StartSmoothFocusOnSelection() { // Store needed data EditorCameraFocusOperationInfo focusOpInfo = EditorCameraFocus.GetFocusOperationInfo(Camera, _focusSettings); _lastFocusPoint = focusOpInfo.FocusPoint; Vector3 cameraDestinationPoint = focusOpInfo.CameraDestinationPosition; Transform cameraTransform = Camera.transform; // If the distance to travel is small enough, we can exit if ((cameraDestinationPoint - cameraTransform.position).magnitude < 1e-4f) { yield break; } // We will need this to modify the position using 'Vector3.SmoothDamp' Vector3 velocity = Vector3.zero; // We will need this to modify the camera ortho size using 'Mathf.SmoothDamp'. float orthoSizeVelocity = 0.0f; // The first iteration of the 'while' loop will perform the first focus step. We will // set this to true here just in case the focus operation is cancelled by another camera // operation. This will allow the user to orbit the camera even if it wasn't focused 100%. _wasFocused = true; while (true) { // Calculate the new position cameraTransform.position = Vector3.SmoothDamp(cameraTransform.position, cameraDestinationPoint, ref velocity, _focusSettings.SmoothFocusTime); // Calculate the new camera ortho size SetOrthoSize(Mathf.SmoothDamp(Camera.orthographicSize, focusOpInfo.OrthoCameraHalfVerticalSize, ref orthoSizeVelocity, _focusSettings.SmoothFocusTime)); // Recalculate the orbit focus to ensure proper orbit if the focus operation is not completed 100%. CalculateOrbitOffsetAlongLook(focusOpInfo); // If the position is close enough to the target position and the camera ortho size // is close enough to the target size, we can exit the loop. if ((cameraTransform.position - cameraDestinationPoint).magnitude < 1e-3f && Mathf.Abs(Camera.orthographicSize - focusOpInfo.OrthoCameraHalfVerticalSize) < 1e-3f) { // Clamp to make sure we got the correct values and then exit the loop cameraTransform.position = cameraDestinationPoint; Camera.orthographicSize = focusOpInfo.OrthoCameraHalfVerticalSize; break; } yield return(null); } }
/// <summary> /// Performs a camera focus operation on the currently selected game objects. The /// method uses the current focs settings to perform the focus operation. /// </summary> /// <remarks> /// The method has no effect if there are no objects currently selected. /// </remarks> public void FocusOnSelection() { // No objects selected? if (EditorObjectSelection.Instance.NumberOfSelectedObjects == 0) { return; } // Focus the camera based on the chosen focus method if (_focusSettings.FocusMode == EditorCameraFocusMode.Instant) { // Get the focus info EditorCameraFocusOperationInfo focusOpInfo = EditorCameraFocus.GetFocusOperationInfo(Camera, _focusSettings); // Note: We will also adjust the ortho size to make sure things are all well when // switching from a perspective to orthographic camera. Camera.orthographicSize = focusOpInfo.OrthoCameraHalfVerticalSize; Camera.transform.position = focusOpInfo.CameraDestinationPosition; // The camera was focused _wasFocused = true; _lastFocusPoint = focusOpInfo.FocusPoint; CalculateOrbitOffsetAlongLook(focusOpInfo); } else if (_focusSettings.FocusMode == EditorCameraFocusMode.ConstantSpeed) { StopCoroutine("StartConstantFocusOnSelection"); StopCoroutine("StartSmoothZoom"); StopCoroutine("StartSmoothPan"); StartCoroutine("StartConstantFocusOnSelection"); } else if (_focusSettings.FocusMode == EditorCameraFocusMode.Smooth) { StopCoroutine("StartSmoothFocusOnSelection"); StopCoroutine("StartSmoothZoom"); StopCoroutine("StartSmoothPan"); StartCoroutine("StartSmoothFocusOnSelection"); } }
/// <summary> /// Starts a constant focus operation on the current object selection. /// </summary> private IEnumerator StartConstantFocusOnSelection() { // Store needed data EditorCameraFocusOperationInfo focusOpInfo = EditorCameraFocus.GetFocusOperationInfo(Camera, _focusSettings); _lastFocusPoint = focusOpInfo.FocusPoint; Vector3 cameraDestinationPoint = focusOpInfo.CameraDestinationPosition; float cameraSpeed = _focusSettings.ConstantFocusSpeed; Transform cameraTransform = Camera.transform; // Calculate the vector which is used to move the camera from its current position to the destination position. // We will normalize this vector so that we can move along it with the required speed. Vector3 fromCamPosToDestination = cameraDestinationPoint - cameraTransform.position; float distanceToTravel = fromCamPosToDestination.magnitude; // Needed later inside the 'while' loop if (distanceToTravel < 1e-4f) { yield break; // No focus necessary? } fromCamPosToDestination.Normalize(); // We will need this to know how much we travelled Vector3 initialCameraPosition = cameraTransform.position; // We will need this to adjust the ortho camera size float initialCameraOrthoSize = Camera.orthographicSize; // The first iteration of the 'while' loop will perform the first focus step. We will // set this to true here just in case the focus operation is cancelled by another camera // operation. This will allow the user to orbit the camera even if it wasn't focused 100%. _wasFocused = true; while (true) { // Move the camera along the direction vector with the desired speed cameraTransform.position += (fromCamPosToDestination * cameraSpeed * Time.deltaTime); // Calculate the new camera ortho size. This is done by lerping between the initial // ortho size and the target size. The interpolation factor is the ratio between how // much we travelled so far and the total distance that we have to travel. float distanceTraveledSoFar = (cameraTransform.position - initialCameraPosition).magnitude; SetOrthoSize(Mathf.Lerp(initialCameraOrthoSize, focusOpInfo.OrthoCameraHalfVerticalSize, distanceTraveledSoFar / distanceToTravel)); // Recalculate the orbit focus to ensure proper orbit if the focus operation is not completed 100%. CalculateOrbitOffsetAlongLook(focusOpInfo); // Check if the camera has reached the destination position or if it went past it. It is very // probable that most of the times, the camera will move further away than the target position. // When that happens, we will clamp the camera position and exit the coroutine. In order to detect // this situation, we will perform a dot product between the camera move direction vector and // the vector which unites the current camera position with the target position. When this dot // product is < 0, it means that the camera has moved too far away and we will clamp its position // and exit. This could also probably be done using a variable which holds the accumulated travel // distance. When this distance becomes >= than the original length of 'fromCamPosToDestination', // we can exit. if (Vector3.Dot(fromCamPosToDestination, cameraDestinationPoint - cameraTransform.position) <= 0.0f && Mathf.Abs(Camera.orthographicSize - focusOpInfo.OrthoCameraHalfVerticalSize) < 1e-3f) { cameraTransform.position = cameraDestinationPoint; break; } yield return(null); } }
/// <summary> /// Rotates the camera based on user input. /// </summary> private void RotateCameraBasedOnUserInput() { // If no mouse movemenet was performed, we don't need to continue if (!_mouse.WasMouseMovedSinceLastFrame) { return; } //added by me if (WereAnyUIElementsHovered()) { return; } bool orbit = _cameraOrbitShortcut.IsActive() || toolBarController.isOrbiting; bool orbitSelected = toolBarController.isOrbitingSelected; // //bool orbit = _cameraOrbitShortcut.IsActive(); bool lookAround = !orbit && _cameraLookAroundShortcut.IsActive(); //if (orbit || lookAround) //added by me if (orbit || lookAround || orbitSelected) // { // Make sure all coroutines are stopped to avoid any conflicts StopAllCoroutines(); // Calculate the amount of rotation which must be applied float rotationSpeedTimesDeltaTime = _rotationSpeedInDegrees * Time.deltaTime; // Rotate based on the type of rotation we are dealing with. // Note: Even if the rotation mode is set to orbit, we will still perform a 'LookAround' rotation // if the camera hasn't been focused. //added by me if (orbitSelected) //围绕选中物体旋转 { Transform cameraTransform = Camera.transform; EditorCameraOrbit.OrbitCameraBaseOnSelected(Camera, -_mouse.CursorOffsetSinceLastFrame.y * rotationSpeedTimesDeltaTime, _mouse.CursorOffsetSinceLastFrame.x * rotationSpeedTimesDeltaTime, EditorCameraFocus.GetFocusOperationInfo(Camera, _focusSettings).FocusPoint); } else // if (lookAround || !_wasFocused) { EditorCameraRotation.RotateCamera(Camera, -_mouse.CursorOffsetSinceLastFrame.y * rotationSpeedTimesDeltaTime, _mouse.CursorOffsetSinceLastFrame.x * rotationSpeedTimesDeltaTime); } else if (_wasFocused && orbit) { // Calculate the orbit point. This is done by moving from the camera position along the camera // look vector by a distance equal to '_orbitOffsetAlongLook'. Transform cameraTransform = Camera.transform; Vector3 orbitPoint = cameraTransform.position + cameraTransform.forward * _orbitOffsetAlongLook; EditorCameraOrbit.OrbitCamera(Camera, -_mouse.CursorOffsetSinceLastFrame.y * rotationSpeedTimesDeltaTime, _mouse.CursorOffsetSinceLastFrame.x * rotationSpeedTimesDeltaTime, orbitPoint); } } }