From c607e220884246be14d35da24da6dda35a2eb407 Mon Sep 17 00:00:00 2001
From: lcy <1459594991@qq.com>
Date: 星期二, 23 六月 2026 17:13:55 +0800
Subject: [PATCH] 662 武将试炼 武将副本头像条改Scroller滚动条

---
 /dev/null                                  |   11 --
 Main/System/HeroTrial/HeroTrialHeroItem.cs |   55 ++++++++---
 Main/System/HeroTrial/HeroTrialWin.cs      |  183 ++++++++++++++++++++++++++++++++----
 3 files changed, 202 insertions(+), 47 deletions(-)

diff --git a/Main/System/HeroTrial/HeroTrialCarouselView.cs b/Main/System/HeroTrial/HeroTrialCarouselView.cs
deleted file mode 100644
index a2b086b..0000000
--- a/Main/System/HeroTrial/HeroTrialCarouselView.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-using System.Collections.Generic;
-using UnityEngine;
-
-public class HeroTrialCarouselView : CarouselView<HeroTrialHeroItem, int>
-{
-    [Header("UI References")]
-    public RectTransform content;
-    public GameObject heroTrialItemPrefab;
-
-    [Header("Carousel Settings")]
-    public float itemSpacing = 150f;
-    public float scaleMax = 1.3f;
-    public float scaleMin = 0.8f;
-
-    bool isEventBound;
-
-    protected override RectTransform Content => content;
-    protected override GameObject ItemPrefab => heroTrialItemPrefab;
-    protected override float ItemSpacing => itemSpacing;
-    protected override float ScaleMax => scaleMax;
-    protected override float ScaleMin => scaleMin;
-
-    public uint CurrentHeroID
-    {
-        get
-        {
-            if (TryGetCurrentData(out int heroID))
-                return (uint)heroID;
-            return 0;
-        }
-    }
-
-    public byte CurrentPassLevelNum
-    {
-        get
-        {
-            uint heroID = CurrentHeroID;
-            if (heroID != 0 && HeroTrialManager.Instance.TryGetHeroPassLevelNum(heroID, out byte passLevelNum))
-                return passLevelNum;
-            return 0;
-        }
-    }
-
-    protected override void OnDestroy()
-    {
-        UnbindEvents();
-        base.OnDestroy();
-    }
-
-    public void BindEvents()
-    {
-        if (isEventBound)
-            return;
-
-        isEventBound = true;
-        if (HeroTrialManager.Instance != null)
-            HeroTrialManager.Instance.OnUpdateHeroTrialInfoEvent += OnHeroTrialDataUpdate;
-    }
-
-    public void UnbindEvents()
-    {
-        if (!isEventBound)
-            return;
-
-        isEventBound = false;
-        if (HeroTrialManager.Instance != null)
-            HeroTrialManager.Instance.OnUpdateHeroTrialInfoEvent -= OnHeroTrialDataUpdate;
-    }
-
-    void OnHeroTrialDataUpdate()
-    {
-        RefreshData();
-    }
-
-    public void RefreshData()
-    {
-        uint prevHeroID = CurrentHeroID;
-        List<int> heroIDs = HeroTrialManager.Instance.GetHeroTrialHeroIDList();
-
-        int newIndex = FindHeroIndex(heroIDs, prevHeroID);
-        SetDataList(heroIDs, newIndex >= 0 ? newIndex : 0);
-    }
-
-    int FindHeroIndex(List<int> heroIDs, uint heroID)
-    {
-        if (heroID == 0 || heroIDs.IsNullOrEmpty())
-            return -1;
-
-        for (int i = 0; i < heroIDs.Count; i++)
-        {
-            if ((uint)heroIDs[i] == heroID)
-                return i;
-        }
-
-        return -1;
-    }
-
-    protected override void RefreshItem(HeroTrialHeroItem item, int heroID, int realIndex, bool isSelected)
-    {
-        HeroTrialManager.Instance.TryGetHeroPassLevelNum((uint)heroID, out byte passLevelNum);
-        item.UpdateData((uint)heroID, passLevelNum, realIndex);
-        item.onItemClick = SelectIndex;
-    }
-}
diff --git a/Main/System/HeroTrial/HeroTrialCarouselView.cs.meta b/Main/System/HeroTrial/HeroTrialCarouselView.cs.meta
deleted file mode 100644
index 475bfa0..0000000
--- a/Main/System/HeroTrial/HeroTrialCarouselView.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 97cf454b383948fcb6b584596e6ac35d
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/System/HeroTrial/HeroTrialHeroItem.cs b/Main/System/HeroTrial/HeroTrialHeroItem.cs
index 47331c8..038e9ad 100644
--- a/Main/System/HeroTrial/HeroTrialHeroItem.cs
+++ b/Main/System/HeroTrial/HeroTrialHeroItem.cs
@@ -3,7 +3,7 @@
 using UnityEngine;
 using UnityEngine.UI;
 
