using System.Collections; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif /// /// This script is to apply the appearance data and facial expressions to the character. /// namespace SoftKitty.MasterCharacterCreator { public class CharacterBoneControl : MonoBehaviour { [Header("Don't change this on the prefabs from package.")] public int DefaultSex = 0; [Header("AutoInittialize will inittialize this character with default appearance on start.")] public bool AutoInittialize = false; [Header("Ignore height setting and make all characters same height.")] public bool ForceHeightEven = false; [Header("Make the appearance sliders have wider range.")] public float SliderMutiplier = 0F; [Header("Make the character randomly blink.")] public bool AutoBlink = true; [Range(0F,100F)] public float EyeOpen = 100F; [Header("Disable this if you want other system to manage blend shapes, such as LipSync system.")] public bool ManageBlendShapes = true; #region ComponentsReference [Header("Components Reference")] public SkinnedMeshRenderer EyesRenderer; public SkinnedMeshRenderer EyeShadowsRenderer; public SkinnedMeshRenderer HeadRenderer; public SkinnedMeshRenderer TeethRenderer; public SkinnedMeshRenderer BodyRenderer; public SkinnedMeshRenderer PantsRenderer; public SkinnedMeshRenderer FeetRenderer; public SkinnedMeshRenderer HandsRenderer; public SkinnedMeshRenderer HelmetRenderer; public SkinnedMeshRenderer EyelashRenderer; public Transform [] Bones; #endregion #region variables [HideInInspector] public CharacterAppearance MyData; public Dictionary BoneDictionary = new Dictionary(); [HideInInspector] public Animation BackAnimation; [HideInInspector] public Animation TailAnimation; [HideInInspector] public Animation HeadAccAnimation; [HideInInspector] public float mHeight = 1F; [HideInInspector] public Transform LookAtTarget; [HideInInspector] public string EditorPath = ""; public Color RimColor { get => _rimColor; set { if (!Application.isPlaying) return; _rimColor = value; foreach (var obj in RendererMapping.Values) { if (obj != null) obj.material.SetColor("_OutlineRimColor", _rimColor); } } } private Color _rimColor; public Dictionary AccessoryObjs = new Dictionary(); public Dictionary AccessoryIDs = new Dictionary(); private Dictionary MyRenderer = new Dictionary(); private Dictionary RendererMapping = new Dictionary(); public bool Inited = false; public bool isInited { get { return Inited; } } private bool ShowHair = true; private bool ShowFace = true; private float BlinkValue = 0F; private int[] OldOutfitID; private int PhotoMode = 0; private float BlinkTimer =5F; private Uint8Color[] OldCusColor1; private Uint8Color[] OldCusColor2; private Uint8Color[] OldCusColor3; private Coroutine BlinkCo; private int OutfitSlotsCount; private KeyValuePair ActiveEmotion = new KeyValuePair(); #endregion #region internal methods private void Awake() { InternalInit(); } public void InternalInit() { MyRenderer.Clear(); ActiveEmotion = new KeyValuePair("null", 0F); RendererMapping.Clear(); RendererMapping.Add(OutfitSlots.Armor, BodyRenderer); RendererMapping.Add(OutfitSlots.Helmet, HelmetRenderer); RendererMapping.Add(OutfitSlots.Gauntlet, HandsRenderer); RendererMapping.Add(OutfitSlots.Boot, FeetRenderer); RendererMapping.Add(OutfitSlots.Pants, PantsRenderer); BoneDictionary.Clear(); foreach (Transform trans in Bones) { if (trans.tag == "Bone") { BoneDictionary.Add(trans.name, trans); } } OutfitSlotsCount = System.Enum.GetValues(typeof(OutfitSlots)).Length; OldOutfitID = new int[OutfitSlotsCount]; for (int i = 0; i < OutfitSlotsCount; i++) { OldOutfitID[i] = 0; } OldCusColor1 = new Uint8Color[OutfitSlotsCount]; OldCusColor2 = new Uint8Color[OutfitSlotsCount]; OldCusColor3 = new Uint8Color[OutfitSlotsCount]; for (int i = 0; i < OutfitSlotsCount; i++) { OldCusColor1[i] = Uint8Color.Set(Color.white); OldCusColor2[i] = Uint8Color.Set(Color.white); OldCusColor3[i] = Uint8Color.Set(Color.white); } } private void UpdateRace() { if (CharacterDataSetting.instance == null) return; if (Application.isEditor && !Application.isPlaying) { HeadRenderer.sharedMaterials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleHeadColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleHeadColorTexture); HeadRenderer.sharedMaterials[0].SetTexture("_MaskMap3", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleHairTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleHairTexture); HeadRenderer.sharedMaterials[0].SetTexture("_BodyNormal", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleHeadNormalTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleHeadNormalTexture); BodyRenderer.sharedMaterials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleBodyColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleBodyColorTexture); BodyRenderer.sharedMaterials[0].SetTexture("_BodyNormal", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleBodyNormalTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleBodyNormalTexture); PantsRenderer.sharedMaterials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleBodyColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleBodyColorTexture); PantsRenderer.sharedMaterials[0].SetTexture("_BodyNormal", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleBodyNormalTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleBodyNormalTexture); HandsRenderer.sharedMaterials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleHandColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleHandColorTexture); FeetRenderer.sharedMaterials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleFeetColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleFeetColorTexture); } else { HeadRenderer.materials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleHeadColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleHeadColorTexture); HeadRenderer.materials[0].SetTexture("_MaskMap3", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleHairTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleHairTexture); HeadRenderer.materials[0].SetTexture("_BodyNormal", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleHeadNormalTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleHeadNormalTexture); BodyRenderer.materials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleBodyColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleBodyColorTexture); BodyRenderer.materials[0].SetTexture("_BodyNormal", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleBodyNormalTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleBodyNormalTexture); PantsRenderer.materials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleBodyColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleBodyColorTexture); PantsRenderer.materials[0].SetTexture("_BodyNormal", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleBodyNormalTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleBodyNormalTexture); HandsRenderer.materials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleHandColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleHandColorTexture); FeetRenderer.materials[0].SetTexture("_MainTex", MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].MaleFeetColorTexture : CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].FemaleFeetColorTexture); } for (int i = 0; i < CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].RaceMorph.Length; i++) { HeadRenderer.SetBlendShapeWeight(i + 13, CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].RaceMorph[i]); } for (int i = 0; i < CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].TeethMorph.Length; i++) { TeethRenderer.SetBlendShapeWeight(i + 1, CharacterDataSetting.instance.RaceSettings[MyData._CharacterData.Race].TeethMorph[i]); } } private void SetOutfitColor(OutfitSlots _slot) { OldCusColor1[(int)_slot] = MyData._CusColor1[(int)_slot]; OldCusColor2[(int)_slot] = MyData._CusColor2[(int)_slot]; OldCusColor3[(int)_slot] = MyData._CusColor3[(int)_slot]; if ((int)_slot >= 5) { if (AccessoryObjs.ContainsKey(_slot.ToString()+ "Type")) { foreach (Renderer obj in AccessoryObjs[_slot.ToString() + "Type"].GetComponentsInChildren(true)) { if (Application.isEditor && !Application.isPlaying ) { if (obj.sharedMaterial != null) { obj.sharedMaterial.SetColor("_Color1", Uint8Color.Get(MyData._CusColor1[(int)_slot])); obj.sharedMaterial.SetColor("_Color2", Uint8Color.Get(MyData._CusColor2[(int)_slot])); obj.sharedMaterial.SetColor("_Color3", Uint8Color.Get(MyData._CusColor3[(int)_slot])); } } else { if (obj.material != null) { obj.material.SetColor("_Color1", Uint8Color.Get(MyData._CusColor1[(int)_slot])); obj.material.SetColor("_Color2", Uint8Color.Get(MyData._CusColor2[(int)_slot])); obj.material.SetColor("_Color3", Uint8Color.Get(MyData._CusColor3[(int)_slot])); } } } } } else { if (RendererMapping.ContainsKey(_slot) && RendererMapping[_slot] != null) { if (Application.isEditor && !Application.isPlaying) { if (RendererMapping[_slot].sharedMaterial != null) { RendererMapping[_slot].sharedMaterial.SetColor("_Color1", Uint8Color.Get(MyData._CusColor1[(int)_slot])); RendererMapping[_slot].sharedMaterial.SetColor("_Color2", Uint8Color.Get(MyData._CusColor2[(int)_slot])); RendererMapping[_slot].sharedMaterial.SetColor("_Color3", Uint8Color.Get(MyData._CusColor3[(int)_slot])); } } else { if (RendererMapping[_slot].material != null) { RendererMapping[_slot].material.SetColor("_Color1", Uint8Color.Get(MyData._CusColor1[(int)_slot])); RendererMapping[_slot].material.SetColor("_Color2", Uint8Color.Get(MyData._CusColor2[(int)_slot])); RendererMapping[_slot].material.SetColor("_Color3", Uint8Color.Get(MyData._CusColor3[(int)_slot])); } } } } } private OutfitInfo GetOutfitSetting(OutfitSlots _slot, int _id, int _sex) { switch (_slot) { case OutfitSlots.Gauntlet: return _sex == 0 ? CharacterDataSetting.instance.MaleGloveSetting[_id] : CharacterDataSetting.instance.FemaleGloveSetting[_id]; case OutfitSlots.Boot: return _sex == 0 ? CharacterDataSetting.instance.MaleBootSetting[_id] : CharacterDataSetting.instance.FemaleBootSetting[_id]; case OutfitSlots.Helmet: return _sex == 0 ? CharacterDataSetting.instance.MaleHelmetSetting[_id] : CharacterDataSetting.instance.FemaleHelmetSetting[_id]; case OutfitSlots.Pants: return _sex == 0 ? CharacterDataSetting.instance.MalePantsSetting[_id] : CharacterDataSetting.instance.FemalePantsSetting[_id]; default: return _sex == 0 ? CharacterDataSetting.instance.MaleArmorSetting[_id] : CharacterDataSetting.instance.FemaleArmorSetting[_id]; } } private void Start() { if (AutoInittialize && !Inited) Initialize(new CharacterAppearance(CharacterData.Create((byte)DefaultSex))); } private void CheckHairVisibility() { if (AccessoryObjs.ContainsKey("HairType")) { AccessoryObjs["HairType"].SetActive(ShowHair); } if (AccessoryObjs.ContainsKey("BeardType")) { AccessoryObjs["BeardType"].SetActive(ShowHair); } } private void OnDestroy() { } private void LoadSkinnedMesh(SkinnedMeshRenderer _renderer, string _meshPath, string _matPath, string[] boneNames) { if (_meshPath.Length > 0 && _matPath.Length > 0) { _renderer.enabled = false; _renderer.sharedMesh = CharacterManager.LoadMesh(_meshPath); if (Application.isEditor && !Application.isPlaying) { if(CharacterManager.LoadMaterial(_matPath)!=null) _renderer.sharedMaterial = CharacterManager.LoadMaterial(_matPath); } else{ _renderer.material = CharacterManager.LoadMaterial(_matPath); } Transform[] bones = new Transform[boneNames.Length]; for (int i = 0; i < bones.Length; i++) { bones[i] = BoneDictionary[boneNames[i]]; } _renderer.bones = bones; _renderer.enabled = true; Bounds _bound = _renderer.localBounds; _bound.center = Vector3.zero; _bound.extents = new Vector3(0.8F, 1.8F, 0.8F); _renderer.localBounds = _bound; } else { _renderer.enabled = false; } } private void Update() { if (!Inited) return; CheckEmotions(); CheckOutfits(); CheckPhotoMode(); CheckLookAt(); } private void CheckLookAt() { if (LookAtTarget != null) { Vector3 _dirL = (LookAtTarget.position - BoneDictionary["LookAtL"].position).normalized; if (Vector3.Angle(_dirL, BoneDictionary["Bip001 Head"].up) < (DefaultSex==0?20F:12F)) { Quaternion _lookRotL = Quaternion.LookRotation( -_dirL, Vector3.up); if(DefaultSex==1) _lookRotL = Quaternion.LookRotation(_dirL, -Vector3.up); BoneDictionary["LookAtL"].rotation = Quaternion.RotateTowards(BoneDictionary["LookAtL"].rotation, _lookRotL, 300F * Time.deltaTime); } Vector3 _dirR = (LookAtTarget.position - BoneDictionary["LookAtR"].position).normalized; if (Vector3.Angle(_dirR, BoneDictionary["Bip001 Head"].up) < (DefaultSex == 0 ? 20F : 12F)) { Quaternion _lookRotR = Quaternion.LookRotation(-_dirR, Vector3.up); if (DefaultSex == 1) _lookRotR = Quaternion.LookRotation(_dirR, Vector3.up); BoneDictionary["LookAtR"].rotation = Quaternion.RotateTowards(BoneDictionary["LookAtR"].rotation, _lookRotR, 300F * Time.deltaTime); } } else { BoneDictionary["LookAtL"].localRotation = Quaternion.RotateTowards(BoneDictionary["LookAtL"].localRotation, Quaternion.identity, Time.deltaTime * 900F); BoneDictionary["LookAtR"].localRotation = Quaternion.RotateTowards(BoneDictionary["LookAtR"].localRotation, Quaternion.identity, Time.deltaTime * 900F); } } private void CheckPhotoMode() { if (HeadRenderer == null || !Application.isPlaying) return; if (PhotoMode != CharacterManager.PhotoMode) { PhotoMode = CharacterManager.PhotoMode; if (PhotoMode == 0) { UpdateMaterialData(); } else { HeadRenderer.materials[0].SetColor("_Color1", new Color(0F, 0F, 0F, 0F)); HeadRenderer.materials[0].SetColor("_Color2", new Color(0F, 0F, 0F, 0F)); HeadRenderer.materials[0].SetColor("_Color3", new Color(0F, 0F, 0F, 0F)); HeadRenderer.materials[1].SetColor("_BaseColor", new Color(0F, 0F, 0F, 0F)); } } } private void CheckOutfits() { for (int i = 0; i < OldOutfitID.Length; i++) { if (OldOutfitID[i] != MyData._OutfitID[i]) SwitchOutfit((OutfitSlots)i, MyData._OutfitID[i]); if (OldCusColor1[i] != MyData._CusColor1[i] || OldCusColor2[i] != MyData._CusColor2[i] || OldCusColor3[i] != MyData._CusColor3[i]) SetOutfitColor((OutfitSlots)i); } } private void CheckEmotions() { if (HeadRenderer != null) { if (HeadRenderer.enabled != ShowFace) HeadRenderer.enabled = ShowFace; if (TeethRenderer.enabled != ShowFace) TeethRenderer.enabled = ShowFace; if (EyesRenderer.enabled != ShowFace) EyesRenderer.enabled = ShowFace; if (EyeShadowsRenderer.enabled != ShowFace) EyeShadowsRenderer.enabled = ShowFace; if (ActiveEmotion.Key != "null") { ActiveEmotion = new KeyValuePair(ActiveEmotion.Key, Mathf.MoveTowards(ActiveEmotion.Value, 0F, Time.deltaTime)); if (ActiveEmotion.Value <= 0F) ActiveEmotion = new KeyValuePair("null",0F); } for (int i = 1; i <= 21; i++) { if ((ManageBlendShapes || i < 6 || i > 12) && (i<13 || i>18)) { HeadRenderer.SetBlendShapeWeight(i, Mathf.MoveTowards(HeadRenderer.GetBlendShapeWeight(i), CharacterManager.CharacterEmotions.ContainsKey(ActiveEmotion.Key) ? CharacterManager.CharacterEmotions[ActiveEmotion.Key].GetHeadMorph(i) : 0F, Time.deltaTime * 300F)); } } TeethRenderer.SetBlendShapeWeight(0, Mathf.MoveTowards(TeethRenderer.GetBlendShapeWeight(0), CharacterManager.CharacterEmotions.ContainsKey(ActiveEmotion.Key) ? CharacterManager.CharacterEmotions[ActiveEmotion.Key].GetTeethOpen() : 0F, Time.deltaTime * 300F)); float _eyeClose = Mathf.Clamp((CharacterManager.CharacterEmotions.ContainsKey(ActiveEmotion.Key) ? CharacterManager.CharacterEmotions[ActiveEmotion.Key].GetHeadMorph(0) : 0F)+ BlinkValue + (100F - EyeOpen), 0F, 100F); HeadRenderer.SetBlendShapeWeight(0, Mathf.MoveTowards(HeadRenderer.GetBlendShapeWeight(0), _eyeClose, Time.deltaTime * 200F)); if (EyelashRenderer) { EyelashRenderer.SetBlendShapeWeight(0, HeadRenderer.GetBlendShapeWeight(0)); EyelashRenderer.SetBlendShapeWeight(1, HeadRenderer.GetBlendShapeWeight(3)); EyelashRenderer.SetBlendShapeWeight(2, HeadRenderer.GetBlendShapeWeight(21)); } if (AutoBlink) { BlinkTimer = Mathf.MoveTowards(BlinkTimer, 0F, Time.deltaTime); if (BlinkTimer <= 0F) { BlinkTimer = Random.Range(5F, 10F); Blink(); } } } } private void LateUpdate() { BoneTransform(); } private void BoneTransform() { if (CharacterDataSetting.instance == null) return; foreach (CharacterBoneDeformSetting obj in MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.MaleBoneSettings : CharacterDataSetting.instance.FemaleBoneSettings) { if (BoneDictionary.ContainsKey(obj.BoneNmae)) { ApplyBoneData(BoneDictionary[obj.BoneNmae], obj); } else { BoneDictionary.Add(obj.BoneNmae, FindAllChild(transform, obj.BoneNmae)); ApplyBoneData(BoneDictionary[obj.BoneNmae], obj); } } mHeight = (ForceHeightEven ? 1F : ((MyData._CharacterData.Sex == 0 ? 0.7F : 0.8F) + MyData._CharacterData.DataFloat[81] * 0.004F)); transform.localScale = Vector3.one * mHeight; } IEnumerator DoBlink() { while (BlinkValue < 100F) { BlinkValue += Time.deltaTime * 500F; } yield return new WaitForSeconds(0.3F); while (BlinkValue >0F) { BlinkValue = Mathf.MoveTowards(BlinkValue, 0F, Time.deltaTime * 200F); } } private void LoadAccessories() { foreach (AccessoryInfo setting in MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.MaleAccessorySettings : CharacterDataSetting.instance.FemaleAccessorySettings) { int _id = (int)setting.Slot>9? MyData._OutfitID[(int)setting.Slot-5] : MyData._CharacterData.DataInt[(int)setting.Slot]; bool _load = false; if (AccessoryIDs.ContainsKey(setting.DisplayName)) { if (AccessoryIDs[setting.DisplayName] != _id) _load = true; } else { _load = true; } if (_load) { if (AccessoryObjs.ContainsKey(setting.DisplayName)) { if (AccessoryObjs[setting.DisplayName] != null) { if (AccessoryObjs[setting.DisplayName].name != setting.SkinnedRendererName) { DestroyImmediate(AccessoryObjs[setting.DisplayName]); } } AccessoryObjs.Remove(setting.DisplayName); } if (AccessoryIDs.ContainsKey(setting.DisplayName)) AccessoryIDs.Remove(setting.DisplayName); if (setting.SkinnedRendererName != "") { FindAllChild(transform, setting.SkinnedRendererName).GetComponent().enabled = false; } if (_id > 0 || !setting.ZeroForNull) { GameObject _newAccObj = Instantiate(CharacterManager.LoadObject(setting.PrefabPath + _id.ToString("00")), BoneDictionary[setting.RootBoneNames]); if (setting.Slot == CharacterDataSetting.CharacterTextureNames.Back) BackAnimation = _newAccObj.GetComponentInChildren(); else if (setting.Slot == CharacterDataSetting.CharacterTextureNames.Tail) TailAnimation = _newAccObj.GetComponentInChildren(); else if (setting.Slot == CharacterDataSetting.CharacterTextureNames.BeardID) HeadAccAnimation = _newAccObj.GetComponentInChildren(); #if UNITY_EDITOR foreach (var obj in _newAccObj.GetComponentsInChildren(true)) { CreateEditorMaterialCopy(obj); } #endif _newAccObj.transform.localPosition = Vector3.zero; _newAccObj.transform.localEulerAngles = Vector3.zero; _newAccObj.transform.localScale = Vector3.one; if (_newAccObj.tag == "Skinned" && _newAccObj.GetComponentInChildren()) { if (setting.SkinnedRendererName != "") { SkinnedMeshRenderer _proxyRenderer = FindAllChild(transform, setting.SkinnedRendererName).GetComponent(); SkinnedMeshRenderer _accRenderer = _newAccObj.GetComponentInChildren(); Transform[] _bones = new Transform[_accRenderer.bones.Length]; for (int i = 0; i < _bones.Length; i++) { _bones[i] = BoneDictionary[_accRenderer.bones[i].name]; } _proxyRenderer.sharedMesh = _accRenderer.sharedMesh; if (Application.isEditor && !Application.isPlaying) { _proxyRenderer.sharedMaterial = _accRenderer.sharedMaterial; } else { _proxyRenderer.material = _accRenderer.sharedMaterial; } _proxyRenderer.rootBone = BoneDictionary[_accRenderer.rootBone.name]; _proxyRenderer.bones = _bones; _proxyRenderer.enabled = true; _proxyRenderer.ResetBounds(); _newAccObj.transform.SetParent(_proxyRenderer.transform); _newAccObj.SetActive(false); _newAccObj = _proxyRenderer.gameObject; } else { SkinnedMeshRenderer _accRenderer = _newAccObj.GetComponentInChildren(); Transform[] _bones = new Transform[_accRenderer.bones.Length]; for (int i = 0; i < _bones.Length; i++) { if (BoneDictionary.ContainsKey(_accRenderer.bones[i].name)) { _bones[i] = BoneDictionary[_accRenderer.bones[i].name]; } else { _bones[i] = _accRenderer.bones[i]; if (BoneDictionary.ContainsKey(_accRenderer.bones[i].parent.name)) { Vector3 _localPos = _accRenderer.bones[i].localPosition; Quaternion _localRot= _accRenderer.bones[i].localRotation; Vector3 _localScale = _accRenderer.bones[i].localScale; _accRenderer.bones[i].SetParent(BoneDictionary[_accRenderer.bones[i].parent.name],false); _accRenderer.bones[i].localPosition= _localPos; _accRenderer.bones[i].localRotation= _localRot; _accRenderer.bones[i].localScale= _localScale; } } } _accRenderer.bones = _bones; if (BoneDictionary.ContainsKey(_accRenderer.rootBone.name)) _accRenderer.rootBone = BoneDictionary[_accRenderer.rootBone.name]; _newAccObj.transform.SetParent(transform); _newAccObj.transform.localPosition = Vector3.zero; _newAccObj.transform.localEulerAngles = Vector3.zero; _newAccObj.transform.localScale = Vector3.one; } } AccessoryObjs.Add(setting.DisplayName, _newAccObj); AccessoryIDs.Add(setting.DisplayName, _id); } } if (AccessoryObjs.ContainsKey(setting.DisplayName)) { foreach (Renderer obj in AccessoryObjs[setting.DisplayName].GetComponentsInChildren(true)) { if ((int)setting.Slot > 9) { if (Application.isEditor && !Application.isPlaying) { obj.sharedMaterial.SetColor("_Color1", Uint8Color.Get(MyData._CusColor1[(int)setting.Slot - 5])); obj.sharedMaterial.SetColor("_Color2", Uint8Color.Get(MyData._CusColor2[(int)setting.Slot - 5])); obj.sharedMaterial.SetColor("_Color3", Uint8Color.Get(MyData._CusColor3[(int)setting.Slot - 5])); } else { obj.material.SetColor("_Color1", Uint8Color.Get(MyData._CusColor1[(int)setting.Slot - 5])); obj.material.SetColor("_Color2", Uint8Color.Get(MyData._CusColor2[(int)setting.Slot - 5])); obj.material.SetColor("_Color3", Uint8Color.Get(MyData._CusColor3[(int)setting.Slot - 5])); } } else { if (Application.isEditor && !Application.isPlaying) { obj.sharedMaterial.SetColor(setting.MatSlotName, Uint8Color.Get(MyData._CharacterData.DataColor[(int)setting.ColorType])); } else { obj.material.SetColor(setting.MatSlotName, Uint8Color.Get(MyData._CharacterData.DataColor[(int)setting.ColorType])); } } } } } CheckHairVisibility(); } private void ApplyMaterialData(Renderer _renderer, CharacterMaterialSetting _data, int _id) { if (_renderer == null) return; Material _mat = (Application.isEditor && !Application.isPlaying) ? _renderer.sharedMaterials[_id] : _renderer.materials[_id]; if (_data.ColorType != CharacterDataSetting.CharacterColorNames.None) { _mat.SetColor(_data.SlotName, Uint8Color.Get(MyData._CharacterData.DataColor[(int)_data.ColorType])); } if (_data.TextureType != CharacterDataSetting.CharacterTextureNames.None) { _mat.SetTexture(_data.SlotName, CharacterManager.LoadTexture(_data.TextureBaseName + ((int)MyData._CharacterData.DataInt[(int)_data.TextureType]).ToString("00"))); } if (_data.FloatType != CharacterDataSetting.CharacterBoneSliderNames.None) { if (_data.TextureBaseName == "offsetx") { _mat.SetTextureOffset(_data.SlotName, new Vector2(GetBoneValue(_data.FloatType, 0F, _data.SliderMin, _data.SliderMax), _mat.GetTextureOffset(_data.SlotName).y)); } else if (_data.TextureBaseName == "offsety") { _mat.SetTextureOffset(_data.SlotName, new Vector2(_mat.GetTextureOffset(_data.SlotName).x, GetBoneValue(_data.FloatType, 0F, _data.SliderMin, _data.SliderMax))); } else if (_data.TextureBaseName == "tilingx") { _mat.SetTextureScale(_data.SlotName, new Vector2(GetBoneValue(_data.FloatType, 1F, _data.SliderMin, _data.SliderMax), _mat.GetTextureScale(_data.SlotName).y)); } else if (_data.TextureBaseName == "tilingy") { _mat.SetTextureScale(_data.SlotName, new Vector2(_mat.GetTextureScale(_data.SlotName).x, GetBoneValue(_data.FloatType, 1F, _data.SliderMin, _data.SliderMax))); } else { _mat.SetFloat(_data.SlotName, MyData._CharacterData.DataFloat[(int)_data.FloatType] * 0.01F); } } } private void ApplyBoneData(Transform _bone, CharacterBoneDeformSetting _data) { if (_data.SetPos && _data.PositionSliders.Length >= 3) { _bone.localPosition = new Vector3(GetBoneValue(_data.PositionSliders[0].SliderType, _data.OriPos.x, _data.PositionSliders[0].MinOffset, _data.PositionSliders[0].MaxOffset), GetBoneValue(_data.PositionSliders[1].SliderType, _data.OriPos.y, _data.PositionSliders[1].MinOffset, _data.PositionSliders[1].MaxOffset), GetBoneValue(_data.PositionSliders[2].SliderType, _data.OriPos.z, _data.PositionSliders[2].MinOffset, _data.PositionSliders[2].MaxOffset) ); } if (_data.SetRot && _data.RotationSliders.Length >= 3) { _bone.localEulerAngles = new Vector3(GetBoneValue(_data.RotationSliders[0].SliderType, _data.OriRot.x, _data.RotationSliders[0].MinOffset, _data.RotationSliders[0].MaxOffset), GetBoneValue(_data.RotationSliders[1].SliderType, _data.OriRot.y, _data.RotationSliders[1].MinOffset, _data.RotationSliders[1].MaxOffset), GetBoneValue(_data.RotationSliders[2].SliderType, _data.OriRot.z, _data.RotationSliders[2].MinOffset, _data.RotationSliders[2].MaxOffset) ); } if (_data.SetScale && _data.ScaleSliders.Length >= 3) { _bone.localScale = new Vector3(GetBoneValue(_data.ScaleSliders[0].SliderType, _data.OriScale.x, _data.ScaleSliders[0].MinOffset, _data.ScaleSliders[0].MaxOffset), GetBoneValue(_data.ScaleSliders[1].SliderType, _data.OriScale.y, _data.ScaleSliders[1].MinOffset, _data.ScaleSliders[1].MaxOffset), GetBoneValue(_data.ScaleSliders[2].SliderType, _data.OriScale.z, _data.ScaleSliders[2].MinOffset, _data.ScaleSliders[2].MaxOffset) ); } } private float GetBoneValue(CharacterDataSetting.CharacterBoneSliderNames _type, float _oriValue, float _min, float _max) { float _value = MyData._CharacterData.DataFloat[(int)_type] * 0.01F; if (_type != CharacterDataSetting.CharacterBoneSliderNames.None) { if (_value > 0.5F) { return Mathf.Lerp(_oriValue, _max + _max * SliderMutiplier, (_value - 0.5F) * 2F); } else if (_value < 0.5F) { return Mathf.Lerp(_oriValue, _min - _min * SliderMutiplier, (0.5F - _value) * 2F); } else { return _oriValue; } } else { return _oriValue; } } private Transform FindAllChild(Transform _mother, string _name) { Transform result = null; Transform[] allMyChild = _mother.GetComponentsInChildren(true); foreach (Transform obj in allMyChild) { if (obj.name == _name) { result = obj.transform; } } return result; } private void CheckIntersection() { if ( BodyRenderer.sharedMesh.blendShapeCount > 0) { BodyRenderer.SetBlendShapeWeight(0, GetOutfitSetting(OutfitSlots.Gauntlet, OldOutfitID[(int)OutfitSlots.Gauntlet], MyData._CharacterData.Sex).PossibleIntersect ? 100F : 0F); } if (PantsRenderer.sharedMesh.blendShapeCount > 0) { PantsRenderer.SetBlendShapeWeight(0, GetOutfitSetting(OutfitSlots.Boot, OldOutfitID[(int)OutfitSlots.Boot], MyData._CharacterData.Sex).PossibleIntersect ? 100F : 0F); } } public void UpdateBreastSize() { if (MyData._Sex == Sex.Female && BodyRenderer!=null && BodyRenderer.sharedMesh.blendShapeCount > 0 && GetOutfitSetting(OutfitSlots.Armor, OldOutfitID[(int)OutfitSlots.Armor], MyData._CharacterData.Sex).BreastMorphID>-1) { BodyRenderer.SetBlendShapeWeight(GetOutfitSetting(OutfitSlots.Armor, OldOutfitID[(int)OutfitSlots.Armor], MyData._CharacterData.Sex).BreastMorphID, MyData._CharacterData.DataFloat[87]); } } private void CheckOverride() { for (int i = 0; i < OutfitSlotsCount; i++) { OutfitInfo _info = GetOutfitSetting((OutfitSlots)i, OldOutfitID[i], MyData._CharacterData.Sex); if (_info.OverrideMask1) { if (RendererMapping[_info.OverrideSlot].material != null && GetOutfitSetting(_info.OverrideSlot, OldOutfitID[(int)_info.OverrideSlot], MyData._CharacterData.Sex).CanBeOverride) { if (Application.isEditor && !Application.isPlaying) { RendererMapping[_info.OverrideSlot].sharedMaterial.SetTexture("_MaskMap1", _info.OverrideMask1); RendererMapping[_info.OverrideSlot].sharedMaterial.SetColor("_Color1", Uint8Color.Get(OldCusColor1[i])); } else { RendererMapping[_info.OverrideSlot].material.SetTexture("_MaskMap1", _info.OverrideMask1); RendererMapping[_info.OverrideSlot].material.SetColor("_Color1", Uint8Color.Get(OldCusColor1[i])); } } } } } private void ClearOverride() { for (int i = 0; i < OutfitSlotsCount; i++) { OutfitInfo _info = GetOutfitSetting((OutfitSlots)i, OldOutfitID[i], MyData._CharacterData.Sex); if (_info.OverrideMask1) { if (RendererMapping[_info.OverrideSlot].material!=null && GetOutfitSetting(_info.OverrideSlot, OldOutfitID[(int)_info.OverrideSlot], MyData._CharacterData.Sex).CanBeOverride) { if (Application.isEditor && !Application.isPlaying) { RendererMapping[_info.OverrideSlot].sharedMaterial.SetTexture("_MaskMap1", null); RendererMapping[_info.OverrideSlot].sharedMaterial.SetColor("_Color1", new Color(0F, 0F, 0F)); } else { RendererMapping[_info.OverrideSlot].material.SetTexture("_MaskMap1", null); RendererMapping[_info.OverrideSlot].material.SetColor("_Color1", new Color(0F, 0F, 0F)); } } } } } #endregion /// /// Initialize this character with Appearance data. /// /// public void Initialize(CharacterAppearance _data) { MyData = _data; if (Application.isEditor && !Application.isPlaying) { #if UNITY_EDITOR AssetDatabase.Refresh(); InternalInit(); CheckOutfits(); CreateEditorMaterialCopy(HeadRenderer); CreateEditorMaterialCopy(EyesRenderer); UpdateMaterialData(); CheckOverride(); CheckIntersection(); UpdateBreastSize(); BoneTransform(); #endif } else { UpdateMaterialData(); } Inited = true; } /// /// Switch the outfit with slot type and mesh id. /// /// /// public void SwitchOutfit(OutfitSlots slot, int _id) { if (OldOutfitID[(int)slot] == _id) return; ClearOverride(); OldOutfitID[(int)slot] = _id; switch (slot) { case OutfitSlots.Armor: LoadSkinnedMesh(BodyRenderer,GetOutfitSetting(OutfitSlots.Armor,_id,MyData._CharacterData.Sex).MeshPath, GetOutfitSetting(OutfitSlots.Armor, _id, MyData._CharacterData.Sex).MaterialPath, GetOutfitSetting(OutfitSlots.Armor, _id, MyData._CharacterData.Sex).BoneNames); if (Application.isEditor && !Application.isPlaying) CreateEditorMaterialCopy(BodyRenderer); break; case OutfitSlots.Pants: LoadSkinnedMesh(PantsRenderer, GetOutfitSetting(OutfitSlots.Pants, _id, MyData._CharacterData.Sex).MeshPath, GetOutfitSetting(OutfitSlots.Pants, _id, MyData._CharacterData.Sex).MaterialPath, GetOutfitSetting(OutfitSlots.Pants, _id, MyData._CharacterData.Sex).BoneNames); if (Application.isEditor && !Application.isPlaying) CreateEditorMaterialCopy(PantsRenderer); break; case OutfitSlots.Boot: LoadSkinnedMesh(FeetRenderer, GetOutfitSetting(OutfitSlots.Boot, _id, MyData._CharacterData.Sex).MeshPath, GetOutfitSetting(OutfitSlots.Boot, _id, MyData._CharacterData.Sex).MaterialPath, GetOutfitSetting(OutfitSlots.Boot, _id, MyData._CharacterData.Sex).BoneNames); if (Application.isEditor && !Application.isPlaying) CreateEditorMaterialCopy(FeetRenderer); break; case OutfitSlots.Gauntlet: LoadSkinnedMesh(HandsRenderer, GetOutfitSetting(OutfitSlots.Gauntlet, _id, MyData._CharacterData.Sex).MeshPath, GetOutfitSetting(OutfitSlots.Gauntlet, _id, MyData._CharacterData.Sex).MaterialPath, GetOutfitSetting(OutfitSlots.Gauntlet, _id, MyData._CharacterData.Sex).BoneNames); if (Application.isEditor && !Application.isPlaying) CreateEditorMaterialCopy(HandsRenderer); break; case OutfitSlots.Helmet: LoadSkinnedMesh(HelmetRenderer, GetOutfitSetting(OutfitSlots.Helmet, _id, MyData._CharacterData.Sex).MeshPath, GetOutfitSetting(OutfitSlots.Helmet, _id, MyData._CharacterData.Sex).MaterialPath, GetOutfitSetting(OutfitSlots.Helmet, _id, MyData._CharacterData.Sex).BoneNames); if (Application.isEditor && !Application.isPlaying) CreateEditorMaterialCopy(HelmetRenderer); ShowHair = !GetOutfitSetting(OutfitSlots.Helmet, _id, MyData._CharacterData.Sex).HideHair; ShowFace = !GetOutfitSetting(OutfitSlots.Helmet, _id, MyData._CharacterData.Sex).HideFace; CheckHairVisibility(); break; } SetOutfitColor(slot); if (!Application.isEditor || Application.isPlaying) { UpdateMaterialData(); CheckOverride(); CheckIntersection(); UpdateBreastSize(); } } /// /// Force the character to blink at once. /// public void Blink() { if (BlinkCo != null) StopCoroutine(BlinkCo); BlinkCo = StartCoroutine(DoBlink()); } /// /// Set the emotion type and how long it lasts /// /// /// public void SetEmotion(string _uid, float _length) { ActiveEmotion = new KeyValuePair(_uid, _length); } /// /// Stop the current emotion and reset to the default emotion. /// public void StopEmotion() { ActiveEmotion = new KeyValuePair("null", 0F); } /// /// Update the materials, call this if you have changed the appearance data. /// public void UpdateMaterialData() { if (CharacterDataSetting.instance == null) return; foreach (CharacterMaterialSetting obj in MyData._CharacterData.Sex == 0 ? CharacterDataSetting.instance.MaleMaterialSettings : CharacterDataSetting.instance.FemaleMaterialSettings) { foreach (string _rendererName in obj.RendererName) { string[] _names = new string[1]; if (_rendererName.Contains("$")) { _names = _rendererName.Split('$'); } else { _names[0] = _rendererName; } int _id = 0; if (_names.Length > 1) _id = int.Parse(_names[1]); if (MyRenderer.ContainsKey(_names[0])) { ApplyMaterialData(MyRenderer[_names[0]], obj, _id); } else { MyRenderer.Add(_names[0], FindAllChild(transform, _names[0]).GetComponent()); ApplyMaterialData(MyRenderer[_names[0]], obj, _id); } } } LoadAccessories(); UpdateRace(); UpdateBreastSize(); } /// /// Create a copy of the materials of the specified renderer. /// /// public void CreateEditorMaterialCopy(Renderer _renderer) { #if UNITY_EDITOR if (!Application.isPlaying && _renderer!=null && _renderer.sharedMaterials.Length>0) { Material[] _mats = new Material[_renderer.sharedMaterials.Length]; if (!AssetDatabase.IsValidFolder(EditorPath + "/" + _renderer.name)) AssetDatabase.CreateFolder(EditorPath, _renderer.name); for (int i = 0; i < _renderer.sharedMaterials.Length; i++) { AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(_renderer.sharedMaterials[i]), EditorPath + "/" + _renderer.name + "/" + _renderer.sharedMaterials[i].name + ".mat"); _mats[i] = (Material)AssetDatabase.LoadAssetAtPath(EditorPath + "/" + _renderer.name + "/" + _renderer.sharedMaterials[i].name + ".mat", typeof(Material)); } _renderer.sharedMaterials = _mats; _renderer.sharedMaterial = _mats[0]; } #endif } } }