Files
RedHotRoast-ios/Assets/Scripts/ModuleUI/Live/LiveUI.cs
T

419 lines
15 KiB
C#

// using System;
using System;
using System.Collections.Generic;
using System.IO;
// using System.IO;
using FairyGUI;
using FGUI.LG_Common;
using FGUI.LG_live;
using SGModule.Common.Extensions;
using UnityEngine;
using UnityEngine.Video;
namespace RedHotRoast
{
public class LiveUI : BaseUI
{
private const int MaxVisibleCount = 6; // 一屏最多6个播放器
private const int PreloadCount = 2; // 上下各预加载一屏
private static readonly Dictionary<item_live, VideoPlayer> dictionary_ = new();
private readonly Dictionary<int, GLoader> activeLoaders = new();
private readonly Dictionary<int, bool> _fileIsExist = 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 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)
{
var livedata_ = PreDownloadManager.GetLiveDataByIndex(LiveConfig[index], index);
item.state.selectedIndex = livedata_.progress >= 100 ? 0 : 1;
item.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;
}
}
// 初始化页面逻辑
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();
UnityEngine.Object.Destroy(videoParent);
foreach (var t in loader_list)
if (t != null && !t.isDisposed && t.texture != null)
{
t.texture.Dispose();
t.texture = null;
}
MemoryManager.CleanMemoryMonitor();
activeLoaders.Clear();
_fileIsExist.Clear();
GLoaderPool.Instance.DisposeAll();
}
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.onScroll.Add(OnScrollUpdate);
ui.list_.scrollPane.onScrollEnd.Add(OnScrollEnd);
// 打开页面时初始化一次
OnScrollEnd();
}
private void OnScrollUpdate()
{
if (LiveConfig == null || LiveConfig.Count == 0) return;
var firstVisibleIndex = ui.list_.GetFirstChildInView();
var lastVisibleIndex = Mathf.Min(firstVisibleIndex + MaxVisibleCount - 1, ui.list_.numItems - 1);
var startIndex = Mathf.Max(0, firstVisibleIndex - PreloadCount);
var endIndex = Mathf.Min(ui.list_.numItems - 1, lastVisibleIndex + PreloadCount);
// 回收超出范围 loader
var keysToRemove = new List<int>();
foreach (var kv in activeLoaders)
{
var idx = kv.Key;
if (idx < startIndex || idx > endIndex)
{
GLoaderPool.Instance.ReturnLoader(kv.Value);
var oldItem = ui.list_.GetChildAt(idx) as item_live;
if (oldItem != null) {
(oldItem.img_cover as com_loaderMask_circlle).loader = null;
}
keysToRemove.Add(idx);
}
}
foreach (var k in keysToRemove) activeLoaders.Remove(k);
// 分配 loader 并加载图片
for (var i = startIndex; i <= endIndex; i++)
{
if (activeLoaders.ContainsKey(i)) continue;
var item = ui.list_.GetChildAt(i) as item_live;
if (item == null) continue;
if ((item.img_cover as com_loaderMask_circlle).loader != null && !(item.img_cover as com_loaderMask_circlle).loader.isDisposed)
GLoaderPool.Instance.ReturnLoader((item.img_cover as com_loaderMask_circlle).loader);
var loader = GLoaderPool.Instance.GetLoader();
(item.img_cover as com_loaderMask_circlle).loader = loader;
item.img_cover.AddChild(loader);
loader.SetSize(item.img_cover.width, item.img_cover.height);
item.img_cover.visible = true;
_fileIsExist.TryGetValue(i, out var value);
if (!value)
{
var localPath = Path.Combine(TextureHelper.getResPath(), "LiveVideoCovers", LiveConfig[i].Name + "_cover" + ".jpg");
if (File.Exists(localPath))
{
_fileIsExist[i] = true;
Debug.Log($"[SetImgLoader] 本地存在,直接加载 {LiveConfig[i].Name + "_cover"}");
CrazyAsyKit.StartCoroutine(TextureHelper.LoadTexture(LiveConfig[i].Name + "_cover", loader, null,
"LiveVideoCovers/"));
}
else
{
_fileIsExist[i] = false;
CrazyAsyKit.StartCoroutine(LiveVideoManager.Instance.LoadCover(LiveConfig[i].Name + "_cover", tex =>
{
if (tex != null)
{
if (loader != null)
{
loader.texture = new NTexture(tex);
loader.visible = true;
}
}
else
{
Debug.LogWarning("封面获取失败");
}
}));
}
}
else
{
CrazyAsyKit.StartCoroutine(TextureHelper.LoadTexture(LiveConfig[i].Name + "_cover", loader, null,
"LiveVideoCovers/"));
}
activeLoaders[i] = loader;
}
}
private HashSet<item_live> lastVisibleItems = new();
private void OnScrollEnd()
{
var tasks = new List<(GLoader loader, string fileName, Action<NTexture> callback, string folder, string localFolder)>();
var firstVisibleIndex = ui.list_.GetFirstChildInView();
var lastVisibleIndex = Mathf.Min(firstVisibleIndex + MaxVisibleCount - 1, ui.list_.numItems - 1);
var startIndex = Mathf.Max(0, firstVisibleIndex - PreloadCount);
var endIndex = Mathf.Min(ui.list_.numItems - 1, lastVisibleIndex + PreloadCount);
for (var i = startIndex; i <= endIndex; i++)
{
_fileIsExist.TryGetValue(i, out var value);
if (value) continue;
if (ui.list_.GetChildAt(i) is item_live item)
{
if ((item.img_cover as com_loaderMask_circlle).loader != null && !(item.img_cover as com_loaderMask_circlle).loader.isDisposed)
GLoaderPool.Instance.ReturnLoader((item.img_cover as com_loaderMask_circlle).loader);
var loader = GLoaderPool.Instance.GetLoader();
(item.img_cover as com_loaderMask_circlle).loader = loader;
item.img_cover.AddChild(loader);
loader.SetSize(item.img_cover.width, item.img_cover.height);
var idx = i;
tasks.Add((loader, LiveConfig[i].Name + "_cover", texture =>
{
if (texture != null) _fileIsExist[idx] = true;
}, "LiveAlbums/", FolderNames.VideoCoversName));
activeLoaders[i] = loader;
}
}
TextureHelper.SetImgLoaders(tasks);
Debug.Log($"[OnScrollEnd]==lastVisibleItems=== {lastVisibleItems.Count}");
VideoLoadScheduler.ClearAll();
// 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 < 100) 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 < 100 ? 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.img_mask.fillAmount = (float)(100 - livedata_.progress) / 100;
// 点击事件
item.SetClick(() =>
{
if (GameHelper.GetLevel() < GameHelper.GetCommonModel().UnlockLive[1])
{
if (DataMgr.IsUnlockLive.Value < 0 && !GameHelper.GetVipPrivilege(Subscription.UnlockLive.As<int>()))
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)
{
dictionary_.TryGetValue(item, out var player);
// 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;
}
#endregion
}
public class LiveData
{
public int AD_num;
public int progress;
public int Singleprogress;
public long LiveADTime;
}
}