Files
BallCrushBest_GP/Assets/Scripts/ModuleUI/Live/LiveUI.cs
T
2026-04-20 12:06:34 +08:00

296 lines
9.3 KiB
C#

using System.Collections.Generic;
using FairyGUI;
using FGUI.LG_live;
using SGModule.Common.Extensions;
using UnityEngine;
using UnityEngine.Video;
namespace BallKingdomCrush
{
public class LiveUI : BaseUI
{
private const int MaxVisibleCount = 6; // 一屏最多6个播放器
private static readonly Dictionary<item_live, VideoPlayer> dictionary_ = new();
private LiveUICtrl ctrl;
private float late_time = 0.1f;
private List<Live> LiveConfig;
private LiveModel model;
private com_live ui;
private GameObject videoParent;
public LiveUI(LiveUICtrl ctrl) : base(ctrl)
{
uiName = UIConst.LiveUI;
this.ctrl = ctrl;
}
protected override void SetUIInfo(UIInfo uiInfo)
{
uiInfo.packageName = "LG_live";
uiInfo.assetName = "com_live";
uiInfo.layerType = UILayerType.Popup;
uiInfo.isNeedOpenAnim = false;
uiInfo.isNeedCloseAnim = false;
uiInfo.isNeedUIMask = true;
}
private void UpdateEvent()
{
late_time = 0.1f;
}
// 初始化页面逻辑
private void InitView()
{
}
#region
protected override void OnInit()
{
videoParent = new GameObject("VideoPlayerParent");
VideoPlayerPool.Instance.Init(videoParent, MaxVisibleCount);
}
protected override void OnClose()
{
// 归还所有播放器
foreach (var kvp in dictionary_)
VideoPlayerPool.Instance.ReturnPlayer(kvp.Value);
dictionary_.Clear();
VideoPlayerPool.Instance.DisposeAll();
Object.Destroy(videoParent);
foreach (var t in loader_list)
if (t != null && !t.isDisposed && t.texture != null)
{
t.texture.Dispose();
t.texture = null;
}
GLoaderPool.Instance.DisposeAll();
TextureHelper.ClearMaterialPool();
// 强制卸载未使用的资源
Resources.UnloadUnusedAssets();
MemoryManager.CleanMemoryMonitor();
}
protected override void OnBind()
{
ui = baseUI as com_live;
}
private readonly List<GLoader> loader_list = new();
protected override void OnOpenBefore(object args)
{
LiveConfig = ConfigSystem.GetConfig<Live>();
ui.list_.itemRenderer = RendererList;
Debug.Log($"LiveConfig.Count==1=== {LiveConfig.Count}");
ui.list_.numItems = LiveConfig.Count;
ui.btn_close.SetClick(() => { CtrlCloseUI(); });
InitView();
// 滚动过程中实时刷新可见播放器
ui.list_.scrollPane.onScrollEnd.Add(OnScrollEnd);
// 打开页面时初始化一次
OnScrollEnd();
}
private HashSet<item_live> lastVisibleItems = new();
private void OnScrollEnd()
{
Debug.Log($"[OnScrollEnd]==lastVisibleItems=== {lastVisibleItems.Count}");
// 1️⃣ 回收上一次的可见播放器
foreach (var oldItem in lastVisibleItems)
if (dictionary_.TryGetValue(oldItem, out var player))
{
player.Pause();
player.targetTexture?.Release();
VideoPlayerPool.Instance.ReturnPlayer(player);
dictionary_.Remove(oldItem);
oldItem.com_loader.visible = false;
oldItem.img_cover.visible = true;
}
lastVisibleItems.Clear();
// 2️⃣ 获取当前可见项
var firstIndex = ui.list_.GetFirstChildInView();
var lastIndex = Mathf.Min(firstIndex + MaxVisibleCount, ui.list_.numItems);
HashSet<item_live> newVisibleItems = new();
for (var i = firstIndex; i < lastIndex; i++)
if (ui.list_.GetChildAt(i) is item_live item)
{
newVisibleItems.Add(item);
// 分配播放器
if (!dictionary_.ContainsKey(item))
{
var player = VideoPlayerPool.Instance.GetPlayer();
if (player != null)
{
dictionary_[item] = player;
BindPlayerToItem(item, i);
}
}
}
// 3️⃣ 保存为“上一次可见项”
lastVisibleItems = newVisibleItems;
}
private void BindPlayerToItem(item_live item, int index)
{
var data = PreDownloadManager.GetLiveDataByIndex(LiveConfig[index], index);
Debug.Log($"[绑定播放器 进度] progress==1=== {data.progress}");
if (data.progress <= 0) return;
var player = dictionary_[item];
var loader = item.com_loader.GetChild("loader") as GLoader;
item.com_loader.visible = true;
if (!loader_list.Contains(loader)) loader_list.Add(loader);
TextureHelper.SetVideoLoader(player, loader, LiveConfig[index].Name, vp =>
{
if (vp != null && !item.isDisposed)
{
if (data.progress >= 100)
{
item.img_cover.visible = false;
GameDispatcher.Instance.Dispatch(GameMsg.liveVideoLoaded);
}
}
});
}
private void RendererList(int index, GObject obj)
{
var livedata_ = PreDownloadManager.GetLiveDataByIndex(LiveConfig[index], index);
var item = (item_live)obj;
// UI状态显示
item.state.selectedIndex = livedata_.progress <= 0 ? 1 : 0;
if (LiveConfig[index].SubscribeUnlock == 1)
{
if (livedata_.progress < 100) item.vip.selectedIndex = 1;
else item.vip.selectedIndex = 2;
}
else item.vip.selectedIndex = 0;
item.mask.img_mask.fillAmount = (float)(100 - livedata_.progress) / 100;
var coverLoader = item.img_cover.GetChild("loader") as GLoader;
LiveVideoManager.Instance.GetVideoCover(coverLoader, LiveConfig[index].Name + "_cover", (tex) => {
if (tex != null) {
if (coverLoader != null) {
coverLoader.texture = new NTexture(tex);
coverLoader.visible = true;
}
}
});
// 点击事件
item.SetClick(() =>
{
if (GameHelper.GetLevel() < GameHelper.GetCommonModel().UnlockLive[1])
{
if (DataMgr.IsUnlockLive.Value < 0 && DataMgr.VipLevel.Value < 0) UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.SecretUnlockUI_Open, 2);
else if (DataMgr.IsUnlockLive.Value == 0) UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.UnlockTipsUI_Open, 2);
else HandleDetailOpen(item, index);
}
else
{
HandleDetailOpen(item, index);
}
});
}
private void HandleDetailOpen(item_live item, int index)
{
if (dictionary_.TryGetValue(item, out var player))
uiCtrlDispatcher.Dispatch(UICtrlMsg.LiveDetailUI_Open, (index, player));
}
protected override void OnOpen(object args)
{
}
protected override void OnHide()
{
}
protected override void OnDisplay(object args)
{
}
#endregion
#region
protected override void AddListener()
{
GameDispatcher.Instance.AddListener(GameMsg.LiveChange, Refresh);
HallManager.Instance.UpdateEvent += UpdateEvent;
}
protected override void RemoveListener()
{
GameDispatcher.Instance.RemoveListener(GameMsg.LiveChange, Refresh);
HallManager.Instance.UpdateEvent -= UpdateEvent;
}
private void Refresh(object param = null)
{
var index = param.As<int>();
// ui.list_.itemRenderer = RendererList;
// Debug.Log($"LiveConfig.Count==2=== {LiveConfig.Count}");
// ui.list_.numItems = LiveConfig.Count;
if (ui.list_.GetChildAt(index) is item_live item)
{
item.state.selectedIndex = 0;
var livedata_ = PreDownloadManager.GetLiveDataByIndex(LiveConfig[index], index);
item.mask.img_mask.fillAmount = (float)(100 - livedata_.progress) / 100;
BindPlayerToItem(item, index);
if (LiveConfig[index].SubscribeUnlock == 1)
{
if (livedata_.progress < 100) item.vip.selectedIndex = 1;
else item.vip.selectedIndex = 2;
}
else item.vip.selectedIndex = 0;
}
}
#endregion
}
public class LiveData
{
public int AD_num;
public int progress;
public int Singleprogress;
public long LiveADTime;
}
}