using System.Collections; using UnityEngine; using UnityEngine.UI; public class ObjectFocus : MonoBehaviour { public enum LerpMethod { None, Linear, EaseInOut } [SerializeField] Transform _target; [SerializeField] float _duration = 2f; [SerializeField] LerpMethod _lerpMethod = LerpMethod.Linear; [SerializeField] Button _cameraResetButton; Camera _camera; Vector3 _focusPoint = Vector3.zero; string _focusedObjectName = ""; // used primarily for checking selected object float _distanceObjectViewOffset = 30.0f; bool _isFocusing; bool _isUsingCoroutine = false; public void StopUsingCoroutine() { _isUsingCoroutine = false; _cameraResetButton.interactable = true; } private void Awake() { _camera = GetComponent(); } private void Update() { UpdateFocusState(); } [ContextMenu("Focus Camera")] public void FocusCameraTarget() { GameObject obj = GameObject.Find(_G.TARGET); FocusCameraObj(obj); } public void FocusCamera() { GameObject obj = GameObject.Find(SceneModeManager.SelectedName); FocusCameraObj(obj); } public void FocusCameraObj(GameObject obj) { print("name=="+name); if(name=="FocusTarget"){print("Object target=="+_G.TARGET); obj=GameObject.Find(_G.TARGET);} if (obj == null) return; _focusedObjectName = obj.name; _target = obj.transform; _focusPoint = _target.position; int objectNumber = Get.GetObjectIndex(_focusedObjectName); _G.CC = _focusPoint; _isFocusing = true; // Get the bounds of the object in world space Renderer[] renderers = _target.GetComponentsInChildren(); Bounds bounds = new Bounds(); bool isBoundsEmpty = true; foreach (Renderer renderer in renderers) { if (isBoundsEmpty) { isBoundsEmpty = false; bounds.center = renderer.bounds.center; bounds.size = renderer.bounds.size; } else { bounds.Encapsulate(renderer.bounds); } } System.Array.Clear(renderers, 0, renderers.Length); GameObject attachedTo = GameObject.Find(_G.OBJs[objectNumber][22]); Vector3 objDirection = obj.transform.forward; Quaternion targetRotation; // Calculate the distance the camera should be from the object based on its size float objectSize = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z); //float distanceFullOjectView = objectSize / (2 * Mathf.Tan(_camera.fieldOfView * 0.5f * Mathf.Deg2Rad)); float distance = Mathf.Max(_G._MinDistanceToCamera, objectSize + _distanceObjectViewOffset); // Position the camera to look at the center of the object and adjust its distance Vector3 center = bounds.center; Vector3 targetPosition = center - objDirection * distance; if (attachedTo.name != "floor" && attachedTo.name != "ceil") { // For a wall, position the camera using the forward of the wall targetPosition = center - attachedTo.transform.forward * distance; } targetPosition.y = 0; // Make camera look in the direction of the target Vector3 directionToTarget = (_focusPoint - targetPosition).normalized; targetRotation = Quaternion.LookRotation(directionToTarget); StartCoroutine(MoveCameraCoroutine(targetPosition, targetRotation)); } public void FocusCamera(Vector3 cameraFocusPoint, Vector3 cameraPosition, Quaternion cameraRotation) { StartCoroutine(MoveCameraCoroutine(cameraPosition, cameraRotation)); _G.CC = cameraFocusPoint; } void UpdateFocusState() { if (!_isFocusing) { return; } bool hasCameraCenterChanged = _G.CC != _focusPoint; if (hasCameraCenterChanged) { _isFocusing = false; return; } bool isDifferentObjectSeleted = SceneModeManager.SelectedName != "" && SceneModeManager.SelectedName != _focusedObjectName && SceneModeManager.CompareSceneMode(SceneModes.ReadyMove); if (isDifferentObjectSeleted) { _isFocusing = false; UnfocusCamera(); } } /// /// Camera exits focused mode. Its pivot point changes to the center of the room. Its position and direction face towards the newly selected object. /// void UnfocusCamera() { Vector3 defaultCameraHorizontalVector = _G._DefaultCameraPosition - _G._DefaultCameraFocusPoint; defaultCameraHorizontalVector.y = 0; float cameraDistance = defaultCameraHorizontalVector.magnitude; Vector3 selectionPosition = GameObject.Find(SceneModeManager.SelectedName).transform.position; // TODO : refactor with object reference instead of find() Vector3 cameraDirection = selectionPosition - _G._DefaultCameraFocusPoint; cameraDirection.y = 0; cameraDirection.Normalize(); Vector3 cameraPosition = _G._DefaultCameraFocusPoint + -1.0f * cameraDistance * cameraDirection; Quaternion cameraRotation = Quaternion.LookRotation(cameraDirection); FocusCamera(_G._DefaultCameraFocusPoint, cameraPosition, cameraRotation); } IEnumerator MoveCameraCoroutine(Vector3 targetPos, Quaternion targetRot) { _isUsingCoroutine = true; _G.CAMSET = CamSettings.Focus; float progress = _duration; Vector3 currentPos = _camera.transform.position; Quaternion currentRot = _camera.transform.rotation; while (progress > 0) { float ratio = 1f - (progress / _duration); switch (_lerpMethod) { case LerpMethod.None: { _camera.transform.position = targetPos; _camera.transform.rotation = targetRot; yield break; } case LerpMethod.Linear: { break; } case LerpMethod.EaseInOut: { ratio = EaseInOut(ratio); break; } } Vector3 newPos = Vector3.Lerp(currentPos, targetPos, ratio); Quaternion rot = Quaternion.Lerp(currentRot, targetRot, ratio); _camera.transform.position = newPos; _camera.transform.rotation = rot; yield return null; if (!_isUsingCoroutine) { _cameraResetButton.interactable = true; yield break; } progress -= Time.deltaTime; } _camera.transform.position = targetPos; _camera.transform.rotation = targetRot; _G.CAMSET = CamSettings.Front; _isUsingCoroutine = false; _cameraResetButton.interactable = true; } public static float EaseOut(float t) { return 1 - (1 - t) * (1 - t); } public static float EaseIn(float t) { return t * t; } public static float EaseInOut(float t) { if (t < 0.5f) { return 0.5f * EaseIn(t * 2); } else { return 0.5f * (EaseOut((t - 0.5f) * 2) + 1); } } public static void SelectedFocusCamera(string objname){ GameObject obj = Get.o1(objname); if (obj == null) return; float _distanceObjectViewOffset = 30.0f; string _focusedObjectName = obj.name; Transform _target = obj.transform; Vector3 _focusPoint = _target.position; int objectNumber = Get.GetObjectIndex(_focusedObjectName); _G.CC = _focusPoint; // Get the bounds of the object in world space Renderer[] renderers = _target.GetComponentsInChildren(); Bounds bounds = new(); bool isBoundsEmpty = true; foreach (Renderer renderer in renderers) { if (isBoundsEmpty) { isBoundsEmpty = false; bounds.center = renderer.bounds.center; bounds.size = renderer.bounds.size; } else { bounds.Encapsulate(renderer.bounds); } } System.Array.Clear(renderers, 0, renderers.Length); GameObject attachedTo = GameObject.Find(_G.OBJs[objectNumber][22]); Vector3 objDirection = obj.transform.forward; Quaternion targetRotation; // Calculate the distance the camera should be from the object based on its size float objectSize = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z); //float distanceFullOjectView = objectSize / (2 * Mathf.Tan(_camera.fieldOfView * 0.5f * Mathf.Deg2Rad)); float distance = Mathf.Max(_G._MinDistanceToCamera, objectSize + _distanceObjectViewOffset); // Position the camera to look at the center of the object and adjust its distance Vector3 center = bounds.center; Vector3 targetPosition = center - objDirection * distance; if (attachedTo.name != "floor" && attachedTo.name != "ceil") { // For a wall, position the camera using the forward of the wall targetPosition = center - attachedTo.transform.forward * distance; } targetPosition.y = 0; // Make camera look in the direction of the target Vector3 directionToTarget = (_focusPoint - targetPosition).normalized; targetRotation = Quaternion.LookRotation(directionToTarget); StaticCoroutine.Start(MoveCameraCoroutineObjectDuplicate(targetPosition, targetRotation)); } static IEnumerator MoveCameraCoroutineObjectDuplicate(Vector3 targetPos, Quaternion targetRot) { Camera _camera=Get.o1("MainCamera").GetComponent(); _G.CAMSET = CamSettings.Focus; float _duration=1f; float progress = _duration; _camera.transform.GetPositionAndRotation(out Vector3 currentPos, out Quaternion currentRot); while (progress > 0) { float ratio = 1f - (progress / _duration); LerpMethod _lerpMethod = LerpMethod.Linear; switch (_lerpMethod) { case LerpMethod.None: { _camera.transform.SetPositionAndRotation(targetPos, targetRot); yield break; } case LerpMethod.Linear: { break; } case LerpMethod.EaseInOut: { ratio = EaseInOut(ratio); break; } } Vector3 newPos = Vector3.Lerp(currentPos, targetPos, ratio); Quaternion rot = Quaternion.Lerp(currentRot, targetRot, ratio); _camera.transform.position = newPos; _camera.transform.rotation = rot; yield return null; progress -= Time.deltaTime; } _camera.transform.SetPositionAndRotation(targetPos, targetRot); _G.CAMSET = CamSettings.Front; } }