Files
ft/Client/LocalPackages/LeviathanVideo/Runtime/LeviathanVideoSharedMaterialController.cs
2026-06-29 21:18:33 +08:00

148 lines
5.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*----------------------------------------------------------------
// 多 RawImage + 多 Decoder、同时只播一路时共用一份 UI 材质,仅当前激活 Decoder 写贴图与参数。
//----------------------------------------------------------------*/
using UnityEngine;
/// <summary>
/// 与多个 <see cref="LeviathanVideoDecoder"/> 配合:全组共用<strong>一个</strong> <see cref="Material"/> 实例,
/// 任意时刻只有 <see cref="ActivateDecoder"/> 指定的那一路会把它赋到自己的 RawImage 并更新 Y/U/V。
/// 要求:各解码器的 <see cref="LeviathanVideoDecoderBase.AlphaType"/> 与控制器上配置的 Shared Alpha Type 一致(同一套 Shader
/// </summary>
public class LeviathanVideoSharedMaterialController : MonoBehaviour
{
private static Shader FindShaderForAlphaType(LeviathanVideoDecoderBase.PlayAlphaType alphaType)
{
string name = alphaType switch
{
LeviathanVideoDecoderBase.PlayAlphaType.RightSide => "LeviathanVideo/YUV420P_Alpha_Right",
LeviathanVideoDecoderBase.PlayAlphaType.BottomSide => "LeviathanVideo/YUV420P_Alpha_Bottom",
LeviathanVideoDecoderBase.PlayAlphaType.ChromaKey => "LeviathanVideo/YUV420P_ChromaKey",
_ => "LeviathanVideo/YUV420P",
};
return Shader.Find(name);
}
[SerializeField]
[Tooltip("共用材质使用的 Alpha/Shader 类型,须与各 Decoder 的 Alpha Type 一致")]
private LeviathanVideoDecoderBase.PlayAlphaType _sharedAlphaType = LeviathanVideoDecoderBase.PlayAlphaType.ChromaKey;
[SerializeField]
[Tooltip("可选:用工程里的材质做模板 Instantiate为空则按 Shared Alpha Type 从 Shader 创建")]
private Material _materialTemplate;
private Material _sharedMaterial;
private LeviathanVideoDecoder _activeDecoder;
/// <summary>当前独占共用材质的解码器;无则为 null。</summary>
public LeviathanVideoDecoder ActiveDecoder => _activeDecoder;
/// <summary>共用材质实例(只读,勿在外部 Dispose。</summary>
public Material SharedMaterial
{
get
{
EnsureSharedMaterial();
return _sharedMaterial;
}
}
private void EnsureSharedMaterial()
{
if (_sharedMaterial != null)
return;
if (_materialTemplate != null)
{
_sharedMaterial = new Material(_materialTemplate);
return;
}
var sh = FindShaderForAlphaType(_sharedAlphaType);
if (sh == null)
{
LeviathanLogConfig.LogError(nameof(LeviathanVideoSharedMaterialController),
$"无法创建共用材质Shader 未找到AlphaType={_sharedAlphaType}");
return;
}
_sharedMaterial = new Material(sh);
}
/// <summary>
/// 将共用材质交给指定解码器;可选停止上一路。
/// </summary>
/// <param name="decoder">若为 null则仅解绑当前路并清空激活项</param>
/// <param name="stopPreviousDecoder">为 true 时对上一路调用 <see cref="LeviathanVideoDecoderBase.Stop"/></param>
public void ActivateDecoder(LeviathanVideoDecoder decoder, bool stopPreviousDecoder = true)
{
EnsureSharedMaterial();
if (_sharedMaterial == null)
return;
if (_activeDecoder == decoder)
{
if (decoder != null)
decoder.RefreshSharedMaterialDisplay();
return;
}
if (_activeDecoder != null)
{
if (stopPreviousDecoder)
_activeDecoder.Stop();
_activeDecoder.UnbindSharedMaterialController();
_activeDecoder = null;
}
if (decoder == null)
return;
if (decoder.AlphaType != _sharedAlphaType)
{
LeviathanLogConfig.LogError(nameof(LeviathanVideoSharedMaterialController),
$"ActivateDecoder: 解码器 AlphaType={decoder.AlphaType} 与控制器 {_sharedAlphaType} 不一致,拒绝绑定。请统一 Inspector 中的 Alpha Type。");
return;
}
_activeDecoder = decoder;
_activeDecoder.BindToSharedMaterialController(this, _sharedMaterial);
_activeDecoder.RefreshSharedMaterialDisplay();
}
/// <summary>解绑当前解码器并停止播放(共用材质仍保留在控制器上)。</summary>
public void DeactivateCurrent(bool stopDecoder = true)
{
if (_activeDecoder == null)
return;
if (stopDecoder)
_activeDecoder.Stop();
_activeDecoder.UnbindSharedMaterialController();
_activeDecoder = null;
}
private void OnDestroy()
{
if (_activeDecoder != null)
{
_activeDecoder.UnbindSharedMaterialController();
_activeDecoder = null;
}
if (_sharedMaterial != null)
{
Destroy(_sharedMaterial);
_sharedMaterial = null;
}
}
/// <summary>
/// 解码器销毁或主动 <see cref="LeviathanVideoDecoder.UnbindSharedMaterialController"/> 时调用,清除激活引用。
/// </summary>
public void NotifyDecoderReleased(LeviathanVideoDecoder decoder)
{
if (_activeDecoder == decoder)
_activeDecoder = null;
}
}