-public class HeroTrialHeroItem : MonoBehaviour, ICarouselItem
+public class HeroTrialHeroItem : CellView
 {
     [SerializeField] Image bgImage;
     [SerializeField] Image isActImage;
@@ -15,9 +15,14 @@
     [SerializeField] TextEx goText;
     [SerializeField] ButtonEx clickButton;
     [SerializeField] Image redImage;
+    [SerializeField] RectTransform scaleRoot;
+    [SerializeField] float selectedScale = 1.3f;
+    [SerializeField] float unselectedScale = 0.8f;
+
     public RectTransform rectTransform;
-    public Action<int> onItemClick;
-    public int dataIndex;
+    Action<int> onItemClick;
+    int heroDataIndex;
+    uint currentHeroID;
 
     public RectTransform RectTransform
     {
@@ -29,20 +34,29 @@
         }
     }
 
-    void Awake()
+    public void UpdateData(uint heroID, int index, bool selected, Action<int> clickAction)
     {
-        rectTransform = GetComponent<RectTransform>();
-    }
-
-
-    public void UpdateData(uint heroID, byte passLevelNum, int index)
-    {
-        dataIndex = index;
+        heroDataIndex = index;
+        onItemClick = clickAction;
 
         HeroConfig heroConfig = HeroConfig.Get((int)heroID);
         if (heroConfig == null)
             return;
 
+        if (currentHeroID != heroID)
+        {
+            currentHeroID = heroID;
+            RefreshStaticHeroInfo(heroConfig);
+        }
+
+        UpdateLockState(heroConfig);
+        RefreshRed(heroConfig.HeroID);
+        SetSelected(selected);
+        clickButton.SetListener(OnClick);
+    }
+
+    void RefreshStaticHeroInfo(HeroConfig heroConfig)
+    {
         isActImage.SetActive(heroConfig.IsActLimit > 0);
 
         qualityBgImage.SetSprite("heroheadBG" + heroConfig.Quality);
@@ -54,10 +68,6 @@
             if (skinConfig != null)
                 heroHeadImage.sprite = UILoader.LoadSprite("HeroHead", skinConfig.SquareIcon);
         }
-
-        UpdateLockState(heroConfig);
-        RefreshRed(heroConfig.HeroID);
-        clickButton.SetListener(() => onItemClick?.Invoke(dataIndex));
     }
 
     void RefreshRed(int heroID)
@@ -81,5 +91,20 @@
     {
         string bgKey = selected ? "HeroTrialHeroBgSelect" : "HeroTrialHeroBgUnSelect";
         bgImage.SetSprite(bgKey);
+
+        RectTransform rect = scaleRoot != null ? scaleRoot : RectTransform;
+        if (rect == null)
+            return;
+
+        float currentScale = selected ? selectedScale : unselectedScale;
+        float maxScale = Mathf.Max(selectedScale, unselectedScale);
+        float posY = (maxScale - currentScale) * rect.rect.height * 0.5f;
+        rect.localScale = Vector3.one * currentScale;
+        rect.anchoredPosition = rect.anchoredPosition.SetY(posY);
+    }
+
+    void OnClick()
+    {
+        onItemClick?.Invoke(heroDataIndex);
     }
 }
diff --git a/Main/System/HeroTrial/HeroTrialWin.cs b/Main/System/HeroTrial/HeroTrialWin.cs
index da57a92..4bd2321 100644
--- a/Main/System/HeroTrial/HeroTrialWin.cs
+++ b/Main/System/HeroTrial/HeroTrialWin.cs
@@ -1,18 +1,24 @@
 using System.Collections.Generic;
+using EnhancedUI.EnhancedScroller;
 using UnityEngine;
