From b689754acfb6b2503631bbfb019cbbed04fd7b5f Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期四, 04 十二月 2025 09:19:51 +0800
Subject: [PATCH] 125 战斗 新增预加载资源编辑器查看状态功能

---
 Assets/Editor/Tool/BattlePreloadResWatcher.cs.meta |   11 +
 Assets/Editor/Tool/BattlePreloadResWatcher.cs      |  396 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 407 insertions(+), 0 deletions(-)

diff --git a/Assets/Editor/Tool/BattlePreloadResWatcher.cs b/Assets/Editor/Tool/BattlePreloadResWatcher.cs
new file mode 100644
index 0000000..62657de
--- /dev/null
+++ b/Assets/Editor/Tool/BattlePreloadResWatcher.cs
@@ -0,0 +1,396 @@
+using UnityEngine;
+using UnityEditor;
+using System.Collections.Generic;
+using System.Linq;
+
+/// <summary>
+/// 鎴樻枟棰勫姞杞借祫婧愮洃鎺х獥鍙�
+/// </summary>
+public class BattlePreloadResWatcher : EditorWindow
+{
+    private Vector2 scrollPosition;
+    private bool showSpineResources = true;
+    private bool showAudioResources = true;
+    private string filterText = "";
+    private bool autoRefresh = true;
+    private double lastRefreshTime = 0;
+    private const double AUTO_REFRESH_INTERVAL = 1.0; // 1绉掕嚜鍔ㄥ埛鏂�
+    
+    private List<BattleCacheManager.ResourceReferenceView> spineResourceViews = new List<BattleCacheManager.ResourceReferenceView>();
+    private List<BattleCacheManager.ResourceReferenceView> audioResourceViews = new List<BattleCacheManager.ResourceReferenceView>();
+    private HashSet<string> allBattleGuids = new HashSet<string>();
+    
+    private GUIStyle headerStyle;
+    private GUIStyle evenRowStyle;
+    private GUIStyle oddRowStyle;
+    private GUIStyle loadedStyle;
+    private GUIStyle unloadedStyle;
+    
+    [MenuItem("Tools/鎴樻枟/棰勫姞杞借祫婧愮洃鎺�")]
+    public static void ShowWindow()
+    {
+        var window = GetWindow<BattlePreloadResWatcher>("鎴樻枟璧勬簮鐩戞帶");
+        window.minSize = new Vector2(800, 400);
+        window.Show();
+    }
+    
+    private void OnEnable()
+    {
+        RefreshData();
+    }
+    
+    private void OnGUI()
+    {
+        InitStyles();
+        
+        // 椤堕儴宸ュ叿鏍�
+        DrawToolbar();
+        
+        // 缁熻淇℃伅
+        DrawStatistics();
+        
+        GUILayout.Space(5);
+        
+        // 婊氬姩鍖哄煙
+        scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
+        
+        // Spine璧勬簮
+        if (showSpineResources)
+        {
+            DrawResourceSection("Spine 璧勬簮", spineResourceViews);
+        }
+        
+        GUILayout.Space(10);
+        
+        // Audio璧勬簮
+        if (showAudioResources)
+        {
+            DrawResourceSection("Audio 璧勬簮", audioResourceViews);
+        }
+        
+        EditorGUILayout.EndScrollView();
+        
+        // 鑷姩鍒锋柊
+        if (autoRefresh && EditorApplication.timeSinceStartup - lastRefreshTime > AUTO_REFRESH_INTERVAL)
+        {
+            RefreshData();
+            lastRefreshTime = EditorApplication.timeSinceStartup;
+            Repaint();
+        }
+    }
+    
+    private void InitStyles()
+    {
+        if (headerStyle == null)
+        {
+            headerStyle = new GUIStyle(EditorStyles.boldLabel)
+            {
+                fontSize = 14,
+                normal = { textColor = Color.white }
+            };
+            
+            evenRowStyle = new GUIStyle(EditorStyles.label)
+            {
+                normal = { background = MakeTexture(2, 2, new Color(0.3f, 0.3f, 0.3f, 0.1f)) }
+            };
+            
+            oddRowStyle = new GUIStyle(EditorStyles.label)
+            {
+                normal = { background = MakeTexture(2, 2, new Color(0.3f, 0.3f, 0.3f, 0.3f)) }
+            };
+            
+            loadedStyle = new GUIStyle(EditorStyles.label)
+            {
+                normal = { textColor = Color.green }
+            };
+            
+            unloadedStyle = new GUIStyle(EditorStyles.label)
+            {
+                normal = { textColor = Color.red }
+            };
+        }
+    }
+    
+    private Texture2D MakeTexture(int width, int height, Color color)
+    {
+        Color[] pixels = new Color[width * height];
+        for (int i = 0; i < pixels.Length; i++)
+        {
+            pixels[i] = color;
+        }
+        
+        Texture2D texture = new Texture2D(width, height);
+        texture.SetPixels(pixels);
+        texture.Apply();
+        return texture;
+    }
+    
+    private void DrawToolbar()
+    {
+        EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
+        
+        if (GUILayout.Button("鍒锋柊鏁版嵁", EditorStyles.toolbarButton, GUILayout.Width(80)))
+        {
+            RefreshData();
+        }
+        
+        autoRefresh = GUILayout.Toggle(autoRefresh, "鑷姩鍒锋柊", EditorStyles.toolbarButton, GUILayout.Width(80));
+        
+        GUILayout.Space(10);
+        
+        showSpineResources = GUILayout.Toggle(showSpineResources, "鏄剧ずSpine", EditorStyles.toolbarButton, GUILayout.Width(80));
+        showAudioResources = GUILayout.Toggle(showAudioResources, "鏄剧ずAudio", EditorStyles.toolbarButton, GUILayout.Width(80));
+        
+        GUILayout.Space(10);
+        
+        GUILayout.Label("绛涢��:", GUILayout.Width(40));
+        filterText = GUILayout.TextField(filterText, EditorStyles.toolbarTextField, GUILayout.Width(200));
+        
+        GUILayout.FlexibleSpace();
+        
+        if (GUILayout.Button("娓呯┖缂撳瓨", EditorStyles.toolbarButton, GUILayout.Width(80)))
+        {
+            if (EditorUtility.DisplayDialog("纭", "纭畾瑕佹竻绌烘墍鏈夋垬鏂楄祫婧愮紦瀛樺悧锛�", "纭畾", "鍙栨秷"))
+            {
+                BattleCacheManager.DebugAPI.ClearAllCache();
+                RefreshData();
+            }
+        }
+        
+        EditorGUILayout.EndHorizontal();
+    }
+    
+    private void DrawStatistics()
+    {
+        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
+        
+        EditorGUILayout.LabelField("缂撳瓨缁熻", EditorStyles.boldLabel);
+        
+        EditorGUILayout.BeginHorizontal();
+        EditorGUILayout.LabelField($"Spine 璧勬簮鎬绘暟: {spineResourceViews.Count}", GUILayout.Width(200));
+        EditorGUILayout.LabelField($"Audio 璧勬簮鎬绘暟: {audioResourceViews.Count}", GUILayout.Width(200));
+        EditorGUILayout.LabelField($"鎴樺満鏁伴噺: {allBattleGuids.Count}", GUILayout.Width(200));
+        EditorGUILayout.EndHorizontal();
+        
+        int spineLoaded = spineResourceViews.Count(v => v.IsLoaded);
+        int audioLoaded = audioResourceViews.Count(v => v.IsLoaded);
+        
+        EditorGUILayout.BeginHorizontal();
+        EditorGUILayout.LabelField($"Spine 宸插姞杞�: {spineLoaded}", GUILayout.Width(200));
+        EditorGUILayout.LabelField($"Audio 宸插姞杞�: {audioLoaded}", GUILayout.Width(200));
+        EditorGUILayout.LabelField($"鎬诲紩鐢ㄨ鏁�: {spineResourceViews.Sum(v => v.TotalRefCount) + audioResourceViews.Sum(v => v.TotalRefCount)}", GUILayout.Width(200));
+        EditorGUILayout.EndHorizontal();
+        
+        // 鎴樺満鍒楄〃
+        if (allBattleGuids.Count > 0)
+        {
+            GUILayout.Space(5);
+            EditorGUILayout.LabelField("娲昏穬鎴樺満:", EditorStyles.boldLabel);
+            EditorGUILayout.BeginHorizontal();
+            foreach (var guid in allBattleGuids)
+            {
+                string displayGuid = string.IsNullOrEmpty(guid) ? "[涓绘垬鍦篯" : guid.Substring(0, Mathf.Min(8, guid.Length)) + "...";
+                EditorGUILayout.LabelField($"鈥� {displayGuid}", GUILayout.Width(150));
+            }
+            EditorGUILayout.EndHorizontal();
+        }
+        
+        EditorGUILayout.EndVertical();
+    }
+    
+    private void DrawResourceSection(string title, List<BattleCacheManager.ResourceReferenceView> resources)
+    {
+        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
+        
+        EditorGUILayout.LabelField(title, headerStyle);
+        GUILayout.Space(5);
+        
+        // 琛ㄥご
+        EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
+        EditorGUILayout.LabelField("璧勬簮璺緞", EditorStyles.toolbarButton, GUILayout.Width(600));
+        EditorGUILayout.LabelField("鐘舵��", EditorStyles.toolbarButton, GUILayout.Width(60));
+        EditorGUILayout.LabelField("寮曠敤璁℃暟", EditorStyles.toolbarButton, GUILayout.Width(80));
+        EditorGUILayout.LabelField("鎴樺満鍒嗗竷", EditorStyles.toolbarButton, GUILayout.ExpandWidth(true));
+        EditorGUILayout.EndHorizontal();
+        
+        // 绛涢�夎祫婧�
+        var filteredResources = resources;
+        if (!string.IsNullOrEmpty(filterText))
+        {
+            filteredResources = resources.Where(r => r.ResourcePath.ToLower().Contains(filterText.ToLower())).ToList();
+        }
+        
+        // 鍒涘缓灞呬腑鏍峰紡
+        GUIStyle centeredStyle = new GUIStyle(GUI.skin.label);
+        centeredStyle.alignment = TextAnchor.MiddleCenter;
+        
+        GUIStyle centeredLoadedStyle = new GUIStyle(loadedStyle);
+        centeredLoadedStyle.alignment = TextAnchor.MiddleCenter;
+        
+        GUIStyle centeredUnloadedStyle = new GUIStyle(unloadedStyle);
+        centeredUnloadedStyle.alignment = TextAnchor.MiddleCenter;
+        
+        // 璧勬簮璺緞鏍峰紡锛堝彲鐐瑰嚮锛�
+        GUIStyle pathStyle = new GUIStyle(GUI.skin.label);
+        pathStyle.wordWrap = false;
+        pathStyle.normal.textColor = new Color(0.4f, 0.7f, 1f); // 娣¤摑鑹茶〃绀哄彲鐐瑰嚮
+        
+        // 璧勬簮琛�
+        for (int i = 0; i < filteredResources.Count; i++)
+        {
+            var resource = filteredResources[i];
+            var rowStyle = (i % 2 == 0) ? evenRowStyle : oddRowStyle;
+            
+            EditorGUILayout.BeginHorizontal(rowStyle);
+            
+            // 璧勬簮璺緞锛堝彲鐐瑰嚮锛屾坊鍔� Tooltip锛�
+            GUIContent pathContent = new GUIContent(resource.ResourcePath, "鐐瑰嚮閫変腑璧勬簮\n" + resource.ResourcePath);
+            Rect pathRect = GUILayoutUtility.GetRect(pathContent, pathStyle, GUILayout.Width(600));
+            
+            if (GUI.Button(pathRect, pathContent, pathStyle))
+            {
+                // 鐐瑰嚮鏃堕�変腑璧勬簮
+                SelectAssetInEditor(resource.ResourcePath);
+            }
+            
+            // 榧犳爣鎮仠鏃舵樉绀烘墜鍨嬪厜鏍�
+            EditorGUIUtility.AddCursorRect(pathRect, MouseCursor.Link);
+            
+            // 鍔犺浇鐘舵�侊紙灞呬腑锛�
+            var statusStyle = resource.IsLoaded ? centeredLoadedStyle : centeredUnloadedStyle;
+            EditorGUILayout.LabelField(resource.IsLoaded ? "宸插姞杞�" : "鏈姞杞�", statusStyle, GUILayout.Width(60));
+            
+            // 寮曠敤璁℃暟锛堝眳涓級
+            EditorGUILayout.LabelField(resource.TotalRefCount.ToString(), centeredStyle, GUILayout.Width(80));
+            
+            // 鎴樺満鍒嗗竷
+            string battleInfo = string.Join(", ", resource.BattlefieldRefCounts.Select(kvp => 
+            {
+                string guidDisplay = string.IsNullOrEmpty(kvp.Key) ? "[涓籡" : kvp.Key.Substring(0, Mathf.Min(4, kvp.Key.Length));
+                return $"{guidDisplay}({kvp.Value})";
+            }));
+            EditorGUILayout.LabelField(battleInfo, GUILayout.ExpandWidth(true));
+            
+            EditorGUILayout.EndHorizontal();
+        }
+        
+        if (filteredResources.Count == 0)
+        {
+            EditorGUILayout.LabelField("娌℃湁璧勬簮鏁版嵁", EditorStyles.centeredGreyMiniLabel);
+        }
+        
+        EditorGUILayout.EndVertical();
+    }
+    
+    private void RefreshData()
+    {
+        spineResourceViews.Clear();
+        audioResourceViews.Clear();
+        allBattleGuids.Clear();
+        
+        // 鑾峰彇Spine璧勬簮
+        var spineCache = BattleCacheManager.DebugAPI.GetSpineCache();
+        foreach (var kvp in spineCache)
+        {
+            spineResourceViews.Add(new BattleCacheManager.ResourceReferenceView(kvp.Key, kvp.Value));
+        }
+        
+        // 鑾峰彇Audio璧勬簮
+        var audioCache = BattleCacheManager.DebugAPI.GetAudioCache();
+        foreach (var kvp in audioCache)
+        {
+            audioResourceViews.Add(new BattleCacheManager.ResourceReferenceView(kvp.Key, kvp.Value));
+        }
+        
+        // 鑾峰彇鎵�鏈夋垬鍦篏UID
+        allBattleGuids = BattleCacheManager.DebugAPI.GetAllBattleGuids();
+        
+        // 鎺掑簭
+        spineResourceViews = spineResourceViews.OrderBy(v => v.ResourcePath).ToList();
+        audioResourceViews = audioResourceViews.OrderBy(v => v.ResourcePath).ToList();
+    }
+    
+    /// <summary>
+    /// 鍦ㄧ紪杈戝櫒涓�変腑璧勬簮
+    /// </summary>
+    private void SelectAssetInEditor(string resourcePath)
+    {
+        // resourcePath 鏍煎紡: directory/assetName (渚嬪: Battle/Audio/bgm_001)
+        // 闇�瑕佽浆鎹负: Assets/ResourcesOut/{directory}/{assetName}{extension}
+        
+        // 灏濊瘯澶氱鍙兘鐨勬墿灞曞悕
+        string[] possibleExtensions = new string[]
+        {
+            ".asset",       // SkeletonDataAsset
+            ".prefab",      // Prefabs
+            ".png",         // Textures
+            ".jpg",         // Textures
+            ".wav",         // Audio
+            ".mp3",         // Audio
+            ".ogg",         // Audio
+            ".bytes",       // Binary data
+            "",             // 鏃犳墿灞曞悕
+        };
+        
+        Object asset = null;
+        string foundPath = null;
+        
+        // 灏濊瘯鎵�鏈夊彲鑳界殑璺緞
+        foreach (var ext in possibleExtensions)
+        {
+            string fullPath = $"Assets/ResourcesOut/{resourcePath}{ext}";
+            asset = AssetDatabase.LoadAssetAtPath<Object>(fullPath);
+            if (asset != null)
+            {
+                foundPath = fullPath;
+                break;
+            }
+        }
+        
+        if (asset != null)
+        {
+            // 鍦� Project 绐楀彛涓�変腑骞堕珮浜�
+            Selection.activeObject = asset;
+            EditorGUIUtility.PingObject(asset);
+            Debug.Log($"宸查�変腑璧勬簮: {foundPath}");
+        }
+        else
+        {
+            // 濡傛灉鎵句笉鍒拌祫婧愶紝灏濊瘯浣跨敤 AssetDatabase.FindAssets 杩涜妯$硦鎼滅储
+            string assetName = System.IO.Path.GetFileName(resourcePath);
+            string[] guids = AssetDatabase.FindAssets(assetName);
+            
+            if (guids != null && guids.Length > 0)
+            {
+                // 鎵惧埌鍖归厤鐨勮祫婧愶紝浼樺厛閫夋嫨璺緞鏈�鍖归厤鐨�
+                string bestMatch = null;
+                foreach (var guid in guids)
+                {
+                    string assetPath = AssetDatabase.GUIDToAssetPath(guid);
+                    if (assetPath.Contains(resourcePath))
+                    {
+                        bestMatch = assetPath;
+                        break;
+                    }
+                }
+                
+                // 濡傛灉娌℃湁瀹屽叏鍖归厤锛屼娇鐢ㄧ涓�涓粨鏋�
+                if (bestMatch == null)
+                {
+                    bestMatch = AssetDatabase.GUIDToAssetPath(guids[0]);
+                }
+                
+                asset = AssetDatabase.LoadAssetAtPath<Object>(bestMatch);
+                if (asset != null)
+                {
+                    Selection.activeObject = asset;
+                    EditorGUIUtility.PingObject(asset);
+                    Debug.Log($"閫氳繃鎼滅储鎵惧埌璧勬簮: {bestMatch}\n(鍘熷璺緞: {resourcePath})");
+                    return;
+                }
+            }
+            
+            Debug.LogWarning($"鏈壘鍒拌祫婧�: {resourcePath}\n灏濊瘯鐨勫熀纭�璺緞: Assets/ResourcesOut/{resourcePath}[extensions]");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Assets/Editor/Tool/BattlePreloadResWatcher.cs.meta b/Assets/Editor/Tool/BattlePreloadResWatcher.cs.meta
new file mode 100644
index 0000000..298b3ad
--- /dev/null
+++ b/Assets/Editor/Tool/BattlePreloadResWatcher.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c91f4ead846c5154db3aa7ed7b93eb8a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

--
Gitblit v1.8.0