Files
beyond/Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/MVC/Sequencer/SequencerTools.cs
2024-11-20 15:21:28 +01:00

279 lines
11 KiB
C#

// Copyright (c) Pixel Crushers. All rights reserved.
using UnityEngine;
namespace PixelCrushers.DialogueSystem
{
/// <summary>
/// A static utility class for Sequencer.
/// </summary>
public static class SequencerTools
{
/// <summary>
/// Sequencer commands usually specify a subject to which the command applies (e.g., where to
/// aim the camera). This utility function that returns the specified subject.
/// </summary>
/// <returns>
/// The transform of the specified subject, or null if the specifier names a game
/// object that isn't in the scene.
/// </returns>
/// <param name='specifier'>
/// <c>"speaker"</c>, <c>"listener"</c>, or the name of a game object in the scene.
/// </param>
/// <param name='speaker'>
/// Speaker.
/// </param>
/// <param name='listener'>
/// Listener.
/// </param>
/// <param name='defaultSubject'>
/// Default subject.
/// </param>
public static Transform GetSubject(string specifier, Transform speaker, Transform listener, Transform defaultSubject = null)
{
if (string.IsNullOrEmpty(specifier))
{
return defaultSubject ?? speaker;
}
else if (string.Compare(specifier, SequencerKeywords.Speaker, System.StringComparison.OrdinalIgnoreCase) == 0)
{
return speaker;
}
else if (string.Compare(specifier, SequencerKeywords.Listener, System.StringComparison.OrdinalIgnoreCase) == 0)
{
return listener;
}
else
{
GameObject go = FindSpecifier(specifier);
return (go != null) ? go.transform : defaultSubject;
}
}
/// <summary>
/// Returns true if specifier specifies a tag ('tag=foo').
/// </summary>
public static bool SpecifierSpecifiesTag(string specifier)
{
return !string.IsNullOrEmpty(specifier) && specifier.StartsWith("tag=", System.StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Assumes specifier specifies a tag ('tag=foo'). Returns the tag.
/// </summary>
public static string GetSpecifiedTag(string specifier)
{
return specifier.Substring("tag=".Length);
}
/// <summary>
/// Finds a game object with the specified name, returning any match in scene before
/// trying to return any non-scene matches in the project. Checks GameObjects registered
/// with the specifier as its actor name first.
/// </summary>
/// <returns>
/// The specified game object.
/// </returns>
/// <param name='specifier'>
/// The name to search for.
/// </param>
/// <param name='onlyActiveInScene'>Only search active objects in the scene.</param>
public static GameObject FindSpecifier(string specifier, bool onlyActiveInScene = false)
{
if (string.IsNullOrEmpty(specifier)) return null;
// Check for 'tag=' keyword:
if (SpecifierSpecifiesTag(specifier))
{
var tag = GetSpecifiedTag(specifier);
var taggedGO = GameObject.FindGameObjectWithTag(tag);
if (taggedGO != null) return taggedGO;
var results = Tools.FindGameObjectsWithTagHard(tag);
return (results.Length > 0) ? results[0] : null;
}
// Search registered actors:
var t = CharacterInfo.GetRegisteredActorTransform(specifier);
if (t != null) return t.gameObject;
// Search for active objects in scene:
var match = GameObject.Find(specifier);
if (match != null) return match;
if (onlyActiveInScene) return null;
// Search for all objects in scene, including inactive as long as it's a child of an active object:
match = Tools.GameObjectHardFind(specifier);
if (match != null) return match;
// Search for all objects, including loaded-but-not-instantiated (i.e., prefabs):
foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[])
{
if (string.Compare(specifier, go.name, System.StringComparison.OrdinalIgnoreCase) == 0)
{
return go;
}
}
return null;
}
/// <summary>
/// Gets the default camera angle for a subject.
/// </summary>
/// <returns>The default camera angle. If the subject doesn't have a DefaultCameraAngle
/// component, returns "Closeup".</returns>
/// <param name="subject">Subject.</param>
public static string GetDefaultCameraAngle(Transform subject)
{
var defaultCameraAngle = (subject != null) ? subject.GetComponentInChildren<DefaultCameraAngle>() : null;
return (defaultCameraAngle != null) ? defaultCameraAngle.cameraAngle : "Closeup";
}
/// <summary>
/// Gets <c>parameters[i]</c>.
/// </summary>
/// <returns>
/// <c>parameters[i]</c>, or the specified default value if <c>i</c> is out of range.
/// </returns>
/// <param name='parameters'>
/// An array of parameters.
/// </param>
/// <param name='i'>
/// The index into <c>parameters[]</c>
/// </param>
/// <param name='defaultValue'>
/// The default value to return if <c>i</c> is out of range.
/// </param>
public static string GetParameter(string[] parameters, int i, string defaultValue = null)
{
return ((parameters != null) && (i < parameters.Length)) ? parameters[i] : defaultValue;
}
/// <summary>
/// Gets <c>parameters[i]</c> as the specified type. Culture invariant (i.e., floats use '.' for
/// decimal point).
/// </summary>
/// <returns>
/// <c>parameters[i]</c> as type T, or the specified default value if <c>i</c> is out of range
/// or <c>parameters[i]</c> can't be converted to type T.
/// </returns>
/// <param name='parameters'>
/// An array of parameters.
/// </param>
/// <param name='i'>
/// The index into <c>parameters[]</c>
/// </param>
/// <param name='defaultValue'>
/// The default value to return if <c>i</c> is out of range or the parameter can't be converted
/// to type T.
/// </param>
/// <typeparam name='T'>
/// The type to convert the parameter to.
/// </typeparam>
/// <example>
/// // Get parameters[1] as a float, defaulting to 5f:
/// float duration = GetParameterAs<float>(parameters, 1, 5f);
/// </example>
public static T GetParameterAs<T>(string[] parameters, int i, T defaultValue)
{
try
{
return ((parameters != null) && (i < parameters.Length))
? (T)System.Convert.ChangeType(parameters[i], typeof(T), System.Globalization.CultureInfo.InvariantCulture)
: defaultValue;
}
catch (System.Exception)
{
return defaultValue;
}
}
/// <summary>
/// Gets the i-th parameter as a float.
/// </summary>
/// <returns>
/// The parameter as float, or defaultValue if out of range.
/// </returns>
/// <param name='parameters'>
/// The array of parameters.
/// </param>
/// <param name='i'>
/// The zero-based index of the parameter.
/// </param>
/// <param name='defaultValue'>
/// The default value to use if the parameter doesn't exist or isn't valid for the type.
/// </param>
public static float GetParameterAsFloat(string[] parameters, int i, float defaultValue = 0)
{
return GetParameterAs<float>(parameters, i, defaultValue);
}
/// <summary>
/// Gets the i-th parameter as an int.
/// </summary>
/// <returns>
/// The parameter as an int, or defaultValue if out of range.
/// </returns>
/// <param name='parameters'>
/// The array of parameters.
/// </param>
/// <param name='i'>
/// The zero-based index of the parameter.
/// </param>
/// <param name='defaultValue'>
/// The default value to use if the parameter doesn't exist or isn't valid for the type.
/// </param>
public static int GetParameterAsInt(string[] parameters, int i, int defaultValue = 0)
{
return GetParameterAs<int>(parameters, i, defaultValue);
}
/// <summary>
/// Gets the i-th parameter as a bool.
/// </summary>
/// <returns>
/// The parameter as bool, or defaultValue if out of range.
/// </returns>
/// <param name='parameters'>
/// The array of parameters.
/// </param>
/// <param name='i'>
/// The zero-based index of the parameter.
/// </param>
/// <param name='defaultValue'>
/// The default value to use if the parameter doesn't exist or isn't valid for the type.
/// </param>
public static bool GetParameterAsBool(string[] parameters, int i, bool defaultValue = false)
{
return GetParameterAs<bool>(parameters, i, defaultValue);
}
/// <summary>
/// Gets the audio source on a subject, using the Dialogue Manager as the subject if the
/// specified subject is <c>null</c>. If no audio source exists on the subject, this
/// method adds one.
/// </summary>
/// <returns>The audio source.</returns>
/// <param name="subject">Subject.</param>
public static AudioSource GetAudioSource(Transform subject)
{
GameObject go = (subject != null) ? subject.gameObject : DialogueManager.instance.gameObject;
AudioSource audio = go.GetComponentInChildren<AudioSource>();
return (audio != null) ? audio : go.AddComponent<AudioSource>();
}
/// <summary>
/// Checks if a Lua variable "Mute" is <c>true</c>.
/// </summary>
/// <returns><c>true</c> if audio is muted; otherwise, <c>false</c>.</returns>
public static bool IsAudioMuted()
{
return DialogueLua.GetVariable("Mute").asBool;
}
}
}