// Copyright (C) 2023 Nicholas Maltbie
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Serialization;
namespace nickmaltbie.OpenKCC.CameraControls.Config
{
[Serializable]
public class CameraConfig
{
[Header("Input Actions")]
///
/// Action to rotate camera.
///
[FormerlySerializedAs("lookAction")]
[Tooltip("Player look action to rotate camera.")]
[SerializeField]
public InputActionReference lookActionReference;
///
/// Override for the look action of the network camera controller.
///
private InputAction overrideLookAction;
///
/// Gest or sets the look action associated with this network camera controller.
///
public InputAction LookAction
{
get => overrideLookAction ?? lookActionReference?.action;
set => overrideLookAction = value;
}
///
/// Zoom action to zoom in and out.
///
[Tooltip("Player zoom action with camera.")]
[FormerlySerializedAs("zoomAction")]
[SerializeField]
public InputActionReference zoomActionReference;
///
/// Override for the zoom action of the network camera controller.
///
private InputAction overrideZoomAction;
///
/// Gest or sets the zoom action associated with this network camera controller.
///
public InputAction ZoomAction
{
get => overrideZoomAction ?? zoomActionReference?.action;
set => overrideZoomAction = value;
}
[Header("Rotation Bounds")]
///
/// Maximum pitch for rotating character camera in degrees
///
public float maxPitch = 90;
///
/// Minimum pitch for rotating character camera in degrees
///
public float minPitch = -90;
///
/// Rotation rate of camera in degrees per second per one unit of axis movement
///
public float rotationRate = 180;
///
/// Transform holding camera position and rotation data
///
public Transform cameraTransform;
///
/// Camera offset from character center
///
public Vector3 baseCameraOffset;
///
/// Minimum distance (closest zoom) of player camera
///
public float minCameraDistance = 0.0f;
///
/// Maximum distance (farthest zoom) of player camera
///
public float maxCameraDistance = 4.0f;
///
/// Current distance of the camera from the player position
///
public float currentDistance;
///
/// Zoom distance change in units per second
///
public float zoomSpeed = 1.0f;
///
/// What can the camera collide with
///
public LayerMask cameraRaycastMask = ~0;
///
/// Distance in which the third person character will be completely transparent and only cast shadows
///
public float shadowOnlyDistance = 0.5f;
///
/// Distance where the player object will dither but still be visible
///
public float ditherDistance = 1.0f;
///
/// Base object where all the third person character is stored.
///
public GameObject thirdPersonCharacterBase;
///
/// Time in seconds it takes to transition between opacity states.
///
public float transitionTime = 0.1f;
///
/// Should this camera config rotate the avatar along the yaw.
///
public bool rotatePlayer = false;
///
/// Objects to ignore when drawing raycast for camera.
///
private List ignoreObjects = new List();
///
/// Ignore objects for drawing raycast for camera.
///
public List IgnoreObjects => ignoreObjects;
///
/// Get the current distance of the camera from the player camera location.
///
public float CameraDistance { get; set; }
///
/// Source camera position in real world space, this is where the head of
/// the player would be, where the camera zooms out from
///
public Vector3 CameraSource(Transform transform) => baseCameraOffset + transform.position;
///
/// Add an object to the ignore list when ray casting camera position
///
///
public void AddIgnoreObject(GameObject go) => ignoreObjects.Add(go);
///
/// Remove an object to the ignore list when raycasting camera position
///
///
public bool RemoveIgnoreObject(GameObject go) => ignoreObjects.Remove(go);
///
/// Setup the camera config for a camera controller.
///
/// Game object with attached collider.
public void Setup(GameObject go)
{
baseCameraOffset = cameraTransform == null ? Vector3.zero : cameraTransform.localPosition;
currentDistance = Mathf.Clamp(currentDistance, minCameraDistance, maxCameraDistance);
ignoreObjects.Add(go);
LookAction?.Enable();
ZoomAction?.Enable();
}
}
}