// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Animancer
{
/// An object which can be converted to another type.
/// https://kybernetik.com.au/animancer/api/Animancer/IConvertable_1
public interface IConvertable
{
/************************************************************************************************************************/
/// Returns the equivalent of this object as .
T Convert();
/************************************************************************************************************************/
}
/// Utility methods for .
/// https://kybernetik.com.au/animancer/api/Animancer/ConvertableUtilities
public static partial class ConvertableUtilities
{
/************************************************************************************************************************/
///
/// Custom conversion functions used as a fallback
/// for types that can't implement .
///
public static readonly Dictionary>
CustomConverters = new();
/************************************************************************************************************************/
/// Tries to convert the `original` to .
///
///
/// - If the `original` is already a then it's returned directly.
/// - Or if it's an then is used.
/// - Otherwise, this method throws an .
///
///
public static T ConvertOrThrow(object original)
{
if (TryConvert(original, out var converted))
return converted;
throw new ArgumentException(
$"Unable to convert '{AnimancerUtilities.ToStringOrNull(original)}'" +
$" to '{typeof(T).GetNameCS()}'.");
}
/************************************************************************************************************************/
/// Tries to convert the `original` to .
///
///
/// - If the `original` is already a then it's returned directly.
/// - Or if it's an then is used.
/// - Otherwise, this method returns the default(T).
///
///
public static T ConvertOrDefault(object original)
{
TryConvert(original, out var converted);
return converted;
}
/************************************************************************************************************************/
/// Tries to convert the `original` to .
///
///
/// - If the `original` is already a then it's returned directly.
/// - Or if it's an then is used.
/// - Otherwise, this method returns false.
///
///
public static bool TryConvert(object original, out T converted)
{
if (original is null)
{
converted = default;
return converted == null;// True for value type, false for reference type.
}
if (original is T t)
{
converted = t;
return true;
}
if (original is IConvertable convertable)
{
converted = convertable.Convert();
return true;
}
if (CustomConverters.TryGetValue(original.GetType(), out var converter))
{
converted = (T)converter(original, typeof(T));
return converted != null;
}
converted = default;
return false;
}
/************************************************************************************************************************/
/// Initializes the inbuilt custom converters.
static ConvertableUtilities()
{
CustomConverters.Add(typeof(GameObject), TryGetComponent);
}
/************************************************************************************************************************/
/// Tries to get a component if the `original` is a .
private static object TryGetComponent(object original, Type type)
{
if (original is GameObject gameObject &&
gameObject.TryGetComponent(type, out var component))
return component;
return null;
}
/************************************************************************************************************************/
}
}