protected void BuildTextureDataWithFolder() { #region Step1: Find all files string sFolderTx = Application.dataPath + "/" + SceneConstant.m_sArtworkPath + TypeName + SceneConstant.m_sSceneTexturesPath; string sFolderDoc = Application.dataPath + "/" + SceneConstant.m_sArtworkPath + TypeName + SceneConstant.m_sDecoratesPath; CRuntimeLogger.Log("将从" + sFolderTx + "和" + sFolderDoc + "收集信息"); DirectoryInfo dirtx = new DirectoryInfo(sFolderTx); DirectoryInfo dirdoc = new DirectoryInfo(sFolderDoc); if (!dirtx.Exists || !dirdoc.Exists) { CRuntimeLogger.LogWarning("你选择目录内容不太对吧!"); return; } List <FileInfo> allTextures = new List <FileInfo>(); allTextures.AddRange(dirtx.GetFiles("*.png", SearchOption.AllDirectories)); allTextures.AddRange(dirdoc.GetFiles("*.png", SearchOption.AllDirectories)); List <FileInfo> allModels = dirdoc.GetFiles("*.fbx", SearchOption.AllDirectories).ToList(); #endregion #region Step2: Create SceneType CSceneType scenetypes = new CSceneType(); scenetypes.Load(); if (null == scenetypes[TypeName]) { CSceneTypeElement newType = scenetypes.CreateElement(TypeName); newType.m_bCanRot = CanRotate; newType.m_eEdgeType = EdgeType; newType.m_iCliffType = CliffType; newType.m_bHasGroundOffset = HasGroundOffset; } else { scenetypes[TypeName].m_bCanRot = CanRotate; scenetypes[TypeName].m_eEdgeType = EdgeType; scenetypes[TypeName].m_iCliffType = CliffType; scenetypes[TypeName].m_bHasGroundOffset = HasGroundOffset; } scenetypes.Save(); #endregion #region Step3: Bake Texture Atlas Dictionary <int, int> codes = new Dictionary <int, int>(new IntEqualityComparer()); Dictionary <string, Texture2D> txDic = new Dictionary <string, Texture2D>(); foreach (FileInfo fileInfo in allTextures) { string sFileName = CommonFunctions.GetLastName(fileInfo.FullName); string[] twoparts = sFileName.Split('_'); string sAssetPath = "Assets" + fileInfo.FullName.Replace("\\", "/").Replace(Application.dataPath.Replace("\\", "/"), ""); Texture2D t1 = AssetDatabase.LoadAssetAtPath(sAssetPath, typeof(Texture2D)) as Texture2D; txDic.Add(sFileName, (Texture2D)EditorCommonFunctions.GetReadWritable(t1)); //Check whether is a template texture int iCode, iRepeat; if (2 == twoparts.Length && !string.IsNullOrEmpty(twoparts[0]) && int.TryParse(twoparts[0].Substring(1, twoparts[0].Length - 1), out iCode) && int.TryParse(twoparts[1], out iRepeat)) { if (codes.ContainsKey(iCode)) { if (codes[iCode] < iRepeat) { codes[iCode] = iRepeat; } } else { codes.Add(iCode, iRepeat); } } } Dictionary <string, Rect> textureDic = EditorCommonFunctions.PackTexture( txDic, SceneConstant.m_sArtworkPath + TypeName + SceneConstant.m_sSceneTexturesPath, Shader.Find("Mobile/Unlit (Supports Lightmap)"), EditorCommonFunctions.EPackColorFormat.ForcePng); #endregion #region Step4: Make template CSceneGroudTemplate tamplate = new CSceneGroudTemplate { m_sSceneType = TypeName }; foreach (KeyValuePair <string, Rect> kvp in textureDic) { CSceneGroudTemplateElement newGT = tamplate.CreateElement(); tamplate.ChangeName(newGT.m_sElementName, kvp.Key); newGT.m_vUV = CommonFunctions.Rect2V4(kvp.Value); } tamplate.Save(); #endregion #region Step5: Make Scene Texture CSceneTexture newT = new CSceneTexture { m_sSceneType = TypeName }; for (int lt = 0; lt < 3; ++lt) { for (int rt = 0; rt < 3; ++rt) { for (int rb = 0; rb < 3; ++rb) { for (int lb = 0; lb < 3; ++lb) { int iCode, iRots; bool bFlip; FindCodeAndRot(codes, lt, rt, rb, lb, out iCode, out iRots, out bFlip); if (iCode < 0) { CRuntimeLogger.LogError(string.Format("组合没有找到{0}-{1}-{2}-{3}", lt, rt, rb, lb)); return; } CSceneTextureElement newE = newT.CreateElement(); int iCode2 = lt * CommonFunctions.IntPow(3, 0) + rt * CommonFunctions.IntPow(3, 1) + rb * CommonFunctions.IntPow(3, 2) + lb * CommonFunctions.IntPow(3, 3); newT.ChangeName(newE.m_sElementName, "T" + iCode2); if (iCode2 != newE.m_iID) { newT.ChangeId(newE.m_iID, iCode2); } newE.m_iTemplate = iCode; newE.m_iRotNumber = iRots; newE.m_iTextureCount = codes[iCode]; newE.m_bReflect = bFlip; } } } } newT.Save(); #endregion #region Step6: Make Decorate Dictionary <int, string> modelTemplates = new Dictionary <int, string>(new IntEqualityComparer()); Dictionary <int, int> modelRepeates = new Dictionary <int, int>(new IntEqualityComparer()); foreach (FileInfo fileInfo in allModels) { string sFileName = CommonFunctions.GetLastName(fileInfo.FullName); string[] twoparts = sFileName.Split('_'); string sAssetPath = "Assets" + fileInfo.FullName.Replace("\\", "/").Replace(Application.dataPath.Replace("\\", "/"), ""); //Check whether is a template texture int iCode, iRepeat; if (3 == twoparts.Length && int.TryParse(twoparts[1], out iCode) && int.TryParse(twoparts[2], out iRepeat) && iCode < 3 && iCode >= 0) { //Make template data if (!modelTemplates.ContainsKey(iCode)) { modelTemplates.Add(iCode, twoparts[0] + "_" + iCode); } if (!modelRepeates.ContainsKey(iCode)) { modelRepeates.Add(iCode, iRepeat); } else if (modelRepeates[iCode] < iRepeat) { modelRepeates[iCode] = iRepeat; } //Make the mesh List <Vector3> verts = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> trangles = new List <int>(); GameObject go = AssetDatabase.LoadMainAssetAtPath(sAssetPath) as GameObject; if (null != go) { foreach (MeshFilter mf in go.GetComponentsInChildren <MeshFilter>(true)) { Mesh editablemesh = (Mesh)EditorCommonFunctions.GetReadWritable(mf.sharedMesh); int iVertCount = verts.Count; Rect rct; MeshRenderer mr = mf.gameObject.GetComponent <MeshRenderer>(); if (null != mr && null != mr.sharedMaterial && null != mr.sharedMaterial.mainTexture && textureDic.ContainsKey(mr.sharedMaterial.mainTexture.name)) { rct = textureDic[mr.sharedMaterial.mainTexture.name]; } else if (textureDic.ContainsKey(editablemesh.name)) { rct = textureDic[editablemesh.name]; } else { CRuntimeLogger.LogWarning("Mesh找不到贴图:" + sAssetPath); return; } if (mf.transform == go.transform) { verts.AddRange(editablemesh.vertices); } else { for (int i = 0; i < editablemesh.vertices.Length; ++i) { Vector3 worldPos = mf.transform.localToWorldMatrix.MultiplyVector(editablemesh.vertices[i]) + mf.transform.position; verts.Add(go.transform.worldToLocalMatrix.MultiplyVector(worldPos - go.transform.position)); } } for (int i = 0; i < editablemesh.uv.Length; ++i) { float fX = Mathf.Clamp01(editablemesh.uv[i].x); float fY = Mathf.Clamp01(editablemesh.uv[i].y); uvs.Add(new Vector2(rct.xMin + rct.width * fX, rct.yMin + rct.height * fY)); } for (int i = 0; i < editablemesh.triangles.Length; ++i) { trangles.Add(iVertCount + editablemesh.triangles[i]); } } } Mesh theMesh = new Mesh { vertices = verts.ToArray(), uv = uvs.ToArray(), triangles = trangles.ToArray() }; theMesh.RecalculateNormals(); Unwrapping.GenerateSecondaryUVSet(theMesh); ; AssetDatabase.CreateAsset(theMesh, "Assets/" + SceneConstant.m_sArtworkPath + TypeName + SceneConstant.m_sDecoratesPath + "/Generate/" + sFileName + ".asset"); } } CSceneDecorate doc = new CSceneDecorate { m_sSceneType = TypeName }; CSceneDecorate olddoc = new CSceneDecorate { m_sSceneType = TypeName }; olddoc.Load(); foreach (KeyValuePair <int, string> kvp in modelTemplates) { CSceneDecorateElement element = doc.CreateElement(kvp.Value); if (element.m_iID != kvp.Key) { doc.ChangeId(element.m_iID, kvp.Key); } element.m_iDecrateRepeat = modelRepeates[kvp.Key]; if (null != olddoc[kvp.Key]) { element.m_bBlockPathfinding = olddoc[kvp.Key].m_bBlockPathfinding; element.m_iDecrateSize = olddoc[kvp.Key].m_iDecrateSize; element.m_bOnlyRotateY = olddoc[kvp.Key].m_bOnlyRotateY; } } doc.Save(); AssetDatabase.Refresh(); #endregion }
public static void MakeAtlasReplaceWithCloth(GameObject pObj, string sParentFolder) { #region Step0: Count Progress int iMC = (int)ECharactorMainColor.ECMC_Max; int iSC = (int)ECharactorSubColor.ECSC_Max + 1; List <string[]> combineList = GetHumanoidCombineList(); int iProgressCount = pObj.GetComponentsInChildren <MeshRenderer>(true).Length + combineList.Count; int iProgressFull = iProgressCount * (2 + 3 * iMC * iSC); int iProgressNow = 0; #endregion #region Step1: make gameobject table and make dirs (1x) CommonFunctions.CreateFolder(Application.dataPath + "/" + sParentFolder + "/Textures/?"); for (int i = 0; i < iMC; ++i) { for (int j = 0; j < iSC; ++j) { CommonFunctions.CreateFolder(Application.dataPath + "/" + sParentFolder + "/Resources/CharMesh/" + string.Format("M{0}S{1}/?", i, j)); } } List <SCharRendererFullInfo> info = new List <SCharRendererFullInfo>(); Dictionary <string, Texture2D[]> contextureCombine = new Dictionary <string, Texture2D[]>(); Dictionary <string, int> infoIndex = new Dictionary <string, int>(); foreach (MeshRenderer renderer in pObj.GetComponentsInChildren <MeshRenderer>(true)) { ++iProgressNow; EditorUtility.DisplayProgressBar("正在收集Renderer信息", string.Format("{0}/{1}", iProgressNow, iProgressFull), iProgressNow / (float)iProgressFull); Texture2D mainTex = renderer.sharedMaterial.GetTexture("_MainTex") as Texture2D; Texture2D colorTex = renderer.sharedMaterial.GetTexture("_ColorTex") as Texture2D; Texture2D shaTex = renderer.sharedMaterial.GetTexture("_ShadowTex") as Texture2D; if (null == mainTex || null == colorTex || null == shaTex) { CRuntimeLogger.LogError("有的材质没有贴图: " + CommonFunctions.FindFullName(pObj, renderer.gameObject)); EditorUtility.ClearProgressBar(); return; } string sTextureName = CommonFunctions.BuildStringOrder(new[] { mainTex.name, colorTex.name, shaTex.name }); Mesh mesh = renderer.gameObject.GetComponent <MeshFilter>().sharedMesh; info.Add(new SCharRendererFullInfo { m_sFullTexName = sTextureName, m_pMesh = mesh, m_sMeshFilterName = AssetDatabase.GetAssetPath(mesh), m_sMeshName = mesh.name, m_pObj = renderer.gameObject, m_sObjectPath = CommonFunctions.FindFullName(pObj, renderer.gameObject), m_pMainTexture = mainTex, m_pColorTexture = colorTex, m_pShaTexture = shaTex, m_pCombinedMesh = new Mesh[0], m_bDiscard = false, m_pCombinedMeshObj = null, m_bCombine = false, }); infoIndex.Add(CommonFunctions.FindFullName(pObj, renderer.gameObject), info.Count - 1); if (!contextureCombine.ContainsKey(sTextureName)) { contextureCombine.Add(sTextureName, new[] { mainTex, colorTex, shaTex }); } } iProgressNow = iProgressCount; #endregion #region Step2: make colored textures (20x) CCharactorColor colors = new CCharactorColor(); colors.Load(); Dictionary <string, Texture2D> outTexture = new Dictionary <string, Texture2D>(); for (int i = 0; i < iMC; ++i) { for (int j = 0; j < iSC; ++j) { Color mainC = colors[string.Format("M{0}", i + 1)].m_cColor; Color subC = Color.white * 0.7f; if (j < (int)ECharactorSubColor.ECSC_Max) { subC = colors[string.Format("S{0}", j + 1)].m_cColor; } foreach (KeyValuePair <string, Texture2D[]> kvp in contextureCombine) { ++iProgressNow; EditorUtility.DisplayProgressBar("正在阵营着色", string.Format("{0}/{1}", iProgressNow, iProgressFull), iProgressNow / (float)iProgressFull); Texture2D outPutT = GetTexture2DWithColor(kvp.Value[0], kvp.Value[1], kvp.Value[2], mainC, subC, j == (int)ECharactorSubColor.ECSC_Max); outTexture.Add(string.Format("{0}_M{1}S{2}", kvp.Key, i, j), outPutT); } iProgressNow = (i * iSC + j + 2) * iProgressCount; } } Shader unlit = Shader.Find("Unlit/Texture"); string sPackTextureName = sParentFolder + "/Textures/" + unlit.name.Replace("/", "_").Replace(".", "_"); Dictionary <string, Rect> packed = EditorCommonFunctions.PackTexture(outTexture, sPackTextureName, unlit, EditorCommonFunctions.EPackColorFormat.ForcePng); #endregion #region Step3: Combine Batch (1x) List <string> sDisableList = new List <string>(); foreach (string[] combines in combineList) { ++iProgressNow; EditorUtility.DisplayProgressBar("正在收集合并Batch信息", string.Format("{0}/{1}", iProgressNow, iProgressFull), iProgressNow / (float)iProgressFull); GameObject parent = info[infoIndex[pObj.name + "/" + combines[0]]].m_pObj; SCharRendererFullInfo cmb = new SCharRendererFullInfo { m_sObjectPath = CommonFunctions.FindFullName(pObj, parent.transform.parent.gameObject) + "/", m_bDiscard = false, m_pObj = null, m_pTransfParentPath = pObj.name + "/" + combines[0], m_bCombine = true, }; string sMeshFilterName = ""; List <GameObject> cmbobjs = new List <GameObject>(); List <Mesh> cmbmeshes = new List <Mesh>(); List <string> cmbtextures = new List <string>(); foreach (string t in combines) { if (!sDisableList.Contains(pObj.name + "/" + t)) { sDisableList.Add(pObj.name + "/" + t); } GameObject theObj = info[infoIndex[pObj.name + "/" + t]].m_pObj; cmb.m_sObjectPath += theObj.name; sMeshFilterName += theObj.name; cmbobjs.Add(theObj); cmbmeshes.Add(info[infoIndex[pObj.name + "/" + t]].m_pMesh); cmbtextures.Add(info[infoIndex[pObj.name + "/" + t]].m_sFullTexName); } cmb.m_pCombinedMeshObj = cmbobjs.ToArray(); cmb.m_pCombinedMesh = cmbmeshes.ToArray(); cmb.m_sTextureNames = cmbtextures.ToArray(); cmb.m_sMeshFilterName = sMeshFilterName; info.Add(cmb); } foreach (string namecmbdisable in sDisableList) { info[infoIndex[namecmbdisable]].m_bDiscard = true; } iProgressNow = (2 + iMC * iSC) * iProgressCount; #endregion #region Step4: Create Meshes (20x) Dictionary <string, string> meshDic = CreateMeshes(info.ToArray(), packed, sParentFolder + "/Resources/CharMesh/", iProgressNow, iProgressFull, iMC, iSC); AssetDatabase.Refresh(); iProgressNow = (2 + iMC * iSC * 2) * iProgressCount; #endregion #region Step5: Assemble Game Objects (20x) //Create the matrix for (int i = 0; i < iMC; ++i) { for (int j = 0; j < iSC; ++j) { CreateObj(i, j, info, meshDic, "Assets/" + sPackTextureName + ".mat", pObj, iProgressNow, iProgressFull); iProgressNow = ((2 + iMC * iSC * 2) + ((i * iSC) + j + 1)) * iProgressCount; } } #endregion EditorUtility.ClearProgressBar(); }