using System.Collections.Generic; using UnityEngine; using System; using System.Linq; using cfg.GfgCfg; using ET; using FairyGUI; using ProtoBuf.Meta; namespace GFGGame { public enum DressUpOption { Auto, Add, Remove } //用于换装对象的数据存储和方法封装 public class DressUpObj { public event Action OnSuitPutOnComplete; // 内部状态控制 private bool _isPuttingOnSuit = false; private int _activeLayerOperationCount = 0; private int _completedLayerOperationCount = 0; private bool needYooAsseetDown = false; public void SetOnSuitPutOnCompleteCallback(Action callback) { _activeLayerOperationCount = 0; _completedLayerOperationCount = 0; OnSuitPutOnComplete += callback; } public void ResetOnSuitPutOnComplete() { _activeLayerOperationCount = 0; _completedLayerOperationCount = 0; OnSuitPutOnComplete = null; ; } public int bgId { get { return _dressUpData.bgId; } } public int suitId { get { return _dressUpData.suitId; } } public int actionId { get { return _dressUpData.actionId; } } public bool IsAction { get { return _dressUpData.actionId > 0; } } public List itemList { get { return _dressUpData.itemList.ToList(); } } private Action onUpdateAction; /// /// /// /// /// /// /// /// /// 是否重置装备数据 public void setSceneObj(GameObject sceneObj, bool needSetMask = false, bool showSceneType = true, GameObject roleObj = null, bool showBg = true, Action onUpdateAction = null) { if (_sceneObj != null && _sceneObj != sceneObj) { PrefabManager.Instance.Restore(_sceneObj); } _sceneObj = sceneObj; _needSetMask = needSetMask; _showSceneType = showSceneType; _showBg = showBg; _roleObj = roleObj; this.onUpdateAction = onUpdateAction; if (_dressUpData.IsNew) { PutOnDefaultDressUpData(_showBg); } else { var tempData = DressUpDataClone(); TakeOffAll(false); PutOnDressUpData(tempData); } Timers.inst.AddUpdate(OnUpdate); } public DressUpData DressUpDataClone() { return _dressUpData.Clone(); } public void Dispose() { _sceneObj = null; _dressUpData = null; Timers.inst.Remove(OnUpdate); foreach (var t in handlers) { t.Release(); } onUpdateAction = null; } private void ClearView() { Timers.inst.Remove(OnUpdate); foreach (var t in handlers) { t.Cancel(); t.Release(); } } //传入一个服装部件Id,判断是否有与此部件同类型服装已穿着 public bool CheckSameTypeIsOn(int itemId) { int subType = ItemUtilCS.GetItemSubType(itemId); for (int i = 0; i < _dressUpData.itemList.Count; i++) { int _subType = ItemUtilCS.GetItemSubType(_dressUpData.itemList[i]); if (subType == _subType) return true; } return false; } /// /// 仅判断换装部件是否已穿着 /// /// /// public bool CheckDressUpItemIsOn(int itemId) { if (itemId == _dressUpData.bgId) { return true; } return _dressUpData.itemList.Contains(itemId); } /// /// 仅判断套装是否穿上 /// /// /// public bool CheckSuitIsOn(int id) { SuitCfg suitCfg = CommonDataManager.Tables.TblSuitCfg.GetOrDefault(id); if (suitCfg == null) { return false; } List items = suitCfg.Parts; foreach (int itemId in items) { if (_dressUpData.actionId == id) { if (SuitCfgArray.Instance.CheckActionContainsItem(itemId, id)) { continue; } } bool isOn = CheckDressUpItemIsOn(itemId); if (!isOn) { return false; } } return true; } public void AddOrRemove(int itemId, bool checkDefault, DressUpOption dressUpOption = DressUpOption.Auto) { int subType = ItemUtilCS.GetItemSubType(itemId); if (subType == ConstDressUpItemType.BEI_JING) { if (!_showBg) { return; } _dressUpData.bgId = itemId; List handlers = DressUpUtil.AddItemAsync(_dressUpData.bgId, _sceneObj, _needSetMask, true, _roleObj); TryAddHandlers(handlers); } else { if (!CheckDressUpItemIsOn(itemId)) { if (dressUpOption != DressUpOption.Remove) { if (checkDefault) { TryCancelActionWhenPutOn(itemId); } CheckRemoveSameType(subType); Add(itemId); } } else { if (dressUpOption != DressUpOption.Add) { Remove(itemId); } } if (checkDefault) { checkDefaultItem(); } } } //脱掉所有换装,换成默认装(不处理背景) public void TakeOffAll(bool checkDefault = true) { if (_sceneObj == null) { return; } _dressUpData.suitId = 0; _dressUpData.actionId = 0; foreach (int itemID in itemList) { AddOrRemove(itemID, false, DressUpOption.Remove); } if (checkDefault) { checkDefaultItem(); } //RoleLevelCfg roleLevelCfg = RoleLevelCfgArray.Instance.GetCfg(GameGlobal.myNumericComponent.GetAsInt(NumericType.Lvl)); // FightDataManager.Instance.score = roleLevelCfg.baseScore; // foreach (int itemId in _dressUpData.itemList) // { // FightDataManager.Instance.score += ItemDataManager.GetItemAdditionScore(itemId, InstanceZonesDataManager.currentScoreType, InstanceZonesDataManager.currentFightTags); // } } //穿上或脱掉一个动作 public void PutOnOrTakeOffAction(int actionId) { if (_dressUpData.actionId == actionId) { CancelAction(); } else { PutOnAction(actionId); } } /// /// 尝试穿戴配置套装 /// /// 套装id /// 尝试穿上动作 /// 排除类型列表 /// 是否显示可选部件 /// 是否只显示主角拥有的部件 public void PutOnSuitCfg(int suitId, bool tryShowAction, int[] excludeType = null, bool showOptional = true, bool CheckOwn = true, bool isDress = false, Action action = null) { _isPuttingOnSuit = true; needYooAsseetDown = false; SuitCfg suitCfg = CommonDataManager.Tables.TblSuitCfg.GetOrDefault(suitId); if (suitCfg == null) { return; } bool oldIsAction = IsAction; _dressUpData.suitId = suitId; bool hasSuitActionRes = DressUpMenuSuitDataManager.CheckSuitHasActionRes(_dressUpData.suitId); _dressUpData.actionId = (hasSuitActionRes && tryShowAction) ? suitId : 0; //找到要穿的散件 List targetItemList = DressUpUtil.GetSuitItems(suitId, IsAction, excludeType, showOptional, CheckOwn, isDress); CompareAndAddItemList(oldIsAction, IsAction, targetItemList); checkDefaultItem(action); } /// /// 取消动作,默认直接脱下 /// /// 转换成站立动作 /// 转换成站立动作时排除一些类型不穿 public void CancelAction(bool changeToStand = false, int[] excludeType = null) { if (_dressUpData.actionId <= 0) { return; } var tempActionId = _dressUpData.actionId; _dressUpData.actionId = 0; //更新非场景类型部件形态 foreach (int itemId in itemList) { if (!DressUpMenuItemCfg1Array.Instance.CheckIsSceneType(itemId)) { //场景类型不受动作影响并且本来就有动画,对非场景类型处理 bool notInAction = SuitCfgArray.Instance.CheckItemNotInAction(itemId); if (notInAction) { //更新成图片模式 Update(itemId); } } } if (changeToStand) { SuitCfg suitCfg = CommonDataManager.Tables.TblSuitCfg.GetOrDefault(tempActionId); List items = new List(suitCfg.Parts); if (suitCfg.PartsOptional != null && suitCfg.PartsOptional.Count > 0) { items.AddRange(suitCfg.PartsOptional); } foreach (int itemId in items) { if (DressUpMenuItemDataManager.CheckHasItem(itemId)) { bool notInAction = SuitCfgArray.Instance.CheckItemNotInAction(itemId); if (!notInAction) { int subType = ItemDataManager.GetItemSubType(itemId); if (excludeType == null || Array.IndexOf(excludeType, subType) < 0) { AddOrRemove(itemId, false, DressUpOption.Add); } } } } } checkDefaultItem(); } //穿戴一组换装数据 public void PutOnDressUpData(DressUpData targetDressUpData, int[] excludeType = null) { bool oldIsAction = IsAction; _dressUpData.suitId = targetDressUpData.suitId; _dressUpData.actionId = targetDressUpData.actionId; var targetItemList = new List(); foreach (var itemId in targetDressUpData.itemList) { int subType = ItemUtilCS.GetItemSubType(itemId); if (excludeType == null || Array.IndexOf(excludeType, subType) < 0) { targetItemList.Add(itemId); } } if (targetDressUpData.bgId > 0 && (excludeType == null || Array.IndexOf(excludeType, ConstDressUpItemType.BEI_JING) < 0)) { targetItemList.Add(targetDressUpData.bgId); } CompareAndAddItemList(oldIsAction, IsAction, targetItemList); checkDefaultItem(); } //穿戴默认换装数据 public void PutOnDefaultDressUpData(bool bgType = false) { var dressUpData = DressUpData.CreateDefault(); if (bgType) { dressUpData.bgId = 180002; } PutOnDressUpData(dressUpData); } //穿戴一组散件数据(会脱掉不包含的部分) public void PutOnItemList(List targetItemList) { bool oldIsAction = IsAction; _dressUpData.suitId = 0; _dressUpData.actionId = 0; CompareAndAddItemList(oldIsAction, IsAction, targetItemList); checkDefaultItem(); } #region private private GameObject _sceneObj; private GameObject _roleObj; private bool _needSetMask; private bool _showSceneType = true; private bool _showBg = true; private DressUpData _dressUpData = new DressUpData(); private List handlers = new List(); //穿上一个动作 private void PutOnAction(int actionId) { bool hasSuitActionRes = DressUpMenuSuitDataManager.CheckSuitHasActionRes(actionId); _dressUpData.actionId = actionId; if (hasSuitActionRes) { foreach (int itemId in itemList) { if (!DressUpMenuItemCfg1Array.Instance.CheckIsSceneType(itemId)) { //场景类型不受动作影响并且本来就有动画,对非场景类型处理 bool notInAction = SuitCfgArray.Instance.CheckItemNotInAction(itemId); if (notInAction) { //更新成动画模式 Update(itemId); } else { AddOrRemove(itemId, false, DressUpOption.Remove); } } } } else { CancelAction(true); } checkDefaultItem(); } //当穿一件部件时检查是否需要取消动作,如果需要则取消该动作 private void TryCancelActionWhenPutOn(int itemId) { if (_dressUpData.actionId > 0) { bool replaceableByAction = SuitCfgArray.Instance.CheckItemReaplaceableOnAction(itemId, _dressUpData.actionId); if (!replaceableByAction) { CancelAction(); _dressUpData.actionId = 0; } } } private void Add(int itemId) { if (!_showSceneType) { if (DressUpMenuItemCfg1Array.Instance.CheckIsSceneType(itemId)) { return; } } if (!_dressUpData.itemList.Contains(itemId)) { _dressUpData.itemList.Add(itemId); Update(itemId); if (actionId != 0) { ItemCfg itemCfg = CommonDataManager.Tables.TblItemCfg.GetOrDefault(itemId); Transform effGameobj = _sceneObj.transform.Find(string.Format("Role/Body_eff/{0}", itemCfg.Res)); if (effGameobj != null) { if (effGameobj.gameObject != null) { effGameobj.gameObject.SetActive(true); } } } } } public void Update(int itemId) { bool showAni = IsAction || DressUpMenuItemCfg1Array.Instance.CheckIsSceneType(itemId); var handlers = DressUpUtil.AddItemAsync(itemId, _sceneObj, _needSetMask, showAni, _roleObj); TryAddHandlers(handlers); } private void Remove(int itemId) { if (_dressUpData.itemList == null) { return; } if (_dressUpData.itemList.Contains(itemId)) { _dressUpData.itemList.Remove(itemId); var handler = DressUpUtil.RemoveItemAsync(itemId, _sceneObj, _roleObj); TryAddHandler(handler); if (actionId != 0) { ItemCfg itemCfg = CommonDataManager.Tables.TblItemCfg.GetOrDefault(itemId); Transform effGameobj = _sceneObj.transform.Find(string.Format("Role/Body_eff/{0}", itemCfg.Res)); if (effGameobj != null) { if (effGameobj.gameObject != null) { effGameobj.gameObject.SetActive(false); } } } } } private void CheckRemoveSameType(int subType) { ItemTypeCfg itemTypeCfg = CommonDataManager.Tables.TblItemTypeCfg.GetOrDefault(subType); int count = 0; int firstTeshuId = 0; int maxNum = 1; if (itemTypeCfg != null && itemTypeCfg.MaxNum > 0) { maxNum = itemTypeCfg.MaxNum; } else if (subType > ConstDressUpItemType.TE_SHU) { maxNum = 3; } for (int i = 0; i < _dressUpData.itemList.Count; i++) { int itemID = (int)_dressUpData.itemList[i]; int itemSubType = ItemUtilCS.GetItemSubType(itemID); bool isSameType = false; if (itemTypeCfg != null && itemTypeCfg.MaxNum > 0) { if (itemSubType == subType) { isSameType = true; } } else if (subType > ConstDressUpItemType.TE_SHU && itemSubType > ConstDressUpItemType.TE_SHU) { isSameType = true; } else if (itemSubType == subType || (subType == ConstDressUpItemType.LIAN_YI_QUN && (itemSubType == ConstDressUpItemType.SHANG_YI || itemSubType == ConstDressUpItemType.XIA_ZHUANG || itemSubType == ConstDressUpItemType.NEI_DA)) || (subType == ConstDressUpItemType.SHANG_YI && itemSubType == ConstDressUpItemType.LIAN_YI_QUN) || (subType == ConstDressUpItemType.XIA_ZHUANG && itemSubType == ConstDressUpItemType.LIAN_YI_QUN) || (subType == ConstDressUpItemType.NEI_DA && itemSubType == ConstDressUpItemType.LIAN_YI_QUN)) { Remove(itemID); i--; } if (isSameType) { if (count == 0) { firstTeshuId = itemID; } count++; } } if (count >= maxNum) { //超出允许的件数会顶掉第一件 Remove(firstTeshuId); } } //与身上的散件对比差异然后添加 private void CompareAndAddItemList(bool oldIsAction, bool newIsAction, List targetItemList) { bool actionStatusChanged = (oldIsAction && !newIsAction) || (!oldIsAction && newIsAction); foreach (int itemID in itemList) { if (!targetItemList.Contains(itemID)) { //移除不穿的部件 AddOrRemove(itemID, false, DressUpOption.Remove); } else if (actionStatusChanged) { //当动画形态切换时 if (!DressUpMenuItemCfg1Array.Instance.CheckIsSceneType(itemID)) { //非场景类型重穿 Update(itemID); targetItemList.Remove(itemID); } } } foreach (int itemID in targetItemList) { AddOrRemove(itemID, false, DressUpOption.Add); } } //检测当前穿戴是否是一件完整套装,且只穿了一件套装,返回套装id private int CheckCurDressIsSuit() { var suitId = 0; var suitIdList = new List(); for (int i = 0; i < _dressUpData.itemList.Count; i++) { int itemSuitId = SuitCfgArray.Instance.GetSuitIdOfItem(_dressUpData.itemList[i]); if (!suitIdList.Contains(itemSuitId)) { suitIdList.Add(itemSuitId); } } foreach (var itemSuitId in suitIdList) { if (CheckSuitIsOn(itemSuitId)) { suitId = itemSuitId; break; } } _dressUpData.suitId = suitId; return _dressUpData.suitId; } private void checkDefaultItem(Action action = null) { //是否有头发 bool hasFaXing = false; //检查默认资源 //是否有连衣裙 int itemIdLianYiQun = 0; //是否有内搭 bool hasNeiDa = false; //是否有上衣 bool hasShangYi = false; //是否有下装 bool hasXiaZhuang = false; //是否有默认内搭 bool hasNeiDaDefault = false; //是否有默认下装 bool hasXiaZhuangDefault = false; //是否有妆容 bool hasZhuangRong = false; for (int i = 0; i < _dressUpData.itemList.Count; i++) { int itemID = (int)_dressUpData.itemList[i]; int subType = ItemUtilCS.GetItemSubType(itemID); if (subType == (int)ConstDressUpItemType.FA_XING) { hasFaXing = true; } else if (subType == ConstDressUpItemType.LIAN_YI_QUN) { itemIdLianYiQun = itemID; } else if (subType == ConstDressUpItemType.NEI_DA) { hasNeiDa = true; } else if (subType == ConstDressUpItemType.XIA_ZHUANG) { hasXiaZhuang = true; } else if (subType == ConstDressUpItemType.SHANG_YI) { hasShangYi = true; } else if (subType == ConstDressUpItemType.ZHUANG_RONG) { hasZhuangRong = true; } if (itemID == ConstItemID.DEFULT_NEI_DA) { hasNeiDaDefault = true; } else if (itemID == ConstItemID.DEFULT_XIA_ZHUANG) { hasXiaZhuangDefault = true; } } if (!hasFaXing) { Add(ConstItemID.DEFULT_FA_XING); } if (!IsAction) { if (itemIdLianYiQun <= 0) { if (!hasShangYi && (!hasNeiDa || hasNeiDaDefault) && (!hasXiaZhuang || hasXiaZhuangDefault)) { Remove(ConstItemID.DEFULT_XIA_ZHUANG); Remove(ConstItemID.DEFULT_NEI_DA); Add(ConstItemID.DEFULT_LIAN_YI_QUN); } //else //{ // if (!hasXiaZhuang) // { // Add(ConstItemID.DEFULT_XIA_ZHUANG); // } // if (!hasNeiDa) // { // Add(ConstItemID.DEFULT_NEI_DA); // } //} } } CheckCurDressIsSuit(); UpdateBodyView(itemIdLianYiQun, action); var handler = DressUpUtil.UpdateHeadAsync(!hasZhuangRong, _sceneObj, _needSetMask, _roleObj); //handler.Completed += (aob) => { UpdateBodyView(itemIdLianYiQun, action); }; TryAddHandler(handler); //if (action == null) //{ // UpdateBodyView(itemIdLianYiQun); //} //else //{ // //handler.Completed += (aob) => { UpdateBodyView(itemIdLianYiQun, action); }; // UpdateBodyView(itemIdLianYiQun, action); //} } //更新整个身体 private void UpdateBodyView(int itemIdLianYiQun, Action action = null) { string actionRes = null; if (IsAction) { SuitCfg suitCfg = CommonDataManager.Tables.TblSuitCfg.GetOrDefault(_dressUpData.actionId); var hasAniRes = ResPathUtil.CheckDressUpAnimationResExist(suitCfg.AniRes); actionRes = hasAniRes ? suitCfg.AniRes : null; } var handler = DressUpUtil.UpdateBodyAsync(actionRes, _sceneObj, _needSetMask, _roleObj, itemIdLianYiQun); //handler.Completed += (aob) => { // action?.Invoke(needYooAsseetDown); //}; TryAddHandler(handler); } //遍历各部件操作器,检查状态并统一处理 private void OnUpdate(object param = null) { if (_sceneObj == null) { ClearView(); return; } if (handlers != null && handlers.Count > 0) { bool draw = true; needYooAsseetDown = true; foreach (var handler in handlers) { if (!handler.IsDone) { draw = false; } } if (draw) { var t = handlers.ToArray(); Debug.Log($"===draw:{handlers.Count}"); //_activeLayerOperationCount = handlers.Count; int w = 0; int q = 0; foreach (var handler in t) { if (handler.Status == YooAsset.EOperationStatus.Succeed) { if (handler is DressUpLayerOperation) { var duo = (DressUpLayerOperation)handler; Debug.Log($"{duo.actionType}, {duo.resPath}, {duo.effectResPath}"); handler.UpdateView(() => { _completedLayerOperationCount++; //_activeLayerOperationCount + 2 ,是因为update head和body没有_activeLayerOperationCount++???所以handlers.Count总是多两个 Debug.Log($"upLayer:{_completedLayerOperationCount}/{_activeLayerOperationCount + 2}"); if (_isPuttingOnSuit && _activeLayerOperationCount > 0 && _completedLayerOperationCount >= _activeLayerOperationCount + 2) { Debug.Log("进入uplayer的最终回调"); _isPuttingOnSuit = false; OnSuitPutOnComplete?.Invoke(); ResetOnSuitPutOnComplete(); } }); w++; } else if (handler is DressUpRemoveOperation) { var duo = (DressUpRemoveOperation)handler; Debug.Log(duo.itemID); //q++; handler.UpdateView(() => { //_completedLayerOperationCount++; //Debug.Log($"remove:{_completedLayerOperationCount}/{_activeLayerOperationCount}"); //if (_isPuttingOnSuit && // _activeLayerOperationCount > 0 && // _completedLayerOperationCount >= _activeLayerOperationCount) //{ // Debug.Log("进入remove的最终回调"); // _isPuttingOnSuit = false; // OnSuitPutOnComplete?.Invoke(); // ResetOnSuitPutOnComplete(); //} }); } else { Debug.Log("漏了"); } //handler.UpdateView(); // _completedLayerOperationCount++; } handler.Release(); } //Debug.Log($"WWWWWWW:{w}"); //Debug.Log($"WWWWWWW:{q}"); onUpdateAction?.Invoke(); handlers.Clear(); //LogUtil.LogEditor($"draw {TimeHelper.ClientNow()}"); } } //if (_isPuttingOnSuit && _activeLayerOperationCount > 0 && // _completedLayerOperationCount >= _activeLayerOperationCount) //{ // _isPuttingOnSuit = false; // OnSuitPutOnComplete?.Invoke(); //} } private void TryAddHandlers(List t) { if (t != null) { foreach (var h in t) { Debug.Log("_activeLayerOperationCount++"); _activeLayerOperationCount++; TryAddHandler(h); } //this.handlers.AddRange(t); } } private void TryAddHandler(DressUpOperationBase t) { if (t != null) { var len = handlers.Count; for (var i = len - 1; i >= 0; i--) { var h = handlers[i]; if (h.CheckRepeated(t)) { h.Cancel(); h.Release(); handlers.RemoveAt(i); } } this.handlers.Add(t); } } #endregion } }