747 lines
32 KiB
C#
747 lines
32 KiB
C#
|
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;
|
||
|
/// <summary> Original data </summary>
|
||
|
public CharaModelReferencer
|
||
|
Ears,
|
||
|
EarsAlt,
|
||
|
Tail,
|
||
|
TailAlt;
|
||
|
public CharaModelReferencer
|
||
|
EarsAnimation,
|
||
|
TailAnimation;
|
||
|
/// <summary> Custom Animator </summary>
|
||
|
public SimpleAnimation
|
||
|
EarsSimpleAnimation,
|
||
|
TailSimpleAnimation;
|
||
|
|
||
|
public Dictionary<HumanBodyBones, Transform> HumanBones = new Dictionary<HumanBodyBones, Transform>();
|
||
|
private Dictionary<Transform, UIHandle> BoneHandles = new Dictionary<Transform, UIHandle>();
|
||
|
//private Dictionary<Transform, HumanBodyBones> HumanBonesInverse = new Dictionary<Transform, HumanBodyBones>();
|
||
|
|
||
|
public UIKF3MorphPanel MorphPanel;
|
||
|
public UIKF3CharacterPanel CharacterPanel;
|
||
|
|
||
|
private bool isFakeFriend = false;
|
||
|
|
||
|
public static IEnumerator CreateAsync(string modelName, string animationSetName, bool fakeFriend = false, System.Action<KF3FriendContainer> callback = null)
|
||
|
{
|
||
|
GameObject go = new GameObject(modelName);
|
||
|
var container = go.AddComponent<KF3FriendContainer>();
|
||
|
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<SimpleAnimation>();
|
||
|
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<SimpleAnimation>();
|
||
|
|
||
|
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<Renderer>().enabled = false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Error.Log(Color.blue, "Ears Missing");
|
||
|
}
|
||
|
|
||
|
if (Tail && TailAnimation)
|
||
|
{
|
||
|
TailSimpleAnimation = Tail.GetComponentInChildren<SimpleAnimation>();
|
||
|
|
||
|
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<Renderer>().enabled = false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Error.Log(Color.blue, "Tail Missing");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void SetBones()
|
||
|
{
|
||
|
if (isFakeFriend) return;
|
||
|
|
||
|
HumanBones = new Dictionary<HumanBodyBones, Transform>();
|
||
|
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<Transform>().Where(t => t.name.Contains("weapon")).ToList()).Union(extraBones).Distinct();
|
||
|
|
||
|
foreach (var bone in allBones)
|
||
|
{
|
||
|
var tags = new List<SerializableBone.BoneTags>();
|
||
|
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<Osage>() != 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<Renderer>())
|
||
|
{
|
||
|
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<Transform>())
|
||
|
{
|
||
|
switch (child.name)
|
||
|
{
|
||
|
case "md_eye_base":
|
||
|
{
|
||
|
UIKF3MorphSlider.CreateLookAt(this, morphPanel.EyesPanel);
|
||
|
|
||
|
SkinnedMeshRenderer meshRenderer = child.GetComponent<SkinnedMeshRenderer>();
|
||
|
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<SkinnedMeshRenderer>();
|
||
|
var toggle = UIKF3MorphSlider.CreateEyeToggle(this, meshRenderer, morphPanel.EyesPanel, MorphPanel.EyesToggleGroup);
|
||
|
break;
|
||
|
}
|
||
|
case "md_mouth_base":
|
||
|
{
|
||
|
SkinnedMeshRenderer meshRenderer = child.GetComponent<SkinnedMeshRenderer>();
|
||
|
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<SkinnedMeshRenderer>();
|
||
|
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<InverseKinematics>();
|
||
|
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<UIHandle> {
|
||
|
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<InverseKinematics>();
|
||
|
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<UIHandle> {
|
||
|
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<InverseKinematics>();
|
||
|
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<UIHandle> {
|
||
|
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<InverseKinematics>();
|
||
|
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<UIHandle> {
|
||
|
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<InverseKinematics>())
|
||
|
{
|
||
|
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<Osage>() == 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<InverseKinematics>())
|
||
|
{
|
||
|
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<KF3AssetBundle> 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<KF3AssetBundle> 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);
|
||
|
});
|
||
|
}
|
||
|
}
|