using System.Collections; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace FiradzoAssets { public class EquipmentAttachmentHelper : MonoBehaviour { [SerializeField, Tooltip("SkinnedMeshRenderer reference from source asset. Required to read bones structure")] private SkinnedMeshRenderer skinnedMeshSource; [SerializeField, Tooltip("SkinnedMeshRenderer component on the object that need to be binded")] private SkinnedMeshRenderer thisSkinnedMesh; [Space(10f)] [SerializeField] private bool forceRebind; [SerializeField, HideInInspector] private bool isBinded; [SerializeField, HideInInspector] private string lastBindedMeshName; private void Awake() { BindItemToBones(); } public void SetSkinnedMeshSource(SkinnedMeshRenderer skinnedMeshSource) { this.skinnedMeshSource = skinnedMeshSource; #if UNITY_EDITOR EditorUtility.SetDirty(this); #endif } private void BindItemToBones() { if (isBinded || skinnedMeshSource == null || thisSkinnedMesh == null) { return; } var bones = new Transform[skinnedMeshSource.bones.Length]; var root = transform.parent; for (int i = 0; i < skinnedMeshSource.bones.Length; i++) { var bone = FindTransfomInChildRecursive(root, skinnedMeshSource.bones[i].name); if (bone == null) { Debug.LogErrorFormat("Can't find bone with name {0}", skinnedMeshSource.bones[i].name); return; } bones[i] = bone; } thisSkinnedMesh.rootBone = bones[0]; thisSkinnedMesh.bones = bones; isBinded = true; lastBindedMeshName = thisSkinnedMesh.sharedMesh.name; #if UNITY_EDITOR if (!Application.isPlaying) { EditorUtility.SetDirty(this); EditorUtility.SetDirty(thisSkinnedMesh); } #endif } private Transform FindTransfomInChildRecursive(Transform transform, string transformName) { if (transform.name == transformName) { return transform; } var childCount = transform.childCount; if (transform.childCount > 0) { Transform result; for (int i = 0; i < childCount; i++) { result = FindTransfomInChildRecursive(transform.GetChild(i), transformName); if (result != null) { return result; } } } return null; } #if UNITY_EDITOR private void OnValidate() { if (forceRebind) { forceRebind = false; isBinded = false; } if (thisSkinnedMesh == null) { isBinded = false; thisSkinnedMesh = GetComponent(); TryLoadSourceSkinnedMeshRenderer(); } if (isBinded && thisSkinnedMesh != null) { if (string.IsNullOrEmpty(lastBindedMeshName) || thisSkinnedMesh.sharedMesh.name != lastBindedMeshName) { TryLoadSourceSkinnedMeshRenderer(); isBinded = false; } } BindItemToBones(); } private void TryLoadSourceSkinnedMeshRenderer() { if (thisSkinnedMesh != null && thisSkinnedMesh.sharedMesh != null && skinnedMeshSource == null) { var assetPath = AssetDatabase.GetAssetPath(thisSkinnedMesh.sharedMesh); var sourceFBX = AssetDatabase.LoadAssetAtPath(assetPath); var sourceAsset = sourceFBX.transform.Find(thisSkinnedMesh.sharedMesh.name); if (sourceAsset != null) { skinnedMeshSource = sourceAsset.GetComponent(); if (!Application.isPlaying) { EditorUtility.SetDirty(this); } } } } #endif } }