using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; public class DanMachiCharacterContainer : ObjectContainer, IAnimated { protected override System.Type _serializeType => typeof(DanMachiCharacterSerializable); protected override System.Type _keyframeType => typeof(DanMachiCharacterKeyframeData); public CharacterAsset Data; public string AnimationSet; public string Animation; public GameObject Body; public MorphPanel MorphPanel; public CharacterPanel CharacterPanel; public List Animations; private Animator _animator; private AnimatorOverrideController _animatorController; private Dictionary _humanBones = new Dictionary(); public List Bones = new List(); public void Init() { _animator = GetComponentInChildren(); if(_animator != null) { _animator.applyRootMotion = false; _animator.runtimeAnimatorController = _animatorController = Instantiate(SharedResources.Instance.GenericAnimatorController); } else { Error.Log(Color.red, $"{name} has no animator"); } CreateMorphPanel(); CreateCharacterPanel(); SetBones(); } public void Rebuild(CharacterAsset model) { DestroyImmediate(Body); Build(model); } public void Build(CharacterAsset model) { Data = model; var assetPath = Path.Combine(DanMachiAssetLibrary.Instance.LocalFilesPath, model.FilePath); var characterAsset = AssetLibrary.LoadFromFile(assetPath); var assetNames = characterAsset.GetAllAssetNames(); var characterModel = assetNames.FirstOrDefault(a => Path.GetFileName(a).StartsWith("CP_") && a.EndsWith(".prefab")); if(!string.IsNullOrEmpty(characterModel)) { Body = Instantiate(characterAsset.LoadAsset(characterModel), transform) as GameObject; } else { Body = new GameObject(); Body.transform.SetParent(transform); foreach (var go in characterAsset.LoadAllAssets()) { Instantiate(go, Body.transform); } } LoadedAssets = new List() { new AssetBundleEntry(model.AssetName, assetPath, characterAsset) }; AssetLibrary.UnloadAsset(assetPath); SetDefaultMaterials(transform); Init(); } public void LoadAnimationSet(CharacterAsset animationSet) { if (animationSet != null) { AnimationSet = animationSet.Costume; Animation = ""; var animationAsset = AssetBundle.LoadFromFile(Path.Combine(DanMachiAssetLibrary.Instance.LocalFilesPath, animationSet.FilePath)); Animations = animationAsset.LoadAllAssets().ToList(); animationAsset.Unload(false); } } public void PlayAnimation(string clipName) { var anim = Animations.FirstOrDefault(a=>a.name == clipName); PlayAnimation(anim); } public void PlayAnimation(AnimationClip anim) { if(_animator == null) { Error.Log(Color.red, $"{name} has no animator"); return; } if(anim == null) { Animation = ""; _animator.enabled = false; } else { Animation = anim.name; _animator.enabled = true; _animatorController["Anim"] = anim; } } public void SetDefaultMaterials(Transform t) { List materials = new List(); foreach (var renderer in t.GetComponentsInChildren()) { foreach (var material in renderer.sharedMaterials) { if (materials.Contains(material)) continue; materials.Add(material); material.shader = Shader.Find("DanMachiUnlit"); } } } public void SetBones() { _humanBones.Clear(); Bones.Clear(); if (_animator == null) return; var humanBones = new Dictionary(); var allBones = new Dictionary(); foreach(var bone in _animator.transform.GetComponentsInChildren()) { if (!allBones.ContainsKey(bone.name)) { allBones[bone.name] = bone; } } humanBones.Add(HumanBodyBones.Hips, TryGet(allBones,"Hips")); humanBones.Add(HumanBodyBones.Spine, TryGet(allBones,"Spine")); humanBones.Add(HumanBodyBones.RightUpperLeg, TryGet(allBones,"RightUpLeg")); humanBones.Add(HumanBodyBones.RightLowerLeg, TryGet(allBones,"RightLeg")); humanBones.Add(HumanBodyBones.RightFoot, TryGet(allBones,"RightFoot")); humanBones.Add(HumanBodyBones.RightToes, TryGet(allBones,"RightToeBase")); humanBones.Add(HumanBodyBones.LeftUpperLeg, TryGet(allBones,"LeftUpLeg")); humanBones.Add(HumanBodyBones.LeftLowerLeg, TryGet(allBones,"LeftLeg")); humanBones.Add(HumanBodyBones.LeftFoot, TryGet(allBones,"LeftFoot")); humanBones.Add(HumanBodyBones.LeftToes, TryGet(allBones,"LeftToeBase")); humanBones.Add(HumanBodyBones.Chest, TryGet(allBones,"Spine1")); humanBones.Add(HumanBodyBones.UpperChest, TryGet(allBones,"Spine2")); humanBones.Add(HumanBodyBones.Neck, TryGet(allBones,"Neck")); humanBones.Add(HumanBodyBones.Head, TryGet(allBones,"Head")); humanBones.Add(HumanBodyBones.RightShoulder, TryGet(allBones,"RightShoulder")); humanBones.Add(HumanBodyBones.RightUpperArm, TryGet(allBones,"RightArm")); humanBones.Add(HumanBodyBones.RightLowerArm, TryGet(allBones,"RightForeArm")); humanBones.Add(HumanBodyBones.RightHand, TryGet(allBones,"RightHand")); humanBones.Add(HumanBodyBones.RightIndexProximal, TryGet(allBones,"RightHandIndex1")); humanBones.Add(HumanBodyBones.RightIndexIntermediate, TryGet(allBones,"RightHandIndex2")); humanBones.Add(HumanBodyBones.RightMiddleProximal, TryGet(allBones,"RightHandMiddle1")); humanBones.Add(HumanBodyBones.RightMiddleIntermediate, TryGet(allBones,"RightHandMiddle2")); humanBones.Add(HumanBodyBones.RightRingProximal, TryGet(allBones,"RightHandRing1")); humanBones.Add(HumanBodyBones.RightRingIntermediate, TryGet(allBones,"RightHandRing2")); humanBones.Add(HumanBodyBones.RightLittleProximal, TryGet(allBones,"RightHandPinky1")); humanBones.Add(HumanBodyBones.RightLittleIntermediate, TryGet(allBones,"RightHandPinky2")); humanBones.Add(HumanBodyBones.RightThumbProximal, TryGet(allBones,"RightHandThumb1")); humanBones.Add(HumanBodyBones.RightThumbIntermediate, TryGet(allBones,"RightHandThumb2")); humanBones.Add(HumanBodyBones.LeftShoulder, TryGet(allBones,"LeftShoulder")); humanBones.Add(HumanBodyBones.LeftUpperArm, TryGet(allBones,"LeftArm")); humanBones.Add(HumanBodyBones.LeftLowerArm, TryGet(allBones,"LeftForeArm")); humanBones.Add(HumanBodyBones.LeftHand, TryGet(allBones,"LeftHand")); humanBones.Add(HumanBodyBones.LeftIndexProximal, TryGet(allBones,"LeftHandIndex1")); humanBones.Add(HumanBodyBones.LeftIndexIntermediate, TryGet(allBones,"LeftHandIndex2")); humanBones.Add(HumanBodyBones.LeftMiddleProximal, TryGet(allBones,"LeftHandMiddle1")); humanBones.Add(HumanBodyBones.LeftMiddleIntermediate, TryGet(allBones,"LeftHandMiddle2")); humanBones.Add(HumanBodyBones.LeftRingProximal, TryGet(allBones,"LeftHandRing1")); humanBones.Add(HumanBodyBones.LeftRingIntermediate, TryGet(allBones,"LeftHandRing2")); humanBones.Add(HumanBodyBones.LeftLittleProximal, TryGet(allBones,"LeftHandPinky1")); humanBones.Add(HumanBodyBones.LeftLittleIntermediate, TryGet(allBones,"LeftHandPinky2")); humanBones.Add(HumanBodyBones.LeftThumbProximal, TryGet(allBones,"LeftHandThumb1")); humanBones.Add(HumanBodyBones.LeftThumbIntermediate, TryGet(allBones,"LeftHandThumb2")); foreach(var bone in humanBones) { if(bone.Value != null) { var tags = new List() { SerializableBone.BoneTags.Humanoid }; if (bone.Value.name.Contains("Left")) { tags.Add(SerializableBone.BoneTags.Left); } else if (bone.Value.name.Contains("Right")) { tags.Add(SerializableBone.BoneTags.Right); } if((bone.Key >= HumanBodyBones.LeftThumbProximal && bone.Key <= HumanBodyBones.LeftLittleDistal) || (bone.Key >= HumanBodyBones.RightThumbProximal && bone.Key <= HumanBodyBones.RightLittleDistal)) { tags.Add(SerializableBone.BoneTags.Finger); } UIHandle.CreateAsChild(bone.Value).Init(this, tags).WithLineRenderer(); } } foreach(var bone in allBones.Values.Except(humanBones.Values)) { var tags = new List(); if (bone.GetComponent() != null) { tags.Add(SerializableBone.BoneTags.Dynamic); } UIHandle.CreateAsChild(bone).Init(this, tags).WithLineRenderer(); } _humanBones = humanBones; Bones = allBones.Values.ToList(); } public T TryGet(Dictionary dict, string key) { if (dict.ContainsKey(key)) { return dict[key]; } return default(T); } public void CreateMorphPanel() { var morphRenderers = new Dictionary>(); foreach (var rend in gameObject.GetComponentsInChildren()) { if(rend.sharedMesh.blendShapeCount > 0) { morphRenderers.Add(rend, new List()); } } if (morphRenderers.Count == 0) { if(MorphPanel != null) { Destroy(MorphPanel.gameObject); MorphPanel = null; InstantiatedObjects.Remove(MorphPanel.gameObject); } return; } if(MorphPanel != null) { MorphPanel.Init(morphRenderers.Select(mr => mr.Key.sharedMesh.name).ToList()); } else { MorphPanel = MorphPanel.Create(morphRenderers.Select(mr => mr.Key.sharedMesh.name).ToList()); MorphPanel.name = $"Chr_{Data.Id} Morphs"; InstantiatedObjects.Add(MorphPanel.gameObject); DanMachiInterface.Instance.SelectedObjectToolbar.AttachToThis(MorphPanel.GetComponent()); } foreach (var rend in morphRenderers) { var mesh = rend.Key.sharedMesh; for(int i = 0; i < mesh.blendShapeCount; i++) { var panel = MorphPanel.CreateMorph(mesh.name, this, rend.Key, i, mesh.GetBlendShapeName(i).Replace("blendShape1.","")); var helper = panel.MorphHelper; if (morphRenderers.ContainsKey(rend.Key)) morphRenderers[rend.Key].Add(helper); else morphRenderers.Add(rend.Key, new List() { helper }); } } Morphs = morphRenderers; } public void CreateCharacterPanel() { if(CharacterPanel != null) { CharacterPanel.Init(this); } else { CharacterPanel = CharacterPanel.Create(this); CharacterPanel.name = $"Chr_{Data.Id} Settings"; InstantiatedObjects.Add(CharacterPanel.gameObject); DanMachiInterface.Instance.SelectedObjectToolbar.AttachToThis(CharacterPanel.GetComponent()); } } public override Vector3 GetCenter() { if (_humanBones.ContainsKey(HumanBodyBones.Hips)) { return _humanBones[HumanBodyBones.Hips].position; } return base.GetCenter(); } public Animator GetAnimator() { return _animator; } public override void PastePose(KeyframeData frame, PoseLoadOptions pasteParams) { PlayAnimation(""); if (pasteParams.Root) { transform.SetTransform(frame.Root); } var frameData = frame as DanMachiCharacterKeyframeData; if (frameData == null) return; foreach (var bone in frameData.Bones.Bones) { var targetBone = Bones.FirstOrDefault(b => b.name == bone.Name); if (targetBone == null) continue; bone.Transform.ApplyTo(targetBone.transform); } foreach(var morph in frameData.Morphs) { var renderer = Morphs.Keys.FirstOrDefault(k => k.name == morph.Key); if (renderer == null) continue; foreach(var value in morph.Value) { var helper = Morphs[renderer].FirstOrDefault(h => h.Name == value.Name); if (helper == null) continue; helper.Value = value.Value; helper.UpdateMorph(value.Strength); } } SetKeyframe(); } }