using UnityEngine; #if UNITY_POST_PROCESSING_STACK_V2 using UnityEngine.Rendering.PostProcessing; using System; #endif #if HDPipeline using UnityEngine.Rendering.HighDefinition; #endif using UnityEngine.Rendering; namespace Gaia { /// /// A script to handle auto focus for Gaia /// /// Our last hit point /// private Vector3 m_dofTrackingPoint = Vector3.negativeInfinity; #endregion #region Unity Function /// /// Get the main camera if it doesnt exist /// private void Start() { SetupAutoFocus(); GetCurrentDepthOfFieldSettings(); } /// /// Apply on disable /// private void OnDisable() { if (GaiaUtils.CheckIfSceneProfileExists()) { GaiaGlobal.Instance.SceneProfile.m_depthOfFieldFocusDistance = m_actualFocusDistance; } SetEditorDepthOfFieldSettings(); } private void OnDestroy() { SetEditorDepthOfFieldSettings(); SetDOFStatus(false); } /// /// Process DOF update /// private void Update() { if (m_renderPipeLine != GaiaConstants.EnvironmentRenderer.BuiltIn) { return; } #if UNITY_POST_PROCESSING_STACK_V2 if (m_sourceCamera == null || m_dof == null) { return; } #endif //Update the focus target UpdateDofTrackingPoint(); } #endregion #region Depth Of Field Functions public void SetDOFMainSettings(float aperture, float focalLength) { #if UNITY_POST_PROCESSING_STACK_V2 if (m_dof == null) { GetDepthOfFieldComponent(); } m_dof.aperture.value = aperture; m_dof.focalLength.value = focalLength; #endif } /// /// Do a raycast to update the focus target /// private void UpdateDofTrackingPoint() { switch (m_trackingType) { case GaiaConstants.DOFTrackingType.LeftMouseClick: { if (Input.GetMouseButton(0)) { Ray ray = m_sourceCamera.ScreenPointToRay(Input.mousePosition); FocusOnRayCast(ray); } break; } case GaiaConstants.DOFTrackingType.RightMouseClick: { if (Input.GetMouseButton(1)) { Ray ray = m_sourceCamera.ScreenPointToRay(Input.mousePosition); FocusOnRayCast(ray); } break; } case GaiaConstants.DOFTrackingType.FollowScreen: { Ray ray = new Ray(m_sourceCamera.transform.position, m_sourceCamera.transform.forward); FocusOnRayCast(ray); break; } case GaiaConstants.DOFTrackingType.FollowTarget: { m_dofTrackingPoint = m_targetObject.transform.position; break; } case GaiaConstants.DOFTrackingType.FixedOffset: { if (m_debug) { m_debug = false; Debug.Log("Debug mode is not available in Fixed Offset Tracking Mode. We have turned off Debug Mode for you."); } #if UNITY_POST_PROCESSING_STACK_V2 m_dof.focusDistance.value = m_focusOffset; #endif break; } } if (m_debug) { if (!Vector3.Equals(m_dofTrackingPoint,Vector3.negativeInfinity) && (m_debugSphere == null || m_debugSphere.transform.position != m_dofTrackingPoint)) { if (m_debugSphere != null) { Destroy(m_debugSphere); } m_debugSphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); Destroy(m_debugSphere.GetComponent()); m_debugSphere.transform.position = m_dofTrackingPoint; m_debugSphere.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); } } #if UNITY_POST_PROCESSING_STACK_V2 if (m_trackingType != GaiaConstants.DOFTrackingType.FixedOffset) { SetNewDOFValue(m_dof.focusDistance.value); } m_actualFocusDistance = m_dof.focusDistance.value; #endif if (GaiaUtils.CheckIfSceneProfileExists()) { GaiaGlobal.Instance.SceneProfile.m_depthOfFieldFocusDistance = m_actualFocusDistance; } } private void FocusOnRayCast(Ray ray) { if (Physics.Raycast(ray, out var hit, m_maxFocusDistance, m_targetLayer)) { if (m_debug) { Debug.Log("Auto DOF Ray collided with: " + hit.collider.name); } if (m_interactWithPlayer) { if (hit.transform.gameObject.tag != "Player") { m_maxDistanceExceeded = false; m_dofTrackingPoint = hit.point; } else { m_maxDistanceExceeded = true; } } else { m_maxDistanceExceeded = false; m_dofTrackingPoint = hit.point; } } else { m_maxDistanceExceeded = true; } } public void RemoveDebugSphere() { if (m_debugSphere != null) { DestroyImmediate(m_debugSphere); } } private void SetNewDOFValue(float startValue, float timeMultiplier = 3.5f) { if (m_sourceCamera == null) { return; } #if UNITY_POST_PROCESSING_STACK_V2 if (m_dof == null) { GetDepthOfFieldComponent(); } else { if (m_maxDistanceExceeded) { m_dof.focusDistance.value = m_maxFocusDistance; } else { m_dof.focusDistance.value = Mathf.Lerp(startValue, Vector3.Distance(m_sourceCamera.transform.position ,m_dofTrackingPoint) + m_focusOffset, Time.deltaTime * timeMultiplier); } } #endif } /// /// Setup autofocus object /// public void SetupAutoFocus() { m_renderPipeLine = GaiaUtils.GetActivePipeline(); if (m_dofTrackingPoint.x > 0) { //Removes warning } if (m_maxDistanceExceeded) { //Removes warning } //Set up main camera if (m_sourceCamera == null) { m_sourceCamera = GaiaUtils.GetCamera(); if (m_sourceCamera == null) { Debug.Log("DOF Autofocus exiting, unable to find main camera!"); enabled = false; return; } } //Determine tracking type if (m_trackingType == GaiaConstants.DOFTrackingType.FollowTarget && m_targetObject == null) { Debug.Log("Tracking target is missing, falling back to follow screen!"); m_trackingType = GaiaConstants.DOFTrackingType.FollowScreen; } #if UNITY_POST_PROCESSING_STACK_V2 //Gets DOF component if (m_dof == null) { GetDepthOfFieldComponent(); } if (m_dof != null) { m_dof.focusDistance.value = m_maxFocusDistance; } #endif } private void GetDepthOfFieldComponent() { if (m_renderPipeLine != GaiaConstants.EnvironmentRenderer.BuiltIn) { return; } #if UNITY_POST_PROCESSING_STACK_V2 //Find our DOF component if (m_dof == null) { GameObject ppObj = GameObject.Find("Global Post Processing"); if (ppObj == null) { Debug.Log("DOF Autofocus exiting, unable to global post processing object!"); enabled = false; return; } PostProcessVolume ppVolume = ppObj.GetComponent(); { if (ppVolume == null) { Debug.Log("DOF Autofocus exiting, unable to global post processing volume!"); enabled = false; return; } } PostProcessProfile ppProfile = ppVolume.sharedProfile; if (ppProfile == null) { Debug.Log("DOF Autofocus exiting, unable to global post processing profile!"); enabled = false; return; } if (!ppProfile.HasSettings()) { Debug.Log("DOF Autofocus exiting, unable to find dof settings!"); enabled = false; return; } if (!ppProfile.TryGetSettings(out m_dof)) { Debug.Log("DOF Autofocus exiting, unable to find dof settings!"); m_dof = null; enabled = false; } } if (m_dof != null) { m_dof.active = true; m_dof.enabled.value = true; m_dof.focusDistance.overrideState = true; m_maxDistanceExceeded = true; } #endif } /// /// Sets the focus distance on the DOF component based on camera distance divided by 4 /// /// public void SetDOFStatus(bool enabled) { if (!enabled) { #if UNITY_POST_PROCESSING_STACK_V2 if (m_dof != null && m_sourceCamera != null) { m_dof.focusDistance.value = m_sourceCamera.farClipPlane / 4f; } #endif } } /// /// Grabs the DOF aperture and focal length and updates the systems values to use these /// public void GetCurrentDepthOfFieldSettings() { #if UNITY_POST_PROCESSING_STACK_V2 if (m_dof != null) { m_dofAperture = m_dof.aperture.value; m_dofFocalLength = m_dof.focalLength.value; } #endif } /// /// Sets the depth of field focus distance to 100 if it's less than 20 /// This should remove a blury game view when not in play mode /// private void SetEditorDepthOfFieldSettings() { #if UNITY_POST_PROCESSING_STACK_V2 if (m_dof == null) { return; } if (m_dof.focusDistance.value < 20f) { m_dof.focusDistance.value = 100f; } #endif } #endregion } }