InfraredScreenPositioningView.cs 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using LineUI;
  5. using UnityEngine.UI;
  6. using System.Linq;
  7. using ZIM;
  8. using o0;
  9. using Color = UnityEngine.Color;
  10. using InfraredManager;
  11. using Org.BouncyCastle.Asn1.Crmf;
  12. using ZIM.Unity;
  13. using o0.Project;
  14. using UnityEngine.SceneManagement;
  15. public enum ScreenPositioningStep {
  16. None, //
  17. Start,//开始界面
  18. AutoEnd,//自动定位结束后界面
  19. Marker,//进行标记界面
  20. Manual,//手动界面
  21. LightCtrl,//灯光调整界面
  22. Successful,//结果选择界面
  23. }
  24. public class LinePosition
  25. {
  26. public int index;
  27. public List<Vector3> pos;
  28. }
  29. public class InfraredScreenPositioningView : JCUnityLib.ViewBase
  30. {
  31. [SerializeField]
  32. RectTransform canvasRectTransform;
  33. [SerializeField]
  34. RectTransform draggableParent;
  35. [SerializeField]
  36. GameObject cameraLight;
  37. [SerializeField]
  38. RectTransform pointsParent;
  39. [SerializeField]
  40. RectTransform pos1;
  41. [SerializeField]
  42. RectTransform pos2;
  43. [SerializeField]
  44. RectTransform pos3;
  45. [SerializeField]
  46. RectTransform pos4;
  47. //画线时候的点偏移量
  48. float offset = 10;
  49. [SerializeField]
  50. Line line;
  51. List<LinePosition> oldLinePosition;
  52. Vector3 beginPos;
  53. Vector3 endPos;
  54. //相机感光部分
  55. [SerializeField]
  56. Slider slider;
  57. [SerializeField]
  58. GameObject textTip1;
  59. [SerializeField]
  60. GameObject textTip2;
  61. [SerializeField]
  62. Button btnAuto;
  63. [SerializeField]
  64. Button btnHandMovement;
  65. [SerializeField]
  66. BtnRecordInfrared btnRecordInfrared;
  67. bool bAuto = true;
  68. [SerializeField] Color normalColor = Color.white;
  69. [SerializeField] Color highlightedColor = Color.green;
  70. [SerializeField] Color normalTextColor = Color.black;
  71. [SerializeField] Color highlightedTextColor = Color.white;
  72. [Header("Common Layout Group")]
  73. [SerializeField]
  74. GameObject mask;
  75. [SerializeField]
  76. Line maskLine;
  77. [SerializeField]
  78. RawImage rawImage;
  79. [Tooltip("Demo测试时候显示")]
  80. [SerializeField]
  81. RectTransform crosshair;
  82. [SerializeField]
  83. RectTransform crosshairRed;
  84. [Tooltip("存在校准数据时候显示")]
  85. [SerializeField] LineGenerator CurrentUILineGenerator;//开始显示屏幕线条
  86. [Header("Start Layout Group")]
  87. [SerializeField]
  88. GameObject LayoutStart;
  89. [SerializeField]
  90. GameObject StartTextTip1;
  91. [SerializeField]
  92. GameObject StartTextTipHasData;
  93. [Tooltip("没有存在校准数据时候显示")]
  94. [SerializeField]
  95. GameObject BottomAutoBtn;
  96. [Tooltip("存在校准数据时候显示")]
  97. [SerializeField]
  98. GameObject BottomConfirmBtn;
  99. [Header("AutoEnd Layout Group")]
  100. [SerializeField]
  101. GameObject LayoutAutoEnd;
  102. [SerializeField] Button AutoEndConfirmBtn;
  103. [Header("LightCtrl Layout Group")]
  104. [SerializeField]
  105. GameObject LayoutLightCtrl;
  106. [SerializeField] Slider sliderContrast;
  107. //亮度
  108. [SerializeField] Slider sliderBrightness;
  109. [Header("Marker Layout Group")]
  110. [SerializeField]
  111. GameObject LayoutMarker;
  112. [SerializeField]
  113. RectTransform crosshairSmall;
  114. [Tooltip("标记页面标题提示")]
  115. [SerializeField] TextAutoLanguage2 markerTextAutoLanguage2;
  116. [SerializeField]
  117. RectTransform markerPointsParent;
  118. [SerializeField]
  119. List<RectTransform> markerPosList;
  120. [SerializeField]
  121. Line markerPointsLine;
  122. [SerializeField]
  123. PointMarker pointMarker;
  124. [Header("Manual Layout Group")]
  125. [SerializeField]
  126. GameObject LayoutManual;
  127. [Header("Successful Layout Group")]
  128. [SerializeField]
  129. GameObject LayoutSuccessful;
  130. [Tooltip("选择框的Line")]
  131. [SerializeField]
  132. Sprite[] ResultLines;// 0: 选中状态, 1: 未选中状态
  133. [Tooltip("选择框图片")]
  134. [SerializeField]
  135. Image[] ResultImages;
  136. [Tooltip("选择框按钮")]
  137. [SerializeField]
  138. Button[] ResultImagesButtons;
  139. [SerializeField]
  140. Button[] ResultButtons; // 结果选择按钮
  141. [SerializeField]
  142. RawImage CameraFirstImage; //第一个结果屏幕
  143. [SerializeField]
  144. RawImage CameraSecondImage; //第二个结果屏幕
  145. [SerializeField] LineGenerator FirstUILineGenerator;//第一个结果屏幕线条
  146. [SerializeField] LineGenerator SecondUILineGenerator;//第二个结果屏幕线条
  147. bool bMarkerFinish = false;
  148. ScreenPositioningStep perStepView = ScreenPositioningStep.None;//最后一次进入LayoutSuccessful的页面
  149. //标记当前页面情况
  150. ScreenPositioningStep curStepView = ScreenPositioningStep.Start;//设置一个开始页面
  151. InfraredDemo infraredDemo;
  152. bool doLocateAuto;
  153. int DefaultResolutionIndex;
  154. private void Awake()
  155. {
  156. //设置一次显示相机的image 的颜色
  157. rawImage.color = Color.white;
  158. offset = line.MyThickness;
  159. }
  160. void Start()
  161. {
  162. //获取InfraredDemo
  163. infraredDemo = InfraredDemo._ins;
  164. doLocateAuto = false;
  165. textTip1.SetActive(true);
  166. //设置btnAuto 高亮
  167. //OnButtonClick(btnAuto);
  168. textTip2.SetActive(false);
  169. //动态设置marker的提示语
  170. //if (BluetoothAim.ins!=null && markerTextAutoLanguage2 != null)
  171. //{
  172. // string name = "";
  173. // bool switchValue = false;
  174. // if (BluetoothAim.ins.isMainConnectToHOUYIPRO())
  175. // {
  176. // name = TextAutoLanguage2.GetTextByKey("TitleTipMarker-HOUYIPro");
  177. // }
  178. // else if (BluetoothAim.ins.isMainConnectToARTEMISPRO())
  179. // {
  180. // name = TextAutoLanguage2.GetTextByKey("TitleTipMarker-ArtemisPro");
  181. // }
  182. // else if (BluetoothAim.ins.isMainConnectToGun())
  183. // {
  184. // //name = TextAutoLanguage2.GetTextByKey("TitleTipMarker-M9");
  185. // switchValue = true;
  186. // }
  187. // if (switchValue)
  188. // {
  189. // markerTextAutoLanguage2.SetTextKey("TitleTipMarker-M9");
  190. // }
  191. // else {
  192. // markerTextAutoLanguage2.textFormatArgs = new object[] { name };
  193. // }
  194. //}
  195. //手动不高亮
  196. //ResetButton(btnHandMovement);
  197. //quadUnityVectorList.Clear();
  198. //quadUnityVectorList.Add(new Vector2(16.39f, 35.91f));
  199. //quadUnityVectorList.Add(new Vector2(233.35f, 51.08f));
  200. //quadUnityVectorList.Add(new Vector2(94.15f, 219.11f));
  201. //quadUnityVectorList.Add(new Vector2(243.12f, 237.40f));
  202. Debug.Log("quadUnityVectorList count:" + ScreenLocate.quadUnityVectorList.Count);
  203. if (ScreenLocate.quadUnityVectorList.Count == 0)
  204. {
  205. Debug.Log("GetLocalPos");
  206. GetLocalPos();
  207. }
  208. else
  209. {
  210. Vector2 texSize = ScreenLocate.Main.getUVCCameraInfoSize;
  211. Debug.Log("texSize:" + texSize + " = " + canvasRectTransform.rect);
  212. //自动识别时候四个点
  213. SyncQuadUnityVectorListToPos();
  214. //pos1.anchoredPosition = ScreenLocate.quadUnityVectorList[0].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  215. //pos2.anchoredPosition = ScreenLocate.quadUnityVectorList[1].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  216. //pos4.anchoredPosition = ScreenLocate.quadUnityVectorList[2].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  217. //pos3.anchoredPosition = ScreenLocate.quadUnityVectorList[3].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  218. }
  219. //更新start相关ui
  220. UpdateStartUI();
  221. //记录操作的位置信息
  222. oldLinePosition = new List<LinePosition>();
  223. SetLinePos();
  224. //相机感光度
  225. if (infraredDemo)
  226. {
  227. ////重置偏移量
  228. //infraredDemo.ResetCenterOffset();
  229. //////重置识别点
  230. ////ScreenLocate.Main.ScreenIdentification.ClearQuadCache();
  231. //////清除一下记录的点
  232. ////ScreenLocate.quadUnityVectorList.Clear();
  233. //infraredDemo.ResetPositioningData();
  234. slider.onValueChanged.AddListener((value) =>
  235. {
  236. infraredDemo.onSliderEvent(value);
  237. });
  238. infraredDemo.onSetSliderValue(slider);
  239. //对比度
  240. sliderContrast.onValueChanged.AddListener((value) =>
  241. {
  242. infraredDemo.onSliderCustomEvent(value, -20.0f, 20.0f);
  243. });
  244. infraredDemo.onSetSliderCustomValue(sliderContrast, -20.0f, 20.0f);
  245. //亮度
  246. sliderBrightness.onValueChanged.AddListener((value) =>
  247. {
  248. infraredDemo.onSliderCustomBrightnessEvent(value, -20.0f, 20.0f);
  249. });
  250. infraredDemo.onSetSliderCustomBrightnessValue(sliderBrightness, -20.0f, 20.0f);
  251. offset = line.MyThickness = markerPointsLine.MyThickness = infraredDemo.lineWidth.Get();
  252. //LineGenerator 比 line 宽少了大概2倍
  253. CurrentUILineGenerator.LineThickness = infraredDemo.lineWidth.Get() * 2;
  254. //扇形宽
  255. markerPointsLine.MyFanWidth = line.MyFanWidth = infraredDemo.fanWidth.Get();
  256. ZIM.Unity.QuadrilateralInCamera screen = ScreenLocate.Main.ScreenIdentification.Screen.QuadInCamera;
  257. CurrentUILineGenerator.Points = infraredDemo.ConvertQuadToPoints(screen, ScreenLocate.Main.getUVCCameraInfoSize);
  258. }
  259. else {
  260. //编辑器使用
  261. if (Application.isEditor || Application.platform == RuntimePlatform.WindowsPlayer) {
  262. slider.onValueChanged.AddListener((value) =>
  263. {
  264. double originalMin = 0.0;
  265. double originalMax = 10.0;
  266. double targetMin = -1;
  267. double targetMax = 1;
  268. // 计算转换后的值
  269. double result = InfraredDemo.MapValue(value, originalMin, originalMax, targetMin, targetMax);
  270. //int _current = (int)(result);
  271. Debug.Log("_current:" + value + " , result:" + result);
  272. ScreenLocate.Main.pcContrast = (float)result;
  273. });
  274. float v = ScreenLocate.Main.pcContrast;
  275. // 目标区间 [0, 10] 的边界值
  276. double targetMin = 0.0;
  277. double targetMax = 10.0;
  278. double originalMin = -1;
  279. double originalMax = 1;
  280. // 计算转换后的值
  281. double v2 = InfraredDemo.MapValue(v, originalMin, originalMax, targetMin, targetMax);
  282. Debug.Log("PC获取相机的感光度:" + v + " = " + v2);
  283. slider.SetValueWithoutNotify((float)v2);
  284. // 对 sliderContrast 和 sliderBrightness 调用统一的处理函数
  285. HandleSliderValueChanged(sliderContrast, value => ScreenLocate.Main.pcContrast = value, ScreenLocate.Main.pcContrast);
  286. HandleSliderValueChanged(sliderBrightness, value => ScreenLocate.Main.pcBrightness = value, ScreenLocate.Main.pcBrightness);
  287. }
  288. }
  289. initSelectInfo();
  290. //if (ScreenLocate.Main.getUVCTexture)
  291. //{
  292. // //渲染相机画面
  293. // rawImage.texture = ScreenLocate.Main.getUVCTexture;
  294. // //Debug.Log("rawImage.texture:" + rawImage.texture.name);
  295. //}
  296. //slider.onValueChanged.AddListener((value) => {
  297. // //onSliderEvent(value);
  298. // infraredDemo.SetBrightness(value);
  299. //});
  300. //slider.value = infraredDemo.brightness.Get();
  301. //修改分辨率。是否清晰一点?
  302. //DefaultResolutionIndex = infraredDemo?.ResolutionIndex ?? 0;
  303. //Debug.Log("[InfraredScreenPositioningView]开始记录进入时候的分辨率:" + DefaultResolutionIndex);
  304. //infraredDemo?.SetResolutionNew(ScreenLocate.Main.HighScreenLocateResolutionIndex);
  305. //if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked)
  306. //{
  307. // SB_EventSystem.ins.AwakenSimulateMouse();
  308. // // Debug.Log("simulate-mouse-close");
  309. //}
  310. }
  311. // 两个滑块值处理
  312. void HandleSliderValueChanged(UnityEngine.UI.Slider slider, System.Action<float> setValue, float pcValue)
  313. {
  314. double targetMin2 = -20.0;
  315. double targetMax2 = 20.0;
  316. double originalMin2 = -1;
  317. double originalMax2 = 1;
  318. slider.onValueChanged.AddListener((value) =>
  319. {
  320. double result = InfraredDemo.MapValue(value, targetMin2, targetMax2, originalMin2, originalMax2);
  321. Debug.Log($"{slider.name}_current: {value}, result: {result}");
  322. setValue((float)result);
  323. });
  324. double mappedValue = InfraredDemo.MapValue(pcValue, originalMin2, originalMax2, targetMin2, targetMax2);
  325. Debug.Log($"{slider.name} PC获取相机的感光度: {pcValue} = {mappedValue}");
  326. slider.SetValueWithoutNotify((float)mappedValue);
  327. }
  328. private void OnDestroy()
  329. {
  330. //修改回进入手动调节页面时候的分辨率
  331. //infraredDemo?.SetResolutionNew(DefaultResolutionIndex);
  332. Debug.Log("OnDestroy*********************************AwakenSimulateMouse:" + SB_EventSystem.ins.simulateMouseIsAwaked);
  333. if (SB_EventSystem.ins && !SB_EventSystem.ins.simulateMouseIsAwaked)
  334. {
  335. SB_EventSystem.ins.AwakenSimulateMouse();
  336. }
  337. }
  338. public RawImage Bg => rawImage;
  339. void Update()
  340. {
  341. if (enterFromZimWebCamera && ScreenLocate.Main.DebugOnZIMDemo) {
  342. // ZimWebCamera场景测试
  343. rawImage.texture = ScreenLocate.Main.outputRawImages[7].texture;
  344. if (ScreenLocate.Main.infraredSpotBuffer[0].CameraLocation.HasValue)
  345. {
  346. // 检测到光点
  347. var posInCanvas = ScreenLocate.Main.infraredSpotBuffer[0].CameraLocation.Value.pixelToLocalPosition_AnchorCenter(ScreenLocate.Main.CameraSize, rawImage.rectTransform.rect);
  348. crosshair.gameObject.SetActive(true);
  349. crosshair.anchoredPosition = posInCanvas;
  350. }
  351. else
  352. crosshair.gameObject.SetActive(false);
  353. //渲染相机画面
  354. CameraSecondImage.texture = rawImage.texture;
  355. CameraFirstImage.texture = rawImage.texture;
  356. }
  357. else if (InfraredDemo.running)
  358. {
  359. //渲染相机画面
  360. Texture texture = InfraredDemo.infraredCameraHelper.GetCameraTexture();
  361. if (rawImage.texture == null || texture.GetNativeTexturePtr() != rawImage.texture.GetNativeTexturePtr())
  362. {
  363. rawImage.texture = texture;
  364. //渲染相机画面
  365. CameraSecondImage.texture = rawImage.texture;
  366. CameraFirstImage.texture = rawImage.texture;
  367. }
  368. if (ScreenLocate.Main.infraredSpotBuffer[0].CameraLocation.HasValue)
  369. {
  370. // 检测到光点
  371. var posInCanvas = ScreenLocate.Main.infraredSpotBuffer[0].CameraLocation.Value.pixelToLocalPosition_AnchorCenter(ScreenLocate.Main.CameraSize, rawImage.rectTransform.rect);
  372. crosshairSmall.gameObject.SetActive(true);
  373. crosshairSmall.anchoredPosition = posInCanvas;
  374. }
  375. else
  376. crosshairSmall.gameObject.SetActive(false);
  377. //rawImage.material = InfraredDemo.infraredCameraHelper.GetCameraMaterial();
  378. //可见光调节页面出现红十字光标
  379. if (curStepView == ScreenPositioningStep.LightCtrl)
  380. {
  381. if (ScreenLocate.Main.infraredSpotBuffer[0].CameraLocation.HasValue)
  382. {
  383. // 检测到光点
  384. var posInCanvas = ScreenLocate.Main.infraredSpotBuffer[0].CameraLocation.Value.pixelToLocalPosition_AnchorCenter(ScreenLocate.Main.CameraSize, rawImage.rectTransform.rect);
  385. crosshairRed.gameObject.SetActive(true);
  386. crosshairRed.anchoredPosition = posInCanvas;
  387. }
  388. else
  389. crosshairRed.gameObject.SetActive(false);
  390. }
  391. else if (crosshairRed.gameObject.activeSelf) {
  392. crosshairRed.gameObject.SetActive(false);
  393. }
  394. }
  395. }
  396. /// <summary>
  397. /// 根据enum操作ui
  398. /// </summary>
  399. /// <param name="step"></param>
  400. public void SetScreenPositioningStepState(ScreenPositioningStep step = ScreenPositioningStep.None)
  401. {
  402. curStepView = step;
  403. AllScreenPositioningStepFalse();
  404. switch (step)
  405. {
  406. case ScreenPositioningStep.Start:
  407. maskLine.SetDrawMask(true);
  408. LayoutStart.SetActive(true);
  409. UpdateStartUI();
  410. break;
  411. case ScreenPositioningStep.AutoEnd:
  412. maskLine.SetDrawMask(true);
  413. LayoutAutoEnd.SetActive(true);
  414. pointsParent.gameObject.SetActive(false);
  415. CurrentUILineGenerator.enabled = true;
  416. QuadrilateralInCamera screenAuto = ScreenLocate.Main.ScreenIdentification.QuadAuto;
  417. if (screenAuto == null)
  418. {
  419. AutoEndConfirmBtn.interactable = false;
  420. }
  421. else
  422. {
  423. //存在数据,显示确认按钮
  424. AutoEndConfirmBtn.interactable = true;
  425. }
  426. break;
  427. case ScreenPositioningStep.LightCtrl:
  428. maskLine.SetDrawMask(false);
  429. LayoutLightCtrl.SetActive(true);
  430. CurrentUILineGenerator.enabled = true;
  431. pointsParent.gameObject.SetActive(false);
  432. //setPointsLocation(ScreenLocate.quadUnityVectorList, pointsParent.gameObject, true);
  433. break;
  434. case ScreenPositioningStep.Marker:
  435. //显示提示
  436. pointMarker.ShowHintImageParent(true);
  437. perStepView = ScreenPositioningStep.Marker;
  438. bMarkerFinish = false;
  439. maskLine.SetDrawMask(true);
  440. LayoutMarker.SetActive(true);
  441. CurrentUILineGenerator.enabled = false;
  442. pointsParent.gameObject.SetActive(false);
  443. SyncQuadUnityVectorListToMarkerPointesPos();
  444. //setPointsLocation(ScreenLocate.quadUnityVectorList, pointsParent.gameObject, true);
  445. break;
  446. case ScreenPositioningStep.Manual:
  447. SaveStartOldLinePosition();
  448. perStepView = ScreenPositioningStep.Manual;
  449. bMarkerFinish = false;
  450. LayoutManual.SetActive(true);
  451. bAuto = false;
  452. doLocateAuto = false;
  453. draggableParent.gameObject.SetActive(true);
  454. pointsParent.gameObject.SetActive(false);
  455. break;
  456. case ScreenPositioningStep.Successful:
  457. LayoutSuccessful.SetActive(true);
  458. pointsParent.gameObject.SetActive(false);
  459. CurrentUILineGenerator.enabled = false;
  460. break;
  461. }
  462. }
  463. void AllScreenPositioningStepFalse()
  464. {
  465. LayoutStart.SetActive(false);
  466. LayoutMarker.SetActive(false);
  467. LayoutManual.SetActive(false);
  468. LayoutAutoEnd.SetActive(false);
  469. LayoutLightCtrl.SetActive(false);
  470. LayoutSuccessful.SetActive(false);
  471. }
  472. /// <summary>
  473. /// 开始页面时候ui
  474. /// </summary>
  475. void UpdateStartUI() {
  476. pointsParent.gameObject.SetActive(false);
  477. CurrentUILineGenerator.enabled = true;
  478. if (ScreenLocate.quadUnityVectorList.Count == 0)
  479. {
  480. BottomConfirmBtn.SetActive(false);
  481. StartTextTip1.SetActive(true);
  482. StartTextTipHasData.SetActive(false);
  483. }
  484. else
  485. {
  486. //存在数据,显示确认按钮,确认按钮直接跳转到游戏
  487. BottomConfirmBtn.SetActive(true);
  488. StartTextTip1.SetActive(false);
  489. StartTextTipHasData.SetActive(true);
  490. }
  491. }
  492. public void OnClick_Back()
  493. {
  494. AudioMgr.ins.PlayBtn();
  495. ViewMgr.Instance.DestroyView<InfraredScreenPositioningView>();
  496. }
  497. /// <summary>
  498. /// 返回最开始页面
  499. /// </summary>
  500. public void OnClick_BackLayoutStart()
  501. {
  502. ClearPointsData();
  503. SetScreenPositioningStepState(ScreenPositioningStep.Start);
  504. }
  505. void ClearPointsData() {
  506. //重置中心点0
  507. infraredDemo.ResetCenterOffset();
  508. //清除白线数据
  509. infraredDemo.ResetPositioningData();
  510. //上面应该清空了 ScreenLocate.Main.ScreenIdentification.QuadAuto
  511. onClearCurrentUILineGenerator();
  512. }
  513. /// <summary>
  514. /// 进入环境光测试
  515. /// </summary>
  516. public void OnClick_EnterLightCtrl() {
  517. SetScreenPositioningStepState(ScreenPositioningStep.LightCtrl);
  518. }
  519. /// <summary>
  520. /// 进入屏幕标记
  521. /// </summary>
  522. public void OnClick_EnterMarker() {
  523. SetScreenPositioningStepState(ScreenPositioningStep.Marker);
  524. }
  525. /// <summary>
  526. /// successful 返回页面时候,根据ScreenPositioningStep区分
  527. /// </summary>
  528. public void OnClick_BackByScreenPositioningStep()
  529. {
  530. SetScreenPositioningStepState(ScreenPositioningStep.LightCtrl);
  531. //清空两个绘制线
  532. onClearSuccessfullLineGenerator();
  533. //if(perStepView == ScreenPositioningStep.Manual)
  534. // SetScreenPositioningStepState(ScreenPositioningStep.Manual);
  535. //else
  536. // SetScreenPositioningStepState(ScreenPositioningStep.Marker);
  537. }
  538. /// <summary>
  539. /// 直接进入游戏流程
  540. /// </summary>
  541. public void OnClick_EnterGame()
  542. {
  543. //对比确认效果。直接进入游戏引导页面
  544. EnterGame();
  545. }
  546. /// <summary>
  547. /// 进入自动流程校准操作
  548. /// </summary>
  549. public void OnClick_EnterAuto()
  550. {
  551. Debug.Log("*********** OnClick_EnterAuto ************");
  552. //自动按钮时候进入之前的校准流程
  553. ClearPointsData();
  554. OnClick_Auto();
  555. }
  556. /// <summary>
  557. /// 进入标记页面自动流程校准操作
  558. /// </summary>
  559. public void OnClick_EnterAutoByMarker()
  560. {
  561. Debug.Log("*********** OnClick_EnterAutoByMarker ************");
  562. //自动按钮时候进入之前的校准流程
  563. ClearPointsData();
  564. markerPointsLine.SetLine(new List<Vector2>());
  565. //隐藏提示
  566. pointMarker.ShowHintImageParent(false);
  567. OnClick_Auto();
  568. }
  569. /// <summary>
  570. /// 自动识别
  571. /// </summary>
  572. public void OnClick_Auto()
  573. {
  574. bAuto = true;
  575. doLocateAuto = true;
  576. //textTip1.SetActive(false);
  577. //textTip2.SetActive(true);
  578. //ResetButton(btnAuto);
  579. if (enterFromZimWebCamera)
  580. {
  581. ScreenLocate _screenLocate = FindAnyObjectByType<ScreenLocate>();
  582. _screenLocate.EnterScreenLocateManualAuto();
  583. return;
  584. }
  585. if (InfraredDemo.running)
  586. {
  587. InfraredDemo.infraredCameraHelper.EnterScreenLocateManualAuto();
  588. }
  589. }
  590. /// <summary>
  591. /// 进入手动界面
  592. /// </summary>
  593. public void OnClick_EnterManual()
  594. {
  595. SetScreenPositioningStepState(ScreenPositioningStep.Manual);
  596. }
  597. /// <summary>
  598. /// 切换成手动方式
  599. /// </summary>
  600. public void onHandMovement()
  601. {
  602. bAuto = false;
  603. doLocateAuto = false;
  604. draggableParent.gameObject.SetActive(true);
  605. pointsParent.gameObject.SetActive(false);
  606. mask.SetActive(false);
  607. cameraLight.SetActive(true);
  608. }
  609. /// <summary>
  610. /// 自动识别后同步
  611. /// </summary>
  612. public void SyncScreenPosition()
  613. {
  614. Vector2 texSize = ScreenLocate.Main.getUVCCameraInfoSize;
  615. Debug.Log("texSize:" + texSize + " = " + canvasRectTransform.rect);
  616. SyncQuadUnityVectorListToPos();
  617. SetRectanglePoints(linePosConversion(pos1.localPosition, pos2.localPosition, pos3.localPosition, pos4.localPosition));
  618. SyncQuadUnityVectorListToMarkerPointesPos();
  619. //显示提示
  620. pointMarker.ShowHintImageParent(true);
  621. AutoEndConfirmBtn.interactable = true;
  622. if (curStepView == ScreenPositioningStep.Start || curStepView == ScreenPositioningStep.AutoEnd) {
  623. //如果是开始页面进行自动定位的
  624. if (curStepView != ScreenPositioningStep.AutoEnd) {
  625. SetScreenPositioningStepState(ScreenPositioningStep.AutoEnd);
  626. }
  627. }
  628. else if (curStepView == ScreenPositioningStep.Marker || curStepView == ScreenPositioningStep.Manual) {
  629. //显示最后结果
  630. if(bMarkerFinish) SetScreenPositioningStepState(ScreenPositioningStep.Successful);
  631. }
  632. //屏幕变化情况下。同步修改对应的line
  633. //设置两个线段
  634. QuadrilateralInCamera screenAuto = ScreenLocate.Main.ScreenIdentification.QuadAuto;
  635. QuadrilateralInCamera screenSemiAuto = ScreenLocate.Main.ScreenIdentification.QuadSemiAuto;
  636. if (screenAuto != null)
  637. {
  638. Debug.Log("[校准流程]Successful自动识别screenAuto信息 ------------ ");
  639. CurrentUILineGenerator.Points = infraredDemo.ConvertQuadToPoints(screenAuto, texSize);
  640. FirstUILineGenerator.Points = infraredDemo.ConvertQuadToPoints(screenAuto, texSize);
  641. }
  642. else
  643. {
  644. Debug.LogError("screenAuto 不存在!");
  645. }
  646. if (screenSemiAuto != null)
  647. {
  648. Debug.Log("[校准流程]Successful半自动识别screenSemiAuto信息 ------------ ");
  649. SecondUILineGenerator.Points = infraredDemo.ConvertQuadToPoints(screenSemiAuto, texSize);
  650. }
  651. else
  652. {
  653. Debug.LogError("screenSemiAuto 不存在!");
  654. }
  655. }
  656. /// <summary>
  657. /// 清空白线数据
  658. /// </summary>
  659. void onClearCurrentUILineGenerator() {
  660. if (CurrentUILineGenerator.Points.Length != 0) CurrentUILineGenerator.Points = new Vector2[0];//System.Array.Clear(CurrentUILineGenerator.Points, 0, CurrentUILineGenerator.Points.Length);
  661. }
  662. /// <summary>
  663. /// 清空最后识别的两个自动和半自动数据线
  664. /// </summary>
  665. void onClearSuccessfullLineGenerator()
  666. {
  667. if(FirstUILineGenerator.Points.Length !=0) FirstUILineGenerator.Points = new Vector2[0]; //System.Array.Clear(FirstUILineGenerator.Points, 0, FirstUILineGenerator.Points.Length);
  668. if (SecondUILineGenerator.Points.Length !=0) SecondUILineGenerator.Points = new Vector2[0]; //System.Array.Clear(SecondUILineGenerator.Points, 0, SecondUILineGenerator.Points.Length);
  669. }
  670. #region 绘制线段部分
  671. //点击拖拽的开始位置
  672. public void onBeginPos(int index, Vector3 pos)
  673. {
  674. Debug.Log("pos begin: " + pos);
  675. beginPos = pos;
  676. }
  677. public void onDragPos(int index, Vector3 pos)
  678. {
  679. //设置线段的点
  680. SetRectanglePoints(linePosConversion(pos1.localPosition, pos2.localPosition, pos3.localPosition, pos4.localPosition));
  681. }
  682. //点击拖拽的结束位置
  683. public void onEndPos(int index, Vector3 pos)
  684. {
  685. Debug.Log("pos end: " + pos);
  686. endPos = pos;
  687. if (beginPos == endPos) return;
  688. //Debug.Log(index+",最后的点:" + pos);
  689. //再记录一次最后的点
  690. SetLinePos();
  691. }
  692. //同步设置图片对应的位置到line
  693. public void SetLinePos()
  694. {
  695. //记录一个操作点的操作位置
  696. AddOldLinePosition();
  697. //设置线段的点
  698. SetRectanglePoints(linePosConversion(pos1.localPosition, pos2.localPosition, pos3.localPosition, pos4.localPosition));
  699. }
  700. void AddOldLinePosition()
  701. {
  702. Vector3[] v = new Vector3[4];
  703. pos1.GetWorldCorners(v);
  704. Vector3[] v1 = new Vector3[4];
  705. pos1.GetLocalCorners(v1);
  706. //for (int i = 0; i < 4; i++)
  707. //{
  708. // Debug.Log(i + " =1= " + v[i]);
  709. // Debug.Log(i + " =2= " + v1[i]);
  710. //}
  711. //记录一个操作点的操作位置
  712. List<Vector3> screenPositions = new List<Vector3>();
  713. screenPositions.Add(pos1.localPosition);
  714. screenPositions.Add(pos2.localPosition);
  715. screenPositions.Add(pos3.localPosition);
  716. screenPositions.Add(pos4.localPosition);
  717. LinePosition linePosition = new LinePosition();
  718. linePosition.index = oldLinePosition.Count;
  719. linePosition.pos = screenPositions;
  720. oldLinePosition.Add(linePosition);
  721. }
  722. /// <summary>
  723. /// 记录一个开始位置
  724. /// </summary>
  725. void SaveStartOldLinePosition() {
  726. oldLinePosition.Clear();
  727. //记录一个操作点的操作位置
  728. List<Vector3> screenPositions = new List<Vector3>();
  729. screenPositions.Add(pos1.localPosition);
  730. screenPositions.Add(pos2.localPosition);
  731. screenPositions.Add(pos3.localPosition);
  732. screenPositions.Add(pos4.localPosition);
  733. LinePosition linePosition = new LinePosition();
  734. linePosition.index = 1;
  735. linePosition.pos = screenPositions;
  736. oldLinePosition.Add(linePosition);
  737. }
  738. //转换绘制线段的点
  739. List<Vector2> linePosConversion(Vector3 _pos1, Vector3 _pos2, Vector3 _pos3, Vector3 _pos4)
  740. {
  741. List<Vector2> _screenPositions = new List<Vector2>();
  742. //点为负数的增大 offset,正数减少 offset
  743. //Vector2 startPos1 = new Vector2(_pos1.x - pos1.rect.width * 0.5f + offset, _pos1.y - pos1.rect.height * 0.5f + offset);
  744. //Vector2 startPos2 = new Vector2(_pos2.x + pos2.rect.width * 0.5f - offset, _pos2.y - pos2.rect.height * 0.5f + offset);
  745. //Vector2 startPos3 = new Vector2(_pos3.x + pos3.rect.width * 0.5f - offset, _pos3.y + pos3.rect.height * 0.5f - offset);
  746. //Vector2 startPos4 = new Vector2(_pos4.x - pos4.rect.width * 0.5f + offset, _pos4.y + pos4.rect.height * 0.5f - offset);
  747. Vector2 startPos1 = new Vector2(_pos1.x + offset, _pos1.y + offset);
  748. Vector2 startPos2 = new Vector2(_pos2.x - offset, _pos2.y + offset);
  749. Vector2 startPos3 = new Vector2(_pos3.x - offset, _pos3.y - offset);
  750. Vector2 startPos4 = new Vector2(_pos4.x + offset, _pos4.y - offset);
  751. _screenPositions.Add(startPos1);
  752. _screenPositions.Add(startPos2);
  753. _screenPositions.Add(startPos3);
  754. _screenPositions.Add(startPos4);
  755. return _screenPositions;
  756. }
  757. void SetRectanglePoints(List<Vector2> screenPositions)
  758. {
  759. line.SetLine(screenPositions);
  760. }
  761. //撤回上一个元素
  762. public void onRecall()
  763. {
  764. // 获取并删除最后一个元素,并且保留一个元素
  765. if (oldLinePosition.Count > 1) // 确保列表不为空
  766. {
  767. // 获取回退的那个元素点
  768. LinePosition lastElement_second = oldLinePosition[oldLinePosition.Count - 2];
  769. // 获取最后一个元素
  770. //LinePosition lastElement = oldLinePosition[oldLinePosition.Count - 1];
  771. //Debug.Log(JsonUtility.ToJson(lastElement) + " = " + oldLinePosition.Count);
  772. oldLinePosition.RemoveAt(oldLinePosition.Count - 1); // 删除最后一个元素
  773. pos1.localPosition = lastElement_second.pos[0];
  774. pos2.localPosition = lastElement_second.pos[1];
  775. pos3.localPosition = lastElement_second.pos[2];
  776. pos4.localPosition = lastElement_second.pos[3];
  777. //设置线段的点
  778. SetRectanglePoints(linePosConversion(lastElement_second.pos[0], lastElement_second.pos[1], lastElement_second.pos[2], lastElement_second.pos[3]));
  779. }
  780. }
  781. //是不是从Demo界面进入该页面的
  782. public bool enterFromInfraredDemo { get; set; } = false;
  783. //是否从测试场景进入
  784. public bool enterFromZimWebCamera { get; set; } = false;
  785. //确认修改
  786. public void onConfirmation()
  787. {
  788. if (enterFromZimWebCamera)
  789. {
  790. ConfirmScreenLocateManualTest();
  791. if (oldLinePosition.Count > 1) // 确保列表不为空
  792. {
  793. LinePosition lastElement = oldLinePosition[oldLinePosition.Count - 1];
  794. oldLinePosition.Clear();
  795. oldLinePosition.Add(lastElement);
  796. }
  797. SaveLocalPos();
  798. AudioMgr.ins.PlayBtn();
  799. ViewManager2.HideView(ViewManager2.Path_InfraredScreenPositioningView);
  800. return;
  801. }
  802. if (!ConfirmScreenLocateManual()) return;
  803. if (oldLinePosition.Count > 1) // 确保列表不为空
  804. {
  805. //LinePosition lastElement = oldLinePosition[oldLinePosition.Count - 1];
  806. oldLinePosition.Clear();
  807. //oldLinePosition.Add(lastElement);
  808. }
  809. if (InfraredDemo.running)
  810. {
  811. //跳转入界面
  812. AudioMgr.ins.PlayBtn();
  813. if (!enterFromInfraredDemo)
  814. {
  815. //每次初始化重置一下引导
  816. infraredDemo.resetInfraredPlayerPrefs();
  817. //GameObject connectGuidanceView = ViewManager2.getGameObjectAndShowView(ViewManager2.Path_ConnectGuidanceView);
  818. //connectGuidanceView.GetComponent<ConnectGuidanceView>().showTextipInfrared();
  819. if (!PlayerPrefs.HasKey("hideInfraredBowAndArrow"))
  820. {
  821. //如果是红外连接成功,记录一个tag
  822. PlayerPrefs.SetInt("hideInfraredBowAndArrow", 1);
  823. }
  824. onEnterInfrared();
  825. }
  826. else {
  827. ViewManager2.HideView(ViewManager2.Path_InfraredScreenPositioningView);
  828. }
  829. }
  830. //存储一次节点
  831. SaveLocalPos();
  832. }
  833. //重置位置
  834. public void onReset()
  835. {
  836. oldLinePosition.Clear();
  837. // 获取屏幕的四个角的像素坐标
  838. Vector2 bottomLeft = new Vector2(0, 0);
  839. // 将屏幕像素坐标转换为 Canvas 的局部坐标
  840. Vector2 localBottomLeft;
  841. RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, bottomLeft, null, out localBottomLeft);
  842. // 打印结果
  843. Debug.Log("Local Bottom Left: " + localBottomLeft);
  844. //int _x = Mathf.FloorToInt(Mathf.Abs(localBottomLeft.x) - 120), _y = Mathf.FloorToInt(Mathf.Abs(localBottomLeft.y) - 77);
  845. int _x = Mathf.FloorToInt(Mathf.Abs(localBottomLeft.x)), _y = Mathf.FloorToInt(Mathf.Abs(localBottomLeft.y));
  846. pos1.anchoredPosition = new Vector3(-_x, -_y, 0); //Bottom Left
  847. pos2.anchoredPosition = new Vector3(_x, -_y, 0); //Bottom Right
  848. pos3.anchoredPosition = new Vector3(_x, _y, 0); //Top Right
  849. pos4.anchoredPosition = new Vector3(-_x, _y, 0); //Top Left
  850. //pos1.anchoredPosition = new Vector3(_x, _y, 0);
  851. //pos2.anchoredPosition = new Vector3(-_x, _y, 0);
  852. //pos3.anchoredPosition = new Vector3(-_x, -_y, 0);
  853. //pos4.anchoredPosition = new Vector3(_x, -_y, 0);
  854. //设置一次位置
  855. SetLinePos();
  856. btnRecordInfrared.Reset();
  857. ScreenLocate.Main.ScreenIdentification.ClearQuadCache();
  858. if (enterFromZimWebCamera)
  859. {
  860. ScreenLocate.Main.ScreenQuad.gameObject.SetActive(false);
  861. ScreenLocate.Main.UILineGenerator.Points = new Vector2[0];
  862. }
  863. if (curStepView == ScreenPositioningStep.Start || curStepView == ScreenPositioningStep.AutoEnd)
  864. {
  865. //如果是开始页面进行自动定位的失败的
  866. if (curStepView != ScreenPositioningStep.AutoEnd) {
  867. SetScreenPositioningStepState(ScreenPositioningStep.AutoEnd);
  868. }
  869. AutoEndConfirmBtn.interactable = false;
  870. }
  871. }
  872. /// <summary>
  873. /// 标准四个点
  874. /// </summary>
  875. /// <param name="index"></param>
  876. /// <param name="pos"></param>
  877. public void onManualNewPos(int index, Vector3 pos)
  878. {
  879. Debug.Log("pos end: " + pos);
  880. if (index == 0)
  881. pos1.localPosition = pos;
  882. else if (index == 1)
  883. pos2.localPosition = pos;
  884. else if (index == 2)
  885. pos3.localPosition = pos;
  886. else if (index == 3)
  887. pos4.localPosition = pos;
  888. //再记录一次最后的点
  889. SetLinePos();
  890. }
  891. /// <summary>
  892. /// 处理新流程,先记录手动,然后到自动识别处理
  893. /// </summary>
  894. public void onManualToAutomatic() {
  895. if (enterFromZimWebCamera)
  896. {
  897. ConfirmScreenLocateManualTest();
  898. if (oldLinePosition.Count > 1) // 确保列表不为空
  899. {
  900. LinePosition lastElement = oldLinePosition[oldLinePosition.Count - 1];
  901. oldLinePosition.Clear();
  902. oldLinePosition.Add(lastElement);
  903. }
  904. SaveLocalPos();
  905. //到自动
  906. OnClick_Auto();
  907. return;
  908. }
  909. if (!ConfirmScreenLocateManual()) {
  910. Debug.LogError("ConfirmScreenLocateManual is false!");
  911. return;
  912. }
  913. if (oldLinePosition.Count > 1) // 确保列表不为空
  914. {
  915. LinePosition lastElement = oldLinePosition[oldLinePosition.Count - 1];
  916. oldLinePosition.Clear();
  917. oldLinePosition.Add(lastElement);
  918. }
  919. //存储一次节点
  920. SaveLocalPos();
  921. Debug.Log("[校准流程]进入自动校准数据,调用EnterScreenLocateManualAuto");
  922. bAuto = true;
  923. doLocateAuto = true;
  924. //自动校准
  925. InfraredDemo.infraredCameraHelper.EnterScreenLocateManualAuto();
  926. }
  927. /// <summary>
  928. /// PointMarker 调用
  929. /// </summary>
  930. public void onFinishManualToAutomatic() {
  931. bMarkerFinish = true;
  932. onManualToAutomatic();
  933. }
  934. #endregion
  935. List<Vector2> _locatePointList = new();
  936. float _texWidth;
  937. float _texHeight;
  938. void RecordLocatePoint(RectTransform p, Vector2 pivot)
  939. {
  940. Vector2 pos = JCUnityLib.RectTransformUtils.GetPositionByPivot(p, pivot);
  941. pos.x = Mathf.Clamp01(pos.x / Screen.width);
  942. pos.y = Mathf.Clamp01(pos.y / Screen.height);
  943. _locatePointList.Add(pos);
  944. }
  945. bool ConfirmScreenLocateManual()
  946. {
  947. if (InfraredDemo.running)
  948. {
  949. //渲染截图
  950. Texture2D texture2D = InfraredDemo.infraredCameraHelper.EnterScreenLocateManual();
  951. if (texture2D == null)
  952. {
  953. Debug.Log("EnterScreenLocateManual = null");
  954. InfraredDemo.infraredCameraHelper.QuitScreenLocateManual(null);
  955. return false;
  956. }
  957. _locatePointList.Clear();
  958. _texWidth = texture2D.width;
  959. _texHeight = texture2D.height;
  960. RecordLocatePoint(pos1, new Vector2(0, 0));
  961. RecordLocatePoint(pos2, new Vector2(1, 0));
  962. RecordLocatePoint(pos3, new Vector2(1, 1));
  963. RecordLocatePoint(pos4, new Vector2(0, 1));
  964. //RecordLocatePoint(pos1, new Vector2(0.5f, 0.5f));
  965. //RecordLocatePoint(pos2, new Vector2(0.5f, 0.5f));
  966. //RecordLocatePoint(pos3, new Vector2(0.5f, 0.5f));
  967. //RecordLocatePoint(pos4, new Vector2(0.5f, 0.5f));
  968. InfraredDemo.infraredCameraHelper.QuitScreenLocateManual(_locatePointList);
  969. FindObjectOfType<InfraredDemo>().SetLocatePointsToCameraRender(_locatePointList, 1, 1);
  970. //同步数据
  971. ScreenLocate.quadUnityVectorList.Clear();
  972. ScreenLocate.quadUnityVectorList.Add(_locatePointList[0]);
  973. ScreenLocate.quadUnityVectorList.Add(_locatePointList[1]);
  974. //两个点切换,顺序不一样
  975. ScreenLocate.quadUnityVectorList.Add(_locatePointList[3]);
  976. ScreenLocate.quadUnityVectorList.Add(_locatePointList[2]);
  977. ScreenLocate.SaveScreenLocateVectorList();
  978. Debug.Log("[校准流程]设置QuitScreenLocateManual()手动数据,保存quadUnityVectorList");
  979. return true;
  980. }
  981. return false;
  982. }
  983. void ConfirmScreenLocateManualTest()
  984. {
  985. //渲染截图
  986. ScreenLocate _screenLocate = FindAnyObjectByType<ScreenLocate>();
  987. Texture2D texture2D = _screenLocate.EnterScreenLocateManual();
  988. if (texture2D == null)
  989. {
  990. _screenLocate.QuitScreenLocateManual(null);
  991. return;
  992. }
  993. _locatePointList.Clear();
  994. _texWidth = texture2D.width;
  995. _texHeight = texture2D.height;
  996. RecordLocatePoint(pos1, new Vector2(0, 0));
  997. RecordLocatePoint(pos2, new Vector2(1, 0));
  998. RecordLocatePoint(pos3, new Vector2(1, 1));
  999. RecordLocatePoint(pos4, new Vector2(0, 1));
  1000. _screenLocate.QuitScreenLocateManual(_locatePointList);
  1001. //FindObjectOfType<InfraredDemo>().SetLocatePointsToCameraRender(_locatePointList, _texWidth, _texHeight);
  1002. setPointsLocation(_locatePointList,pointsParent.gameObject,!bAuto);
  1003. if (!doLocateAuto) // 设置手动定位数据
  1004. setPointsManual(_locatePointList, GameObject.Find("WebCameraView/CameraImage0/ScreenQuad"));
  1005. //同步数据
  1006. ScreenLocate.quadUnityVectorList.Clear();
  1007. ScreenLocate.quadUnityVectorList.Add(new Vector2(_locatePointList[0].x, _locatePointList[0].y));
  1008. ScreenLocate.quadUnityVectorList.Add(new Vector2(_locatePointList[1].x, _locatePointList[1].y));
  1009. //两个点切换,顺序不一样
  1010. ScreenLocate.quadUnityVectorList.Add(new Vector2(_locatePointList[3].x, _locatePointList[3].y));
  1011. ScreenLocate.quadUnityVectorList.Add(new Vector2(_locatePointList[2].x, _locatePointList[2].y));
  1012. ScreenLocate.SaveScreenLocateVectorList();
  1013. }
  1014. void setPointsLocation(List<Vector2> targetList, GameObject pointsTF2, bool active = true)
  1015. {
  1016. //GameObject pointsTF2 = GameObject.Find("WebCameraView/CameraImage0/ScreenQuad");
  1017. pointsTF2.SetActive(active);
  1018. if (pointsTF2.transform.childCount == targetList.Count)
  1019. {
  1020. for (int i = 0; i < pointsTF2.transform.childCount; i++)
  1021. {
  1022. Transform pointTF = pointsTF2.transform.GetChild(i);
  1023. Vector2 pos = targetList[i];
  1024. pointTF.localPosition = pos.pixelToLocalPosition_AnchorCenter(Vector2.one, pointsTF2.GetComponent<RectTransform>().rect);
  1025. pointTF.gameObject.SetActive(true);
  1026. }
  1027. }
  1028. }
  1029. void setPointsManual(List<Vector2> targetList, GameObject pointsTF2, bool active = true)
  1030. {
  1031. setPointsLocation(targetList, pointsTF2, active);
  1032. var lo = new Vector2(-0.5f, -0.5f);
  1033. ScreenLocate.Main.UILineGenerator.Points = new Vector2[4] {
  1034. 2 * (targetList[0] + lo),
  1035. 2 * (targetList[1] + lo),
  1036. 2 * (targetList[2] + lo),
  1037. 2 * (targetList[3] + lo) };
  1038. }
  1039. void SaveLocalPos()
  1040. {
  1041. List<Vector3> screenPositions = new List<Vector3>();
  1042. screenPositions.Add(pos1.anchoredPosition);
  1043. screenPositions.Add(pos2.anchoredPosition);
  1044. screenPositions.Add(pos3.anchoredPosition);
  1045. screenPositions.Add(pos4.anchoredPosition);
  1046. string saveStr = string.Join(';', screenPositions.Select(v => $"{v.x},{v.y}")); //,{v.z}
  1047. Debug.Log("Local UI Position: " + saveStr);
  1048. PlayerPrefs.SetString("ScreenPositioningView", saveStr);
  1049. }
  1050. void GetLocalPos()
  1051. {
  1052. string posListStr = PlayerPrefs.GetString("ScreenPositioningView", "");
  1053. if (!string.IsNullOrWhiteSpace(posListStr))
  1054. {
  1055. List<Vector2> posList = posListStr.Split(';')
  1056. .Select(s =>
  1057. {
  1058. string[] parts = s.Split(',');
  1059. return new Vector2(float.Parse(parts[0]), float.Parse(parts[1]));
  1060. })
  1061. .ToList();
  1062. pos1.anchoredPosition = posList[0];
  1063. pos2.anchoredPosition = posList[1];
  1064. pos3.anchoredPosition = posList[2];
  1065. pos4.anchoredPosition = posList[3];
  1066. SetRectanglePoints(linePosConversion(pos1.localPosition, pos2.localPosition, pos3.localPosition, pos4.localPosition));
  1067. }
  1068. }
  1069. #region 按钮颜色切换
  1070. private void OnButtonClick(Button button)
  1071. {
  1072. // 切换按钮颜色
  1073. ColorBlock colors = button.colors;
  1074. colors.normalColor = highlightedColor;
  1075. colors.highlightedColor = highlightedColor;
  1076. button.colors = colors;
  1077. // 切换字体颜色
  1078. Text buttonText = button.GetComponentInChildren<Text>();
  1079. buttonText.color = highlightedTextColor;
  1080. }
  1081. private void ResetButton(Button button)
  1082. {
  1083. // 重置按钮颜色
  1084. ColorBlock colors = button.colors;
  1085. colors.normalColor = normalColor;
  1086. colors.highlightedColor = normalColor;
  1087. button.colors = colors;
  1088. // 重置字体颜色
  1089. Text buttonText = button.GetComponentInChildren<Text>();
  1090. buttonText.color = normalTextColor;
  1091. }
  1092. #endregion
  1093. #region 标定完成之后进入游戏界面
  1094. void onEnterInfrared()
  1095. {
  1096. //添加进入射箭场景
  1097. if (PlayerPrefs.GetInt("entry-guider-infrared-" + LoginMgr.myUserInfo.id, 0) == 0)
  1098. {
  1099. Debug.Log("-----进入射箭场景!");
  1100. NewUserGuiderManager newUserGuiderManager = FindObjectOfType<NewUserGuiderManager>();
  1101. newUserGuiderManager.curConfigKey = "开始-红外调整";
  1102. //b端都是红外设备流程
  1103. if (CommonConfig.StandaloneModeOrPlatformB)
  1104. {
  1105. newUserGuiderManager.isNewModule = true;
  1106. }
  1107. else {
  1108. newUserGuiderManager.isNewModule = AimHandler.ins.aimDeviceInfo.type == (int)AimDeviceType.HOUYIPRO || AimHandler.ins.aimDeviceInfo.type == (int)AimDeviceType.Gun || AimHandler.ins.aimDeviceInfo.type == (int)AimDeviceType.ARTEMISPRO;
  1109. }
  1110. //进入射箭场景
  1111. GlobalData.pkMatchType = PKMatchType.None;
  1112. GameMgr.gameType = 1;
  1113. //射一箭回到连接页面,Device.view
  1114. GameMgr.bNavBack = true;
  1115. GameMgr.bShowDistance = false;
  1116. if (!CommonConfig.StandaloneModeOrPlatformB)
  1117. {
  1118. AimHandler.ins.bInitOne = false;//true
  1119. }
  1120. //关闭计时器
  1121. GameMgr.turnOffTimer = true;
  1122. //关闭左边靶子和底部速度栏
  1123. GameMgr.HideTargetView = true;
  1124. GameMgr.HideBillboard = true;
  1125. GameMgr.ButtonCount = 0;
  1126. UnityEngine.SceneManagement.SceneManager.LoadScene(
  1127. "Game", UnityEngine.SceneManagement.LoadSceneMode.Single);
  1128. PlayerPrefs.SetInt("entry-guider-infrared-" + LoginMgr.myUserInfo.id, 1);
  1129. }
  1130. else
  1131. {
  1132. Debug.Log("-----跳转回连接界面!");
  1133. //如不是第一次,则应该跳转回连接界面
  1134. ViewMgr.Instance.DestroyView<SmartArcheryView>();
  1135. ViewManager2.HideView(ViewManager2.Path_ConnectGuidanceView);
  1136. }
  1137. }
  1138. #endregion
  1139. #region 最后选择算法处理UI
  1140. int selected = -1;
  1141. void initSelectInfo() {
  1142. for (int i = 0; i < 2; i++)
  1143. {
  1144. int currentIndex = i; // 将 i 赋值给局部变量
  1145. ResultImagesButtons[currentIndex].onClick.AddListener(() => SelectImage(currentIndex));
  1146. //ResultButtons[currentIndex].onClick.AddListener(() =>
  1147. //{
  1148. // if (currentIndex == 0)
  1149. // {
  1150. // OnFirstResult();
  1151. // }
  1152. // else if (currentIndex == 1)
  1153. // {
  1154. // OnSecondResult();
  1155. // }
  1156. //});
  1157. }
  1158. //默认选择1 自动
  1159. SelectImage(0);
  1160. }
  1161. // 添加一个选择函数
  1162. void SelectImage(int selectedIndex)
  1163. {
  1164. //如果重复选中则跳转
  1165. if (selected == selectedIndex) {
  1166. if (selected == 0)
  1167. {
  1168. OnFirstResult();
  1169. }
  1170. else if (selected == 1)
  1171. {
  1172. OnSecondResult();
  1173. }
  1174. return;
  1175. }
  1176. // 遍历所有图片
  1177. selected = selectedIndex;
  1178. //for (int i = 0; i < ResultImages.Length; i++)
  1179. //{
  1180. // // 如果是选中的 index,赋值为 ResultLines[0],否则赋值为 ResultLines[1]
  1181. // if (i == selectedIndex)
  1182. // {
  1183. // selected = i;
  1184. // ResultImages[i].sprite = ResultLines[0];
  1185. // ResultButtons[i].interactable = true;
  1186. // }
  1187. // else
  1188. // {
  1189. // ResultImages[i].sprite = ResultLines[1];
  1190. // ResultButtons[i].interactable = false;
  1191. // }
  1192. //}
  1193. }
  1194. //选择全自动结果后进入游戏
  1195. void OnFirstResult()
  1196. {
  1197. ScreenLocate.Main.SelectScreenAfterLocate(ScreenLocate.ScreenIdentificationTag.Auto);
  1198. UpdateQuadUnityVectorList();
  1199. onCompelete();
  1200. }
  1201. //选择半自动结果
  1202. void OnSecondResult()
  1203. {
  1204. ScreenLocate.Main.SelectScreenAfterLocate(ScreenLocate.ScreenIdentificationTag.SemiAuto);
  1205. UpdateQuadUnityVectorList();
  1206. onCompelete();
  1207. }
  1208. public void onCompelete()
  1209. {
  1210. if (enterFromZimWebCamera)
  1211. {
  1212. SaveLocalPos();
  1213. ViewManager2.HideView(ViewManager2.Path_InfraredScreenPositioningView);
  1214. return;
  1215. }
  1216. EnterGame();
  1217. //存储一次节点
  1218. SaveLocalPos();
  1219. }
  1220. void EnterGame() {
  1221. if (InfraredDemo.running)
  1222. {
  1223. //跳转入界面
  1224. AudioMgr.ins.PlayBtn();
  1225. if (!enterFromInfraredDemo)
  1226. {
  1227. //每次初始化重置一下引导
  1228. infraredDemo.resetInfraredPlayerPrefs();
  1229. //GameObject connectGuidanceView = ViewManager2.getGameObjectAndShowView(ViewManager2.Path_ConnectGuidanceView);
  1230. //connectGuidanceView.GetComponent<ConnectGuidanceView>().showTextipInfrared();
  1231. if (!PlayerPrefs.HasKey("hideInfraredBowAndArrow"))
  1232. {
  1233. //如果是红外连接成功,记录一个tag
  1234. PlayerPrefs.SetInt("hideInfraredBowAndArrow", 1);
  1235. }
  1236. onEnterInfrared();
  1237. }
  1238. else
  1239. {
  1240. ViewManager2.HideView(ViewManager2.Path_InfraredScreenPositioningView);
  1241. }
  1242. }
  1243. }
  1244. /// <summary>
  1245. /// 选择模式后更新 quadUnityVectorList
  1246. /// </summary>
  1247. void UpdateQuadUnityVectorList() {
  1248. ScreenLocate.Main.UpdateQuadUnityVectorList();
  1249. SyncQuadUnityVectorListToPos();
  1250. infraredDemo?.SetLocatePointsToCameraRender(ScreenLocate.quadUnityVectorList, 1, 1);
  1251. _locatePointList.Clear();
  1252. }
  1253. void SyncQuadUnityVectorListToPos() {
  1254. Debug.Log("[ScreenLocate] SyncQuadUnityVectorListToPos quadUnityVectorList:" + ScreenLocate.Main.PrintVector2List(ScreenLocate.quadUnityVectorList));
  1255. pos1.anchoredPosition = ScreenLocate.quadUnityVectorList[0].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  1256. pos2.anchoredPosition = ScreenLocate.quadUnityVectorList[1].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  1257. pos4.anchoredPosition = ScreenLocate.quadUnityVectorList[2].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  1258. pos3.anchoredPosition = ScreenLocate.quadUnityVectorList[3].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  1259. }
  1260. //这个脚本存在时候。任何切换操作都直接处理删除
  1261. //void OnSceneUnloaded(Scene scene)
  1262. //{
  1263. // ViewManager2.HideView(ViewManager2.Path_ConnectGuidanceView);
  1264. // ViewManager2.HideView(ViewManager2.Path_InfraredScreenPositioningView);
  1265. //}
  1266. //void OnEnable()
  1267. //{
  1268. // SceneManager.sceneUnloaded += OnSceneUnloaded;
  1269. //}
  1270. //void OnDisable()
  1271. //{
  1272. // SceneManager.sceneUnloaded -= OnSceneUnloaded;
  1273. //}
  1274. #endregion
  1275. #region 判断点是否在 quad 内部
  1276. //判断maskline
  1277. public bool IsPointInMaskLine(Vector2 point) {
  1278. return IsPointInQuad(point, maskLine.ScreenPositions);
  1279. }
  1280. //实现基于射线法,通过数交点的奇偶性来判断点是否在多边形内
  1281. bool IsPointInQuad(Vector2 point, List<Vector2> quadVertices)
  1282. {
  1283. if (quadVertices.Count != 4)
  1284. {
  1285. Debug.LogError("Quad must have exactly 4 vertices.");
  1286. return false;
  1287. }
  1288. bool isInside = false;
  1289. int vertexCount = quadVertices.Count;
  1290. for (int i = 0, j = vertexCount - 1; i < vertexCount; j = i++)
  1291. {
  1292. Vector2 vi = quadVertices[i];
  1293. Vector2 vj = quadVertices[j];
  1294. // 检查射线是否与边相交
  1295. if (((vi.y > point.y) != (vj.y > point.y)) &&
  1296. (point.x < (vj.x - vi.x) * (point.y - vi.y) / (vj.y - vi.y) + vi.x))
  1297. {
  1298. isInside = !isInside;
  1299. }
  1300. }
  1301. return isInside;
  1302. }
  1303. /// <summary>
  1304. /// 判断四个点是否能够形成有效的四边形,并根据面积阈值过滤小四边形
  1305. /// </summary>
  1306. /// <param name="points">四个点</param>
  1307. /// <param name="minArea">面积阈值,用于过滤面积太小的四边形</param>
  1308. /// <returns>是否是有效的四边形</returns>
  1309. public bool IsValidQuadrilateral(Vector2[] points, float minArea = 100000.0f)
  1310. {
  1311. if (points.Length != 4)
  1312. {
  1313. Debug.Log("四个点数不足,无法形成四边形。");
  1314. return false; // 如果点数不是4,直接返回false
  1315. }
  1316. // 计算四边形的面积
  1317. float area = CalculateArea(points);
  1318. Debug.Log($"四边形面积: {area}");
  1319. if (area < minArea)
  1320. {
  1321. Debug.Log($"面积小于阈值: {minArea},返回 false。");
  1322. return false; // 面积太小,返回 false
  1323. }
  1324. // 检查是否有三点共线
  1325. for (int i = 0; i < points.Length; i++)
  1326. {
  1327. Vector2 a = points[i];
  1328. Vector2 b = points[(i + 1) % points.Length];
  1329. Vector2 c = points[(i + 2) % points.Length];
  1330. if (ArePointsCollinear(a, b, c))
  1331. {
  1332. Debug.Log($"点 {a}, {b}, {c} 共线,返回 false。");
  1333. return false; // 存在共线点,返回 false
  1334. }
  1335. }
  1336. // 检查是否为矩形或接近矩形
  1337. if (!IsRectangle(points))
  1338. {
  1339. // 如果不是矩形,检查是否是梯形
  1340. if (!IsTrapezoid(points))
  1341. {
  1342. Debug.Log("既不是矩形,也不是梯形,返回 false。");
  1343. return false; // 不是矩形也不是梯形,返回 false
  1344. }
  1345. else
  1346. {
  1347. Debug.Log("是梯形。");
  1348. }
  1349. }
  1350. else
  1351. {
  1352. Debug.Log("是矩形。");
  1353. }
  1354. // 检查对角线是否相交
  1355. if (DoLinesIntersect(points[0], points[1], points[2], points[3]) ||
  1356. DoLinesIntersect(points[1], points[2], points[3], points[0]))
  1357. {
  1358. Debug.Log("对角线相交,返回 false。");
  1359. return false; // 对角线相交,返回 false
  1360. }
  1361. // 检查点的排列顺序,确保是顺时针或逆时针
  1362. if (!ArePointsClockwise(points) && !ArePointsClockwise(points.Reverse().ToArray()))
  1363. {
  1364. Debug.Log("点的排列顺序不正确,返回 false。");
  1365. return false; // 点的排列顺序不正确
  1366. }
  1367. Debug.Log("四边形有效,返回 true。");
  1368. return true; // 通过所有检查,返回 true
  1369. }
  1370. /// <summary>
  1371. /// 判断是否是矩形(近似90度角)
  1372. /// </summary>
  1373. private bool IsRectangle(Vector2[] points)
  1374. {
  1375. // 角度容差范围,允许夹角有小的偏差
  1376. const float dotProductThreshold = 0.1f;
  1377. for (int i = 0; i < points.Length; i++)
  1378. {
  1379. Vector2 a = points[i];
  1380. Vector2 b = points[(i + 1) % points.Length];
  1381. Vector2 c = points[(i + 2) % points.Length];
  1382. // 计算向量 AB 和 BC 的内积
  1383. Vector2 ab = b - a;
  1384. Vector2 bc = c - b;
  1385. float dotProduct = Vector2.Dot(ab.normalized, bc.normalized);
  1386. // 如果内积接近 0,表示夹角接近 90 度
  1387. if (Mathf.Abs(dotProduct) > dotProductThreshold)
  1388. {
  1389. Debug.Log($"点 {a}, {b}, {c} 的夹角不接近 90 度,返回 false。");
  1390. return false; // 角度不接近 90 度
  1391. }
  1392. }
  1393. return true;
  1394. }
  1395. /// <summary>
  1396. /// 判断是否是梯形
  1397. /// </summary>
  1398. private bool IsTrapezoid(Vector2[] points)
  1399. {
  1400. // 斜率容差范围,允许斜率差异较小
  1401. const float slopeThreshold = 0.2f;
  1402. // 计算对角线的斜率
  1403. float slope1 = (points[1].y - points[0].y) / (points[1].x - points[0].x);
  1404. float slope2 = (points[3].y - points[2].y) / (points[3].x - points[2].x);
  1405. // 如果对角线斜率差异小于容差范围,则认为是梯形
  1406. if (Mathf.Abs(slope1 - slope2) < slopeThreshold)
  1407. {
  1408. Debug.Log("对角线平行,判断为梯形。");
  1409. return true; // 对角线平行,返回 true
  1410. }
  1411. else
  1412. {
  1413. Debug.Log($"对角线斜率差异过大: {slope1} vs {slope2},不是梯形,返回 false。");
  1414. return false; // 斜率差异过大,不是梯形
  1415. }
  1416. }
  1417. //计算四边形面积
  1418. float CalculateArea(Vector2[] points)
  1419. {
  1420. float area = 0f;
  1421. int n = points.Length;
  1422. for (int i = 0; i < n; i++)
  1423. {
  1424. Vector2 current = points[i];
  1425. Vector2 next = points[(i + 1) % n];
  1426. area += current.x * next.y - current.y * next.x;
  1427. }
  1428. return Mathf.Abs(area) / 2f;
  1429. }
  1430. //确保点不共线
  1431. //判断点是否在同一条直线上(即共线),如果共线则无法形成四边形。可以通过计算任意三点的面积是否为 0 来验证是否共线:
  1432. bool ArePointsCollinear(Vector2 a, Vector2 b, Vector2 c)
  1433. {
  1434. float area = Mathf.Abs(a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)) / 2.0f;
  1435. return Mathf.Approximately(area, 0f);
  1436. }
  1437. //确保边不相交
  1438. bool DoLinesIntersect(Vector2 a, Vector2 b, Vector2 c, Vector2 d)
  1439. {
  1440. float cross(Vector2 p1, Vector2 p2, Vector2 p3)
  1441. {
  1442. return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
  1443. }
  1444. float d1 = cross(a, b, c);
  1445. float d2 = cross(a, b, d);
  1446. float d3 = cross(c, d, a);
  1447. float d4 = cross(c, d, b);
  1448. return d1 * d2 < 0 && d3 * d4 < 0;
  1449. }
  1450. //顺时针或逆时针排列顶点
  1451. bool ArePointsClockwise(Vector2[] points)
  1452. {
  1453. float sum = 0;
  1454. for (int i = 0; i < points.Length; i++)
  1455. {
  1456. Vector2 current = points[i];
  1457. Vector2 next = points[(i + 1) % points.Length];
  1458. sum += (next.x - current.x) * (next.y + current.y);
  1459. }
  1460. return sum < 0; // 小于0为顺时针,大于0为逆时针
  1461. }
  1462. #endregion
  1463. #region marker line 部分渲染
  1464. /// <summary>
  1465. /// maker 界面渲染
  1466. /// </summary>
  1467. void SyncQuadUnityVectorListToMarkerPointesPos()
  1468. {
  1469. if (ScreenLocate.quadUnityVectorList.Count == 4)
  1470. {
  1471. Debug.Log("[ScreenLocate] SyncQuadUnityVectorListToMarkerPointesPos quadUnityVectorList:" + ScreenLocate.Main.PrintVector2List(ScreenLocate.quadUnityVectorList));
  1472. markerPosList[0].anchoredPosition = ScreenLocate.quadUnityVectorList[0].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  1473. markerPosList[1].anchoredPosition = ScreenLocate.quadUnityVectorList[1].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  1474. markerPosList[2].anchoredPosition = ScreenLocate.quadUnityVectorList[3].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  1475. markerPosList[3].anchoredPosition = ScreenLocate.quadUnityVectorList[2].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
  1476. SetMarkerRectanglePoints(linePosConversion(markerPosList[0].localPosition, markerPosList[1].localPosition, markerPosList[2].localPosition, markerPosList[3].localPosition));
  1477. }
  1478. }
  1479. void SetMarkerRectanglePoints(List<Vector2> screenPositions)
  1480. {
  1481. markerPointsLine.SetLine(screenPositions);
  1482. }
  1483. #endregion
  1484. }