419 lines
15 KiB
C#
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 LoveLegend
|
|
{
|
|
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;
|
|
}
|
|
} |