ARVideoCanvasHelper.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using System.Collections;
  4. namespace UMP
  5. {
  6. public class ARVideoCanvasHelper : MonoBehaviour
  7. {
  8. // Name of properties that we will use in shader to set the left/right and top/bottom border size
  9. private const string SHADER_BORDER_U_WIDTH = "_BorderUWidth";
  10. private const string SHADER_BORDER_V_WIDTH = "_BorderVWidth";
  11. // Main camera property that we will use to find the size of gameobject that have "MeshRenderer " component
  12. [SerializeField]
  13. private Camera _mainCamera = null;
  14. // Media player property that we will use to get current video size
  15. [SerializeField]
  16. private UniversalMediaPlayer _mediaPlayer = null;
  17. // Default size of video canvas (used if native library can't return correct video size)
  18. [SerializeField]
  19. public int _defaultWidth = 640;
  20. [SerializeField]
  21. public int _defaultHeight = 640;
  22. private MeshRenderer _meshRenderer;
  23. private RawImage _rawImageRenderer;
  24. private Material _objectMaterial;
  25. private Vector2 _objectSize;
  26. private Vector2 _videoSize;
  27. private Vector2 _calcSize;
  28. private Vector2 _borderUVSize;
  29. private IEnumerator _updateCanvasRatioEnum;
  30. private void Start()
  31. {
  32. _rawImageRenderer = gameObject.GetComponent<RawImage>();
  33. _meshRenderer = gameObject.GetComponent<MeshRenderer>();
  34. if (_rawImageRenderer == null && _meshRenderer == null)
  35. {
  36. Debug.LogError("Object need have MeshRenderer or RawImage component!");
  37. return;
  38. }
  39. _objectMaterial = _rawImageRenderer != null ? _rawImageRenderer.material : _meshRenderer.material;
  40. if (_mediaPlayer != null)
  41. {
  42. _mediaPlayer.AddImageReadyEvent(OnPlayerImageReady);
  43. _mediaPlayer.AddStoppedEvent(OnPlayerStopped);
  44. }
  45. ShowVideoCanvasBorder(true);
  46. }
  47. private void OnDestroy()
  48. {
  49. if (_mediaPlayer != null)
  50. {
  51. _mediaPlayer.RemoveImageReadyEvent(OnPlayerImageReady);
  52. _mediaPlayer.RemoveStoppedEvent(OnPlayerStopped);
  53. }
  54. if (_updateCanvasRatioEnum != null)
  55. StopCoroutine(_updateCanvasRatioEnum);
  56. ShowVideoCanvasBorder(false);
  57. }
  58. /// <summary>
  59. /// Calculate the size of video canvas borders and send results to custom shader
  60. /// </summary>
  61. private IEnumerator UpdateVideoCanvasRatio()
  62. {
  63. while (true)
  64. {
  65. _objectSize = GetPixelSizeOfMeshRenderer(_meshRenderer, _mainCamera);
  66. if (_objectSize == Vector2.zero)
  67. _objectSize = GetPixelSizeOfRawImage(_rawImageRenderer);
  68. _calcSize = Vector2.zero;
  69. _calcSize.x = (_objectSize.y / _videoSize.y) * _videoSize.x;
  70. if (_calcSize.x < _objectSize.x)
  71. _calcSize.y = _objectSize.y;
  72. else
  73. _calcSize = new Vector2(_objectSize.x, (_objectSize.x / _videoSize.x) * _videoSize.y);
  74. _borderUVSize = new Vector2((1 - (_calcSize.x / _objectSize.x)) * 0.5f, (1 - (_calcSize.y / _objectSize.y)) * 0.5f);
  75. _objectMaterial.SetFloat(SHADER_BORDER_U_WIDTH, _borderUVSize.x);
  76. _objectMaterial.SetFloat(SHADER_BORDER_V_WIDTH, _borderUVSize.y);
  77. yield return null;
  78. }
  79. }
  80. /// <summary>
  81. /// Show/Hide special video canvas borders in output texture
  82. /// </summary>
  83. private void ShowVideoCanvasBorder(bool state)
  84. {
  85. _objectMaterial.SetFloat(SHADER_BORDER_U_WIDTH, state ? 1 : 0);
  86. _objectMaterial.SetFloat(SHADER_BORDER_V_WIDTH, state ? 1 : 0);
  87. }
  88. private void OnPlayerImageReady(Texture2D image)
  89. {
  90. _videoSize = new Vector2(image.width, image.height);
  91. if (_updateCanvasRatioEnum == null)
  92. {
  93. _updateCanvasRatioEnum = UpdateVideoCanvasRatio();
  94. StartCoroutine(_updateCanvasRatioEnum);
  95. }
  96. }
  97. private void OnPlayerStopped()
  98. {
  99. if (!_mediaPlayer.Loop)
  100. {
  101. if (_updateCanvasRatioEnum != null)
  102. {
  103. StopCoroutine(_updateCanvasRatioEnum);
  104. _updateCanvasRatioEnum = null;
  105. }
  106. ShowVideoCanvasBorder(true);
  107. }
  108. }
  109. /// <summary>
  110. /// Get size in pixels of gameobject that have "MeshRenderer" component
  111. /// </summary>
  112. /// <param name="meshRenderer">Gameobject "MeshRenderer" component</param>
  113. /// <param name="camera">Main camera of current scene</param>
  114. /// <returns></returns>
  115. public static Vector2 GetPixelSizeOfMeshRenderer(MeshRenderer meshRenderer, Camera camera)
  116. {
  117. if (meshRenderer == null)
  118. return Vector2.zero;
  119. Vector3 posStart = camera.WorldToScreenPoint(new Vector3(meshRenderer.bounds.min.x, meshRenderer.bounds.min.y, meshRenderer.bounds.min.z));
  120. Vector3 posEnd = camera.WorldToScreenPoint(new Vector3(meshRenderer.bounds.max.x, meshRenderer.bounds.max.y, meshRenderer.bounds.min.z));
  121. float widthX = Mathf.Abs((posEnd.x - posStart.x));
  122. float widthY = Mathf.Abs((posEnd.y - posStart.y));
  123. return new Vector2((int)widthX, (int)widthY);
  124. }
  125. /// <summary>
  126. /// Get size in pixels of gameobject that have "RawImage" component
  127. /// </summary>
  128. /// <param name="rawImage">Gameobject "RawImage" component</param>
  129. /// <returns></returns>
  130. public static Vector2 GetPixelSizeOfRawImage(RawImage rawImage)
  131. {
  132. if (rawImage == null)
  133. return Vector2.zero;
  134. return new Vector2(rawImage.rectTransform.rect.width, rawImage.rectTransform.rect.height);
  135. }
  136. }
  137. }