ScreenLocate.cs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. #define ENABLE_LOG
  2. using InfraredManager;
  3. using o0;
  4. using SLAMUVC;
  5. using System;
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using UnityEngine;
  10. using UnityEngine.Experimental.AI;
  11. using UnityEngine.UI;
  12. using ZIM;
  13. using ZIM.Unity;
  14. using static SLAMUVC.UVCManager;
  15. using Color = UnityEngine.Color;
  16. using Time = UnityEngine.Time;
  17. [RequireComponent(typeof(Canvas))]
  18. public partial class ScreenLocate : MonoBehaviour
  19. {
  20. public InfraredCameraHelper InfraredCameraHelper;
  21. private const string TAG = "ScreenLocate#";
  22. public enum InfraredCount : int
  23. {
  24. Single = 1,
  25. Double = 2
  26. }
  27. enum Mode
  28. {
  29. InfraredLocate,
  30. ScreenMap,
  31. ScreenLocateManual
  32. }
  33. enum Platform
  34. {
  35. Window,
  36. Android
  37. }
  38. Platform mPlatform = Platform.Android;
  39. // 2个灯,顺序根据红外灯的大小 由大到小, 坐标通过 InfraredSpot.ScreenUV 和 InfraredSpot.CameraLocation 获得
  40. public InfraredSpot[] InfraredSpots
  41. {
  42. get
  43. {
  44. infraredCount = InfraredCount.Double;
  45. return infraredSpotBuffer;
  46. }
  47. }
  48. // 1个灯, 坐标通过 InfraredSpot.ScreenUV 和 InfraredSpot.CameraLocation 获得
  49. public InfraredSpot InfraredSpotSingle
  50. {
  51. get
  52. {
  53. infraredCount = InfraredCount.Single;
  54. return infraredSpotBuffer[0];
  55. }
  56. }
  57. public InfraredSpot[] infraredSpotBuffer;
  58. public string GetInfraredCount() { return infraredCount.ToString(); }
  59. /// <summary>
  60. /// CameraLocation 的偏移量
  61. /// </summary>
  62. public Vector2 CameraLocationOffset { get; set; } = new Vector2(0, 0);
  63. public Vector2 UVOffset { get; set; } = new Vector2(0, 0);
  64. // public InfraredDemo InfraredDemoMain => FindObjectOfType<InfraredDemo>();
  65. #region UVC 处理的对象
  66. //public UVCManager mUVCManager;
  67. public CameraInfo mUVCCameraInfo;
  68. public bool getUVCCameraInfo => mUVCCameraInfo != null ? true : false;
  69. public Vector2 getUVCCameraInfoSize => getUVCCameraInfo ? mUVCCameraInfo.Size : new Vector2(320, 240);
  70. private Texture mUVCTexture;
  71. public Texture getUVCTexture => mUVCTexture;
  72. public Texture setUVCTexture {
  73. set {
  74. mUVCTexture = value;
  75. }
  76. }
  77. private Texture2D mUVCTexture2D;
  78. // [SerializeField] Texture2DArray mUVCOutArray;
  79. #endregion
  80. public Text Info;
  81. public List<RectTransform> CrosshairInCamera;
  82. public List<RectTransform> CrosshairInScreen;
  83. public RectTransform ScreenQuad;
  84. public Toggle SaveToggle;
  85. public Toggle FullScreenToggle;
  86. public LineGenerator UILineGenerator;
  87. public bool ShowScreenQuad = false;
  88. // output的图像
  89. // 图0是摄像机原图,图1是屏幕识别的全部可选线段,图2是识别出的屏幕画面,图3是识别出的屏幕四条边,图4是图2和图3的叠加,图5显示3种不同颜色的算法识别线段
  90. public List<RawImage> outputRawImages;
  91. [NonSerialized] public Texture[] outputTexture2D;
  92. public RawImage FullScreenImage;
  93. public PixelCheaker ScreenPixelCheaker;
  94. public InfraredSpotSettings InfraredSpotSettings;
  95. public o0.Geometry2D.Vector<int> CameraSize { get; set; }
  96. public Texture2D DebugScreenImage;
  97. public bool DebugOnEditorWin = false;
  98. // private SynchronizationContext mainContext;
  99. //是否单点显示
  100. public bool bSinglePoint = true;//默认单点识别
  101. [NonSerialized] public float ReDoLocateCalibrationRatio = 0.04f; // 重复定位时校准的距离比例,例如先手动定位,再自动定位,会以手动的结果来校准
  102. [NonSerialized] public InfraredCount infraredCount = InfraredCount.Single;
  103. bool bIdentifyRed = true;//默认设备红色
  104. bool bIdentifyGreen = true;
  105. #region 性能检测相关
  106. public Text m_UITime;
  107. const float m_UIUpdateInterval = 0.1f;
  108. float m_UIUpdateTimer = 0.0f;
  109. List<float> m_History = new List<float>(100);
  110. int m_ValidHistoryFrames = 0;
  111. float m_AverageTime = float.NaN;
  112. float m_MedianTime = float.NaN;
  113. float m_MinTime = float.NaN;
  114. float m_MaxTime = float.NaN;
  115. public float updateInterval = 0.5F;
  116. private double lastInterval;
  117. private int frames = 0;
  118. private float fps;
  119. public Text m_FPS;
  120. #endregion
  121. #region PC部分参数
  122. //亮度
  123. public float pcBrightness { get; set; } = 0.0f;
  124. //对比度
  125. public float pcContrast { get; set; } = 0.0f;
  126. #endregion
  127. InfraredLocate infraredLocate;
  128. RectTransform canvas;
  129. Mode mode;
  130. List<(Vector2 pos, GameObject go)> pointManual = new List<(Vector2, GameObject)>();
  131. //o0.Project.WebCam o0WebCam = null;
  132. o0.Project.ScreenIdentification screenIdentification;
  133. public o0.Project.ScreenIdentification ScreenIdentification => screenIdentification;
  134. /// <summary>
  135. /// 正在识别的状态,自动识别时候记录
  136. /// </summary>
  137. bool bAutomaticRecognition { get; set; } = false;//进行捕获时
  138. bool bAutomaticRecognitionStart { get; set; } = false;//是否进行捕获
  139. bool bAutomaticRecognitionEnd { get; set; } = false;//是否结束捕获
  140. [NonSerialized] public RectTransform BackQuad = null;
  141. static public ScreenLocate Main;
  142. static public void AutoLightPixels(Color[] pixels, int width, int height)
  143. {
  144. var newTex = pixels.zimAutoLightSimple(width, height);
  145. DebugTexture(7, newTex);
  146. Main.FullScreenImage.texture = newTex;
  147. }
  148. static public void DebugTexture(int index, Texture texture)
  149. {
  150. LateDestory(Main.outputRawImages[index].texture);
  151. Main.outputRawImages[index].texture = texture;
  152. if (Main.outputTexture2D != null)
  153. Main.outputTexture2D[index] = texture;
  154. }
  155. static void LateDestory(UnityEngine.Object o) => Main.StartCoroutine(Main.LateDestoryIEnum(o));
  156. static public void SetScreen(UnityEngine.Color? color = null)
  157. {
  158. if (Main.BackQuad == null)
  159. {
  160. var canvas = GameObject.Find("WebCameraView").GetComponent<RectTransform>();
  161. var background = canvas.Find("Background");
  162. Main.BackQuad = background.GetChild(0).GetComponent<RectTransform>();
  163. }
  164. Main.BackQuad.parent.gameObject.SetActive(color != null);
  165. Main.BackQuad.GetComponent<RawImage>().color = color ?? Color.black;
  166. //Debug.Log("Set Screen " + color.GetColorName());
  167. }
  168. static public void SetScreen(Rect rect, UnityEngine.Color? color = null)
  169. {
  170. if (Main.BackQuad == null)
  171. {
  172. var canvas = GameObject.Find("WebCameraView").GetComponent<RectTransform>();
  173. var background = canvas.Find("Background");
  174. Main.BackQuad = background.GetChild(0).GetComponent<RectTransform>();
  175. }
  176. Main.BackQuad.parent.gameObject.SetActive(color != null);
  177. Main.BackQuad.anchorMin = rect.min;
  178. Main.BackQuad.anchorMax = rect.max;
  179. Main.BackQuad.GetComponent<RawImage>().color = color ?? Color.black;
  180. //Debug.Log("Set Screen " + color.GetColorName());
  181. }
  182. static void DebugBackQuad(Rect? rect = null)
  183. {
  184. if (Main.BackQuad)
  185. {
  186. Main.BackQuad.parent.GetComponent<RawImage>().enabled = false;
  187. Main.BackQuad.GetComponent<RawImage>().color = Color.white;
  188. Main.BackQuad.parent.gameObject.SetActive(!Main.BackQuad.parent.gameObject.activeSelf);
  189. if (rect.HasValue)
  190. {
  191. Main.BackQuad.anchorMin = rect.Value.min;
  192. Main.BackQuad.anchorMax = rect.Value.max;
  193. }
  194. }
  195. }
  196. public void ReSizeTexture(int width, int height)
  197. {
  198. Debug.Log("Cur mUVCTexture Size: [" + mUVCTexture.width + "," + mUVCTexture.height + "]");
  199. return;
  200. if (mUVCTexture.width < width || mUVCTexture.height < height) // 如果当前分辨率太小,则重新new一个texture
  201. {
  202. Texture2D tex = new Texture2D(
  203. width, height,
  204. TextureFormat.ARGB32,
  205. false, /* mipmap */
  206. true /* linear */);
  207. tex.filterMode = FilterMode.Point;
  208. tex.Apply();
  209. mUVCTexture = tex;
  210. mUVCCameraInfo.previewTexture = tex;
  211. var nativeTexPtr = mUVCCameraInfo.previewTexture.GetNativeTexturePtr();
  212. }
  213. }
  214. void Awake()
  215. {
  216. Main = this;
  217. #if !UNITY_EDITOR_WIN
  218. DebugOnEditorWin = false;
  219. #endif
  220. //if (mUVCDrawer)
  221. // mUVCDrawer.StartPreviewAction += UVCIsReady;
  222. }
  223. void OnDestroy()
  224. {
  225. //if (mUVCDrawer)
  226. // mUVCDrawer.StartPreviewAction -= UVCIsReady;
  227. }
  228. void Start()
  229. {
  230. //mainContext = SynchronizationContext.Current;
  231. outputTexture2D = new Texture[8];
  232. canvas = transform.GetComponent<RectTransform>();
  233. mode = Mode.InfraredLocate;
  234. if (DebugScreenImage && DebugOnEditorWin)
  235. {
  236. screenIdentification = new o0.Project.ScreenIdentification();
  237. screenIdentification.LocateScreen();
  238. }
  239. FullScreenToggle.onValueChanged.AddListener((i) =>
  240. {
  241. Screen.fullScreen = i;
  242. });
  243. infraredCount = InfraredCount.Single;
  244. #region 性能检测相关
  245. for (var i = 0; i < m_History.Capacity; ++i)
  246. {
  247. m_History.Add(0.0f);
  248. }
  249. lastInterval = Time.realtimeSinceStartup;
  250. frames = 0;
  251. #endregion
  252. }
  253. IEnumerator LateDestoryIEnum(UnityEngine.Object o)
  254. {
  255. while (true)
  256. {
  257. yield return new WaitForEndOfFrame();
  258. Destroy(o);
  259. }
  260. }
  261. //ZIMWebCamera场景使用
  262. public void WebCamIsReady(Texture texture)
  263. {
  264. mPlatform = Platform.Window;
  265. mUVCTexture = texture;
  266. mUVCCameraInfo = new CameraInfo(mUVCTexture);
  267. brightness = 0;
  268. //UVC准备好
  269. InfraredCameraHelper?.InvokeOnUVCIsReady(mUVCCameraInfo);
  270. }
  271. /// <summary>
  272. /// UVCManager 创建初始化时候,更新此函数
  273. /// </summary>
  274. /// <param name="cameraInfo"></param>
  275. public void UVCIsReady(CameraInfo cameraInfo)
  276. {
  277. mPlatform = Platform.Android;
  278. mUVCTexture = cameraInfo.previewTexture;
  279. mUVCCameraInfo = cameraInfo;
  280. Debug.Log("UVCIsReady:" + mUVCCameraInfo);
  281. //UVC准备好
  282. InfraredCameraHelper?.InvokeOnUVCIsReady(mUVCCameraInfo);
  283. }
  284. /// <summary>
  285. /// 获取新的 previewTexture
  286. /// </summary>
  287. public void UVCUpdate(bool bChange)
  288. {
  289. mUVCTexture = mUVCCameraInfo.previewTexture;
  290. Debug.Log("[ScreenLocate] UVCUpdate:" + mUVCCameraInfo + ",bChange:"+bChange);
  291. InfraredCameraHelper?.InvokeOnUVCIsUpdate();
  292. //这里判断是否进入自动识别?
  293. if (bAutomaticRecognitionStart) {
  294. bAutomaticRecognitionStart = false;
  295. Debug.Log("[ScreenLocate] UVCUpdate 开始自动识别 Capture:" + Capture + " ,Delay: " + Delay);
  296. screenIdentification.LocateScreen(Capture, Delay);
  297. }
  298. if (bAutomaticRecognitionEnd) {
  299. bAutomaticRecognitionEnd = false;
  300. Debug.Log("[ScreenLocate] UVCUpdate 结束捕获,当前摄像机分辨率为: " + mUVCCameraInfo.Size);
  301. bAutomaticRecognition = false;
  302. }
  303. }
  304. int brightness = 0;
  305. /// <summary>
  306. /// 设置算法红外灯的亮度值
  307. /// </summary>
  308. /// <param name="value"></param>
  309. public void SetInfraredLocateBrightnessThreshold(float value)
  310. {
  311. if (infraredLocate != null)
  312. {
  313. if (value >= 0 && value <= 1)
  314. infraredLocate.SetBrightnessThreshold(value); // 参数是 红外灯的亮度阈值,阈值越小能够检测到的亮度就越低,默认值是0.93
  315. }
  316. }
  317. void Update()
  318. {
  319. //++frames;
  320. //float timeNow = Time.realtimeSinceStartup;
  321. //if (timeNow > lastInterval + updateInterval)
  322. //{
  323. // fps = (float)(frames / (timeNow - lastInterval));
  324. // frames = 0;
  325. // lastInterval = timeNow;
  326. //}
  327. //if (m_FPS != null)
  328. // m_FPS.text = "FPS:" + fps.ToString("f2");
  329. if (mUVCCameraInfo == null) return;
  330. if (screenIdentification == null)
  331. {
  332. screenIdentification = new o0.Project.ScreenIdentification();
  333. //pc 不切换分辨率了
  334. #if UNITY_ANDROID
  335. //screenIdentification.OnLocateScreenEnter += OnLocateScreenEnter;
  336. screenIdentification.OnLocateScreenEnd += OnLocateScreenEnd;
  337. #endif
  338. }
  339. if (infraredLocate == null)
  340. {
  341. infraredLocate = new InfraredLocate(mUVCCameraInfo, screenIdentification, InfraredSpotSettings, ScreenPixelCheaker);
  342. //InfraredDemo 初始化
  343. //float redfilterValue = PlayerPrefs.GetFloat("Init redFilterSliderValue", 0.8f);
  344. //Debug.Log("Init Red filterValue:" + redfilterValue);
  345. //infraredLocate.SetBrightnessThreshold(redfilterValue); // 参数是 红外灯的亮度阈值,阈值越小能够检测到的亮度就越低,默认值是0.93
  346. }
  347. if (screenIdentification.Screen.RefreshCameraSize(getUVCCameraInfoSize)) // 同步分辨率, 分辨率变化后还需同步到InfraredDemo
  348. {
  349. quadUnityVectorList = screenIdentification.Screen.QuadInCamera.GetUnityVertexNormalizedList();
  350. if (!ContainsNaN(quadUnityVectorList))
  351. {
  352. SaveScreenLocateVectorList();
  353. //SyncInfraredDemo();
  354. //SyncInfraredScreenPositioningView();
  355. InfraredCameraHelper?.InvokeOnUVCPosUpdate(quadUnityVectorList);
  356. Debug.Log("[ScreenLocate] RefreshCameraSize 屏幕size改变:[" + (int)getUVCCameraInfoSize.x + "," + (int)getUVCCameraInfoSize.y + "]");
  357. Debug.Log("[ScreenLocate] RefreshCameraSize 屏幕size改变,刷新quadUnityVectorList:" + PrintVector2List(quadUnityVectorList));
  358. }
  359. else {
  360. Debug.LogError("[ScreenLocate] RefreshCameraSize 屏幕size改变,存在NaN值,重新校准:" + PrintVector2List(quadUnityVectorList));
  361. }
  362. if (DebugOnEditorWin)
  363. Main.ShowScreen(Main.ScreenQuad, screenIdentification.Screen.QuadInCamera);
  364. }
  365. //var t0 = Time.realtimeSinceStartup;
  366. /* New*/
  367. //Debug.Log((mUVCCameraInfo != null) +" = "+ mUVCCameraInfo.IsPreviewing + " = "+ screenIdentification.Screen.Active);
  368. if (mUVCCameraInfo != null && mUVCCameraInfo.IsPreviewing) // 成功定位屏幕后才做红外识别
  369. {
  370. //if (bAutomaticRecognition)
  371. //{
  372. // //识别的过程使用的分辨率
  373. // //CreateUVCTexture2DIfNeeded((int)getUVCCameraInfoSize.x, (int)getUVCCameraInfoSize.y);
  374. // if (log1)
  375. // {
  376. // log1 = false;
  377. // Debug.Log("[ScreenLocate] log1:[" + (int)getUVCCameraInfoSize.x + ", " + (int)getUVCCameraInfoSize.y + "]");
  378. // }
  379. //}
  380. //else
  381. //{
  382. // //自动识别完成后使用相机分辨率大小 getUVCCameraInfoSize
  383. // //CreateUVCTexture2DIfNeeded((int)getUVCCameraInfoSize.x, (int)getUVCCameraInfoSize.y);
  384. // if (log2)
  385. // {
  386. // log2 = false;
  387. // Debug.Log("[ScreenLocate] log2:[" + (int)getUVCCameraInfoSize.x + ", " + (int)getUVCCameraInfoSize.y + "]");
  388. // }
  389. //}
  390. //如果是连接了蓝牙设备,并且不是9轴设备。不进行识别算法处理
  391. if (BluetoothAim.ins?.status == BluetoothStatusEnum.ConnectSuccess && AimHandler.ins && AimHandler.ins.bRuning9Axis()) return;
  392. //根据getUVCCameraInfoSize 分辨率渲染
  393. CreateUVCTexture2DIfNeeded((int)getUVCCameraInfoSize.x, (int)getUVCCameraInfoSize.y);
  394. if (!screenIdentification.Update(mUVCTexture2D))
  395. {
  396. CameraSize = new o0.Geometry2D.Vector<int>((int)getUVCCameraInfoSize.x, (int)getUVCCameraInfoSize.y);
  397. var pixels = mUVCTexture2D.GetPixels(); // 从左往右、从下往上
  398. AutoLightPixels(pixels, CameraSize.x, CameraSize.y);
  399. //return;
  400. //InfraredSpots = infraredLocate.Update(pixels);
  401. if (bSinglePoint)
  402. infraredSpotBuffer = infraredLocate.UpdateSingle(pixels);
  403. else
  404. infraredSpotBuffer = infraredLocate.Update(pixels);
  405. if (mode == Mode.ScreenLocateManual)
  406. {
  407. for (int i = 0; i < infraredSpotBuffer.Length; i++)
  408. {
  409. if (infraredSpotBuffer[i].CameraLocation != null)
  410. {
  411. // 检测到光点
  412. var posInCanvas = infraredSpotBuffer[i].CameraLocation.Value.pixelToLocalPosition_AnchorCenter(CameraSize, FullScreenImage.rectTransform.rect);
  413. CrosshairInCamera[i].gameObject.SetActive(true);
  414. CrosshairInCamera[i].anchoredPosition = posInCanvas;
  415. }
  416. else
  417. CrosshairInCamera[i].gameObject.SetActive(false);
  418. }
  419. }
  420. else if(mode == Mode.InfraredLocate)
  421. {
  422. if (mPlatform == Platform.Window) //渲染ui上面的点。进入游戏可以隐藏
  423. {
  424. for (int i = 0; i < infraredSpotBuffer.Length; i++)
  425. {
  426. if (infraredSpotBuffer[i].CameraLocation != null)
  427. {
  428. // 检测到光点
  429. var posInCanvas = infraredSpotBuffer[i].CameraLocation.Value.pixelToLocalPosition_AnchorCenter(CameraSize, outputRawImages[0].rectTransform.rect);
  430. CrosshairInCamera[i].gameObject.SetActive(true);
  431. CrosshairInCamera[i].anchoredPosition = posInCanvas;
  432. }
  433. else
  434. CrosshairInCamera[i].gameObject.SetActive(false);
  435. }
  436. }
  437. //手机端使用 mPlatform == Platform.Android &&
  438. //通用,手机 和 PC
  439. if (infraredSpotBuffer.Length > 0)
  440. {
  441. int redIndex = 0;
  442. int greenIndex = 1;
  443. //仅仅第一个点显示(如果最大点出界了会闪烁)
  444. if (bSinglePoint)
  445. {
  446. redIndex = 0; //单点识别是,可以选择切换颜色
  447. if (infraredSpotBuffer[redIndex].ScreenUV != null)
  448. {
  449. string str = "Single:";
  450. Info.text = str + infraredSpotBuffer[redIndex].ScreenUV.Value.ToString("F4");
  451. //InfraredManager.ConnetDevicesSingle.ins.posAction?.Invoke(new Vector3(infraredSpotBuffer[redIndex].ScreenUV.Value.x * Screen.width, infraredSpotBuffer[redIndex].ScreenUV.Value.y * Screen.height, 0));
  452. onFilterPos(infraredSpotBuffer[redIndex].ScreenUV.Value);
  453. }
  454. }
  455. else
  456. {
  457. //雙點模式下選擇第一個點
  458. if (bIdentifyRed && !bIdentifyGreen)
  459. {
  460. if (infraredSpotBuffer[redIndex].ScreenUV != null)
  461. {
  462. Info.text = "Red" + redIndex + ":" + infraredSpotBuffer[redIndex].ScreenUV.Value.ToString("F4");
  463. //InfraredManager.ConnetDevicesSingle.ins.posAction?.Invoke(new Vector3(infraredSpotBuffer[redIndex].ScreenUV.Value.x * Screen.width, infraredSpotBuffer[redIndex].ScreenUV.Value.y * Screen.height, 0));
  464. onFilterPos2(infraredSpotBuffer[redIndex].ScreenUV.Value, redIndex);
  465. }
  466. else
  467. {
  468. Info.text = "未检测到红色最大点!";
  469. }
  470. }
  471. else if (!bIdentifyRed && bIdentifyGreen)
  472. {
  473. if (infraredSpotBuffer[greenIndex].ScreenUV != null)
  474. {
  475. Info.text = "Green:" + infraredSpotBuffer[greenIndex].ScreenUV.Value.ToString("F4");
  476. //InfraredManager.ConnetDevicesSingle.ins.posAction?.Invoke(new Vector3(infraredSpotBuffer[greenIndex].ScreenUV.Value.x * Screen.width, infraredSpotBuffer[greenIndex].ScreenUV.Value.y * Screen.height, 0));
  477. onFilterPos2(infraredSpotBuffer[greenIndex].ScreenUV.Value, greenIndex);
  478. }
  479. else
  480. {
  481. Info.text = "未检测到绿色点!";
  482. }
  483. }
  484. else
  485. {
  486. //两个不选择和两个全选都跑识别两个点
  487. //自動切換 检测到光点
  488. if (infraredSpotBuffer[redIndex].ScreenUV != null)
  489. {
  490. Info.text = "Red:" + infraredSpotBuffer[redIndex].ScreenUV.Value.ToString("F4");
  491. //InfraredManager.ConnetDevicesSingle.ins.posAction?.Invoke(new Vector3(infraredSpotBuffer[redIndex].ScreenUV.Value.x * Screen.width, infraredSpotBuffer[redIndex].ScreenUV.Value.y * Screen.height, 0));
  492. onFilterPos2(infraredSpotBuffer[redIndex].ScreenUV.Value, redIndex);
  493. }
  494. else if (infraredSpotBuffer[greenIndex].ScreenUV != null)
  495. {
  496. Info.text = "Green:" + infraredSpotBuffer[greenIndex].ScreenUV.Value.ToString("F4");
  497. //InfraredManager.ConnetDevicesSingle.ins.posAction?.Invoke(new Vector3(infraredSpotBuffer[greenIndex].ScreenUV.Value.x * Screen.width, infraredSpotBuffer[greenIndex].ScreenUV.Value.y * Screen.height, 0));
  498. onFilterPos2(infraredSpotBuffer[greenIndex].ScreenUV.Value, greenIndex);
  499. }
  500. else
  501. {
  502. Info.text = "未检测到点!";
  503. }
  504. }
  505. }
  506. }
  507. }
  508. else if (mode == Mode.ScreenMap && DebugOnEditorWin)
  509. {
  510. for (int i = 0; i < infraredSpotBuffer.Length; i++)
  511. {
  512. if (infraredSpotBuffer[i].ScreenUV != null)
  513. {
  514. // 检测到光点
  515. var posInCanvas = infraredSpotBuffer[i].ScreenUV.Value.pixelToLocalPosition_AnchorCenter(new Vector2(1, 1), canvas.rect);
  516. CrosshairInScreen[i].gameObject.SetActive(true);
  517. CrosshairInScreen[i].anchoredPosition = posInCanvas;
  518. }
  519. else
  520. CrosshairInScreen[i].gameObject.SetActive(false);
  521. }
  522. if (Input.GetKeyDown(KeyCode.Escape))
  523. ToMode(Mode.InfraredLocate);
  524. }
  525. }
  526. }
  527. //var t1 = Time.realtimeSinceStartup;
  528. //var dt = t1 - t0;
  529. //m_History[m_ValidHistoryFrames % m_History.Count] = dt;
  530. //++m_ValidHistoryFrames;
  531. //m_UIUpdateTimer += Time.deltaTime;
  532. //if (m_UIUpdateTimer >= m_UIUpdateInterval)
  533. //{
  534. // m_UIUpdateTimer = 0.0f;
  535. // if (m_ValidHistoryFrames >= m_History.Count)
  536. // {
  537. // m_ValidHistoryFrames = 0;
  538. // m_AverageTime = 0.0f;
  539. // m_MinTime = float.PositiveInfinity;
  540. // m_MaxTime = float.NegativeInfinity;
  541. // {
  542. // for (var i = 0; i < m_History.Count; i++)
  543. // {
  544. // var time = m_History[i];
  545. // m_AverageTime += time;
  546. // m_MinTime = Mathf.Min(m_MinTime, time);
  547. // m_MaxTime = Mathf.Max(m_MaxTime, time);
  548. // }
  549. // m_AverageTime /= m_History.Count;
  550. // }
  551. // {
  552. // m_History.Sort();
  553. // // Odd-length history?
  554. // if ((m_History.Count & 1) != 0)
  555. // {
  556. // m_MedianTime = m_History[m_History.Count / 2];
  557. // }
  558. // else
  559. // {
  560. // m_MedianTime = (m_History[m_History.Count / 2] + m_History[m_History.Count / 2 - 1]) / 2.0f;
  561. // }
  562. // }
  563. // }
  564. // var statistics = $"{m_History.Count} 帧样本:\naverage: {m_AverageTime * 1000.0f:F2}ms\nmedian: {m_MedianTime * 1000.0f:F2}ms\nmin: {m_MinTime * 1000.0f:F2}ms\nmax: {m_MaxTime * 1000.0f:F2}ms\n";
  565. // //Method: {m_Method} {UnityEngine.SceneManagement.SceneManager.GetActiveScene().name} |
  566. // if (m_UITime != null)
  567. // m_UITime.text = $"Cam: {mUVCCameraInfo.CurrentWidth}x{mUVCCameraInfo.CurrentHeight}{(mUVCTexture2D? ",T2D:" : "")}{(mUVCTexture2D? mUVCTexture2D.width+ "x" : "")}{(mUVCTexture2D ? mUVCTexture2D.height:"")} \nLast Frame: {dt * 1000.0f:F2}ms \n{statistics}";
  568. //}
  569. //UpdateInputs();
  570. }
  571. Vector2 targetPos = Vector2.zero;
  572. Vector2 movePos = Vector2.zero;
  573. int moveSpeed = 20;
  574. public float filterDis = 3.0f;
  575. void onFilterPos(Vector2 _vector2Pos)
  576. {
  577. //主要用于模拟九轴时候的
  578. //添加一个偏移量,使得最后输出的准心是指向正中心
  579. Vector2 np = new Vector2((_vector2Pos.x - UVOffset.x) * Screen.width, (_vector2Pos.y - UVOffset.y) * Screen.height); //_vector2Pos.pixelToLocalPosition_AnchorCenter(Vector2.one, (transform as RectTransform).rect);
  580. if (Vector2.Distance(np, targetPos) >= filterDis)
  581. {
  582. targetPos = np;
  583. //InfraredManager.ConnetDevicesSingle.ins.posAction?.Invoke(new Vector3(targetPos.x, targetPos.y, 0));
  584. //Vector2 np = new Vector2(uvCenterOffset.x * Screen.width, uvCenterOffset.y * Screen.height);
  585. //point -= np;
  586. InfraredCameraHelper?.InvokeOnPositionUpdate(targetPos);
  587. }
  588. //movePos = Vector3.Lerp(movePos, targetPos, Time.deltaTime * moveSpeed);
  589. //InfraredManager.ConnetDevicesSingle.ins.posAction?.Invoke(new Vector3(movePos.x, movePos.y, 0));
  590. }
  591. Vector2[] _targetPoints2 = new Vector2[] { Vector2.zero, Vector2.zero };
  592. void onFilterPos2(Vector2 _vector2Pos, int index)
  593. {
  594. Vector2 np = new Vector2((_vector2Pos.x - UVOffset.x) * Screen.width, (_vector2Pos.y - UVOffset.y) * Screen.height);
  595. if (Vector2.Distance(np, _targetPoints2[index]) >= filterDis)
  596. {
  597. _targetPoints2[index] = np;
  598. InfraredCameraHelper.InvokeOnPositionUpdate2(_targetPoints2[index], index);
  599. }
  600. }
  601. #region 自动识别
  602. int Capture = 30;
  603. int Delay = 30;
  604. Vector2 EnterResolution;
  605. // int DefaultResolutionIndex;
  606. // readonly public int HighScreenLocateResolutionIndex = 2; // 自动识别时,摄像机分辨率固定为1280 * 720 ( 对应索引是2 )
  607. public void BtnScreenLocate()
  608. {
  609. if (DebugScreenImage)
  610. {
  611. screenIdentification = new o0.Project.ScreenIdentification();
  612. CameraSize = new o0.Geometry2D.Vector<int>(DebugScreenImage.width, DebugScreenImage.height);
  613. WebCamIsReady(DebugScreenImage);
  614. CreateUVCTexture2DIfNeeded();
  615. }
  616. //Debug.Log("BtnScreenLocate Capture:" + Capture + " ,Delay: " + Delay);
  617. //screenIdentification.LocateScreen(Capture, Delay);
  618. OnLocateScreenEnter();
  619. }
  620. // bool log1 = false, log2 = false;
  621. public void OnLocateScreenEnter()
  622. {
  623. bAutomaticRecognition = true;
  624. bAutomaticRecognitionStart = true;
  625. ResetScreenIdentification();
  626. //DefaultResolutionIndex = InfraredDemoMain?.ResolutionIndex ?? 0; // 记录一下进入前的分辨率(游戏场景的分辨率,比识别时更低)
  627. //HighScreenLocateResolutionIndex = InfraredDemoMain.getTextureToResolutionNewIndex(); // index = 0
  628. // Debug.Log("[ScreenLocate] 开始捕获 DefaultResolutionIndex:" + DefaultResolutionIndex + " ,HighScreenLocateResolutionIndex:" + HighScreenLocateResolutionIndex);
  629. // InfraredDemoMain?.SetResolutionNew(HighScreenLocateResolutionIndex);
  630. EnterResolution = mUVCCameraInfo.Size;// 记录一下进入前的分辨率(游戏场景的分辨率,比识别时更低)
  631. Vector2 _HighResolution = mUVCCameraInfo.CurrentCalibrationResolution; //最高的分辨率
  632. Resize((int)_HighResolution.x, (int)_HighResolution.y);
  633. if (DebugOnEditorWin)
  634. screenIdentification.LocateScreen();
  635. //CreateUVCTexture2DIfNeeded();
  636. // log1 = true;
  637. // log2 = true;
  638. }
  639. public void OnLocateScreenEnd()
  640. {
  641. bAutomaticRecognitionEnd = true;
  642. // 记录本次屏幕识别的分辨率(目前采用高分辨率做识别,识别结束后调回低分辨率)
  643. //InfraredDemoMain?.SetResolutionNew(DefaultResolutionIndex);
  644. Resize((int)EnterResolution.x, (int)EnterResolution.y);
  645. }
  646. /**
  647. * 修改相机的实际分辨率
  648. */
  649. public void Resize(int width, int height)
  650. {
  651. if (mUVCCameraInfo == null) return;
  652. #if UNITY_ANDROID
  653. //发送修改指令给相机实际分辨率
  654. mUVCCameraInfo.SetCameraSize(width, height);
  655. #endif
  656. #if UNITY_STANDALONE_WIN
  657. // pc todo 看看怎么处理
  658. // ResizePC(width, height);
  659. #endif
  660. //mUVCCameraInfo.SetSize(width, height); // 手动记录分辨率,这里可能会有问题 width和height是期望的分辨率而不是当前摄像机实际分辨率
  661. Debug.Log($"[ScreenLocate] 开始修改分辨率 mUVCCameraInfo origin:[{ mUVCCameraInfo.CurrentWidth },{ mUVCCameraInfo.CurrentHeight }]=>target:[{ width },{ height }]");
  662. // if (screenIdentification.isInitLocateScreen()) screenIdentification.bStartLocateScreen = true;
  663. }
  664. /// <summary>
  665. /// pc修改分辨率
  666. /// </summary>
  667. /// <param name="width"></param>
  668. /// <param name="height"></param>
  669. public void ResizePC(int width, int height)
  670. {
  671. if (mUVCCameraInfo == null) return;
  672. //if (screenIdentification.isInitLocateScreen()) screenIdentification.bStartLocateScreen = true;
  673. // PcWebCamera pcWebCamera = GetComponent<PcWebCamera>();
  674. // if(pcWebCamera.webCamTexture == null || !pcWebCamera.webCamTexture.isPlaying) return;
  675. //StartCoroutine(ResetWebCam(pcWebCamera, width, height));
  676. mUVCCameraInfo.SetSize(width, height); // 手动记录分辨率,这里可能会有问题 width和height是期望的分辨率而不是当前摄像机实际分辨率
  677. Debug.Log("[ScreenLocate] Resize mUVCCameraInfo.SetSize: [" + mUVCCameraInfo.CurrentWidth + "," + mUVCCameraInfo.CurrentHeight + "]");
  678. }
  679. private System.Collections.IEnumerator ResetWebCam(PcWebCamera pcWebCamera, int newWidth, int newHeight)
  680. {
  681. WebCamTexture _webCamTexture = pcWebCamera.webCamTexture;
  682. // Stop the current WebCamTexture
  683. _webCamTexture.Stop();
  684. // Trigger OnWebCamStopped event
  685. // OnWebCamStopped?.Invoke();
  686. // Wait for a short time to ensure resources are released
  687. yield return new WaitForSeconds(0.5f);
  688. // Create a new WebCamTexture with the new dimensions
  689. _webCamTexture = new WebCamTexture(newWidth, newHeight);
  690. pcWebCamera.webCamTexture = _webCamTexture;
  691. mUVCTexture = _webCamTexture;
  692. // Restart the camera
  693. yield return StartCoroutine(StartWebCam(pcWebCamera));
  694. }
  695. private System.Collections.IEnumerator StartWebCam(PcWebCamera pcWebCamera)
  696. {
  697. WebCamTexture _webCamTexture = pcWebCamera.webCamTexture;
  698. _webCamTexture.Play();
  699. // Wait until the WebCamTexture is playing
  700. while (!_webCamTexture.isPlaying)
  701. {
  702. yield return null;
  703. }
  704. // Trigger OnWebCamStarted event
  705. //OnWebCamStarted?.Invoke();
  706. mUVCCameraInfo.SetSize(_webCamTexture.width, _webCamTexture.height); // 手动记录分辨率,这里可能会有问题 width和height是期望的分辨率而不是当前摄像机实际分辨率
  707. Debug.Log("[ScreenLocate] ResizePc mUVCCameraInfo.SetSize: [" + mUVCCameraInfo.CurrentWidth + "," + mUVCCameraInfo.CurrentHeight + "]");
  708. // if(screenIdentification.isInitLocateScreen())screenIdentification.bStartLocateScreen = true;
  709. }
  710. #endregion
  711. public void BtnScreenMap()
  712. {
  713. ToMode(Mode.ScreenMap);
  714. }
  715. //进入手动定位屏幕
  716. public void BtnScreenLocateManual()
  717. {
  718. ToMode(Mode.ScreenLocateManual);
  719. }
  720. // 重置屏幕识别的数据
  721. public void ResetScreenIdentification()
  722. {
  723. screenIdentification.Screen.Active = false;
  724. }
  725. /// <summary>
  726. /// 固定的顶点顺序: 左下,右下,左上,右上
  727. /// </summary>
  728. public static List<Vector2> quadUnityVectorList = new();
  729. /// <summary>
  730. /// 打印信息
  731. /// </summary>
  732. /// <param name="list">左下,右下,左上,右上</param>
  733. /// <returns></returns>
  734. public string PrintVector2List(List<Vector2> list)
  735. {
  736. if (screenIdentification == null || !screenIdentification.Screen.Active) return "[]";
  737. string result = "";
  738. if (list.Count == 4)
  739. {
  740. result = "左下" + list[0].ToString() + ",右下" + list[1].ToString() + ",左上" + list[2].ToString() + ",右上" + list[3].ToString();
  741. }
  742. else
  743. {
  744. result = "count != 4 error";
  745. }
  746. //foreach (Vector2 vector in list)
  747. //{
  748. // result += vector.ToString() + " ";
  749. //}
  750. //Debug.Log(result);
  751. return result;
  752. }
  753. /// <summary>
  754. /// 判断是否存在NaN
  755. /// </summary>
  756. /// <param name="vectors"></param>
  757. /// <returns></returns>
  758. public bool ContainsNaN(List<Vector2> vectors)
  759. {
  760. foreach (var v in vectors)
  761. {
  762. if (float.IsNaN(v.x) || float.IsNaN(v.y))
  763. {
  764. return true;
  765. }
  766. }
  767. return false;
  768. }
  769. // 标记屏幕的四个角, ScreenQuadObject 下挂了4个子节点用于标记
  770. public void ShowScreen(RectTransform ScreenQuadObject, QuadrilateralInCamera screen)
  771. {
  772. if (screen == null)
  773. {
  774. Info.text = "识别屏幕失败";
  775. return;
  776. }
  777. Info.text = "已识别到屏幕";
  778. if (ScreenQuadObject && ScreenQuadObject.childCount >= 4)
  779. {
  780. ScreenQuadObject.gameObject.SetActive(true);
  781. for (int i = 0; i < 4; i++)
  782. {
  783. if (DebugOnEditorWin)
  784. {
  785. RectTransform t = ScreenQuadObject.GetChild(i) as RectTransform;
  786. t.anchoredPosition = screen.Quad[i].pixelToLocalPosition_AnchorCenter(screen.CameraSize, ScreenQuadObject.rect);
  787. }
  788. }
  789. }
  790. quadUnityVectorList = screen.GetUnityVertexNormalizedList(); // 记录四个点
  791. if (!ContainsNaN(quadUnityVectorList))
  792. {
  793. SaveScreenLocateVectorList();
  794. //SyncInfraredDemo();
  795. if (DebugOnEditorWin)
  796. SyncInfraredScreenPositioningView();
  797. InfraredCameraHelper?.InvokeOnUVCPosUpdate(quadUnityVectorList);
  798. Debug.Log("[ScreenLocate] ShowScreen 已识别到屏幕,更新quadUnityVectorList:" + PrintVector2List(quadUnityVectorList));
  799. }
  800. else
  801. {
  802. Debug.LogError("[ScreenLocate] RefreshCameraSize 屏幕size改变,存在NaN值,重新校准:" + PrintVector2List(quadUnityVectorList));
  803. }
  804. }
  805. public void ShowScreen(QuadrilateralInCamera screen) => ShowScreen(ScreenQuad, screen);
  806. /// <summary>
  807. /// 校准点位置存储到本地
  808. /// </summary>
  809. static public void SaveScreenLocateVectorList()
  810. {
  811. string saveStr = string.Join(";", quadUnityVectorList.Select(v => $"{v.x},{v.y}")); //,{v.z}
  812. Debug.Log("SaveScreenLocateVectorList: " + saveStr);
  813. PlayerPrefs.SetString("ScreenLocateVectorList", saveStr);
  814. }
  815. /// <summary>
  816. /// 获取本地存储校准点位置
  817. /// </summary>
  818. static public bool GetScreenLocateVectorList()
  819. {
  820. string posListStr = PlayerPrefs.GetString("ScreenLocateVectorList", "");
  821. Debug.Log("GetScreenLocateVectorList:"+ posListStr);
  822. if (!string.IsNullOrWhiteSpace(posListStr))
  823. {
  824. quadUnityVectorList.Clear();
  825. quadUnityVectorList = posListStr.Split(';')
  826. .Select(s =>
  827. {
  828. string[] parts = s.Split(',');
  829. return new Vector2(float.Parse(parts[0]), float.Parse(parts[1]));
  830. })
  831. .ToList();
  832. return true;
  833. }
  834. else return false;
  835. }
  836. public Vector2 AdjustPointsOffset(Vector2 inputPoint,string type = "CameraLocation")
  837. {
  838. // 计算从原始中心到输入点的偏移量
  839. if (type == "CameraLocation")
  840. {
  841. CameraLocationOffset = inputPoint - screenIdentification.Screen.TransformToCamera(new Vector2(0.5f, 0.5f) * screenIdentification.Screen.UVSize);
  842. return CameraLocationOffset;
  843. }
  844. else {
  845. //ScreenUV
  846. UVOffset = inputPoint - new Vector2(0.5f, 0.5f);
  847. return UVOffset;
  848. }
  849. }
  850. /// <summary>
  851. /// 这里计算一个偏移后的cameraLocatoin位置
  852. /// </summary>
  853. /// <param name="cameraLocatoin"></param>
  854. /// <returns></returns>
  855. public Vector2 GetOffsetCameraLocation(Vector2 cameraLocatoin) {
  856. return cameraLocatoin - CameraLocationOffset;
  857. }
  858. void ToMode(Mode mode)
  859. {
  860. if (this.mode == mode)
  861. return;
  862. if (mode == Mode.ScreenMap)
  863. {
  864. if (!screenIdentification.Screen.Active)
  865. {
  866. Info.text = "先定位屏幕";
  867. return;
  868. }
  869. Info.text = "按ESC退出";
  870. SetScreen(Color.black);
  871. //Info.transform.SetAsLastSibling();
  872. this.mode = Mode.ScreenMap;
  873. }
  874. else if (mode == Mode.InfraredLocate)
  875. {
  876. Info.text = screenIdentification.Screen.Active ? "已定位屏幕" : "定位屏幕失败";
  877. //Info.text = "已识别到屏幕";
  878. SetScreen(null);
  879. foreach (var i in CrosshairInScreen)
  880. i.gameObject.SetActive(false);
  881. FullScreenImage.gameObject.SetActive(false);
  882. ScreenPixelCheaker.HideImage();
  883. //Info.transform.SetSiblingIndex(transform.childCount - 4);
  884. this.mode = Mode.InfraredLocate;
  885. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  886. Console.WriteLine($"{TAG} Mode.InfraredLocate:已识别到屏幕:{screenIdentification.Screen.Active}");
  887. #endif
  888. }
  889. else if (mode == Mode.ScreenLocateManual)
  890. {
  891. Info.text = "左键单击屏幕 左下角";
  892. FullScreenImage.gameObject.SetActive(true);
  893. ScreenPixelCheaker.ShowImage();
  894. //Info.transform.SetSiblingIndex(transform.childCount - 1);
  895. // var newTex = WebCamera.webCamTexture.AutoLight(10);
  896. //DebugTexture(1, TextureToTexture2D(rawImage.texture));
  897. CreateUVCTexture2DIfNeeded();
  898. DebugTexture(7, mUVCTexture2D.zimAutoLight(brightness));
  899. //mUVCTexture2DTemp = TextureToTexture2D(mUVCCameraInfo.previewTexture);
  900. //DebugTexture(6, mUVCTexture2DTemp.zimAutoLight(brightness));
  901. this.mode = Mode.ScreenLocateManual;
  902. }
  903. }
  904. private Texture2D TextureToTexture2D(Texture texture, int width = 0, int height = 0)
  905. {
  906. if (width == 0)
  907. width = texture.width;
  908. if (height == 0)
  909. height = texture.height;
  910. Texture2D _texture2D = new Texture2D(width, height, TextureFormat.ARGB32, false, true);
  911. RenderTexture currentRT = RenderTexture.active;
  912. RenderTexture renderTexture = RenderTexture.GetTemporary(
  913. width,
  914. height,
  915. 0,
  916. RenderTextureFormat.ARGB32,
  917. RenderTextureReadWrite.Linear);
  918. Graphics.Blit(texture, renderTexture);
  919. RenderTexture.active = renderTexture;
  920. _texture2D.ReadPixels(new Rect(0, 0, width, height), 0, 0);
  921. _texture2D.Apply();
  922. RenderTexture.active = currentRT;
  923. RenderTexture.ReleaseTemporary(renderTexture);
  924. return _texture2D;
  925. }
  926. //public void CreateUVCTexture2DFocusSizeIfNeeded(int width, int height)
  927. //{
  928. // if (mUVCTexture2D != null)
  929. // Destroy(mUVCTexture2D);
  930. // mUVCTexture2D = TextureToTexture2D(mUVCTexture, width, height);
  931. //}
  932. /// <summary>
  933. /// 使用默认的mUVCTexture宽高
  934. /// </summary>
  935. private void CreateUVCTexture2DIfNeeded()
  936. {
  937. if (mUVCTexture2D != null)
  938. Destroy(mUVCTexture2D);
  939. mUVCTexture2D = TextureToTexture2D(mUVCTexture);
  940. }
  941. /// <summary>
  942. /// 根据宽高调整mUVCTexture2D
  943. /// </summary>
  944. /// <param name="width"></param>
  945. /// <param name="height"></param>
  946. private void CreateUVCTexture2DIfNeeded(int width = 0, int height = 0)
  947. {
  948. if (mUVCTexture2D != null)
  949. Destroy(mUVCTexture2D);
  950. mUVCTexture2D = TextureToTexture2D(mUVCTexture, width, height);
  951. }
  952. #region DoubleButton
  953. private DateTime m_firstTime;
  954. private DateTime m_secondTime;
  955. private void Press()
  956. {
  957. Debug.Log("进入手动定位");
  958. BtnScreenLocateManual();
  959. resetTime();
  960. }
  961. public void OnDoubleClick()
  962. {
  963. //超时重置
  964. if (!m_firstTime.Equals(default(DateTime)))
  965. {
  966. var intervalTime = DateTime.Now - m_firstTime;
  967. float milliSeconds = intervalTime.Seconds * 1000 + intervalTime.Milliseconds;
  968. if (milliSeconds >= 400)
  969. resetTime();
  970. }
  971. // 按下按钮时对两次的时间进行记录
  972. if (m_firstTime.Equals(default(DateTime)))
  973. m_firstTime = DateTime.Now;
  974. else
  975. m_secondTime = DateTime.Now;
  976. // 在第二次点击触发,时差小于400ms触发
  977. if (!m_firstTime.Equals(default(DateTime)) && !m_secondTime.Equals(default(DateTime)))
  978. {
  979. var intervalTime = m_secondTime - m_firstTime;
  980. float milliSeconds = intervalTime.Seconds * 1000 + intervalTime.Milliseconds;
  981. if (milliSeconds < 400)
  982. Press();
  983. else
  984. resetTime();
  985. }
  986. }
  987. private void resetTime()
  988. {
  989. m_firstTime = default(DateTime);
  990. m_secondTime = default(DateTime);
  991. }
  992. #endregion
  993. #region 性能检测相关
  994. void InvalidateTimings()
  995. {
  996. m_ValidHistoryFrames = 0;
  997. m_AverageTime = float.NaN;
  998. m_MedianTime = float.NaN;
  999. m_MinTime = float.NaN;
  1000. m_MaxTime = float.NaN;
  1001. }
  1002. void UpdateInputs()
  1003. {
  1004. //重置
  1005. if (Input.GetKeyDown(KeyCode.UpArrow))
  1006. {
  1007. InvalidateTimings();
  1008. }
  1009. }
  1010. #endregion
  1011. }