public List <string> GetListOfAllBundles() { var cookingRulesMap = CookingRulesBuilder.Build(The.Workspace.AssetFiles, Target); var bundles = new HashSet <string>(); foreach (var dictionaryItem in cookingRulesMap) { foreach (var bundle in dictionaryItem.Value.Bundles) { bundles.Add(bundle); } } return(bundles.ToList()); }
private static HashSet <string> GetAllBundles() { var bundles = new HashSet <string>() { CookingRulesBuilder.MainBundleName }; var cookingRulesMap = CookingRulesBuilder.Build(The.Workspace.AssetFiles, The.Workspace.ActiveTarget); foreach (var bundle in cookingRulesMap.SelectMany(i => i.Value.Bundles.Where(bundle => bundle != CookingRulesBuilder.MainBundleName))) { bundles.Add(bundle); } return(bundles); }
private static HashSet <string> GetAllBundles(Target target) { var bundles = new HashSet <string>() { CookingRulesBuilder.MainBundleName }; var cookingRulesMap = CookingRulesBuilder.Build(Lime.AssetBundle.Current, target); foreach (var bundle in cookingRulesMap.SelectMany(i => i.Value.Bundles.Where(bundle => bundle != CookingRulesBuilder.MainBundleName))) { bundles.Add(bundle); } return(bundles); }
public void Cook(List <string> bundles) { AssetCache.Instance.Initialize(); CookingRulesMap = CookingRulesBuilder.Build(InputBundle, Target); LogText = ""; var allTimer = StartBenchmark( $"Asset cooking. Asset cache mode: {AssetCache.Instance.Mode}. Active platform: {Target.Platform}" + System.Environment.NewLine + DateTime.Now + System.Environment.NewLine ); PluginLoader.BeforeBundlesCooking(); var requiredCookCode = !The.Workspace.ProjectJson.GetValue <bool>("SkipCodeCooking"); var bundleBackups = new List <string>(); try { UserInterface.Instance.SetupProgressBar(CalculateOperationCount(bundles)); BeginCookBundles?.Invoke(); var assetsGroupedByBundles = GetAssetsGroupedByBundles(InputBundle.EnumerateFileInfos(), bundles); for (int i = 0; i < bundles.Count; i++) { var extraTimer = StartBenchmark(); CookBundle(bundles[i], assetsGroupedByBundles[i], bundleBackups); StopBenchmark(extraTimer, $"{bundles[i]} cooked: "); } var extraBundles = bundles.ToList(); extraBundles.Remove(CookingRulesBuilder.MainBundleName); extraBundles.Reverse(); PluginLoader.AfterBundlesCooked(extraBundles); if (requiredCookCode) { CodeCooker.Cook(Target, CookingRulesMap, bundles.ToList()); } StopBenchmark(allTimer, "All bundles cooked: "); PrintBenchmark(); } catch (System.Exception e) { Console.WriteLine(e.Message); RestoreBackups(bundleBackups); } finally { cookCanceled = false; RemoveBackups(bundleBackups); EndCookBundles?.Invoke(); UserInterface.Instance.StopProgressBar(); } }
public void CookCustomAssets(List <string> assets) { CookingRulesMap = CookingRulesBuilder.Build(The.Workspace.AssetFiles, Target); var defaultAssetsEnumerator = The.Workspace.AssetFiles; var assetsFileInfo = assets .Select(asset => new FileInfo { Path = asset, LastWriteTime = DateTime.Now }) .ToList(); The.Workspace.AssetFiles = new CustomFilesEnumerator(defaultAssetsEnumerator.Directory, assetsFileInfo); var defaultCookingProfile = AssetCooker.cookingProfile; AssetCooker.cookingProfile = CookingProfile.Partial; CookBundles(GetListOfAllBundles(), false); The.Workspace.AssetFiles = defaultAssetsEnumerator; AssetCooker.cookingProfile = defaultCookingProfile; }
public static void CookCustomAssets(TargetPlatform platform, List <string> assets) { AssetCooker.Platform = platform; cookingRulesMap = CookingRulesBuilder.Build(The.Workspace.AssetFiles, The.Workspace.ActiveTarget); var defaultAssetsEnumerator = The.Workspace.AssetFiles; var assetsFileInfo = assets .Select(asset => new FileInfo { Path = asset, LastWriteTime = DateTime.Now }) .ToList(); The.Workspace.AssetFiles = new CustomFilesEnumerator(defaultAssetsEnumerator.Directory, assetsFileInfo); var defaultCookingProfile = AssetCooker.cookingProfile; AssetCooker.cookingProfile = CookingProfile.Partial; CookBundles(requiredCookCode: false); The.Workspace.AssetFiles = defaultAssetsEnumerator; AssetCooker.cookingProfile = defaultCookingProfile; }
public static void Unpack(TargetPlatform platform) { var cookingRulesMap = CookingRulesBuilder.Build(The.Workspace.AssetFiles, The.Workspace.ActiveTarget); var bundles = new HashSet <string>(); foreach (var dictionaryItem in cookingRulesMap) { foreach (var bundle in dictionaryItem.Value.Bundles) { bundles.Add(bundle); } } foreach (var bundleName in bundles) { string bundlePath = The.Workspace.GetBundlePath(bundleName, The.Workspace.ActivePlatform); var dirInfo = new System.IO.DirectoryInfo(Path.GetDirectoryName(bundlePath)); foreach (var fileInfo in dirInfo.GetFiles('*' + Path.GetExtension(bundlePath), SearchOption.TopDirectoryOnly)) { UnpackBundle(fileInfo.FullName); } } }
public void Cook(IEnumerable <string> bundles) { AssetCache.Instance.Initialize(); CookingRulesMap = CookingRulesBuilder.Build(The.Workspace.AssetFiles, Target); CookBundles(bundles); }
public static void AnalyzeResourcesAction() { var target = The.UI.GetActiveTarget(); requestedPaths = new List <PathRequestRecord>(); var crossRefReport = new List <Tuple <string, List <string> > >(); var missingResourcesReport = new List <string>(); var suspiciousTexturesReport = new List <string>(); var bundles = new HashSet <string>(); var cookingRulesMap = CookingRulesBuilder.Build(AssetBundle.Current, target); AssetBundle.Current = new PackedAssetBundle(The.Workspace.GetBundlePath(target.Platform, CookingRulesBuilder.MainBundleName)); foreach (var i in cookingRulesMap) { if (i.Key.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) { if (i.Value.TextureAtlas == null && i.Value.PVRFormat != PVRFormat.PVRTC4 && i.Value.PVRFormat != PVRFormat.PVRTC4_Forced) { suspiciousTexturesReport.Add(string.Format("{0}: {1}, atlas: none", i.Key, i.Value.PVRFormat)); } if (i.Value.PVRFormat != PVRFormat.PVRTC4 && i.Value.PVRFormat != PVRFormat.PVRTC4_Forced && i.Value.PVRFormat != PVRFormat.PVRTC2) { int w; int h; bool hasAlpha; TextureConverterUtils.GetPngFileInfo(AssetBundle.Current, i.Key, out w, out h, out hasAlpha); if (w >= 1024 || h >= 1024) { suspiciousTexturesReport.Add(string.Format("{3}: {0}, {1}, {2}, {4}, atlas: {5}", w, h, hasAlpha, i.Key, i.Value.PVRFormat, i.Value.TextureAtlas)); } } } foreach (var bundle in i.Value.Bundles) { if (bundle != CookingRulesBuilder.MainBundleName) { bundles.Add(bundle); } } } var savedAssetBundle = AssetBundle.Current; try { var aggregateBundle = new AggregateAssetBundle( bundles.Select( i => new PackedAssetBundle(The.Workspace.GetBundlePath(target.Platform, i))).ToArray()); AssetBundle.Current = new CustomSetAssetBundle(aggregateBundle, aggregateBundle.EnumerateFileInfos().Where(i => { if (cookingRulesMap.TryGetValue(i.Path, out CookingRules rules)) { if (rules.Ignore) { return(false); } } return(true); })); var usedImages = new HashSet <string>(); var usedSounds = new HashSet <string>(); foreach (var srcPath in AssetBundle.Current.EnumerateFiles(null, ".tan")) { using (var scene = (Frame)Node.CreateFromAssetBundle(srcPath)) { foreach (var j in scene.Descendants) { var checkTexture = new Action <SerializableTexture>((Lime.SerializableTexture t) => { if (t == null) { return; } string texPath; try { texPath = t.SerializationPath; } catch { return; } if (string.IsNullOrEmpty(texPath)) { return; } if (texPath.Length == 2 && texPath[0] == '#') { switch (texPath[1]) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': return; default: suspiciousTexturesReport.Add(string.Format("wrong render target: {0}, {1}", texPath, j.ToString())); return; } } string[] possiblePaths = new string[] { texPath + ".atlasPart", texPath + ".pvr", texPath + ".jpg", texPath + ".png", texPath + ".dds", texPath + ".jpg", texPath + ".png", }; foreach (var tpp in possiblePaths) { if (Lime.AssetBundle.Current.FileExists(tpp)) { Lime.AssetBundle.Current.OpenFile(tpp); usedImages.Add(texPath.Replace('\\', '/')); return; } } missingResourcesReport.Add(string.Format("texture missing:\n\ttexture path: {0}\n\tscene path: {1}\n", t.SerializationPath, j.ToString())); }); var checkAnimators = new Action <Node>((Node n) => { if (n.Animators.TryFind <SerializableTexture>("Texture", out var ta)) { foreach (var key in ta.ReadonlyKeys) { checkTexture(key.Value); } } }); if (j is Widget) { var w = j as Lime.Widget; var serializableTexture = w.Texture as SerializableTexture; if (serializableTexture != null) { checkTexture(serializableTexture); } checkAnimators(w); } else if (j is ParticleModifier) { var pm = j as Lime.ParticleModifier; var serializableTexture = pm.Texture as SerializableTexture; if (serializableTexture != null) { checkTexture(serializableTexture); } checkAnimators(pm); } else if (j is Lime.Audio) { var au = j as Lime.Audio; var path = au.Sample.SerializationPath + ".sound"; usedSounds.Add(au.Sample.SerializationPath.Replace('\\', '/')); if (!Lime.AssetBundle.Current.FileExists(path)) { missingResourcesReport.Add(string.Format("audio missing:\n\taudio path: {0}\n\tscene path: {1}\n", path, j.ToString())); } else { using (var tempStream = Lime.AssetBundle.Current.OpenFile(path)) { } } // FIXME: should we check for audio:Sample animators too? } } } var reportList = new List <string>(); foreach (var rpr in requestedPaths) { string pattern = String.Format(@".*[/\\](.*)\.{0}", target.Platform.ToString()); string bundle = ""; foreach (Match m in Regex.Matches(rpr.bundle, pattern, RegexOptions.IgnoreCase)) { bundle = m.Groups[1].Value; } int index = Array.IndexOf(cookingRulesMap[srcPath].Bundles, bundle); if (index == -1) { reportList.Add(string.Format("\t[{0}]=>[{2}]: {1}", string.Join(", ", cookingRulesMap[srcPath].Bundles), rpr.path, bundle)); } } requestedPaths.Clear(); if (reportList.Count > 0) { crossRefReport.Add(new Tuple <string, List <string> >(srcPath, reportList)); } Lime.Application.FreeScheduledActions(); } var allImages = new Dictionary <string, bool>(); foreach (var img in AssetBundle.Current.EnumerateFiles(null, ".png")) { var key = Path.Combine(Path.GetDirectoryName(img), Path.GetFileNameWithoutExtension(img)).Replace('\\', '/'); if (!key.StartsWith("Fonts")) { allImages[key] = false; } } foreach (var img in usedImages) { allImages[img] = true; } var unusedImages = allImages.Where(kv => !kv.Value).Select(kv => kv.Key).ToList(); var allSounds = new Dictionary <string, bool>(); foreach (var sound in AssetBundle.Current.EnumerateFiles(null, ".ogg")) { var key = Path.Combine(Path.GetDirectoryName(sound), Path.GetFileNameWithoutExtension(sound)) .Replace('\\', '/'); allSounds[key] = false; } foreach (var sound in usedSounds) { allSounds[sound] = true; } var unusedSounds = allSounds.Where(kv => !kv.Value).Select(kv => kv.Key).ToList(); Action <string> writeHeader = (s) => { int n0 = (80 - s.Length) / 2; int n1 = (80 - s.Length) % 2 == 0 ? n0 : n0 - 1; Console.WriteLine("\n" + new String('=', n0) + " " + s + " " + new String('=', n1)); }; writeHeader("Cross Bundle Dependencies"); foreach (var scenePath in crossRefReport) { Console.WriteLine("\n" + scenePath.Item1); foreach (var refStr in scenePath.Item2) { Console.WriteLine(refStr); } } writeHeader("Missing Resources"); foreach (var s in missingResourcesReport) { Console.WriteLine(s); } writeHeader("Unused Images"); foreach (var s in unusedImages) { Console.WriteLine(s); } writeHeader("Unused Sounds"); foreach (var s in unusedSounds) { Console.WriteLine(s); } writeHeader("Suspicious Textures"); foreach (var s in suspiciousTexturesReport) { Console.WriteLine(s); } } finally { AssetBundle.Current = savedAssetBundle; } }
public static void Cook(TargetPlatform platform) { AssetCooker.Platform = platform; cookingRulesMap = CookingRulesBuilder.Build(The.Workspace.AssetFiles, The.Workspace.ActiveTarget); CookBundles(); }