const FairyGUI = CS.FairyGUI; const FairyEditor = CS.FairyEditor import FileUtils from "./FileUtils"; import UIWindow, { WindData } from "./UIWindow" const App = FairyEditor.App; type FailureAssetData = { url: string, failure: string[], } export default class FindFailureAssetsWnd extends UIWindow { constructor() { super(new WindData("Extend", "FindFailureAssets")) } static show() { let url = FileUtils.joinUrl("Extend", "FindFailureAssets") if (UIWindow.FindUrl(url) == undefined) { UIWindow.add(new this) } super.show(url) } private state: CS.FairyGUI.Controller; private check: CS.FairyGUI.GButton private progress: CS.FairyGUI.GProgressBar private resList: CS.FairyGUI.GList; private assets = new Map() protected onInit(): void { super.onInit(); this.state = this.contentPane.GetController("state"); this.check = this.contentPane.GetChild("check").asButton; this.progress = this.contentPane.GetChild("progress").asProgress; this.resList = this.contentPane.GetChild("resList").asList; this.resList.itemRenderer = this.onItemRenderer.bind(this); this.resList.onClickItem.Add(this.onListClickItem.bind(this)) this.check.onClick.Add(this.onCheckClick.bind(this)) let cancel = this.contentPane.GetChild("close").asButton cancel.onClick.Add(this.onCancelClick.bind(this)) this.resList.SetVirtual(); } protected onShown(): void { super.onShown(); } protected onHide(): void { super.onHide(); this.resList.data = null; this.resList.numItems = 0; } private async onCheckClick() { if (this.state.selectedIndex == 0) { this.state.selectedIndex = 1; this.assets.clear(); let pkgs = App.project.allPackages; this.progress.value = 0; this.progress.max = FileUtils.getAllPackageItemsCount(); for (let index = 0; index < pkgs.Count; index++) { let pkg = pkgs.get_Item(index); if (this.state.selectedIndex == 0) break for (let j = 0; j < pkg.items.Count; j++) { if (this.state.selectedIndex == 0) break let item = pkg.items.get_Item(j); this.progress.value += 1 if (item.type != CS.FairyEditor.FObjectType.COMPONENT) { continue } //@ts-ignore this.getFailureAssets(item, this.assets, 0) if (this.progress.value % 30 == 0) { await FileUtils.sleep(0) } } } App.consoleView.Log("查找完毕") this.state.selectedIndex = 0; let asset = Array.from(this.assets).map(item => item[1]); this.resList.data = asset; this.resList.numItems = asset.length; this.contentPane.GetChild("projectCount").asTextField.templateVars = FileUtils.getTemplateVars(['value'],[asset.length.toString()]); } else { this.state.selectedIndex = 0; } } private onItemRenderer(index: number, obj: CS.FairyGUI.GComponent): void { let data = this.resList.data[index] as FailureAssetData; obj.data = data; let packageItem = App.project.GetItemByURL(data.url) obj.GetChild("title").text = packageItem.name obj.__onDispose = () => { obj.GetChild("title").text = '' obj.data = null; } } private onListClickItem(item: CS.FairyGUI.EventContext): void { let data = item.data.data as FailureAssetData; let packageItem = App.project.GetItemByURL(data.url) App.consoleView.Log(FileUtils.getUBBUrl(packageItem.GetURL(),`包含无效URL的组件:${packageItem.name}`)) for (let index = 0; index < data.failure.length; index++) { App.consoleView.Log('无效URL:'+data.failure[index]) } } private onCancelClick() { let self = this; this.Hide(); FairyGUI.Timers.inst.Add(0.05, 1, () => { UIWindow.remove(self) }) } /**查找失效资源 */ private getFailureAssets(item: CS.FairyEditor.FPackageItem, map: Map, quertIndex) { let xml = CS.FairyEditor.XMLExtension.Load(item.file) if (!xml) { App.consoleView.LogError(`PackageItem找不到配置文件. Name:${item.name} Index:${quertIndex} File:${item.file}`) return quertIndex; } let rootElements = xml.Elements() for (let index = 0; index < rootElements.Count; index++) { let child = rootElements.get_Item(index) if (child.name != 'displayList') continue let childElements = child.Elements(); for (let index = 0; index < childElements.Count; index++) { const element = childElements.get_Item(index); if (element.name == 'loader' || element.name == 'loader3D') { if (element.GetAttribute('clearOnPublish')) continue let url = element.GetAttribute('url') if (!url) continue //没清理依赖 let packageItem = App.project.GetItemByURL(url) if (!packageItem) { if (!map.has(item.GetURL())) { map.set(item.GetURL(), { url: item.GetURL(), failure: [] }) } map.get(item.GetURL()).failure.push(`name:${element.GetAttribute("name")} file:${element.GetAttribute("fileName")} url:${url}`) } else if (!map.has(packageItem.GetURL())) { if (packageItem.type == FairyEditor.FPackageItemType.COMPONENT) { quertIndex = this.getFailureAssets(packageItem, map, quertIndex) } quertIndex += 1; } } else { let src = element.GetAttribute("src") if (!src) { //系统资源 不需要依赖 continue } let pkg = element.GetAttribute("pkg") if (!pkg) { //自己依赖包的资源 所以不需要pkg pkg = item.owner.id; } let url = `ui://${pkg}${src}` if (src == null) App.consoleView.Log(element.name) let packageItem = App.project.GetItemByURL(url) if (!packageItem) { if (!map.has(item.GetURL())) { map.set(item.GetURL(), { url: item.GetURL(), failure: [] }) } map.get(item.GetURL()).failure.push(`name:${element.GetAttribute("name")} file:${element.GetAttribute("fileName")} url:${url}`) } else if (!map.has(packageItem.GetURL())) { if (packageItem.type == FairyEditor.FPackageItemType.COMPONENT) { quertIndex = this.getFailureAssets(packageItem, map, quertIndex) } quertIndex += 1; } } } } return quertIndex } }