| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- #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;
- /**
- * GameObject保留UVC设备的视频目标材质
- * 如果未设置,则使用与分配此脚本相同的GameObjec。
- */
- public List<GameObject> RenderTargets;
- [HideInInspector]
- public Action<Texture> StartPreviewAction;
- [HideInInspector]
- public Action StopPreviewAction;
- //--------------------------------------------------------------------------------
- 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)
- Console.WriteLine($"{TAG}Start:");
- #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)
- Console.WriteLine($"{TAG}OnUVCAttachEvent:{device}");
- #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)
- Console.WriteLine($"{TAG}OnUVCDetachEvent:{device}");
- #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)
- // Console.WriteLine($"{TAG}OnUVCSelectSize:{device}");
- //#endif
- // if (device.IsTHETA_V || device.IsTHETA_Z1)
- // {
- //#if (!NDEBUG && DEBUG && ENABLE_LOG)
- // Console.WriteLine($"{TAG}OnUVCSelectSize:THETA V/Z1");
- //#endif
- // return FindSize(formats, 3840, 1920);
- // }
- // else if (device.IsTHETA_S)
- // {
- //#if (!NDEBUG && DEBUG && ENABLE_LOG)
- // Console.WriteLine($"{TAG}OnUVCSelectSize:THETA S");
- //#endif
- // return FindSize(formats, 1920, 1080);
- // }
- // else
- // {
- //#if (!NDEBUG && DEBUG && ENABLE_LOG)
- // Console.WriteLine($"{TAG}OnUVCSelectSize:other UVC device,{device}");
- //#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设备接收视频的纹理实例
- */
- public void OnUVCStartEvent(UVCManager manager, UVCDevice device, Texture tex)
- {
- #if (!NDEBUG && DEBUG && ENABLE_LOG)
- Console.WriteLine($"{TAG}OnUVCStartEvent:{device}");
- #endif
- HandleOnStartPreview(tex);
- StartPreviewAction?.Invoke(tex);
- }
- /**
- * 视频获取已完成
- * 实现IUVCdrawer
- * @param manager 调用方UVCManager
- * @param device 对象的UVC设备的信息
- */
- public void OnUVCStopEvent(UVCManager manager, UVCDevice device)
- {
- #if (!NDEBUG && DEBUG && ENABLE_LOG)
- Console.WriteLine($"{TAG}OnUVCStopEvent:{device}");
- #endif
- HandleOnStopPreview();
- StopPreviewAction?.Invoke();
- }
- //================================================================================
- /**
- * 更新目标
- */
- 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)
- Console.WriteLine($"{TAG}UpdateTarget:material={material}");
- #endif
- }
- i++;
- }
- }
- if (!found)
- { //找不到一个目标时,该脚本
- //尝试从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.");
- }
- }
- /**
- * 获取将图像绘制为纹理的材质
- * 如果指定的GameObject具有Skybox/Render/RawImage/Material,则从中获取Material
- * 如果每个都分配了多个,则返回第一个找到的可用项
- * 优先级:Skybox>Render>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
- {
- Console.WriteLine($"{TAG}RestoreTexture:Exception cought");
- }
- 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)
- Console.WriteLine($"{TAG}HandleOnStartPreview:({tex})");
- #endif
- int i = 0;
- foreach (var target in TargetMaterials)
- {
- if (target is Material)
- {
- #if (!NDEBUG && DEBUG && ENABLE_LOG)
- Console.WriteLine($"{TAG}HandleOnStartPreview:assign Texture to Material({target})");
- #endif
- SavedTextures[i++] = (target as Material).mainTexture;
- (target as Material).mainTexture = tex;
- }
- else if (target is RawImage)
- {
- #if (!NDEBUG && DEBUG && ENABLE_LOG)
- Console.WriteLine($"{TAG}HandleOnStartPreview:assign Texture to RawImage({target})");
- #endif
- SavedTextures[i++] = (target as RawImage).texture;
- (target as RawImage).texture = tex;
- }
- }
- }
- /**
- * 映像取得が終了したときのUnity側の処理
- */
- private void HandleOnStopPreview()
- {
- #if (!NDEBUG && DEBUG && ENABLE_LOG)
- Console.WriteLine($"{TAG}HandleOnStopPreview:");
- #endif
- // 描画先のテクスチャをもとに戻す
- RestoreTexture();
- #if (!NDEBUG && DEBUG && ENABLE_LOG)
- Console.WriteLine($"{TAG}HandleOnStopPreview:finished");
- #endif
- }
- } // class UVCDrawer
- } // namespace Serenegiant.UVC
|