#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 { /// /// Represents a sample that loads a base Model and adds extra Animations from other Models to it. /// public class LoadExtraAnimationsSample : MonoBehaviour { /// /// Returns the path to the base "BuddyBase.fbx" Model. /// private string BaseModelPath { get { #if UNITY_EDITOR return $"{Application.dataPath}/TriLib/TriLibSamples/LoadExtraAnimations/Models/BuddyBase.fbx"; #else return "Models/BuddyBase.fbx"; #endif } } /// /// Button to instantiate when a new Animation is loaded. /// [SerializeField] private Button _playAnimationTemplate; /// /// The Animation Component from the base Model. /// private Animation _baseAnimation; /// /// Gathers the AssetLoaderContext from the loaded Animations. /// This list is used to process the Animations if the Animations are loaded before the base Model. /// private readonly IList _loadedAnimations = new List(); /// /// Cached Asset Loader Options instance. /// private AssetLoaderOptions _assetLoaderOptions; /// /// Loads the "Models/BuddyBase.fbx" Model, then loads all the extra Animations in the same folder. /// private void Start() { LoadBaseModel(); LoadAnimation("BuddyIdle.fbx"); LoadAnimation("BuddyWalk.fbx"); LoadAnimation("BuddyJump.fbx"); } /// /// Loads the Animations from the given Model. /// /// The animated Model filename under the same folder as the base Model. private void LoadAnimation(string modelFilename) { var modelsDirectory = FileUtils.GetFileDirectory(BaseModelPath); var modelPath = FileUtils.SanitizePath($"{modelsDirectory}/{modelFilename}"); if (_assetLoaderOptions == null) { _assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions(false, true); _assetLoaderOptions.ImportMeshes = false; _assetLoaderOptions.ImportTextures = false; _assetLoaderOptions.ImportMaterials = false; } AssetLoader.LoadModelFromFile(modelPath, OnAnimationModelLoad, null, OnProgress, OnError, gameObject, _assetLoaderOptions); } /// /// Gathers all Animations from the loaded Model and adds them to the base Model Animation Component. /// /// The context used to load the Model. 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); } /// /// Adds the Animation Clips from the given AssetLoaderContext RootGameObject to the base Model Animations list. /// /// The AssetLoaderContext containing the loaded Animation component. private void AddAnimation(AssetLoaderContext loadedAnimationContext) { var rootGameObjectAnimation = loadedAnimationContext.RootGameObject.GetComponent(); 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(); playAnimationButtonText.text = shortFilename; playAnimationButton.gameObject.SetActive(true); playAnimationButton.onClick.AddListener(delegate { _baseAnimation.CrossFade(animationName); }); } } Destroy(loadedAnimationContext.RootGameObject); } /// /// Loads the Model from BaseModelPath including all Model data. /// private void LoadBaseModel() { if (_assetLoaderOptions == null) { _assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions(false, true); } AssetLoader.LoadModelFromFile(BaseModelPath, OnBaseModelLoad, OnBaseModelMaterialsLoad, OnProgress, OnError, gameObject, _assetLoaderOptions); } /// /// Called when any error occurs. /// /// The contextualized error, containing the original exception and the context passed to the method where the error was thrown. private void OnError(IContextualizedError obj) { Debug.LogError($"An error occurred while loading your Model: {obj.GetInnerException()}"); } /// /// Called when a Model loading progress changes. /// /// The context used to load the Model. /// The loading progress. private void OnProgress(AssetLoaderContext assetLoaderContext, float progress) { } /// /// Called when the Base Model (including Textures and Materials) has been fully loaded. /// This method processes previously loaded Animations from the loaded Animations list. /// /// The context used to load the Model. private void OnBaseModelMaterialsLoad(AssetLoaderContext assetLoaderContext) { Debug.Log($"Base Model loaded:{FileUtils.GetShortFilename(assetLoaderContext.Filename)}"); _baseAnimation = assetLoaderContext.RootGameObject.GetComponent(); for (var i = _loadedAnimations.Count - 1; i >= 0; i--) { AddAnimation(_loadedAnimations[i]); _loadedAnimations.RemoveAt(i); } } /// /// Called when the Base Model Meshes and hierarchy are loaded. /// /// The context used to load the Model. private void OnBaseModelLoad(AssetLoaderContext assetLoaderContext) { } } }