184 lines
7.4 KiB
C#
184 lines
7.4 KiB
C#
#pragma warning disable 649
|
|
using System.Collections.Generic;
|
|
using TriLibCore.Extensions;
|
|
using TriLibCore.Utils;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
namespace TriLibCore.Samples
|
|
{
|
|
/// <summary>
|
|
/// Represents a sample that loads a base Model and adds extra Animations from other Models to it.
|
|
/// </summary>
|
|
public class LoadExtraAnimationsSample : MonoBehaviour
|
|
{
|
|
|
|
#if UNITY_EDITOR
|
|
/// <summary>
|
|
/// The Base Model asset used to locate the filename when running in Unity Editor.
|
|
/// </summary>
|
|
[SerializeField]
|
|
private Object BaseModelAsset;
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Returns the path to the base "BuddyBase.fbx" Model.
|
|
/// </summary>
|
|
private string BaseModelPath
|
|
{
|
|
get
|
|
{
|
|
#if UNITY_EDITOR
|
|
return AssetDatabase.GetAssetPath(BaseModelAsset);
|
|
#else
|
|
return "Models/BuddyBase.fbx";
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Button to instantiate when a new Animation is loaded.
|
|
/// </summary>
|
|
[SerializeField]
|
|
private Button _playAnimationTemplate;
|
|
|
|
/// <summary>
|
|
/// The Animation Component from the base Model.
|
|
/// </summary>
|
|
private Animation _baseAnimation;
|
|
|
|
/// <summary>
|
|
/// Gathers the AssetLoaderContext from the loaded Animations.
|
|
/// This list is used to process the Animations if the Animations are loaded before the base Model.
|
|
/// </summary>
|
|
private readonly IList<AssetLoaderContext> _loadedAnimations = new List<AssetLoaderContext>();
|
|
|
|
/// <summary>
|
|
/// Loads the "Models/BuddyBase.fbx" Model, then loads all the extra Animations in the same folder.
|
|
/// </summary>
|
|
private void Start()
|
|
{
|
|
LoadBaseModel();
|
|
LoadAnimation("BuddyIdle.fbx");
|
|
LoadAnimation("BuddyWalk.fbx");
|
|
LoadAnimation("BuddyJump.fbx");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the Animations from the given Model.
|
|
/// </summary>
|
|
/// <param name="modelFilename">The animated Model filename under the same folder as the base Model.</param>
|
|
private void LoadAnimation(string modelFilename)
|
|
{
|
|
var modelsDirectory = FileUtils.GetFileDirectory(BaseModelPath);
|
|
var modelPath = FileUtils.SanitizePath($"{modelsDirectory}/{modelFilename}");
|
|
var assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions();
|
|
assetLoaderOptions.ImportMeshes = false;
|
|
assetLoaderOptions.ImportTextures = false;
|
|
assetLoaderOptions.ImportMaterials = false;
|
|
AssetLoader.LoadModelFromFile(modelPath, OnAnimationModelLoad, null, OnProgress, OnError, gameObject, assetLoaderOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gathers all Animations from the loaded Model and adds them to the base Model Animation Component.
|
|
/// </summary>
|
|
/// <param name="assetLoaderContext">The context used to load the Model.</param>
|
|
private void OnAnimationModelLoad(AssetLoaderContext assetLoaderContext)
|
|
{
|
|
Debug.Log($"Animation loaded: {FileUtils.GetShortFilename(assetLoaderContext.Filename)}");
|
|
if (_baseAnimation != null)
|
|
{
|
|
AddAnimation(assetLoaderContext);
|
|
}
|
|
else
|
|
{
|
|
_loadedAnimations.Add(assetLoaderContext);
|
|
}
|
|
assetLoaderContext.RootGameObject.SetActive(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds the Animation Clips from the given AssetLoaderContext RootGameObject to the base Model Animations list.
|
|
/// </summary>
|
|
/// <param name="loadedAnimationContext">The AssetLoaderContext containing the loaded Animation component.</param>
|
|
private void AddAnimation(AssetLoaderContext loadedAnimationContext)
|
|
{
|
|
var rootGameObjectAnimation = loadedAnimationContext.RootGameObject.GetComponent<Animation>();
|
|
if (rootGameObjectAnimation != null)
|
|
{
|
|
var shortFilename = FileUtils.GetShortFilename(loadedAnimationContext.Filename);
|
|
var newAnimationClips = rootGameObjectAnimation.GetAllAnimationClips();
|
|
foreach (var newAnimationClip in newAnimationClips)
|
|
{
|
|
var animationName = $"{shortFilename}_{newAnimationClip.name}";
|
|
_baseAnimation.AddClip(newAnimationClip, animationName);
|
|
var playAnimationButton = Instantiate(_playAnimationTemplate, _playAnimationTemplate.transform.parent);
|
|
var playAnimationButtonText = playAnimationButton.GetComponentInChildren<Text>();
|
|
playAnimationButtonText.text = shortFilename;
|
|
playAnimationButton.gameObject.SetActive(true);
|
|
playAnimationButton.onClick.AddListener(delegate
|
|
{
|
|
_baseAnimation.CrossFade(animationName);
|
|
});
|
|
}
|
|
}
|
|
Destroy(loadedAnimationContext.RootGameObject);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the Model from BaseModelPath including all Model data.
|
|
/// </summary>
|
|
private void LoadBaseModel()
|
|
{
|
|
var assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions();
|
|
AssetLoader.LoadModelFromFile(BaseModelPath, OnBaseModelLoad, OnBaseModelMaterialsLoad, OnProgress, OnError, gameObject, assetLoaderOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when any error occurs.
|
|
/// </summary>
|
|
/// <param name="obj">The contextualized error, containing the original exception and the context passed to the method where the error was thrown.</param>
|
|
private void OnError(IContextualizedError obj)
|
|
{
|
|
Debug.LogError($"An error occurred while loading your Model: {obj.GetInnerException()}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when a Model loading progress changes.
|
|
/// </summary>
|
|
/// <param name="assetLoaderContext">The context used to load the Model.</param>
|
|
/// <param name="progress">The loading progress.</param>
|
|
private void OnProgress(AssetLoaderContext assetLoaderContext, float progress)
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the Base Model (including Textures and Materials) has been fully loaded.
|
|
/// This method processes previously loaded Animations from the loaded Animations list.
|
|
/// </summary>
|
|
/// <param name="assetLoaderContext">The context used to load the Model.</param>
|
|
private void OnBaseModelMaterialsLoad(AssetLoaderContext assetLoaderContext)
|
|
{
|
|
Debug.Log($"Base Model loaded:{FileUtils.GetShortFilename(assetLoaderContext.Filename)}");
|
|
_baseAnimation = assetLoaderContext.RootGameObject.GetComponent<Animation>();
|
|
for (var i = _loadedAnimations.Count - 1; i >= 0; i--)
|
|
{
|
|
AddAnimation(_loadedAnimations[i]);
|
|
_loadedAnimations.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the Base Model Meshes and hierarchy are loaded.
|
|
/// </summary>
|
|
/// <param name="assetLoaderContext">The context used to load the Model.</param>
|
|
private void OnBaseModelLoad(AssetLoaderContext assetLoaderContext)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|