Health/Assets/UVC4UnityAndroidPlugin/Scripts/UVCDrawer.cs

380 lines
10 KiB
C#
Raw Normal View History

2023-11-22 19:42:29 +00:00
//#define ENABLE_LOG
/*
* Copyright (c) 2014 - 2022 t_saki@serenegiant.com
*/
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Serenegiant.UVC
{
public class UVCDrawer : MonoBehaviour, IUVCDrawer
{
/**
* IUVCSelectorがセットされていないとき
* IUVCSelectorが解像度選択時にnullを
* ()
*/
public int DefaultWidth = 1280;
/**
* IUVCSelectorがセットされていないとき
* IUVCSelectorが解像度選択時にnullを
* ()
*/
public int DefaultHeight = 720;
/**
*
*/
public UVCFilter[] UVCFilters;
/**
* UVC機器からの映像の描画先Materialを保持しているGameObject
* GameObjecを使う
*/
public List<GameObject> RenderTargets;
//--------------------------------------------------------------------------------
private const string TAG = "UVCDrawer#";
/**
* UVC機器からの映像の描画先Material
* TargetGameObjectから取得する
*
* TargetGameObjectのSkybox
* > TargetGameObjectのRenderer
* > TargetGameObjectのRawImage
* > TargetGameObjectのMaterial
* StartでUnityExceptionを投げる
*/
private UnityEngine.Object[] TargetMaterials;
/**
*
* UVCカメラ映像受け取り用テクスチャをセットする前に
* GetComponent<Renderer>().material.mainTextureに設定されていた値
*/
private Texture[] SavedTextures;
private Quaternion[] quaternions;
//================================================================================
// Start is called before the first frame update
void Start()
{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}Start:");
2023-11-22 19:42:29 +00:00
#endif
UpdateTarget();
}
// // Update is called once per frame
// void Update()
// {
//
// }
//================================================================================
/**
* UVC機器が接続された
* IOnUVCAttachHandlerの実装
* @param manager UVCManager
* @param device UVC機器の情報
* @return true: UVC機器を使用する, false: UVC機器を使用しない
*/
public bool OnUVCAttachEvent(UVCManager manager, UVCDevice device)
{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}OnUVCAttachEvent:{device}");
2023-11-22 19:42:29 +00:00
#endif
// XXX 今の実装では基本的に全てのUVC機器を受け入れる
// ただしTHETA SとTHETA VとTHETA Z1は映像を取得できないインターフェースがあるのでオミットする
// CanDrawと同様にUVC機器フィルターをインスペクタで設定できるようにする
var result = !device.IsRicoh || device.IsTHETA;
result &= UVCFilter.Match(device, UVCFilters);
return result;
}
/**
* UVC機器が取り外された
* IOnUVCDetachEventHandlerの実装
* @param manager UVCManager
* @param device UVC機器の情報
*/
public void OnUVCDetachEvent(UVCManager manager, UVCDevice device)
{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}OnUVCDetachEvent:{device}");
2023-11-22 19:42:29 +00:00
#endif
}
// /**
// * 解像度選択
// * IOnUVCSelectSizeHandlerの実装
// * @param manager 呼び出し元のUVCManager
// * @param device 対象となるUVC機器の情報
// * @param formats 対応している解像度についての情報
// */
// public SupportedFormats.Size OnUVCSelectSize(UVCManager manager, UVCDevice device, SupportedFormats formats)
// {
//#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
// Debug.Log($"{TAG}OnUVCSelectSize:{device}");
2023-11-22 19:42:29 +00:00
//#endif
// if (device.IsTHETA_V || device.IsTHETA_Z1)
// {
//#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
// Debug.Log($"{TAG}OnUVCSelectSize:THETA V/Z1");
2023-11-22 19:42:29 +00:00
//#endif
// return FindSize(formats, 3840, 1920);
// }
// else if (device.IsTHETA_S)
// {
//#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
// Debug.Log($"{TAG}OnUVCSelectSize:THETA S");
2023-11-22 19:42:29 +00:00
//#endif
// return FindSize(formats, 1920, 1080);
// }
// else
// {
//#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
// Debug.Log($"{TAG}OnUVCSelectSize:other UVC device,{device}");
2023-11-22 19:42:29 +00:00
//#endif
// return formats.Find(DefaultWidth, DefaultHeight);
// }
// }
/**
* IUVCDrawerが指定したUVC機器の映像を描画できるかどうかを取得
* IUVCDrawerの実装
* @param manager UVCManager
* @param device UVC機器の情報
*/
public bool CanDraw(UVCManager manager, UVCDevice device)
{
return UVCFilter.Match(device, UVCFilters);
}
/**
*
* IUVCDrawerの実装
* @param manager UVCManager
* @param device UVC機器の情報
* @param tex UVC機器からの映像を受け取るTextureインスタンス
*/
public void OnUVCStartEvent(UVCManager manager, UVCDevice device, Texture tex)
{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}OnUVCStartEvent:{device}");
2023-11-22 19:42:29 +00:00
#endif
HandleOnStartPreview(tex);
}
/**
*
* IUVCDrawerの実装
* @param manager UVCManager
* @param device UVC機器の情報
*/
public void OnUVCStopEvent(UVCManager manager, UVCDevice device)
{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}OnUVCStopEvent:{device}");
2023-11-22 19:42:29 +00:00
#endif
HandleOnStopPreview();
}
//================================================================================
/**
*
*/
private void UpdateTarget()
{
bool found = false;
if ((RenderTargets != null) && (RenderTargets.Count > 0))
{
TargetMaterials = new UnityEngine.Object[RenderTargets.Count];
SavedTextures = new Texture[RenderTargets.Count];
quaternions = new Quaternion[RenderTargets.Count];
int i = 0;
foreach (var target in RenderTargets)
{
if (target != null)
{
var material = TargetMaterials[i] = GetTargetMaterial(target);
if (material != null)
{
found = true;
}
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}UpdateTarget:material={material}");
2023-11-22 19:42:29 +00:00
#endif
}
i++;
}
}
if (!found)
{ // 描画先が1つも見つからなかったときはこのスクリプトが
// AddComponentされているGameObjectからの取得を試みる
// XXX RenderTargetsにgameObjectをセットする
TargetMaterials = new UnityEngine.Object[1];
SavedTextures = new Texture[1];
quaternions = new Quaternion[1];
TargetMaterials[0] = GetTargetMaterial(gameObject);
found = TargetMaterials[0] != null;
}
if (!found)
{
throw new UnityException("no target material found.");
}
}
/**
* Materialを取得する
* GameObjectにSkybox/Renderer/RawImage/MaterialがあればそれからMaterialを取得する
* 使
* : Skybox > Renderer > RawImage > Material
* @param target
* @return nullを返す
*/
UnityEngine.Object GetTargetMaterial(GameObject target/*NonNull*/)
{
// Skyboxの取得を試みる
var skyboxs = target.GetComponents<Skybox>();
if (skyboxs != null)
{
foreach (var skybox in skyboxs)
{
if (skybox.isActiveAndEnabled && (skybox.material != null))
{
RenderSettings.skybox = skybox.material;
return skybox.material;
}
}
}
// Skyboxが取得できなければRendererの取得を試みる
var renderers = target.GetComponents<Renderer>();
if (renderers != null)
{
foreach (var renderer in renderers)
{
if (renderer.enabled && (renderer.material != null))
{
return renderer.material;
}
}
}
// SkyboxもRendererも取得できなければRawImageの取得を試みる
var rawImages = target.GetComponents<RawImage>();
if (rawImages != null)
{
foreach (var rawImage in rawImages)
{
if (rawImage.enabled && (rawImage.material != null))
{
return rawImage;
}
}
}
// SkyboxもRendererもRawImageも取得できなければMaterialの取得を試みる
var material = target.GetComponent<Material>();
if (material != null)
{
return material;
}
return null;
}
private void RestoreTexture()
{
for (int i = 0; i < TargetMaterials.Length; i++)
{
var target = TargetMaterials[i];
try
{
if (target is Material)
{
(target as Material).mainTexture = SavedTextures[i];
}
else if (target is RawImage)
{
(target as RawImage).texture = SavedTextures[i];
}
}
catch
{
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}RestoreTexture:Exception cought");
2023-11-22 19:42:29 +00:00
}
SavedTextures[i] = null;
quaternions[i] = Quaternion.identity;
}
}
private void ClearTextures()
{
for (int i = 0; i < SavedTextures.Length; i++)
{
SavedTextures[i] = null;
}
}
/**
*
* @param tex
*/
private void HandleOnStartPreview(Texture tex)
{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}HandleOnStartPreview:({tex})");
2023-11-22 19:42:29 +00:00
#endif
int i = 0;
foreach (var target in TargetMaterials)
{
if (target is Material)
{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}HandleOnStartPreview:assign Texture to Material({target})");
2023-11-22 19:42:29 +00:00
#endif
SavedTextures[i++] = (target as Material).mainTexture;
(target as Material).mainTexture = tex;
}
else if (target is RawImage)
{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}HandleOnStartPreview:assign Texture to RawImage({target})");
2023-11-22 19:42:29 +00:00
#endif
SavedTextures[i++] = (target as RawImage).texture;
(target as RawImage).texture = tex;
}
}
}
/**
* Unity側の処理
*/
private void HandleOnStopPreview()
{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}HandleOnStopPreview:");
2023-11-22 19:42:29 +00:00
#endif
// 描画先のテクスチャをもとに戻す
RestoreTexture();
#if (!NDEBUG && DEBUG && ENABLE_LOG)
2023-11-23 07:22:09 +00:00
Debug.Log($"{TAG}HandleOnStopPreview:finished");
2023-11-22 19:42:29 +00:00
#endif
}
} // class UVCDrawer
} // namespace Serenegiant.UVC