/// <summary> /// Link /// </summary> /// <param name="psb"></param> /// <param name="resPaths">resource paths</param> /// <param name="baseDir"></param> /// <param name="order">how to arrange images</param> /// <param name="isExternal">Whether this is an external texture PSB</param> public static void Link(this PSB psb, IList <string> resPaths, string baseDir = null, PsbLinkOrderBy order = PsbLinkOrderBy.Convention, bool isExternal = false) { if (isExternal) { psb.MotionResourceInstrument(); } var resList = psb.CollectResources(); var context = FreeMount.CreateContext(); if (order == PsbLinkOrderBy.Order) { for (int i = 0; i < resList.Count; i++) { var resMd = resList[i]; var fullPath = Path.Combine(baseDir ?? "", resPaths[i]); byte[] data = LoadImageBytes(fullPath, resMd, context); resMd.Resource.Data = data; } return; } if (order == PsbLinkOrderBy.Name) { if (psb.Platform == PsbSpec.krkr) { throw new InvalidOperationException( $"Can not link by file name for krkr PSB. Please consider using {PsbLinkOrderBy.Convention}"); } resList.Sort((md1, md2) => (int)(md1.TextureIndex ?? 0) - (int)(md2.TextureIndex ?? 0)); } for (var i = 0; i < resPaths.Count; i++) { var resPath = resPaths[i]; var resName = Path.GetFileNameWithoutExtension(resPath); //var resMd = uint.TryParse(resName, out uint rid) // ? resList.FirstOrDefault(r => r.Index == rid) // : resList.FirstOrDefault(r => // resName == $"{r.Part}{PsbResCollector.ResourceNameDelimiter}{r.Name}"); //Scan for Resource ResourceMetadata resMd = null; if (order == PsbLinkOrderBy.Name) { if (resName == null) { continue; } if (resList.Count == 1 && resPaths.Count == 1) { //If there is only one resource and one texture, we won't care about file name. resMd = resList[0]; } else { var texIdx = ResourceMetadata.GetTextureIndex(resName); if (texIdx == null) { Console.WriteLine($"[WARN]{resPath} is not used since the file name cannot be recognized."); continue; } if (resList.Count <= texIdx.Value) { Console.WriteLine($"[WARN]{resPath} is not used since the tex No. is too large."); continue; } resMd = resList[(int)texIdx.Value]; } } else //if (order == PsbLinkOrderBy.Convention) { resMd = resList.FirstOrDefault(r => resName == $"{r.Part}{PsbResCollector.ResourceNameDelimiter}{r.Name}"); if (resMd == null && uint.TryParse(resName, out uint rid)) { resMd = resList.FirstOrDefault(r => r.Index == rid); } if (resMd == null && psb.Type == PsbType.Pimg) { resMd = resList.FirstOrDefault(r => resName == Path.GetFileNameWithoutExtension(r.Name)); } } if (resMd == null) { Console.WriteLine($"[WARN]{resPath} is not used."); continue; } var fullPath = Path.Combine(baseDir ?? "", resPath.Replace('/', '\\')); byte[] data = LoadImageBytes(fullPath, resMd, context); resMd.Resource.Data = data; } }