2026-04-24 16:57:44 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
2026-05-18 08:42:33 +08:00
|
|
|
|
using Kill.Core;
|
2026-04-24 16:57:44 +08:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
using UnityEngine.Video;
|
|
|
|
|
|
namespace Kill.UI.Components
|
|
|
|
|
|
{
|
|
|
|
|
|
public class VideoCtrl : MonoBehaviour
|
2026-05-18 08:42:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
public bool istest;
|
|
|
|
|
|
public VideoPlayer videoPlayer;
|
2026-04-24 16:57:44 +08:00
|
|
|
|
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public bool needFullScreen = false;
|
|
|
|
|
|
bool isFullScreen = false;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 0:正常播放 1:全屏播放
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public List<RenderTexture> renderTextures;
|
|
|
|
|
|
public RawImage windowImage;
|
|
|
|
|
|
public RawImage fullImage;
|
2026-08-20 15:50:11 +08:00
|
|
|
|
/// <summary>竖屏全屏UI(竖屏视频全屏时使用,在场景中配置)</summary>
|
|
|
|
|
|
public RawImage portraitFullImage;
|
|
|
|
|
|
/// <summary>当前使用的全屏显示目标(根据视频宽高比选择)</summary>
|
|
|
|
|
|
RawImage currentFullImage;
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public GameObject playButton;
|
|
|
|
|
|
public GameObject pauseButton;
|
|
|
|
|
|
public Text totalTimeText;
|
|
|
|
|
|
public Text nowTime;
|
|
|
|
|
|
public Slider slider;
|
|
|
|
|
|
bool isplaying = false;
|
2026-06-08 08:55:10 +08:00
|
|
|
|
bool ispause = true;
|
2026-05-18 08:42:33 +08:00
|
|
|
|
Action playOver;
|
|
|
|
|
|
string url;
|
2026-06-12 16:07:27 +08:00
|
|
|
|
public GameObject loading;
|
2026-05-18 08:42:33 +08:00
|
|
|
|
private void FixedUpdate()
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
if (isplaying)
|
|
|
|
|
|
{
|
2026-04-24 16:57:44 +08:00
|
|
|
|
|
2026-05-18 08:42:33 +08:00
|
|
|
|
OnVideoPlaying();
|
|
|
|
|
|
}
|
2026-04-24 16:57:44 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public void Init(string url, Action playOver)
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-06-12 16:07:27 +08:00
|
|
|
|
if(loading)
|
|
|
|
|
|
loading.SetActive(true);
|
2026-08-20 15:50:11 +08:00
|
|
|
|
// 视频加载完成前隐藏窗口画面,避免显示上一个视频残留
|
|
|
|
|
|
if (windowImage != null)
|
|
|
|
|
|
windowImage.gameObject.SetActive(false);
|
|
|
|
|
|
// 停止播放状态与进度记录,避免加载期间用旧数据刷新进度条/时间
|
|
|
|
|
|
isplaying = false;
|
|
|
|
|
|
lastFrame = 0;
|
|
|
|
|
|
// 重置时间显示,避免加载期间显示上一个视频的旧时长
|
|
|
|
|
|
totalTime = 0;
|
2026-06-08 08:55:10 +08:00
|
|
|
|
nowTime.text=SecondToHour(0);
|
2026-08-20 15:50:11 +08:00
|
|
|
|
if (totalTimeText != null)
|
|
|
|
|
|
totalTimeText.text=SecondToHour(0);
|
|
|
|
|
|
if (slider != null)
|
|
|
|
|
|
slider.value=0;
|
2026-05-18 08:42:33 +08:00
|
|
|
|
this.playOver = playOver;
|
|
|
|
|
|
this.url = url;
|
|
|
|
|
|
SetVideo(url);
|
|
|
|
|
|
if (playButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
playButton.SetActive(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pauseButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
pauseButton.SetActive(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
ispause = true;
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public void PlayVideo()
|
|
|
|
|
|
{
|
|
|
|
|
|
StartCoroutine(YieldPlay());
|
2026-04-24 16:57:44 +08:00
|
|
|
|
|
2026-05-18 08:42:33 +08:00
|
|
|
|
}
|
2026-04-24 16:57:44 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public IEnumerator YieldPlay()
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
yield return new WaitForSeconds(0.1f);
|
|
|
|
|
|
ispause = false;
|
|
|
|
|
|
videoPlayer.Play();
|
|
|
|
|
|
if (playButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
playButton.SetActive(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pauseButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
pauseButton.SetActive(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
isplaying = true;
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public void PauseVideo()
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
ispause = true;
|
|
|
|
|
|
videoPlayer.Pause();
|
|
|
|
|
|
isplaying = false;
|
|
|
|
|
|
if (playButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
playButton.SetActive(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pauseButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
pauseButton.SetActive(false);
|
|
|
|
|
|
}
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public void RePlay()
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
videoPlayer.Stop();
|
|
|
|
|
|
videoPlayer.frame = 0;
|
|
|
|
|
|
PlayVideo();
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public void SetVideo(string url)
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
videoPlayer.url = url;
|
|
|
|
|
|
videoPlayer.prepareCompleted += VideoPrepared;
|
|
|
|
|
|
videoPlayer.Prepare();
|
|
|
|
|
|
if (playButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
playButton.SetActive(true);
|
|
|
|
|
|
}
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-06-08 08:55:10 +08:00
|
|
|
|
public void Stop()
|
|
|
|
|
|
{
|
|
|
|
|
|
videoPlayer.Stop();
|
|
|
|
|
|
videoPlayer.url = "";
|
2026-08-20 15:50:11 +08:00
|
|
|
|
isplaying = false;
|
|
|
|
|
|
lastFrame = 0;
|
2026-06-08 08:55:10 +08:00
|
|
|
|
nowTime.text=SecondToHour(0);
|
2026-08-20 15:50:11 +08:00
|
|
|
|
// 停止时清空总时长与进度条,避免残留上一个视频的显示
|
|
|
|
|
|
totalTime = 0;
|
|
|
|
|
|
if (totalTimeText != null)
|
|
|
|
|
|
totalTimeText.text=SecondToHour(0);
|
|
|
|
|
|
if (slider != null)
|
|
|
|
|
|
slider.value=0;
|
2026-06-08 08:55:10 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
int totalTime = 0;
|
|
|
|
|
|
public void VideoPrepared(VideoPlayer player)
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
if (renderTextures != null && renderTextures.Count > 0)
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
foreach (var r in renderTextures)
|
|
|
|
|
|
Destroy(r);
|
|
|
|
|
|
renderTextures.Clear();
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
renderTextures=new List<RenderTexture>();
|
2026-08-20 15:50:11 +08:00
|
|
|
|
// 窗口视图:完整显示视频并居中,保持比例,多余部分留黑(竖屏视频占满高度、两侧留黑)
|
2026-05-18 08:42:33 +08:00
|
|
|
|
RenderTexture texture = new RenderTexture((int)player.width, (int)player.height, 1);
|
|
|
|
|
|
renderTextures.Add(texture);
|
|
|
|
|
|
player.targetTexture = texture;
|
|
|
|
|
|
windowImage.texture = texture;
|
2026-08-20 15:50:11 +08:00
|
|
|
|
// 视频加载完成,重新显示窗口画面
|
|
|
|
|
|
if (windowImage != null)
|
|
|
|
|
|
windowImage.gameObject.SetActive(true);
|
|
|
|
|
|
FitWindowAspect(windowImage, player.width / (float)Mathf.Max(1, (int)player.height));
|
2026-05-18 08:42:33 +08:00
|
|
|
|
if (needFullScreen)
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-08-20 15:50:11 +08:00
|
|
|
|
// 根据视频宽高比选择全屏UI:竖屏视频用竖屏全屏UI,否则用默认全屏UI
|
|
|
|
|
|
currentFullImage = (player.width < player.height && portraitFullImage != null) ? portraitFullImage : fullImage;
|
|
|
|
|
|
// 全屏纹理按视频分辨率创建,保证宽高比正确、不变形
|
|
|
|
|
|
RenderTexture fullTexture = new RenderTexture((int)player.width, (int)player.height, 1);
|
2026-05-18 08:42:33 +08:00
|
|
|
|
renderTextures.Add(fullTexture);
|
2026-08-20 15:50:11 +08:00
|
|
|
|
currentFullImage.texture = fullTexture;
|
|
|
|
|
|
// 显示区域铺满屏幕,保持视频比例,超出部分裁剪(cover模式:尽量铺满屏幕)
|
|
|
|
|
|
float videoAspect = player.width / (float)Mathf.Max(1, (int)player.height);
|
|
|
|
|
|
var fullRt = currentFullImage.rectTransform;
|
|
|
|
|
|
var fullParent = fullRt.parent as RectTransform;
|
|
|
|
|
|
currentFullImage.uvRect = new Rect(0, 0, 1, 1);
|
|
|
|
|
|
if (fullParent != null && fullParent.rect.width > 0 && fullParent.rect.height > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
float parentW = fullParent.rect.width;
|
|
|
|
|
|
float parentH = fullParent.rect.height;
|
|
|
|
|
|
// 检测全屏UI是否旋转了90°(横屏视频旋转90°后铺满竖屏手机屏幕)
|
|
|
|
|
|
float rotZ = Mathf.Abs(Mathf.DeltaAngle(fullRt.localEulerAngles.z, 0f));
|
|
|
|
|
|
bool rotated90 = rotZ >= 45f && rotZ <= 135f;
|
|
|
|
|
|
if (rotated90)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 旋转90°的UI:矩形宽高互换,旋转后视觉铺满屏幕
|
|
|
|
|
|
fullRt.anchorMin = new Vector2(0.5f, 0.5f);
|
|
|
|
|
|
fullRt.anchorMax = new Vector2(0.5f, 0.5f);
|
|
|
|
|
|
fullRt.pivot = new Vector2(0.5f, 0.5f);
|
|
|
|
|
|
fullRt.sizeDelta = new Vector2(parentH, parentW);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
fullRt.anchorMin = Vector2.zero;
|
|
|
|
|
|
fullRt.anchorMax = Vector2.one;
|
|
|
|
|
|
fullRt.pivot = new Vector2(0.5f, 0.5f);
|
|
|
|
|
|
fullRt.sizeDelta = Vector2.zero;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 按视频比例裁剪(cover):旋转后视频宽对应屏幕高,显示比例需取反
|
|
|
|
|
|
float frameAspect = rotated90 ? parentH / parentW : parentW / parentH;
|
|
|
|
|
|
if (Mathf.Abs(frameAspect - videoAspect) >= 0.001f)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (videoAspect > frameAspect)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 视频相对更宽:裁剪左右
|
|
|
|
|
|
float uvW = frameAspect / videoAspect;
|
|
|
|
|
|
currentFullImage.uvRect = new Rect((1 - uvW) / 2f, 0, uvW, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 视频相对更窄:裁剪上下
|
|
|
|
|
|
float uvH = videoAspect / frameAspect;
|
|
|
|
|
|
currentFullImage.uvRect = new Rect(0, (1 - uvH) / 2f, 1, uvH);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
videoPlayer.frame = 0;
|
|
|
|
|
|
if (slider != null)
|
2026-08-20 15:50:11 +08:00
|
|
|
|
slider.value = 0;
|
|
|
|
|
|
// 总时长计算:优先用 length(秒);切换视频时 frameCount 可能残留旧视频的帧数,作为兜底
|
|
|
|
|
|
float duration = (float)player.length;
|
|
|
|
|
|
if (duration > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
totalTime = (int)(duration + 0.5f);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (player.frameCount > 0 && player.frameRate > 0)
|
2026-05-18 08:42:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
totalTime = (int)(player.frameCount / player.frameRate + 0.5f);
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-08-20 15:50:11 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
totalTime = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (totalTimeText != null)
|
|
|
|
|
|
totalTimeText.text = SecondToHour(totalTime);
|
2026-04-24 16:57:44 +08:00
|
|
|
|
|
2026-05-18 08:42:33 +08:00
|
|
|
|
videoPlayer.prepareCompleted -= VideoPrepared;
|
|
|
|
|
|
|
|
|
|
|
|
player.loopPointReached += VideoOver;
|
|
|
|
|
|
if (playButton != null)
|
|
|
|
|
|
playButton.SetActive(true);
|
2026-06-08 08:55:10 +08:00
|
|
|
|
nowTime.text=SecondToHour(0);
|
2026-06-12 16:07:27 +08:00
|
|
|
|
if(loading)
|
|
|
|
|
|
loading.SetActive(false);
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-08-20 15:50:11 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 窗口显示适配:在窗口内完整显示视频(contain模式)并居中,保持比例,多余部分留黑
|
|
|
|
|
|
/// 竖屏视频占满高度、两侧留黑;横屏视频占满宽度、上下留黑
|
|
|
|
|
|
/// 仅调整windowImage(铺满窗口的RawImage)自身的尺寸,不影响窗口UI位置
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void FitWindowAspect(RawImage image, float videoAspect)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (image == null) return;
|
|
|
|
|
|
var rt = image.rectTransform;
|
|
|
|
|
|
var parent = rt.parent as RectTransform;
|
|
|
|
|
|
float parentW = parent != null ? parent.rect.width : Screen.width;
|
|
|
|
|
|
float parentH = parent != null ? parent.rect.height : Screen.height;
|
|
|
|
|
|
|
|
|
|
|
|
float targetW, targetH;
|
|
|
|
|
|
if (videoAspect >= parentW / parentH)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 视频更宽:宽度铺满,高度按比例缩小,上下留黑
|
|
|
|
|
|
targetW = parentW;
|
|
|
|
|
|
targetH = parentW / videoAspect;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 视频更高:高度铺满,宽度按比例缩小,左右留黑
|
|
|
|
|
|
targetH = parentH;
|
|
|
|
|
|
targetW = parentH * videoAspect;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
rt.anchorMin = new Vector2(0.5f, 0.5f);
|
|
|
|
|
|
rt.anchorMax = new Vector2(0.5f, 0.5f);
|
|
|
|
|
|
rt.pivot = new Vector2(0.5f, 0.5f);
|
|
|
|
|
|
rt.sizeDelta = new Vector2(targetW, targetH);
|
|
|
|
|
|
rt.anchoredPosition = Vector2.zero;
|
|
|
|
|
|
image.uvRect = new Rect(0, 0, 1, 1);
|
|
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public void ShowAnimation(int dir)
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
Animation Anim = GetComponent<Animation>();
|
|
|
|
|
|
if (Anim != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dir == -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
Anim["视频出现"].time = Anim["视频出现"].clip.length;
|
|
|
|
|
|
Anim["视频出现"].speed = -1;
|
|
|
|
|
|
Anim.Play("视频出现");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Anim["视频出现"].time = 0;
|
|
|
|
|
|
Anim["视频出现"].speed = 1;
|
|
|
|
|
|
Anim.Play("视频出现");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
long lastFrame = 0;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 播放中事件(给进度条赋值)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
|
|
|
|
public void OnVideoPlaying()
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
if (slider == null)
|
|
|
|
|
|
return;
|
2026-08-20 15:50:11 +08:00
|
|
|
|
// 帧数据未就绪(重新播放/切换视频的瞬间 frameCount 可能为0),跳过本次刷新,避免除零产生 Infinity/NaN
|
|
|
|
|
|
if (videoPlayer.frameCount <= 0)
|
|
|
|
|
|
return;
|
2026-05-18 08:42:33 +08:00
|
|
|
|
if (Mathf.Abs(videoPlayer.frame - lastFrame) < 1)
|
|
|
|
|
|
return;
|
|
|
|
|
|
slider.value = (videoPlayer.frame + 1) / (float)videoPlayer.frameCount;
|
|
|
|
|
|
lastFrame = videoPlayer.frame;
|
|
|
|
|
|
nowTime.text = SecondToHour((int)(totalTime * slider.value));
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 拖动进度条
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void PointDownUp()
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
//if (slider.value != lastValue)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// videoPlayer.frame = (long)(videoPlayer.frameCount * slider.value);
|
|
|
|
|
|
//}
|
|
|
|
|
|
if (slider.value >= 0.98f)
|
|
|
|
|
|
{
|
|
|
|
|
|
videoPlayer.Stop();
|
|
|
|
|
|
VideoOver(videoPlayer);
|
|
|
|
|
|
return;
|
2026-04-24 16:57:44 +08:00
|
|
|
|
|
2026-05-18 08:42:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
videoPlayer.frame = (long)(videoPlayer.frameCount * slider.value) - 1;
|
|
|
|
|
|
nowTime.text = SecondToHour((int)(totalTime * slider.value));
|
|
|
|
|
|
if (!ispause)
|
|
|
|
|
|
{
|
|
|
|
|
|
videoPlayer.Play();
|
|
|
|
|
|
isplaying = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
// TeacherServer.m_instance.SendVideoProcess((long)(videoPlayer.frameCount * slider.value) - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
public void PointDown()
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
videoPlayer.Pause();
|
|
|
|
|
|
isplaying = false;
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public void Draging()
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
videoPlayer.frame = (long)(videoPlayer.frameCount * slider.value) - 1;
|
|
|
|
|
|
nowTime.text = SecondToHour((int)(totalTime * slider.value));
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public void VideoOver(VideoPlayer vp)
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
vp.loopPointReached -= VideoOver;
|
|
|
|
|
|
isplaying = false;
|
|
|
|
|
|
if (playButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
playButton.SetActive(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pauseButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
pauseButton.SetActive(false);
|
|
|
|
|
|
}
|
2026-08-20 15:50:11 +08:00
|
|
|
|
// 全屏播放结束后自动退出全屏
|
|
|
|
|
|
if (isFullScreen)
|
|
|
|
|
|
SetFullScreen(false);
|
2026-06-08 08:55:10 +08:00
|
|
|
|
playOver?.Invoke();
|
2026-08-20 15:50:11 +08:00
|
|
|
|
// 播放结束不重新加载视频:停止并回到开头,重置UI,等待再次播放
|
|
|
|
|
|
videoPlayer.Stop();
|
|
|
|
|
|
videoPlayer.frame = 0;
|
|
|
|
|
|
lastFrame = 0;
|
|
|
|
|
|
nowTime.text = SecondToHour(0);
|
|
|
|
|
|
if (slider != null) slider.value = 0;
|
|
|
|
|
|
ispause = true;
|
|
|
|
|
|
// 重新订阅播放结束事件,保证再次播放结束后仍能触发
|
|
|
|
|
|
vp.loopPointReached += VideoOver;
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
public void SetFullScreen(bool isFullScreen)
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
this.isFullScreen = isFullScreen;
|
2026-08-20 15:50:11 +08:00
|
|
|
|
// 未设置过全屏目标时兜底用默认全屏UI
|
|
|
|
|
|
if (currentFullImage == null) currentFullImage = fullImage;
|
2026-05-18 08:42:33 +08:00
|
|
|
|
if (isFullScreen)
|
|
|
|
|
|
{
|
|
|
|
|
|
#if UNITY_ANDROID
|
|
|
|
|
|
AndroidStatusBar.statusBarState = AndroidStatusBar.States.Hidden;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
videoPlayer.targetTexture = renderTextures[1];
|
2026-08-20 15:50:11 +08:00
|
|
|
|
currentFullImage.transform.parent.gameObject.SetActive(true);
|
2026-05-18 08:42:33 +08:00
|
|
|
|
UIManager.Instance.AddBackAction(() => SetFullScreen(false));
|
|
|
|
|
|
if (ispause)
|
|
|
|
|
|
PlayVideo();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
#if UNITY_ANDROID
|
|
|
|
|
|
AndroidStatusBar.statusBarState = AndroidStatusBar.States.TranslucentOverContent;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
videoPlayer.targetTexture = renderTextures[0];
|
2026-08-20 15:50:11 +08:00
|
|
|
|
currentFullImage.transform.parent.gameObject.SetActive(false);
|
2026-05-18 08:42:33 +08:00
|
|
|
|
UIManager.Instance.RecoverBackAction();
|
|
|
|
|
|
}
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
2026-05-18 08:42:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 秒转换小时
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="time"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public string SecondToHour(float time)
|
2026-04-24 16:57:44 +08:00
|
|
|
|
{
|
2026-05-18 08:42:33 +08:00
|
|
|
|
int hour = 0;
|
|
|
|
|
|
int minute = 0;
|
|
|
|
|
|
int second = 0;
|
|
|
|
|
|
second = (int)time;
|
|
|
|
|
|
|
2026-08-20 15:50:11 +08:00
|
|
|
|
if (second >= 60)
|
2026-05-18 08:42:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
minute = second / 60;
|
|
|
|
|
|
second = second % 60;
|
|
|
|
|
|
}
|
2026-08-20 15:50:11 +08:00
|
|
|
|
if (minute >= 60)
|
2026-05-18 08:42:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
hour = minute / 60;
|
|
|
|
|
|
minute = minute % 60;
|
|
|
|
|
|
}
|
|
|
|
|
|
string result = "";
|
|
|
|
|
|
if (hour > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
result += hour + ":";
|
2026-04-24 16:57:44 +08:00
|
|
|
|
|
2026-05-18 08:42:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (minute < 10)
|
|
|
|
|
|
result += "0";
|
|
|
|
|
|
result += minute + ":";
|
|
|
|
|
|
if (second < 10)
|
|
|
|
|
|
result += "0";
|
|
|
|
|
|
result += second.ToString();
|
|
|
|
|
|
return result;
|
2026-04-24 16:57:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|