using KF3.Containers; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; public class KF3FriendContainer : KF3CharacterContainer { public bool EyesLocked = false; public float LookAtStrength; public Transform LeftEye, RightEye, SubWeapon, SubWeaponBone; public UIHandleEyes EyeTarget; public Quaternion LeftEyeRotation = Quaternion.identity, RightEyeRotation = Quaternion.identity; /// Original data public CharaModelReferencer Ears, EarsAlt, Tail, TailAlt; public CharaModelReferencer EarsAnimation, TailAnimation; /// Custom Animator public SimpleAnimation EarsSimpleAnimation, TailSimpleAnimation; public Dictionary HumanBones = new Dictionary(); private Dictionary BoneHandles = new Dictionary(); //private Dictionary HumanBonesInverse = new Dictionary(); public UIKF3MorphPanel MorphPanel; public UIKF3CharacterPanel CharacterPanel; private bool isFakeFriend = false; public static IEnumerator CreateAsync(string modelName, string animationSetName, bool fakeFriend = false, System.Action callback = null) { GameObject go = new GameObject(modelName); var container = go.AddComponent(); if (fakeFriend) container.DoNotSave = container.isFakeFriend = true; yield return container.BuildGeneral(modelName, animationSetName); if (!container.isFakeFriend) UIHandleFriend.CreateAsChild(container); container.LoadInProgress = false; callback?.Invoke(container); } protected override void Start() { if (isFakeFriend) return; LeftEyeRotation = LeftEye.localRotation; RightEyeRotation = RightEye.localRotation; base.Start(); } private void Update() { if (LoadInProgress || isFakeFriend) return; if (BodySimpleAnimation && BodySimpleAnimation.clip != null) //check if simple animation component has been set { SimpleAnimation.State currentClip = BodySimpleAnimation.GetStates().FirstOrDefault(state => state.clip == BodySimpleAnimation.clip); if (currentClip.normalizedTime == 1 && currentClip.speed > 0) //check if an animation is playing and if an animation was playing before { RewindAllAnimations(); } else if (currentClip.normalizedTime <= 0 && currentClip.speed < 0) //check if an animation is playing and if an animation was playing before { UnwindAllAnimations(); } } if ((LeftEye && RightEye && EyeTarget) && !EyesLocked) { Vector3 target = Vector3.Lerp(EyeTarget.transform.position, KF3ModelViewerMain.Instance.GetCamera().transform.position, LookAtStrength); LeftEye.LookAt(target, HumanBones[HumanBodyBones.Head].up); RightEye.LookAt(target, HumanBones[HumanBodyBones.Head].up); } } #region Setup public override void SetAnimationReferences() { if (BodyAnimation) { BodySimpleAnimation = Body.GetComponentInChildren(); if (Main.OverrideClip != null) { foreach (var anim in BodyAnimation.prefabAnimeList) { anim.clip = Main.OverrideClip; } } Body.refAnimationObj = BodyAnimation.gameObject; Body.JoinReferenceParam(); } else { Error.Log(Color.blue, "Body Animations Missing"); } if (Ears && EarsAnimation) { EarsSimpleAnimation = Ears.GetComponentInChildren(); Ears.transform.SetParent(Body.boneList.FirstOrDefault(b => b.name == "j_head")); Ears.transform.ResetTransform(); Ears.refAnimationObj = EarsAnimation.gameObject; Ears.JoinReferenceParam(); if (EarsAlt) { EarsAlt.transform.SetParent(Body.boneList.FirstOrDefault(b => b.name == "j_head")); EarsAlt.transform.ResetTransform(); EarsAlt.GetComponentInChildren().enabled = false; } } else { Error.Log(Color.blue, "Ears Missing"); } if (Tail && TailAnimation) { TailSimpleAnimation = Tail.GetComponentInChildren(); Tail.transform.SetParent(Body.boneList.FirstOrDefault(b => b.name == (string.IsNullOrEmpty(BodyAnimation.tailNodeName) ? "j_lowerbody" : BodyAnimation.tailNodeName))); Tail.transform.ResetTransform(); Tail.refAnimationObj = TailAnimation.gameObject; Tail.JoinReferenceParam(); if (TailAlt) { TailAlt.transform.SetParent(Body.boneList.FirstOrDefault(b => b.name == (string.IsNullOrEmpty(BodyAnimation.tailNodeName) ? "j_lowerbody" : BodyAnimation.tailNodeName))); TailAlt.transform.ResetTransform(); TailAlt.GetComponentInChildren().enabled = false; } } else { Error.Log(Color.blue, "Tail Missing"); } } public override void SetBones() { if (isFakeFriend) return; HumanBones = new Dictionary(); var extraBones = Body.boneList.Where(b => b.name.Contains("osg")); HumanBones.Add(HumanBodyBones.Spine, Body.transform.Find("root/pelvis")); HumanBones.Add(HumanBodyBones.Hips, Body.transform.Find("root/pelvis/j_lowerbody")); HumanBones.Add(HumanBodyBones.RightUpperLeg, Body.transform.Find("root/pelvis/j_lowerbody/j_thigh_r")); HumanBones.Add(HumanBodyBones.RightLowerLeg, Body.transform.Find("root/pelvis/j_lowerbody/j_thigh_r/j_leg_r")); HumanBones.Add(HumanBodyBones.RightFoot, Body.transform.Find("root/pelvis/j_lowerbody/j_thigh_r/j_leg_r/j_foot_r")); HumanBones.Add(HumanBodyBones.LeftUpperLeg, Body.transform.Find("root/pelvis/j_lowerbody/j_thigh_l")); HumanBones.Add(HumanBodyBones.LeftLowerLeg, Body.transform.Find("root/pelvis/j_lowerbody/j_thigh_l/j_leg_l")); HumanBones.Add(HumanBodyBones.LeftFoot, Body.transform.Find("root/pelvis/j_lowerbody/j_thigh_l/j_leg_l/j_foot_l")); HumanBones.Add(HumanBodyBones.Chest, Body.transform.Find("root/pelvis/j_upperbody")); HumanBones.Add(HumanBodyBones.UpperChest, Body.transform.Find("root/pelvis/j_upperbody/j_chest")); HumanBones.Add(HumanBodyBones.Neck, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_neck")); HumanBones.Add(HumanBodyBones.Head, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_neck/j_head")); HumanBones.Add(HumanBodyBones.RightShoulder, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r")); HumanBones.Add(HumanBodyBones.RightUpperArm, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r/j_arm_r")); HumanBones.Add(HumanBodyBones.RightLowerArm, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r/j_arm_r/j_forearm_r")); HumanBones.Add(HumanBodyBones.RightHand, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r/j_arm_r/j_forearm_r/j_wrist_r")); HumanBones.Add(HumanBodyBones.RightIndexProximal, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r/j_arm_r/j_forearm_r/j_wrist_r/j_index_a_r")); HumanBones.Add(HumanBodyBones.RightIndexIntermediate, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r/j_arm_r/j_forearm_r/j_wrist_r/j_index_a_r/j_index_b_r")); HumanBones.Add(HumanBodyBones.RightRingProximal, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r/j_arm_r/j_forearm_r/j_wrist_r/j_ring_a_r")); HumanBones.Add(HumanBodyBones.RightRingIntermediate, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r/j_arm_r/j_forearm_r/j_wrist_r/j_ring_a_r/j_ring_b_r")); HumanBones.Add(HumanBodyBones.RightThumbProximal, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r/j_arm_r/j_forearm_r/j_wrist_r/j_thumb_a_r")); HumanBones.Add(HumanBodyBones.RightThumbIntermediate, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_r/j_arm_r/j_forearm_r/j_wrist_r/j_thumb_a_r/j_thumb_b_r")); HumanBones.Add(HumanBodyBones.LeftShoulder, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l")); HumanBones.Add(HumanBodyBones.LeftUpperArm, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l/j_arm_l")); HumanBones.Add(HumanBodyBones.LeftLowerArm, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l/j_arm_l/j_forearm_l")); HumanBones.Add(HumanBodyBones.LeftHand, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l/j_arm_l/j_forearm_l/j_wrist_l")); HumanBones.Add(HumanBodyBones.LeftIndexProximal, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l/j_arm_l/j_forearm_l/j_wrist_l/j_index_a_l")); HumanBones.Add(HumanBodyBones.LeftIndexIntermediate, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l/j_arm_l/j_forearm_l/j_wrist_l/j_index_a_l/j_index_b_l")); HumanBones.Add(HumanBodyBones.LeftRingProximal, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l/j_arm_l/j_forearm_l/j_wrist_l/j_ring_a_l")); HumanBones.Add(HumanBodyBones.LeftRingIntermediate, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l/j_arm_l/j_forearm_l/j_wrist_l/j_ring_a_l/j_ring_b_l")); HumanBones.Add(HumanBodyBones.LeftThumbProximal, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l/j_arm_l/j_forearm_l/j_wrist_l/j_thumb_a_l")); HumanBones.Add(HumanBodyBones.LeftThumbIntermediate, Body.transform.Find("root/pelvis/j_upperbody/j_chest/j_shoulder_l/j_arm_l/j_forearm_l/j_wrist_l/j_thumb_a_l/j_thumb_b_l")); //HumanBonesInverse = HumanBones.Where(d=>d.Value != null).ToDictionary((i) => i.Value, (i) => i.Key); if (Tail) { extraBones = extraBones.Union(Tail.boneList.Where(b => b.name.Contains("osg"))); } if (TailAlt) { extraBones = extraBones.Union(TailAlt.boneList.Where(b => b.name.Contains("osg"))); } if (Ears) { extraBones = extraBones.Union(Ears.boneList.Where(b => b.name.Contains("osg"))); } if (EarsAlt) { extraBones = extraBones.Union(EarsAlt.boneList.Where(b => b.name.Contains("osg"))); } var allBones = HumanBones.Where(b => b.Value != null).Select(b => b.Value).Union(Body.transform.Find("root")?.GetComponentsInChildren().Where(t => t.name.Contains("weapon")).ToList()).Union(extraBones).Distinct(); foreach (var bone in allBones) { var tags = new List(); UIHandle handle; if (HumanBones.ContainsValue(bone)) tags.Add(SerializableBone.BoneTags.Humanoid); if (bone.name.EndsWith("_l")) tags.Add(SerializableBone.BoneTags.Left); else if (bone.name.EndsWith("_r")) tags.Add(SerializableBone.BoneTags.Right); if (extraBones.Contains(bone)) { if (bone.GetComponent() != null) { tags.Add(SerializableBone.BoneTags.Dynamic); handle = UIHandlePhysicsBone.CreateAsChild(this, bone, tags).SetColor(Color.cyan); } else { handle = UIHandleBone.CreateAsChild(this, bone, tags).SetColor(Color.cyan); } } else { handle = UIHandleBone.CreateAsChild(this, bone, tags); } if (bone == HumanBones[HumanBodyBones.Hips]) handle.SetOffset(bone.up * -0.02f); if (bone == HumanBones[HumanBodyBones.Chest]) handle.SetOffset(bone.up * -0.02f); BoneHandles.Add(bone, handle); } } public override void DoStuff() { if (isFakeFriend) return; UIKF3MorphSlider eyeBase = null; foreach (Renderer r in GetComponentsInChildren()) { foreach (Material mat in r.materials) { #if UNITY_ANDROID if(!mat.shader.name.EndsWith("V2")) mat.shader = Shader.Find(mat.shader.name + "V2"); #endif if (mat.shader.name == "PRD/Cheek") { Texture2D tex = mat.GetTexture("_BaseMap") as Texture2D; mat.shader = Shader.Find("Unlit/Transparent"); mat.mainTexture = tex; } } Renderers.Add(r); } var morphPanel = MorphPanel = UIKF3MorphPanel.Create(this); var charaPanel = CharacterPanel = UIKF3CharacterPanel.Create(this); InstantiatedObjects.Add(morphPanel.gameObject); InstantiatedObjects.Add(charaPanel.gameObject); foreach (Transform child in GetComponentsInChildren()) { switch (child.name) { case "md_eye_base": { UIKF3MorphSlider.CreateLookAt(this, morphPanel.EyesPanel); SkinnedMeshRenderer meshRenderer = child.GetComponent(); if (meshRenderer == null || meshRenderer.sharedMesh == null) break; for (int i = 0; i < meshRenderer.sharedMesh.blendShapeCount; i++) { UIKF3MorphSlider.CreateMorph(this, meshRenderer, i, "BS_eye.eye_", morphPanel.EyesPanel); } if (HumanBones.ContainsKey(HumanBodyBones.Head) && HumanBones[HumanBodyBones.Head] != null && !EyeTarget) { Transform head = HumanBones[HumanBodyBones.Head]; EyeTarget = UIHandleEyes.Create(this, head); } eyeBase = UIKF3MorphSlider.CreateEyeToggle(this, meshRenderer, morphPanel.EyesPanel, MorphPanel.EyesToggleGroup); break; } case "md_eye_special_a": case "md_eye_special_b": { SkinnedMeshRenderer meshRenderer = child.GetComponent(); var toggle = UIKF3MorphSlider.CreateEyeToggle(this, meshRenderer, morphPanel.EyesPanel, MorphPanel.EyesToggleGroup); break; } case "md_mouth_base": { SkinnedMeshRenderer meshRenderer = child.GetComponent(); if (meshRenderer == null || meshRenderer.sharedMesh == null) break; for (int i = 0; i < meshRenderer.sharedMesh.blendShapeCount; i++) { UIKF3MorphSlider.CreateMorph(this, meshRenderer, i, "BS_mouth.mouth_", morphPanel.MouthPanel); } break; } case "md_eye_l": LeftEye = child; break; case "md_eye_r": RightEye = child; break; case "md_brow_base": { SkinnedMeshRenderer meshRenderer = child.GetComponent(); if (meshRenderer == null || meshRenderer.sharedMesh == null) break; for (int i = 0; i < meshRenderer.sharedMesh.blendShapeCount; i++) { UIKF3MorphSlider.CreateMorph(this, meshRenderer, i, "BS_brow.brow_", morphPanel.EyebrowsPanel); } break; } case "md_subweapon": { SubWeapon = child; if (SubWeaponBone == null) break; SubWeapon.SetParent(SubWeaponBone); SubWeapon.SetPositionAndRotation(Vector3.zero, Quaternion.identity); break; } case "subweapon": { SubWeaponBone = child; if (SubWeapon == null) break; SubWeapon.SetParent(SubWeaponBone); SubWeapon.SetPositionAndRotation(Vector3.zero, Quaternion.identity); break; } } } if(eyeBase != null) { eyeBase.Toggle.isOn = true; } SetIK(HumanBodyBones.LeftUpperArm); SetIK(HumanBodyBones.RightUpperArm); SetIK(HumanBodyBones.LeftUpperLeg); SetIK(HumanBodyBones.RightUpperLeg); ToggleIK(true); } public void SetIK(HumanBodyBones bone) { var cTr = transform; UIHandleIK ikHandle = null; Color orange = new Color(1.0f, 0.64f, 0.0f); switch (bone) { case HumanBodyBones.LeftUpperArm: { if (HumanBones[HumanBodyBones.LeftHand] == null) return; InverseKinematics IK = gameObject.AddComponent(); IK.upperArm = HumanBones[HumanBodyBones.LeftUpperArm]; IK.forearm = HumanBones[HumanBodyBones.LeftLowerArm]; IK.hand = HumanBones[HumanBodyBones.LeftHand]; IK.elbow = UIHandleIK.CreateTransform("Elbow_L", transform, IK.forearm.position + -cTr.forward * 0.1f); UIHandleIK.CreateAsChild(this, IK.elbow, orange, IK.name, 0.75f); IK.target = UIHandleIK.CreateTransform("Hand_L", transform, IK.hand.position, IK.hand.eulerAngles); ikHandle = UIHandleIK.CreateAsChild(this, IK.target, Color.green, IK.name, 2f); ikHandle.HiddenHandles = new List { BoneHandles[IK.upperArm], BoneHandles[IK.forearm], BoneHandles[IK.hand], }; IK.uppperArm_OffsetRotation = new Vector3(0, 90, 0); IK.forearm_OffsetRotation = new Vector3(-90, 90, 0); IK.SpawnLines(Color.green); break; } case HumanBodyBones.RightUpperArm: { if (HumanBones[HumanBodyBones.RightHand] == null) return; InverseKinematics IK = gameObject.AddComponent(); IK.upperArm = HumanBones[HumanBodyBones.RightUpperArm]; IK.forearm = HumanBones[HumanBodyBones.RightLowerArm]; IK.hand = HumanBones[HumanBodyBones.RightHand]; IK.elbow = UIHandleIK.CreateTransform("Elbow_R", transform, IK.forearm.position + -cTr.forward * 0.1f); UIHandleIK.CreateAsChild(this, IK.elbow, orange, IK.name, 0.75f); IK.target = UIHandleIK.CreateTransform("Hand_R", transform, IK.hand.position, IK.hand.eulerAngles); ikHandle = UIHandleIK.CreateAsChild(this, IK.target, Color.blue, IK.name, 2f); ikHandle.HiddenHandles = new List { BoneHandles[IK.upperArm], BoneHandles[IK.forearm], BoneHandles[IK.hand], }; IK.uppperArm_OffsetRotation = new Vector3(0, 90, 0); IK.forearm_OffsetRotation = new Vector3(-90, 90, 0); IK.SpawnLines(Color.blue); break; } case HumanBodyBones.LeftUpperLeg: { if (HumanBones[HumanBodyBones.LeftFoot] == null) return; InverseKinematics IK = gameObject.AddComponent(); IK.upperArm = HumanBones[HumanBodyBones.LeftUpperLeg]; IK.forearm = HumanBones[HumanBodyBones.LeftLowerLeg]; IK.hand = HumanBones[HumanBodyBones.LeftFoot]; IK.elbow = UIHandleIK.CreateTransform("Knee_L", transform, IK.forearm.position + cTr.forward * 0.2f); UIHandleIK.CreateAsChild(this, IK.elbow, orange, IK.name, 0.75f); IK.target = UIHandleIK.CreateTransform("Foot_L", transform, IK.hand.position, IK.hand.eulerAngles + cTr.forward * 45); ikHandle = UIHandleIK.CreateAsChild(this, IK.target, Color.green, IK.name, 2f); ikHandle.HiddenHandles = new List { BoneHandles[IK.upperArm], BoneHandles[IK.forearm], BoneHandles[IK.hand], }; IK.uppperArm_OffsetRotation = new Vector3(0, 90, 0); IK.forearm_OffsetRotation = new Vector3(-90, 90, 0); IK.hand_OffsetRotation = new Vector3(0, 0, -45); IK.SpawnLines(Color.green); break; } case HumanBodyBones.RightUpperLeg: { if (HumanBones[HumanBodyBones.RightFoot] == null) return; InverseKinematics IK = gameObject.AddComponent(); IK.upperArm = HumanBones[HumanBodyBones.RightUpperLeg]; IK.forearm = HumanBones[HumanBodyBones.RightLowerLeg]; IK.hand = HumanBones[HumanBodyBones.RightFoot]; IK.elbow = UIHandleIK.CreateTransform("Knee_R", transform, IK.forearm.position + cTr.forward * 0.2f); UIHandleIK.CreateAsChild(this, IK.elbow, orange, IK.name, 0.75f); IK.target = UIHandleIK.CreateTransform("Foot_R", transform, IK.hand.position, IK.hand.eulerAngles + cTr.forward * 45); ikHandle = UIHandleIK.CreateAsChild(this, IK.target, Color.blue, IK.name, 2f); ikHandle.HiddenHandles = new List { BoneHandles[IK.upperArm], BoneHandles[IK.forearm], BoneHandles[IK.hand], }; IK.uppperArm_OffsetRotation = new Vector3(0, 90, 0); IK.forearm_OffsetRotation = new Vector3(-90, 90, 0); IK.hand_OffsetRotation = new Vector3(0, 0, -45); IK.SpawnLines(Color.blue); break; } } } #endregion #region Animation public void PlayEarsAnimation(string clipName) { PlayAnimation(EarsSimpleAnimation, clipName); } public void PlayTailAnimation(string clipName) { PlayAnimation(TailSimpleAnimation, clipName); } #endregion #region Control public void UpdateLookAtTarget(float value) { LookAtStrength = value; } public void UpdateMorph(SkinnedMeshRenderer meshRenderer, int id, float value, Slider slider = null) { meshRenderer.SetBlendShapeWeight(id, value); Morphs[meshRenderer].First(m => m.Name == meshRenderer.sharedMesh.GetBlendShapeName(id)).Strength = value; if (slider) slider.SetValueWithoutNotify(value); } #endregion #region Toggles public void ToggleIK(bool value) { foreach (var ik in GetComponents()) { ik.SoftEnabled = value; ik.linesVisible = value; } foreach (UIHandleIK ikHandle in Handles.Where(h=>h.GetType() == typeof(UIHandleIK))) { foreach(var handle in ikHandle.HiddenHandles) { handle.ForceDisplayOff(value); } } IKEnabled = value; } public override void ToggleBonesVisible(bool value) { base.ToggleBonesVisible(value); if (EyeTarget != null) { EyeTarget.ToggleActive(value); } } #endregion public override void Select() { MorphPanel.gameObject.SetActive(true); CharacterPanel.gameObject.SetActive(true); } public override void Deselect() { MorphPanel.gameObject.SetActive(false); CharacterPanel.gameObject.SetActive(false); } public override void PastePose(KeyframeData keyframe1, PoseLoadOptions pasteParams) { var keyframe = keyframe1 as CharacterKeyframeData; this.CurrentAnimation = keyframe.CurrentAnimation; if (keyframe.CurrentAnimation == "") { ToggleIK(keyframe.IKEnabled); this.PlayAnimation(this.BodySimpleAnimation, ""); } else { ToggleIK(false); int currentFrame = TimelineController.Instance.CurrentFrame; FrameContent startFrame = null; foreach (var frame in Frames) { if (frame.FrameNum <= currentFrame && (frame.ObjectData as CharacterKeyframeData).CurrentAnimation == keyframe.CurrentAnimation) { if (startFrame == null || frame.FrameNum > startFrame.FrameNum) { startFrame = frame; } } } float diff = currentFrame - startFrame.FrameNum; this.PlayAnimation(this.BodySimpleAnimation, keyframe.CurrentAnimation, diff * (TimelineController.Instance.FrameDelayMS/1000)); } var body = keyframe.Bones.FirstOrDefault(b => b.Name == "Body") ?? new BoneList(); var ears = keyframe.Bones.FirstOrDefault(b => b.Name == "Ears") ?? new BoneList(); var tail = keyframe.Bones.FirstOrDefault(b => b.Name == "Tail") ?? new BoneList(); var earsAlt = keyframe.Bones.FirstOrDefault(b => b.Name == "EarsAlt") ?? new BoneList(); var tailAlt = keyframe.Bones.FirstOrDefault(b => b.Name == "TailAlt") ?? new BoneList(); if (pasteParams.Root) { keyframe.Root.ApplyTo(transform); } if (pasteParams.Body) { foreach (var bone in this.Body.boneList) { if (pasteParams.Other || bone.GetComponent() == null) body.Bones.FirstOrDefault(b => b.Name == bone.name)?.Transform.ApplyTo(bone, pasteParams); } } if (pasteParams.Tail) { if (this.Tail != null) { foreach (var bone in this.Tail.boneList) { tail.Bones.FirstOrDefault(b => b.Name == bone.name)?.Transform.ApplyTo(bone, pasteParams); } } if (this.TailAlt != null) { foreach (var bone in this.TailAlt.boneList) { tailAlt.Bones.FirstOrDefault(b => b.Name == bone.name)?.Transform.ApplyTo(bone, pasteParams); } } } if (pasteParams.Ears) { if (this.Ears != null) { foreach (var bone in this.Ears.boneList) { ears.Bones.FirstOrDefault(b => b.Name == bone.name)?.Transform.ApplyTo(bone, pasteParams); } } if (this.EarsAlt != null && earsAlt != null) { foreach (var bone in this.EarsAlt.boneList) { earsAlt.Bones.FirstOrDefault(b => b.Name == bone.name)?.Transform.ApplyTo(bone, pasteParams); } } } foreach (var ik in GetComponentsInChildren()) { var bones1 = keyframe.Bones.FirstOrDefault(b => b.Name == "Extra"); if (bones1 != null) { bones1.Bones.FirstOrDefault(b => b.Name == ik.target.name)?.Transform.ApplyTo(ik.target); bones1.Bones.FirstOrDefault(b => b.Name == ik.elbow.name)?.Transform.ApplyTo(ik.elbow); } } if (pasteParams.Morphs) { //MorphPanel.PasteValues(keyframe.Renderers); foreach (var morph in keyframe.Morphs) { var rend = this.Morphs.Keys.FirstOrDefault(k => k.name == morph.ParentName); if (rend == null) continue; MorphHelper h = this.Morphs[rend].FirstOrDefault(m => m.Name == morph.Name); if (h != null) this.UpdateMorph(rend, rend.sharedMesh.GetBlendShapeIndex(morph.Name), morph.Strength, h.Slider); } } if (keyframe.Renderers != null) { foreach (var renderer in keyframe.Renderers) { var rend = this.Renderers.FirstOrDefault(r => KF3CharacterContainerSerializable.GetRendererName(this, r) == renderer.Name); if (rend != null) { rend.enabled = renderer.Value; } } } this.TogglePhysics(keyframe.PhysicsEnabled); this.EyesLocked = keyframe.EyesLocked; this.LeftEyeRotation = Quaternion.Euler(keyframe.LeftEyeRotation); this.RightEyeRotation = Quaternion.Euler(keyframe.RightEyeRotation); this.EyeTarget.transform.localPosition = keyframe.EyeTarget; this.LookAtStrength = keyframe.LookAtStrength; this.CharacterPanel.UpdateSelection(); } public override IEnumerator GetModel(string bodyIdLong, string costumeId) { KF3AssetLibrary lib = Main.Assets; List abList = lib.AssetBundles.Where(ab => ab.FileName.StartsWith($"ch_{bodyIdLong}_")).ToList(); KF3AssetBundle bundle; //load body bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{bodyIdLong}_{costumeId}.prefab"); yield return lib.LoadAsset(bundle, (ab) => { Body = spawnAndGetReferencer(ab); }); //load ears bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{bodyIdLong}_{costumeId}_ear.prefab"); if (bundle == null) { bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{bodyIdLong}_a_ear.prefab"); } yield return lib.LoadAsset(bundle, (ab) => { Ears = spawnAndGetReferencer(ab); }); bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{bodyIdLong}_z_ear.prefab"); yield return lib.LoadAsset(bundle, (ab) => { EarsAlt = spawnAndGetReferencer(ab); }); //load tail bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{bodyIdLong}_{costumeId}_tail.prefab"); if (bundle == null) { bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{bodyIdLong}_a_tail.prefab"); } yield return lib.LoadAsset(bundle, (ab) => { Tail = spawnAndGetReferencer(ab); }); bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{bodyIdLong}_z_tail.prefab"); yield return lib.LoadAsset(bundle, (ab) => { TailAlt = spawnAndGetReferencer(ab); }); } public override IEnumerator GetAnimations(string idLong) { KF3AssetLibrary lib = Main.Assets; KF3AssetBundle bundle; List abList = lib.AssetBundles.Where(ab => ab.FileName.StartsWith($"ch_{idLong}_")).ToList(); //load body motion bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{idLong}_a_mot.prefab"); yield return lib.LoadAsset(bundle, (ab) => { BodyAnimation = spawnAndGetReferencer(ab); }); //load ears motion bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{idLong}_a_ear_mot.prefab"); yield return lib.LoadAsset(bundle, (ab) => { EarsAnimation = spawnAndGetReferencer(ab); }); //load tail motion bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{idLong}_a_tail_mot.prefab"); yield return lib.LoadAsset(bundle, (ab) => { TailAnimation = spawnAndGetReferencer(ab); }); } }