+using UnityEngine.UI;
 
 public class HeroTrialWin : UIBase
 {
-    [SerializeField] HeroTrialCarouselView carouselView;
+    [SerializeField] ScrollerController heroScroller;
     [SerializeField] ScrollerController scroller;
+    [SerializeField] float heroSelectTweenTime = 0.15f;
 
+    List<int> heroIDs;
     List<HeroTrialConfig> currentConfigs = new List<HeroTrialConfig>();
+    int currentHeroIndex = -1;
     uint currentHeroID;
     byte currentPassLevelNum;
     bool currentHeroUnlocked;
     string currentHeroUnlockTip = string.Empty;
     // OnPreOpen 棣栨鎵撳紑鏃剁敤浜庡畾浣嶅埌绾㈢偣鍏冲崱鐨� dataIndex锛�-1 琛ㄧず涓嶈烦杞��
     int jumpTargetDataIndex = -1;
+    bool needJumpToHeroAfterScrollerReady;
 
     protected override void InitComponent()
     {
@@ -20,46 +26,37 @@
 
     protected override void OnPreOpen()
     {
-        carouselView.InitPool();
-        carouselView.BindEvents();
-        carouselView.OnSelectedIndexChanged += OnSelectedIndexChanged;
-
+        SetupHeroScroller();
+        heroScroller.OnRefreshCell += OnRefreshHeroCell;
+        heroScroller.OnRefreshCompleteEvent += OnHeroScrollerRefreshComplete;
         scroller.OnRefreshCell += OnRefreshCell;
         HeroTrialManager.Instance.OnUpdateHeroTrialInfoEvent += OnHeroTrialInfoUpdate;
 
-        carouselView.RefreshData();
-        carouselView.InitWithIndex(GetDefaultHeroIndex());
-
+        RefreshHeroScroller(GetDefaultHeroIndex());
         RefreshScroller();
     }
 
     protected override void OnPreClose()
     {
-        carouselView.UnbindEvents();
-        carouselView.OnSelectedIndexChanged -= OnSelectedIndexChanged;
+        heroScroller.OnRefreshCell -= OnRefreshHeroCell;
+        heroScroller.OnRefreshCompleteEvent -= OnHeroScrollerRefreshComplete;
         scroller.OnRefreshCell -= OnRefreshCell;
         HeroTrialManager.Instance.OnUpdateHeroTrialInfoEvent -= OnHeroTrialInfoUpdate;
     }
 
-    void OnSelectedIndexChanged()
-    {
-        RefreshScroller();
-    }
-
     void OnHeroTrialInfoUpdate()
     {
+        int targetHeroIndex = -1;
         int redHeroIndex = FindRedHeroIndex();
         if (redHeroIndex >= 0)
         {
             List<int> heroIDList = HeroTrialManager.Instance.GetHeroTrialHeroIDList();
             int redHeroID = heroIDList[redHeroIndex];
-            if (carouselView.CurrentHeroID != redHeroID)
-            {
-                carouselView.SelectIndex(redHeroIndex);
-                return;
-            }
+            if (currentHeroID != redHeroID)
+                targetHeroIndex = redHeroIndex;
         }
 
+        RefreshHeroScroller(targetHeroIndex);
         RefreshScroller();
     }
 
@@ -97,13 +94,157 @@
         return -1;
     }
 
+    void RefreshHeroScroller(int selectedIndex)
+    {
+        uint prevHeroID = currentHeroID;
+        heroIDs = HeroTrialManager.Instance.GetHeroTrialHeroIDList();
+
+        if (heroIDs.IsNullOrEmpty())
+        {
+            currentHeroIndex = -1;
+            currentHeroID = 0;
+            heroScroller.Refresh();
+            heroScroller.Restart();
+            return;
+        }
+
+        int heroIndex = selectedIndex;
+        if (heroIndex < 0)
+            heroIndex = FindHeroIndex(prevHeroID);
+        currentHeroIndex = Mathf.Clamp(heroIndex, 0, heroIDs.Count - 1);
+        currentHeroID = (uint)heroIDs[currentHeroIndex];
+
+        SetupHeroScroller();
+        heroScroller.Refresh();
+        for (int i = 0; i < heroIDs.Count; i++)
+        {
+            heroScroller.AddCell(ScrollerDataType.Header, i);
+        }
+        heroScroller.Restart();
+        needJumpToHeroAfterScrollerReady = true;
+        JumpToCurrentHero(false);
+    }
+
+    void SelectHeroIndex(int index)
+    {
+        if (heroIDs.IsNullOrEmpty())
+            return;
+
+        int oldIndex = currentHeroIndex;
+        currentHeroIndex = Mathf.Clamp(index, 0, heroIDs.Count - 1);
+        currentHeroID = (uint)heroIDs[currentHeroIndex];
+        RefreshActiveHeroItems();
+        JumpToCurrentHero(true);
+
+        if (oldIndex != currentHeroIndex)
+            RefreshScroller();
+    }
+
+    void OnRefreshHeroCell(ScrollerDataType type, CellView cell)
+    {
+        _ = type;
+
+        HeroTrialHeroItem heroItem = cell as HeroTrialHeroItem;
+        if (heroItem == null || heroIDs.IsNullOrEmpty())
+            return;
+
+        int dataIndex = Mathf.Clamp(cell.index, 0, heroIDs.Count - 1);
+        heroItem.UpdateData((uint)heroIDs[dataIndex], dataIndex, dataIndex == currentHeroIndex, SelectHeroIndex);
+    }
+
+    void OnHeroScrollerRefreshComplete()
+    {
+        RefreshActiveHeroItems();
+
+        if (!needJumpToHeroAfterScrollerReady)
+            return;
+
+        needJumpToHeroAfterScrollerReady = false;
+        JumpToCurrentHero(false);
+    }
+
+    void RefreshActiveHeroItems()
+    {
+        List<CellView> activeCells = heroScroller.GetActiveCellViews();
+        if (activeCells == null)
+            return;
+
+        for (int i = 0; i < activeCells.Count; i++)
+        {
+            OnRefreshHeroCell(activeCells[i].type, activeCells[i]);
+        }
+    }
+
+    void SetupHeroScroller()
+    {
+        heroScroller.horizontal = true;
+        heroScroller.vertical = false;
+        heroScroller.lockType = EnhanceLockType.None;
+
+        heroScroller.m_Scorller.Loop = false;
+        heroScroller.m_Scorller.snapping = false;
+        heroScroller.m_Scorller.scrollDirection = EnhancedScroller.ScrollDirectionEnum.Horizontal;
+
+        ScrollRect scrollRect = heroScroller.mScrollRect;
+        if (scrollRect != null)
+        {
+            scrollRect.horizontal = true;
+            scrollRect.vertical = false;
+        }
+    }
+
+    void JumpToCurrentHero(bool useTween)
+    {
+        if (heroIDs.IsNullOrEmpty() || currentHeroIndex < 0)
+            return;
+        if (!heroScroller.m_Scorller.inited)
+        {
+            needJumpToHeroAfterScrollerReady = true;
+            return;
+        }
+
+        float scrollerOffset = GetCurrentHeroScrollerOffset();
+        EnhancedScroller.TweenType tweenType = useTween ? EnhancedScroller.TweenType.easeOutQuad : EnhancedScroller.TweenType.immediate;
+        float tweenTime = useTween ? heroSelectTweenTime : 0f;
+        heroScroller.m_Scorller.JumpToDataIndex(currentHeroIndex, scrollerOffset, 0.5f, true, tweenType, tweenTime, RefreshActiveHeroItems);
+    }
+
+    float GetCurrentHeroScrollerOffset()
+    {
+        if (heroIDs.IsNullOrEmpty())
+            return 0.5f;
+
+        float viewportSize = Mathf.Max(1f, heroScroller.m_Scorller.ScrollRectSize);
+        float cellSize = Mathf.Max(1f, heroScroller.GetCellSize(currentHeroIndex));
+        float halfCellOffset = cellSize * 0.5f / viewportSize;
+
+        if (currentHeroIndex <= 0)
+            return halfCellOffset;
+        if (currentHeroIndex >= heroIDs.Count - 1)
+            return Mathf.Clamp01(1f - halfCellOffset);
+        return 0.5f;
+    }
+
+    int FindHeroIndex(uint heroID)
+    {
+        if (heroID == 0 || heroIDs.IsNullOrEmpty())
+            return -1;
+
+        for (int i = 0; i < heroIDs.Count; i++)
+        {
+            if ((uint)heroIDs[i] == heroID)
+                return i;
+        }
+
+        return -1;
+    }
+
     /// <summary>
     /// 鏍规嵁褰撳墠閫変腑鐨勬灏嗭紝鍒锋柊涓嬫柟鐨勫叧鍗croll
     /// </summary>
     void RefreshScroller()
     {
         currentConfigs.Clear();
-        currentHeroID = carouselView.CurrentHeroID;
         currentHeroUnlockTip = string.Empty;
         currentHeroUnlocked = currentHeroID != 0 && HeroTrialManager.Instance.IsHeroTrialHeroUnlocked((int)currentHeroID, out currentHeroUnlockTip);
         if (currentHeroID == 0 || !HeroTrialManager.Instance.TryGetHeroPassLevelNum(currentHeroID, out currentPassLevelNum))

--
Gitblit v1.8.0