206 lines
6.6 KiB
C#
Raw Permalink Normal View History

2025-06-07 17:43:34 +08:00
using UnityEngine;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public class CaptureCamera : MonoBehaviour
{
/// <summary>
///
/// </summary>
[System.NonSerialized]
public Transform cachedTransform;
/// <summary>
///
/// </summary>
[System.NonSerialized]
public Camera cachedCamera;
[System.NonSerialized]
static CaptureCamera _main;
[System.NonSerialized]
static int _layer = -1;
static int _hiddenLayer = -1;
public const string Name = "Capture Camera";
public const string LayerName = "VUI";
public const string HiddenLayerName = "Hidden VUI";
#if UNITY_2019_3_OR_NEWER
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void Init()
{
_main = null;
}
#endif
void OnEnable()
{
cachedCamera = this.GetComponent<Camera>();
cachedTransform = this.gameObject.transform;
if (this.gameObject.name == Name)
_main = this;
}
/// <summary>
///
/// </summary>
public static void CheckMain()
{
if (_main != null && _main.cachedCamera != null)
return;
GameObject go = GameObject.Find(Name);
if (go != null)
{
_main = go.GetComponent<CaptureCamera>();
return;
}
GameObject cameraObject = new GameObject(Name);
Camera camera = cameraObject.AddComponent<Camera>();
camera.depth = 0;
camera.cullingMask = 1 << layer;
camera.clearFlags = CameraClearFlags.SolidColor;
camera.backgroundColor = Color.clear;
camera.orthographic = true;
camera.orthographicSize = 5;
camera.nearClipPlane = -30;
camera.farClipPlane = 30;
camera.enabled = false;
camera.stereoTargetEye = StereoTargetEyeMask.None;
camera.allowHDR = false;
camera.allowMSAA = false;
cameraObject.AddComponent<CaptureCamera>();
}
/// <summary>
///
/// </summary>
public static int layer
{
get
{
if (_layer == -1)
{
_layer = LayerMask.NameToLayer(LayerName);
if (_layer == -1)
{
_layer = 30;
Debug.LogWarning("Please define two layers named '" + CaptureCamera.LayerName + "' and '" + CaptureCamera.HiddenLayerName + "'");
}
}
return _layer;
}
}
/// <summary>
///
/// </summary>
public static int hiddenLayer
{
get
{
if (_hiddenLayer == -1)
{
_hiddenLayer = LayerMask.NameToLayer(HiddenLayerName);
if (_hiddenLayer == -1)
{
Debug.LogWarning("Please define two layers named '" + CaptureCamera.LayerName + "' and '" + CaptureCamera.HiddenLayerName + "'");
_hiddenLayer = 31;
}
}
return _hiddenLayer;
}
}
/// <summary>
///
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="stencilSupport"></param>
/// <returns></returns>
public static RenderTexture CreateRenderTexture(int width, int height, bool stencilSupport)
{
RenderTexture texture = new RenderTexture(width, height, stencilSupport ? 24 : 0, RenderTextureFormat.ARGB32);
texture.antiAliasing = 1;
texture.filterMode = FilterMode.Bilinear;
texture.anisoLevel = 0;
texture.useMipMap = false;
texture.wrapMode = TextureWrapMode.Clamp;
texture.hideFlags = DisplayObject.hideFlags;
return texture;
}
/// <summary>
///
/// </summary>
/// <param name="target"></param>
/// <param name="texture"></param>
/// <param name="contentHeight"></param>
/// <param name="offset"></param>
public static void Capture(DisplayObject target, RenderTexture texture, float contentHeight, Vector2 offset)
{
CheckMain();
Matrix4x4 matrix = target.cachedTransform.localToWorldMatrix;
float scaleX = new Vector4(matrix.m00, matrix.m10, matrix.m20, matrix.m30).magnitude;
float scaleY = new Vector4(matrix.m01, matrix.m11, matrix.m21, matrix.m31).magnitude;
Vector3 forward;
forward.x = matrix.m02;
forward.y = matrix.m12;
forward.z = matrix.m22;
Vector3 upwards;
upwards.x = matrix.m01;
upwards.y = matrix.m11;
upwards.z = matrix.m21;
float halfHeight = contentHeight * 0.5f;
Camera camera = _main.cachedCamera;
camera.targetTexture = texture;
float aspect = (float)texture.width / texture.height;
camera.aspect = aspect * scaleX / scaleY;
camera.orthographicSize = halfHeight * scaleY;
_main.cachedTransform.localPosition = target.cachedTransform.TransformPoint(halfHeight * aspect - offset.x, -halfHeight + offset.y, 0);
if (forward != Vector3.zero)
_main.cachedTransform.localRotation = Quaternion.LookRotation(forward, upwards);
int oldLayer = 0;
if (target.graphics != null)
{
oldLayer = target.graphics.gameObject.layer;
target._SetLayerDirect(CaptureCamera.layer);
}
if (target is Container)
{
oldLayer = ((Container)target).numChildren > 0 ? ((Container)target).GetChildAt(0).layer : CaptureCamera.hiddenLayer;
((Container)target).SetChildrenLayer(CaptureCamera.layer);
}
RenderTexture old = RenderTexture.active;
RenderTexture.active = texture;
GL.Clear(true, true, Color.clear);
camera.Render();
RenderTexture.active = old;
if (target.graphics != null)
target._SetLayerDirect(oldLayer);
if (target is Container)
((Container)target).SetChildrenLayer(oldLayer);
}
}
}