ProjectDDD/Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/MVC/Sequencer/Commands/SequencerCommandCamera.cs

146 lines
6.3 KiB (Stored with Git LFS)
C#

// Copyright (c) Pixel Crushers. All rights reserved.
using UnityEngine;
namespace PixelCrushers.DialogueSystem.SequencerCommands
{
/// <summary>
/// Implements sequencer command: Camera(angle[, gameobject|speaker|listener[, duration]])
///
/// Arguments:
/// -# Name of a camera angle (child transform) defined in cameraAngles. If the angle isn't
/// defined in Sequencer.CameraAngles, looks for a game object in the scene. Default: Closeup.
/// -# (Optional) The subject; can be speaker, listener, or the name of a game object. Default:
/// speaker.
/// -# (Optional) Duration over which to move the camera. Default: immediate.
/// </summary>
[AddComponentMenu("")] // Hide from menu.
public class SequencerCommandCamera : SequencerCommand
{
protected const float SmoothMoveCutoff = 0.05f;
protected Transform subject;
protected Transform angleTransform;
protected Transform cameraTransform;
protected bool isLocalTransform;
protected Quaternion targetRotation;
protected Vector3 targetPosition;
protected float duration;
protected float startTime;
protected float endTime;
protected Quaternion originalRotation;
protected Vector3 originalPosition;
protected virtual void Start()
{
// Get the values of the parameters:
string angle = GetParameter(0, "Closeup");
subject = GetSubject(1);
duration = GetParameterAsFloat(2, 0);
// Get angle:
bool isDefault = string.Equals(angle, "default");
if (isDefault) angle = SequencerTools.GetDefaultCameraAngle(subject);
bool isOriginal = string.Equals(angle, "original");
angleTransform = isOriginal
? ((Camera.main != null) ? Camera.main.transform : speaker)
: ((sequencer.cameraAngles != null) ? sequencer.cameraAngles.transform.Find(angle) : null);
isLocalTransform = true;
if (angleTransform == null)
{
isLocalTransform = false;
angleTransform = SequencerTools.GetSubject(angle, speaker, listener, null);
}
// Log:
if ((angleTransform == null) && DialogueDebug.logWarnings) Debug.LogWarning(string.Format("{0}: Sequencer: Camera({1}): Camera angle '{2}' wasn't found.", new System.Object[] { DialogueDebug.Prefix, GetParameters(), angle }));
else if ((subject == null && !isOriginal) && !(isLocalTransform && angleTransform != null) && DialogueDebug.logWarnings) Debug.LogWarning(string.Format("{0}: Sequencer: Camera({1}): Camera subject '{2}' or GameObject named '{3}' wasn't found.", new System.Object[] { DialogueDebug.Prefix, GetParameters(), GetParameter(1), GetParameter(0) }));
else if (DialogueDebug.logInfo) Debug.Log(string.Format("{0}: Sequencer: Camera({1}, {2}, {3}s)", new System.Object[] { DialogueDebug.Prefix, angle, Tools.GetGameObjectName(subject), duration }));
// If we have a camera angle and subject, move the camera to it:
sequencer.TakeCameraControl();
if (isOriginal || (angleTransform != null && (subject != null || isLocalTransform)))
{
cameraTransform = sequencer.sequencerCameraTransform;
if (isOriginal)
{
targetRotation = sequencer.originalCameraRotation;
targetPosition = sequencer.originalCameraPosition;
}
else if (isLocalTransform)
{
targetRotation = subject.rotation * angleTransform.localRotation;
targetPosition = subject.position + subject.rotation * angleTransform.localPosition;
}
else
{
targetRotation = angleTransform.rotation;
targetPosition = angleTransform.position;
}
// If duration is above the cutoff, smoothly move camera toward camera angle:
if (duration > SmoothMoveCutoff)
{
startTime = DialogueTime.time;
endTime = startTime + duration;
originalRotation = cameraTransform.rotation;
originalPosition = cameraTransform.position;
var useUnscaledTime = DialogueTime.mode != DialogueTime.TimeMode.Gameplay;
var easing = DialogueManager.displaySettings.cameraSettings.cameraEasing;
Tweener.Tween(originalPosition, targetPosition, duration, useUnscaledTime, easing,
onBegin: null,
onValue: (x) => cameraTransform.position = x,
onEnd: Stop);
Tweener.Tween(originalRotation, targetRotation, duration, useUnscaledTime, easing,
onBegin: null,
onValue: (x) => cameraTransform.rotation = x,
onEnd: Stop);
}
else
{
Stop();
}
}
else
{
Stop();
}
}
//--- We've switched to using the Tweener class to allow for more easing styles.
//--- This is just a safeguard now:
protected virtual void Update()
{
if (DialogueTime.time > endTime) Stop();
}
//public void Update()
//{
// // Keep smoothing for the specified duration:
// if (DialogueTime.time < endTime)
// {
// float elapsed = (DialogueTime.time - startTime) / duration;
// cameraTransform.rotation = Quaternion.Lerp(originalRotation, targetRotation, elapsed);
// cameraTransform.position = Vector3.Lerp(originalPosition, targetPosition, elapsed);
// }
// else
// {
// Stop();
// }
//}
protected virtual void OnDestroy()
{
// Final position:
if (angleTransform != null && subject != null)
{
cameraTransform.rotation = targetRotation;
cameraTransform.position = targetPosition;
}
}
}
}