#unity/白日梦/代码缓存
using System;
using System.Collections.Generic;
using System.IO;
using JetBrains.Annotations;
using ResourcesModule.LMNA;
using UnityEditor;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;
namespace MThread.Common.ToolsModule.CardResourceArtImportToolModule
{
/// <summary>
/// 导入的文件路径相关
/// </summary>
public class FilePath
{
public List<string> MainPrefabPath;
public List<string> OtherPrefabPaths;
public List<string> OtherAnimPaths;
public string jsonPath;
}
/// <summary>
/// 道具卡配置类
/// </summary>
public class CardConfig
{
public string OriginIndex;
public string TargetIndex;
public string CardName;
public Dictionary<string, string> OldAndNewNameDic;
}
public class CardType
{
public string CardName; //所属道具卡名字
public string CardNumber; //所属道具卡编号
public string InOut; //所属道具卡局内外
public string OriginalName; //道具卡原名
public bool IsSkin; //是否是皮肤fbx
}
public class CardResourceArtToolEditor : OdinMenuEditorWindow
{
#region 逻辑常量
private const string m_FbxDirIng = "Assets/ResourcesRaw/CommonRegion/InGame/Skins/Cards/";
private const string m_PrefabDirIng = "Assets/BundleResources/CommonRegion/InGame/Skins/Cards/";
private const string m_JsonDirIng = "Assets/BundleResources/CommonRegion/InGame/CardJson/";
private const string m_FbxDirOut = "Assets/ResourcesRaw/CommonRegion/OutsideGame/Skins/Cards/";
private const string m_PrefabDirOut = "Assets/BundleResources/CommonRegion/OutsideGame/Skins/Cards/";
#endregion
#region 逻辑变量
private static List<string> InGameCardList = new List<string>(); //局内道具卡列表
private CardType currentCardType = new CardType(); //当前处理的道具卡数据类型
private FileInfo m_FbxFile; //FBX文件信息
private string numberResult = ""; //新编号 文本
private int currentNumberResult = 0; //新编号 数字
private string cardName = ""; //道具卡名字
private string FbxCardPath = ""; //道具卡路径(fbx)
private string AnimCardPath = ""; //道具卡路径(动画)
private string PrefabCardPath = ""; //道具卡路径(prefab)
private string IndexFullName = ""; //旧道具卡编号 全名
private string OldCardPrefabDirectory = ""; //旧道具卡 文件目录
private string NewCardPrefabDirectory = ""; //新道具卡 文件目录
private string NewPrefabPath = ""; //新prefab路径
private Dictionary<string, string> WriteJsonDic; //写入Json文件列表
public List<GameObject> tempGameObejct; //临时变量
#endregion
#region 道具卡合入界面
private static CardResourceArtToolEditor _CardResourceArtToolEditorUI;
public static CardResourceArtToolEditor GetCardResourceArtToolEditor
{
get
{
return _CardResourceArtToolEditorUI;
}
}
[MenuItem("GameObject/美术道具卡合入")]
private static void OpenWindow()
{
_CardResourceArtToolEditorUI = GetWindow<CardResourceArtToolEditor>();
_CardResourceArtToolEditorUI.position = GUIHelper.GetEditorWindowRect().AlignCenter(1000, 600);
InitData();
}
#endregion
#region 道具卡功能逻辑
/// <summary>
/// 判断节点是否为fbx模型 (之前没绑定的前提下)
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private bool JudgeFBX(string name)
{
string cardNumber = System.Text.RegularExpressions.Regex.Replace(name, @"[^0-9]+", "");
if (cardNumber == String.Empty)
{
return false;
}
string lowerName = name.ToLower();
if (!(lowerName.Contains("ing") || lowerName.Contains("low") || lowerName.Contains("lob") || lowerName.Contains("height")))
{
return false;
}
if (!lowerName.Contains("skin"))
{
return false;
}
return true;
}
/// <summary>
/// 通过道具卡名字获得道具卡类型
/// </summary>
/// <param name="cardType"></param>
/// <param name="cardName"></param>
private string[] GetCardType(ref CardType cardType,string cardName)
{
cardType.CardName = null;
cardType.CardNumber = null;
cardType.InOut = null;
cardType.OriginalName = null;
string[] nameList = cardName.Split('_');
string cardNumber = System.Text.RegularExpressions.Regex.Replace(cardName, @"[^0-9]+", "");
if (cardNumber != String.Empty)
{
cardType.CardNumber = cardNumber;
}
for (int i = 0; i < nameList.Length; i++)
{
if (InGameCardList.Contains(nameList[i]))
{
cardType.CardName = nameList[i];
break;
}
}
string lowerName = cardName.ToLower(); //名字小写处理
if (lowerName.Contains("ing") || lowerName.Contains("low"))
{
cardType.InOut = "ing";
}
else if (lowerName.Contains("lob") || lowerName.Contains("height"))
{
cardType.InOut = "lob";
}
cardType.IsSkin = lowerName.Contains("skin");
cardType.OriginalName = cardName;
return nameList;
}
/// <summary>
/// 根据道具卡类型和物品属性 获得对应的道具卡名字
/// </summary>
/// <param name="cardType"></param>
/// <param name="eAssetFunctionType"></param>
/// <returns></returns>
private string GetCardNameByCardType(CardType cardType, eAssetFunctionType eAssetFunctionType)
{
string cardName = String.Empty;
if (CheckCardTypeNotNull(cardType))
{
switch (eAssetFunctionType)
{
case eAssetFunctionType.Model:
if (cardType.IsSkin)
{
cardName = LMNAResMapUtil.AssembleAssetName(cardType.InOut+cardType.CardNumber+"_"+cardType.CardName+"_skin.FBX", eAssetFunctionType, eAssetLodLevel.None);
}
else
{
cardName = cardType.OriginalName;
}
break;
}
}
return cardName;
}
/// <summary>
/// 如果参照物是有OverController的 新物体也创建一个OverControlller
/// </summary>
/// <param name="trans"></param>
/// <param name="checkResource"></param>
/// <returns></returns>
private string CreateOverController(Transform trans,bool checkResource)
{
string newOverControllerPath = String.Empty;
if (!checkResource)
{
Animator originalAnimator = trans.GetComponent<Animator>();
if (originalAnimator != null)
{
AnimatorOverrideController overrideController = originalAnimator.runtimeAnimatorController as AnimatorOverrideController;
string rootPath = AssetDatabase.GetAssetPath(overrideController);
if (numberResult != IndexFullName && rootPath.Contains(IndexFullName)) //判断是前后不同编号的道具卡
{
newOverControllerPath = rootPath.Replace(IndexFullName, numberResult);
string filePathOnly = Path.GetDirectoryName(newOverControllerPath); //获得文件夹路径
if (!Directory.Exists(filePathOnly))
{
Directory.CreateDirectory(filePathOnly);
}
AnimatorOverrideController newOverrideController = new AnimatorOverrideController();
EditorUtility.CopySerialized(overrideController, newOverrideController);
AssetDatabase.CreateAsset(newOverrideController, newOverControllerPath);
AssetDatabase.Refresh();
}
else if (numberResult == IndexFullName && rootPath.Contains(IndexFullName)) //如果是同一编号的道具卡,说明是第二次创建,直接拿到资源路径就好
{
overrideController = originalAnimator.runtimeAnimatorController as AnimatorOverrideController;
newOverControllerPath = AssetDatabase.GetAssetPath(overrideController);
}
}
}
return newOverControllerPath;
}
/// <summary>
/// 检测是否存在动画(导入)
/// </summary>
/// <param name="fbxPath"></param>
/// <param name="filePath"></param>
/// <param name="checkResource"></param>
/// <param name="fbxName"></param>
private void CheckPushAnim(ref string fbxPath,ref FilePath filePath,bool checkResource,string fbxName)
{
string targetPath = String.Empty;
Object[] fbxSubAssets = AssetDatabase.LoadAllAssetRepresentationsAtPath(fbxPath);
if (fbxSubAssets.Length <= 0) //说明路径不对,需要修正路径到Animations路径
{
targetPath = AnimCardPath + fbxName;
fbxSubAssets = AssetDatabase.LoadAllAssetRepresentationsAtPath(targetPath);
}
foreach (Object subAsset in fbxSubAssets)
{
if (typeof(AnimationClip) == subAsset?.GetType())
{
targetPath = AnimCardPath + fbxName;
string[] splitAssetName = fbxName.Split(LMNAResMapUtil.ASSET_FULL_NAME_SPLITTER_ARRAY, StringSplitOptions.RemoveEmptyEntries);
if (splitAssetName.Length != 2)
{
return;
}
string logigPart = splitAssetName[1]; //逻辑名
string AnimName = LMNAResMapUtil.AssembleAssetName(logigPart.Replace(".FBX",".anim"),
eAssetFunctionType.AnimationClip, eAssetLodLevel.None);
if (!checkResource)
{
//移动对应的fbx文件
if (File.Exists(targetPath))
{
File.Delete(targetPath);
}
AssetDatabase.MoveAsset(fbxPath, targetPath);
AssetDatabase.Refresh();
//基于fbx文件创建Anim动画文件
AnimationClip originalAnimationClip = subAsset as AnimationClip;
AnimationClip targetAnimationClip = new AnimationClip();
EditorUtility.CopySerialized(originalAnimationClip, targetAnimationClip);
AssetDatabase.CreateAsset(targetAnimationClip,AnimCardPath+AnimName);
AssetDatabase.Refresh();
}
filePath.OtherAnimPaths.Add(AnimCardPath + AnimName);
fbxPath = targetPath;
break;
}
}
}
private bool CheckCardTypeNotNull(CardType cardType)
{
return cardType != null && cardType.CardName != null && cardType.CardNumber != null &&
cardType.InOut != null;
}
private bool CompareCardType(CardType source, CardType target)
{
if (CheckCardTypeNotNull(source) && CheckCardTypeNotNull(target))
{
return source.CardName == target.CardName && source.CardNumber == target.CardNumber &&
source.InOut == target.InOut;
}
else
{
return false;
}
}
/// <summary>
/// 初始化数据
/// </summary>
private static void InitData()
{
InGameCardList.Clear();
string[] InGameCards = Directory.GetDirectories(m_PrefabDirIng, "*.*", SearchOption.TopDirectoryOnly);
for (int i = 0; i < InGameCards.Length; i++)
{
string filePathOnly = Path.GetFileName(InGameCards[i]);
InGameCardList.Add(filePathOnly);
}
}
RightTabEditor GetCardData()
{
RightTabEditor RightTabEditorData = new RightTabEditor();
string defaultFolder = PlayerPrefs.GetString("CardFilesDefalutFolder", "");
string folder = EditorUtility.OpenFolderPanel("Select Versions Folder", defaultFolder, "");
if (string.IsNullOrEmpty(folder))
{
return RightTabEditorData;
}
PlayerPrefs.SetString("CardFilesDefalutFolder", folder);
DirectoryInfo direction = new DirectoryInfo(folder);
FileInfo[] fbxFiles = direction.GetFiles("*.fbx", SearchOption.AllDirectories);
if (fbxFiles.Length == 0)
{
// NamingChecker.PopupErrorMessage("未检测到有fbx导入!");
return RightTabEditorData;
}
RightTabEditorData.m_FbxFiles = fbxFiles;
return RightTabEditorData;
}
/// <summary>
/// 导入资源 检测资源是否已有
/// </summary>
/// <param name="fbxFiles"></param>
/// <param name="checkResource"></param>
/// <returns></returns>
public FilePath OnClickLoadButton(FileInfo[] fbxFiles,bool checkResource = false)
{
tempGameObejct = new List<GameObject>();
FilePath filePaths = new FilePath();
List<string> PrefabList = new List<string>(); //已处理预制体名称
for (int i = 0; i < fbxFiles.Length; i++)
{
if (filePaths.OtherPrefabPaths == null)
{
filePaths.OtherPrefabPaths = new List<string>();
}
if (filePaths.OtherAnimPaths == null)
{
filePaths.OtherAnimPaths = new List<string>();
}
m_FbxFile = fbxFiles[i];// 当前fbx文件
string[] nameList = GetCardType(ref currentCardType, m_FbxFile.Name);
WriteJsonDic = new Dictionary<string, string>();
// treeData.Add(fbxFiles[i].Name);
if (nameList.Length <= 1)
{
// EditorUtility.DisplayDialog("小提醒", $"{m_FbxFile.Name}模型文件命名不对哇,请确认一下", "好哒");
continue;
}
if (CheckCardTypeNotNull(currentCardType))
{
numberResult = currentCardType.CardNumber;
cardName = currentCardType.CardName;
if (currentCardType.InOut == "lob")
{
FbxCardPath = m_FbxDirOut + cardName + "/" + numberResult + "/Models/";
AnimCardPath = m_FbxDirOut + cardName + "/" + numberResult + "/Animations/";
PrefabCardPath = m_PrefabDirOut + cardName + "/";
}
else if (currentCardType.InOut == "ing")
{
FbxCardPath = m_FbxDirIng + cardName + "/" + numberResult + "/Models/";
AnimCardPath = m_FbxDirIng + cardName + "/" + numberResult + "/Animations/";
PrefabCardPath = m_PrefabDirIng + cardName + "/";
}
string fbxName = GetCardNameByCardType(currentCardType, eAssetFunctionType.Model);
string fbxPath = LoadFbxFile(fbxName,checkResource);
CheckPushAnim(ref fbxPath, ref filePaths, checkResource, fbxName);
if (fbxPath != String.Empty)
{
filePaths.OtherPrefabPaths.Add(fbxPath);
if (currentCardType.IsSkin)
{
filePaths = CheckCardResourceNameAndCreatePrefab(m_FbxFile.Name, fbxPath, PrefabList, filePaths,checkResource);
}
else
{
// filePaths.
}
}
}
}
if (!checkResource)
{
foreach (KeyValuePair<string,string> keyValuePair in WriteJsonDic)
{
File.WriteAllText(keyValuePair.Key, keyValuePair.Value);
}
AssetDatabase.Refresh();
WriteJsonDic.Clear();
}
for (int i = 0; i < tempGameObejct.Count; i++)
{
DestroyImmediate(tempGameObejct[i]);
}
tempGameObejct.Clear();
return filePaths;
}
/// <summary>
/// 检测道具卡名字是否合法,生成对应的prefab文件
/// </summary>
/// <param name="PrefabList"></param>
public FilePath CheckCardResourceNameAndCreatePrefab(string name,string fbxPath,List<string> PrefabList,FilePath filePaths,bool checkResource = false)
// public void CheckCardResourceNameAndCreatePrefab(RightTabEditor rightTabEditor)
{
if (fbxPath == String.Empty)
{
return filePaths;
}
if (!Directory.Exists(PrefabCardPath))
{
return filePaths;
}
if (!int.TryParse(numberResult,out currentNumberResult))
{
return filePaths;
}
int FileIndex = 0;
DirectoryInfo source = new DirectoryInfo(PrefabCardPath);
List<int> IndexList = new List<int>();
foreach (DirectoryInfo directoryInfo in source.GetDirectories())
{
if (int.TryParse(directoryInfo.Name,out FileIndex))
{
if (currentNumberResult != FileIndex) //把当前需要处理的编号排除在外
{
IndexList.Add(FileIndex);
}
else
{
if (directoryInfo.GetFiles().Length + directoryInfo.GetDirectories().Length > 0) //如果目录内文件非空,说明是重新导入同名fbx文件
{
IndexList.Clear();
IndexList.Add(FileIndex);
break;
}
}
}
}
if (IndexList.Count > 0)
{
IndexList.Sort();
IndexFullName = IndexList[IndexList.Count - 1].ToString().PadLeft(8, '0');
OldCardPrefabDirectory = PrefabCardPath + IndexFullName + "/";
string[] guids = AssetDatabase.FindAssets("t:Prefab", new string[] {OldCardPrefabDirectory});
CardConfig cardConfig = new CardConfig();
cardConfig.OriginIndex = IndexFullName;
cardConfig.TargetIndex = numberResult;
cardConfig.CardName = cardName;
cardConfig.OldAndNewNameDic = new Dictionary<string, string>();
NewCardPrefabDirectory = PrefabCardPath + numberResult + "/";
bool isFbx = false;
Dictionary<string,List<eAssetLodLevel>> otherEffectDic = new Dictionary<string, List<eAssetLodLevel>>();
for (int i = 0; i < guids.Length; i++)
{
string AssetName = AssetDatabase.GUIDToAssetPath(guids[i]);
if (!PrefabList.Contains(AssetName))
{
GameObject MyCardPrefab =
AssetDatabase.LoadAssetAtPath(AssetName, typeof(GameObject)) as GameObject;
Transform[] MyCardPrefabList = MyCardPrefab.GetComponentsInChildren<Transform>();
bool isPrefabFromFbx = false;
for (int j = 0; j < MyCardPrefabList.Length; j++)
{
isFbx = JudgeFBX(MyCardPrefabList[j].name);
if (PrefabUtility.IsPartOfPrefabInstance(MyCardPrefabList[j].gameObject) || isFbx)
{
if (isFbx && PrefabUtility.IsPartOfPrefabInstance(MyCardPrefabList[j].gameObject))
{
Object rootPrefab = PrefabUtility.GetCorrespondingObjectFromOriginalSource(MyCardPrefabList[j].gameObject);
string AssetPath = AssetDatabase.GetAssetPath(rootPrefab);
string Filetype = Path.GetExtension(AssetPath);
if (Filetype.ToLower() != ".fbx") //如果是fbx文件,才会走到下面的逻辑
{
continue;
}
}
string fbxNumber = System.Text.RegularExpressions.Regex.Replace(MyCardPrefabList[j].name, @"[^0-9]+", "");
// string newAssetPath = AssetPath.Replace(fbxNumber, numberResult);
CardType newCardType = new CardType();
GetCardType(ref newCardType, MyCardPrefabList[j].name.Replace(fbxNumber, numberResult));
if (!CompareCardType(currentCardType,newCardType))
{
continue;
// isPrefabFromFbx = true;
// break;
}
NewPrefabPath = PrefabCardPath + numberResult + "/";
if (!Directory.Exists(NewPrefabPath))
{
Directory.CreateDirectory(NewPrefabPath);
}
GameObject prefabInst = Instantiate(MyCardPrefab);
tempGameObejct.Add(prefabInst);
Transform[] prefabTransList = prefabInst.GetComponentsInChildren<Transform>();
List<GameObject> needDeleteGameObjects = new List<GameObject>();
for (int l = 0; l < prefabTransList.Length; l++)
{
if (prefabTransList[l].name == MyCardPrefabList[j].name)
{
GameObject ret = AssetDatabase.LoadAssetAtPath(fbxPath, typeof(GameObject)) as GameObject;
GameObject clone = PrefabUtility.InstantiatePrefab(ret) as GameObject;
if (clone != null)
{
string newOverControllerPath =
CreateOverController(prefabTransList[l], checkResource);
if (newOverControllerPath != string.Empty)
{
if (clone.GetComponent<Animator>() == null)
{
clone.AddComponent<Animator>();
}
Animator newAnimator = clone.GetComponent<Animator>();
newAnimator.runtimeAnimatorController =
AssetDatabase.LoadAssetAtPath<AnimatorOverrideController>(
newOverControllerPath);
}
clone.transform.parent = prefabTransList[l].parent;
needDeleteGameObjects.Add(prefabTransList[l].gameObject);
}
break;
}
}
string NewprefabName = MyCardPrefab.name.Replace(IndexFullName, numberResult);
string OldLogicName = MyCardPrefab.name.Split('&')[1];
string NewLogicName = NewprefabName.Split('&')[1];
AudioSource[] audioSources = prefabInst.GetComponentsInChildren<AudioSource>();
for (int m = 0; m < audioSources.Length; m++)
{
string num = System.Text.RegularExpressions.Regex.Replace(audioSources[m].clip.name, @"[^0-9]+", "");
if (num.Length > 0)
{
// EditorUtility.DisplayDialog("小提醒", $"{NewprefabName}音频不是用了通用资源,请确认一下", "好哒");
}
}
needDeleteGameObjects.ForEach(child => DestroyImmediate(child));
if (filePaths.MainPrefabPath == null)
{
filePaths.MainPrefabPath = new List<string>();
}
filePaths.MainPrefabPath.Add(NewPrefabPath + NewprefabName + ".prefab");
if (!checkResource)
{
RecoverMatrials(MyCardPrefab.transform, prefabInst.transform);
PrefabUtility.SaveAsPrefabAsset(prefabInst, NewPrefabPath + NewprefabName + ".prefab");
AssetDatabase.SaveAssets();
DestroyImmediate(prefabInst.gameObject);
AssetDatabase.Refresh();
}
if (!cardConfig.OldAndNewNameDic.ContainsKey(OldLogicName))
{
cardConfig.OldAndNewNameDic.Add(OldLogicName, NewLogicName);
}
PrefabList.Add(MyCardPrefab.name);
isPrefabFromFbx = true;
break;
}
}
if (isPrefabFromFbx == false)
{
CollectOtherPrefab(otherEffectDic, Path.GetFileName(AssetName));
PrefabList.Add(AssetName);
}
}
}
foreach (KeyValuePair<string,List<eAssetLodLevel>> pair in otherEffectDic)
{
eAssetLodLevel lodLv = eAssetLodLevel.None;
if (pair.Value.Count > 0)
{
pair.Value.Sort();
for (int i = 0; i < pair.Value.Count; i++)
{
lodLv = pair.Value[0];
break;
}
}
string oneOtherName =
LMNAResMapUtil.AssembleAssetName(pair.Key, eAssetFunctionType.GameObject, lodLv);
if (oneOtherName.Contains(IndexFullName))
{
// Debug.Log("path:" + OldCardPrefabDirectory + oneOtherName);
GameObject OldEffectPrefab =
AssetDatabase.LoadAssetAtPath(OldCardPrefabDirectory + oneOtherName, typeof(GameObject)) as GameObject;
string newOtherName = oneOtherName.Replace(IndexFullName, numberResult);
GameObject OldEffectPrefabInst = Instantiate(OldEffectPrefab);
tempGameObejct.Add(OldEffectPrefabInst);
filePaths = CollectionOtherEffectPrefab(OldCardPrefabDirectory + oneOtherName, IndexFullName,
numberResult,
OldEffectPrefabInst, filePaths,checkResource);
string newPrefabLogicName = pair.Key.Replace(IndexFullName, numberResult);
if (!Directory.Exists(NewCardPrefabDirectory))
{
Directory.CreateDirectory(NewCardPrefabDirectory);
}
AudioSource[] audioSources = OldEffectPrefabInst.GetComponentsInChildren<AudioSource>();
for (int j = 0; j < audioSources.Length; j++)
{
string num = System.Text.RegularExpressions.Regex.Replace(audioSources[j].clip.name, @"[^0-9]+", "");
if (num.Length > 0)
{
// EditorUtility.DisplayDialog("小提醒", $"{newPrefabLogicName}音频不是用了通用资源,请确认一下", "好哒");
}
}
filePaths.OtherPrefabPaths.Add(NewCardPrefabDirectory + newOtherName);
if (!checkResource)
{
PrefabUtility.SaveAsPrefabAsset(OldEffectPrefabInst, NewCardPrefabDirectory + newOtherName);
AssetDatabase.SaveAssets();
DestroyImmediate(OldEffectPrefabInst.gameObject);
AssetDatabase.Refresh();
}
if (!cardConfig.OldAndNewNameDic.ContainsKey(pair.Key))
{
cardConfig.OldAndNewNameDic.Add(pair.Key,newPrefabLogicName);
}
}
}
CreateJsonFile(cardConfig,WriteJsonDic,ref filePaths);
}
return filePaths;
}
/// <summary>
/// 把fbx文件复制到工程
/// </summary>
/// <returns></returns>
string LoadFbxFile(string fbxName,bool checkResource = false)
{
string m_FbxPath = String.Empty;
//fbx路径创建
if (!Directory.Exists(FbxCardPath))
{
Directory.CreateDirectory(FbxCardPath);
}
//动画路径创建
if (!Directory.Exists(AnimCardPath))
{
Directory.CreateDirectory(AnimCardPath);
}
if (fbxName == String.Empty)
{
return m_FbxPath;
}
m_FbxPath = FbxCardPath + fbxName;
if (!checkResource)
{
if (File.Exists(m_FbxPath))
{
File.Delete(m_FbxPath);
}
m_FbxFile.CopyTo(m_FbxPath);
AssetDatabase.Refresh();
}
return m_FbxPath;
}
/// <summary>
/// 基于源Json配置文件创建适配新prefab的Json配置文件
/// </summary>
/// <param name="OriginIndex"></param>
/// <param name="TargetIndex"></param>
/// <param name="cardName"></param>
void CreateJsonFile(CardConfig cardConfig,Dictionary<string,string> WriteJsonDic,ref FilePath filePath)
{
string OriginFileName = LMNAResMapUtil.AssembleAssetName(cardConfig.CardName+cardConfig.OriginIndex+".json", eAssetFunctionType.VActionConfig, eAssetLodLevel.None);
string OriginFilePath = m_JsonDirIng + OriginFileName;
string TargetFileName = LMNAResMapUtil.AssembleAssetName(cardConfig.CardName + cardConfig.TargetIndex + ".json",
eAssetFunctionType.VActionConfig, eAssetLodLevel.None);
string TargetFilePath = m_JsonDirIng + TargetFileName;
TextAsset textAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(OriginFilePath);
if (textAsset == null) //如果json文件命名不规则,通过编号去找
{
string[] guids = AssetDatabase.FindAssets( cardConfig.OriginIndex, new string[] {m_JsonDirIng});
if (guids.Length > 1)
{
EditorUtility.DisplayDialog("小提醒", $"{cardConfig.OriginIndex}对应的json配置文件编号不规则,而且存在多个相同编号配置文件,导入失败,请找程序确认一下", "好哒");
return;
}
else
{
if (guids.Length > 0)
{
string AssetName = AssetDatabase.GUIDToAssetPath(guids[0]); //适配json配置文件命名不规则情况
textAsset =
AssetDatabase.LoadAssetAtPath(AssetName, typeof(TextAsset)) as TextAsset;
TargetFilePath = AssetName.Replace(cardConfig.OriginIndex, numberResult);
}
else
{
EditorUtility.DisplayDialog("小提醒", $"{cardConfig.OriginIndex}对应的json配置文件不存在,导入失败,请找程序确认一下", "好哒");
return;
}
}
}
string textString;
if (!WriteJsonDic.ContainsKey(TargetFilePath))
{
textString = textAsset.text;
WriteJsonDic.Add(TargetFilePath,textString);
}
else
{
textString = WriteJsonDic[TargetFilePath];
}
foreach (KeyValuePair<string,string> keyValuePair in cardConfig.OldAndNewNameDic)
{
textString = textString.Replace(Path.GetFileNameWithoutExtension(keyValuePair.Key),
Path.GetFileNameWithoutExtension(keyValuePair.Value));
}
filePath.jsonPath = TargetFilePath;
WriteJsonDic[TargetFilePath] = textString;
}
/// <summary>
/// 收集道具卡之外的 其他特效的命名
/// </summary>
/// <param name="FileName"></param>
/// <returns></returns>
void CollectOtherPrefab(Dictionary<string,List<eAssetLodLevel>> dic,string FileName)
{
string[] splitAssetName = FileName.Split(LMNAResMapUtil.ASSET_FULL_NAME_SPLITTER_ARRAY, StringSplitOptions.RemoveEmptyEntries);
if (splitAssetName.Length != 2)
{
return;
}
eAssetLodLevel lodLv = eAssetLodLevel.None;
string prefixPart = splitAssetName[0];
string logigPart = splitAssetName[1];
string prefixSegment =
prefixPart.Replace(
prefixPart.Substring(0, Math.Min(LMNAResMapUtil.ASSET_NAME_PREFIX_SEGMENT_SIZE, prefixPart.Length)),
"");
bool HasLevel = LMNAResMapUtil.StrToEAssetLodLevelType(prefixSegment, out lodLv); //是否存在等级
if (!dic.ContainsKey(logigPart))
{
List<eAssetLodLevel> assetLevelList = new List<eAssetLodLevel>();
dic.Add(logigPart, assetLevelList);
}
if (HasLevel)
{
dic[logigPart].Add(lodLv);
}
}
/// <summary>
/// 根据预制体路径,收集子物体是否为prefab预制体 如果是 就实例化的
/// </summary>
/// <param name="prefabPath"></param>
/// <param name="beforeName"></param>
/// <param name="AfterName"></param>
FilePath CollectionOtherEffectPrefab(string prefabPath,string beforeName,string afterName,GameObject OldEffectPrefabInst,FilePath filePaths,bool checkResource = false)
{
GameObject ret = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)) as GameObject;
List<string> partList = new List<string>();
Transform[] transList = ret.GetComponentsInChildren<Transform>();
for (int i = 0; i < transList.Length; i++)
{
if (PrefabUtility.IsPartOfPrefabInstance(transList[i].gameObject))
{
GameObject value = PrefabUtility.GetCorrespondingObjectFromOriginalSource(transList[i].gameObject);
string rootPath = AssetDatabase.GetAssetPath(value);
string finalPath = rootPath.Replace(beforeName, afterName);
if (!partList.Contains(finalPath))
{
GameObject partGameObject = AssetDatabase.LoadAssetAtPath(rootPath, typeof(GameObject)) as GameObject;
GameObject partGameObjectInst = Instantiate(partGameObject);
tempGameObejct.Add(partGameObjectInst);
string path =
finalPath.Substring(0, finalPath.LastIndexOf(@"/"));
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
filePaths.OtherPrefabPaths.Add(finalPath);
if (!checkResource)
{
PrefabUtility.SaveAsPrefabAsset(partGameObjectInst, finalPath);
AssetDatabase.SaveAssets();
DestroyImmediate(partGameObjectInst.gameObject);
AssetDatabase.Refresh();
}
Transform[] OldEffectPrefabInstChildren =
OldEffectPrefabInst.GetComponentsInChildren<Transform>();
List<GameObject> needDeleteGameObjects = new List<GameObject>();
for (int j = 0; j < OldEffectPrefabInstChildren.Length; j++)
{
if (transList[i].gameObject.name == OldEffectPrefabInstChildren[j].name)
{
GameObject retTrans =
AssetDatabase.LoadAssetAtPath(finalPath, typeof(GameObject)) as GameObject;
GameObject cloneTrans = PrefabUtility.InstantiatePrefab(retTrans) as GameObject;
if (cloneTrans != null)
{
cloneTrans.transform.parent = OldEffectPrefabInstChildren[j].parent;
needDeleteGameObjects.Add(OldEffectPrefabInstChildren[j].gameObject);
}
break;
}
}
needDeleteGameObjects.ForEach(child => DestroyImmediate(child));
partList.Add(finalPath);
}
}
}
return filePaths;
}
#endregion
#region 奥丁插件相关组件
private OdinMenuTree tree;
private PropertyTree m_LogicPrefabPropertyTree;
private GameObject[] m_LogicPrefab;
#endregion
#region 奥丁插件 相关逻辑变量
private RightTabEditor AllRightTabEditorData;
private List<RightTabEditor> RightTabEditorList;
#endregion
/// <summary>
/// 恢复材质依赖关系
/// </summary>
/// <param name="originalGameObejct"></param>
/// <param name="targetGameObject"></param>
private void RecoverMatrials(Transform originalGameObejct, Transform targetGameObject)
{
MeshRenderer[] OriginalMeshRenderers = originalGameObejct.GetComponentsInChildren<MeshRenderer>();
Dictionary<string,Material[]> OrignalMeshRendererName = new Dictionary<string,Material[]>();
for (int i = 0; i < OriginalMeshRenderers.Length; i++)
{
OrignalMeshRendererName.Add(OriginalMeshRenderers[i].transform.name,OriginalMeshRenderers[i].sharedMaterials);
}
MeshRenderer[] TargetMeshRenderers = targetGameObject.GetComponentsInChildren<MeshRenderer>();
for (int i = 0; i < TargetMeshRenderers.Length; i++)
{
if (OrignalMeshRendererName.ContainsKey(TargetMeshRenderers[i].transform.name))
{
List<Material> newMaterials = new List<Material>(OrignalMeshRendererName[TargetMeshRenderers[i].transform.name]);
TargetMeshRenderers[i].sharedMaterials = newMaterials.ToArray();
}
}
// PrefabUtility.SavePrefabAsset(targetGameObject.gameObject);
}
/// <summary>
/// 刷新当前道具卡列表数据
/// </summary>
public void RefreshData()
{
if (AllRightTabEditorData != null)
{
if (AllRightTabEditorData.m_FbxFiles != null)
{
Dictionary<int,List<FileInfo>> FileInfoDic = new Dictionary<int, List<FileInfo>>();
int number = -1;
for (int i = 0; i < AllRightTabEditorData.m_FbxFiles.Length; i++)
{
if (int.TryParse(System.Text.RegularExpressions.Regex.Replace(AllRightTabEditorData.m_FbxFiles[i].Name, @"[^0-9]+", ""),out number))
{
if (!FileInfoDic.ContainsKey(number))
{
List<FileInfo> FileList = new List<FileInfo>();
FileInfoDic.Add(number,FileList);
}
FileInfoDic[number].Add(AllRightTabEditorData.m_FbxFiles[i]);
}
}
RightTabEditorList.Clear();
foreach (KeyValuePair<int,List<FileInfo>> pair in FileInfoDic)
{
RightTabEditorList.Add(new RightTabEditor(pair.Key,pair.Value.ToArray()));
tree.Add(pair.Key.ToString(),RightTabEditorList[RightTabEditorList.Count-1] );
}
isShow = true;
}
}
}
protected override OdinMenuTree BuildMenuTree()
{
tree = new OdinMenuTree();
return tree;
}
private bool isShow = false;
protected override void OnBeginDrawEditors()
{
// var selected = this.MenuTree.Selection.FirstOrDefault();
// var 24 = this.MenuTree.Config.SearchToolbarHeight;
SirenixEditorGUI.BeginHorizontalToolbar(24);
{
if (isShow)
{
if (SirenixEditorGUI.ToolbarButton(new GUIContent("刷新页面")))
{
RefreshData();
}
if (SirenixEditorGUI.ToolbarButton(new GUIContent("全部导入")))
{
for (int i = 0; i < RightTabEditorList.Count; i++)
{
RightTabEditorList[i].GiganticButton();
}
}
}
// Draws a toolbar with the name of the currently selected menu item
if (SirenixEditorGUI.ToolbarButton(new GUIContent("选择文件夹")))
{
AllRightTabEditorData = GetCardData();
RightTabEditorList = new List<RightTabEditor>();
RefreshData();
GUIUtility.ExitGUI();
}
}
SirenixEditorGUI.EndHorizontalToolbar();
}
/// <summary>
/// 自定义右侧每个Menu对应的Editor
/// </summary>
/// <param name="index"></param>
protected override void DrawEditor(int index)
{
GUILayout.BeginVertical();
base.DrawEditor(index);
//当前选择的Menu对应的对象
RightTabEditor currentTarget = CurrentDrawingTargets[index] as RightTabEditor;
// // object currentTarget = CurrentDrawingTargets[index];
//
// if (currentTarget.m_FbxNumber != -1)
// {
// GUILayout.Label(currentTarget.m_FbxNumber.ToString());
DrawCardSkinInfo(currentTarget);
// }
//
//
GUILayout.EndVertical();
}
private int currentId = -1;
// private RightTabEditor _rightTabEditor;
/// <summary>
/// 绘制道具卡信息
/// </summary>
/// <param name="_rightTabEditor"></param>
private void DrawCardSkinInfo(RightTabEditor _rightTabEditor)
{
// Debug.Log("数字序号是:" + _rightTabEditor.m_FbxNumber);
GUILayout.Label("已导入资源路径索引:↓");
_rightTabEditor.LoadAsset();
m_LogicPrefab = _rightTabEditor.InLinePrefabPreviews;
if (m_LogicPrefab != null && m_LogicPrefab.Length > 0 && currentId != _rightTabEditor.m_FbxNumber)
{
currentId = _rightTabEditor.m_FbxNumber;
m_LogicPrefabPropertyTree = PropertyTree.Create(m_LogicPrefab);
}
if (m_LogicPrefab == null || m_LogicPrefab.Length <= 0)
{
m_LogicPrefabPropertyTree = null;
}
m_LogicPrefabPropertyTree?.Draw(false);
}
}
public class RightTabEditor
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="number"></param>
/// <param name="files"></parcam>
public RightTabEditor(int number = -1,FileInfo[] files = null)
{
m_FbxNumber = number;
m_FbxFiles = files;
FilePath = new FilePath();
if (m_FbxFiles != null)
{
FilePath = CardResourceArtToolEditor.GetCardResourceArtToolEditor.OnClickLoadButton(m_FbxFiles,true);
}
}
#region 道具卡右侧列表需要 属性
[HideInEditorMode]
public int m_FbxNumber; //FBX对应的编号
[HideInEditorMode]
public FileInfo[] m_FbxFiles; //FBX文件信息
[HideInEditorMode]
public FilePath FilePath; //导入文件相关路径
#endregion
[Button("点击导入资源",ButtonSizes.Gigantic)]
public void GiganticButton()
{
if (m_FbxFiles != null)
{
FilePath = CardResourceArtToolEditor.GetCardResourceArtToolEditor.OnClickLoadButton(m_FbxFiles);
// CardResourceArtToolEditor.GetCardResourceArtToolEditor.RefreshData();
}
}
[Button("点击编辑json文件")]
public void EditJsonButton()
{
if (FilePath != null && FilePath.jsonPath != String.Empty)
{
CardDataCtrlEditor.OpenByPath(FilePath.jsonPath);
}
}
/// <summary>
/// 加载预制体
/// </summary>
public void LoadAsset()
{
if (FilePath != null && FilePath.MainPrefabPath != null)
{
List<GameObject> prefabGameObjects = new List<GameObject>();
for (int i = 0; i < FilePath.MainPrefabPath.Count; i++)
{
prefabGameObjects.Add(AssetDatabase.LoadAssetAtPath(FilePath.MainPrefabPath[i], typeof(GameObject)) as GameObject);
}
bool isNullPrefab = false;
for (int i = 0; i < prefabGameObjects.Count; i++)
{
if (prefabGameObjects[i] == null)
{
isNullPrefab = true;
break;
}
}
if (isNullPrefab == false)
{
InLinePrefabPreviews = prefabGameObjects.ToArray() ;
}
FilePath.MainPrefabPath = null;
}
if (FilePath != null && FilePath.OtherPrefabPaths != null)
{
bool isGameObjectNullOther = false;
List<Object> otherGameObjects = new List<Object>();
if (FilePath.OtherPrefabPaths != null)
{
for (int i = 0; i < FilePath.OtherPrefabPaths.Count; i++)
{
otherGameObjects.Add(AssetDatabase.LoadAssetAtPath(FilePath.OtherPrefabPaths[i], typeof(GameObject)));
}
}
if (FilePath.OtherAnimPaths != null)
{
for (int i = 0; i < FilePath.OtherAnimPaths.Count; i++)
{
otherGameObjects.Add(AssetDatabase.LoadAssetAtPath(FilePath.OtherAnimPaths[i], typeof(AnimationClip)));
}
}
for (int i = 0; i < otherGameObjects.Count; i++)
{
if (otherGameObjects[i] == null)
{
isGameObjectNullOther = true;
break;
}
}
if (isGameObjectNullOther == false)
{
InLineOtherPreviews = otherGameObjects.ToArray() ;
}
FilePath.OtherPrefabPaths = null;
FilePath.OtherAnimPaths = null;
}
}
[LabelText("已导入Prefab资源")] //预览模型
[InlineEditor(InlineEditorModes.LargePreview)]
public GameObject[] InLinePrefabPreviews;
[LabelText("其余附带导入资源")] //预览其他资源
[InlineEditor(InlineEditorModes.LargePreview)]
public Object[] InLineOtherPreviews;
}
}