AimHandler.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. using System;
  2. using UnityEngine;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine.UI;
  6. public enum AimDeviceType {
  7. NONE = -1,
  8. HOUYI = 0,
  9. HOUYI2 = 1,
  10. ARTEMIS = 2,
  11. HOUYIPRO = 3,
  12. //枪械类
  13. Gun = 4,
  14. ARTEMISPRO = 5,
  15. }
  16. [Serializable]//需要在转换为json格式的类的上方添加序列化
  17. public class AimDeviceInfo
  18. {
  19. public int id;
  20. public int type = -1;//类型 AimDeviceType
  21. public int pos; //位置
  22. public bool bInitMac = false; //是否初始化Mac
  23. public string mac; //记录当前
  24. public AimDeviceInfo(int _id) {
  25. this.id = _id;
  26. }
  27. public void setInitMac(string macTemp) {
  28. bInitMac = true;
  29. mac = macTemp;
  30. }
  31. public void resetInitMac() {
  32. bInitMac = false;
  33. mac = "";
  34. }
  35. }
  36. [Serializable]
  37. public class AimDeviceInfos
  38. {
  39. public List<AimDeviceInfo> arry;
  40. }
  41. /* 瞄准处理器 */
  42. public class AimHandler : MonoBehaviour
  43. {
  44. CameraToLook m_controlObj {
  45. get {
  46. return CameraToLook.ins;
  47. }
  48. }
  49. //记录一个设备
  50. public AimDeviceInfo aimDeviceInfo = null;
  51. public AimDeviceInfo tempAimDeviceInfo = null;//临时处理值。最后赋值给aimDeviceInfo
  52. public AimDeviceInfos aimDeviceInfos = new AimDeviceInfos();
  53. int deviceSelectIndex = 0;//默认选中第一个设备(1p)
  54. public Action aimDeviceInfoChangeEvent;
  55. public int DeviceType
  56. {
  57. get
  58. {
  59. if (m_axisHandler.GetType() == typeof(Axis9Handler)) return 9;
  60. if (m_axisHandler.GetType() == typeof(Axis663Handler)) return 663;
  61. return 0;
  62. }
  63. }
  64. private AxisBaseHandler m_axisHandler;
  65. //陀螺仪校准进度记录
  66. [NonSerialized] public int gyrCalibrateCompleteCount = 0;
  67. [NonSerialized] public int gyrCalibrateTotalCount = 2000;
  68. public static AimHandler ins;
  69. public bool bInitOne = false;
  70. void Start()
  71. {
  72. ins = this;
  73. BluetoothDispatcher.aim = OnDataReceived;
  74. // m_axisHandler = new Axis9NopackHandler(this); //九轴旧
  75. m_axisHandler = new Axis9Handler(this); //九轴新
  76. // m_axisHandler = new Axis663Handler(this); //双陀螺仪
  77. m_axisHandler.Init();
  78. // StartCoroutine(TestRecord());
  79. }
  80. public void onClearAimDeviceInfosNew()
  81. {
  82. PlayerPrefs.DeleteKey("aim-device-info-" + LoginMgr.myUserInfo.id);
  83. aimDeviceInfos.arry.Clear();
  84. }
  85. /// <summary>
  86. /// 移除2p。即除了1p之后的设备
  87. /// </summary>
  88. public void onClear2PAimDeviceInfosNew()
  89. {
  90. OnGetAimDeviceInfos();
  91. if (aimDeviceInfos.arry.Count > 1)
  92. {
  93. aimDeviceInfos.arry.RemoveRange(1, aimDeviceInfos.arry.Count - 1);
  94. }
  95. OnSaveAimDeviceInfos();
  96. }
  97. public void OnGetAimDeviceInfos() {
  98. string deviceInfo = PlayerPrefs.GetString("aim-device-info-" + LoginMgr.myUserInfo.id, "");
  99. Debug.Log("get deviceSelectIndex:" + deviceInfo);
  100. if (deviceInfo != "")
  101. {
  102. aimDeviceInfos = JsonUtility.FromJson<AimDeviceInfos>(deviceInfo);//这里的类是依据最外层{}决定的
  103. }
  104. aimDeviceInfoChangeEvent?.Invoke();
  105. }
  106. public void OnSaveAimDeviceInfos()
  107. {
  108. aimDeviceInfoChangeEvent?.Invoke();
  109. PlayerPrefs.SetString("aim-device-info-" + LoginMgr.myUserInfo.id, JsonUtility.ToJson(aimDeviceInfos));
  110. }
  111. //创建一个选择值
  112. public void onCreateTempAimDeviceInfo() {
  113. tempAimDeviceInfo = new AimDeviceInfo(deviceSelectIndex);
  114. Debug.Log("onCreateTempAimDeviceInfo deviceSelectIndex:" + deviceSelectIndex);
  115. }
  116. //是否存在AimDeviceInfo,存在更新,不存在创建;
  117. public void onCreateAimDeviceInfoById()
  118. {
  119. OnGetAimDeviceInfos();
  120. //deviceIndex 区分 1p 还是 2p
  121. bool bCanAdd = true;
  122. foreach (AimDeviceInfo p in aimDeviceInfos.arry)
  123. {
  124. if (deviceSelectIndex == p.id)
  125. {
  126. aimDeviceInfo = p;
  127. bCanAdd = false;
  128. }
  129. //Debug.Log("33deviceSelectIndex:" + deviceSelectIndex + ",bCanAdd:" + bCanAdd+ " , id:" + p.id +" , type:"+ p.type);
  130. }
  131. if (bCanAdd)
  132. {
  133. Debug.Log("add deviceSelectIndex:" + deviceSelectIndex);
  134. aimDeviceInfo = new AimDeviceInfo(deviceSelectIndex);
  135. aimDeviceInfos.arry.Add(aimDeviceInfo);
  136. }
  137. OnSaveAimDeviceInfos();
  138. }
  139. public void SetAimDeviceSelectIndex(int selectIndex) {
  140. if (selectIndex < 0) {
  141. Debug.LogWarning("selectIndex不能小于0:"+ selectIndex);
  142. return;
  143. }
  144. deviceSelectIndex = selectIndex;
  145. Debug.Log("SetAimDeviceSelectIndex :" + selectIndex);
  146. }
  147. public void SetTempAimDeviceType(AimDeviceType _aimDeviceType)
  148. {
  149. if (tempAimDeviceInfo == null) return;
  150. tempAimDeviceInfo.type = (int)_aimDeviceType;
  151. }
  152. public void SetAimDeviceType(AimDeviceType _aimDeviceType)
  153. {
  154. if (aimDeviceInfo == null) return;
  155. aimDeviceInfo.type = (int)_aimDeviceType;
  156. _AimDeviceInfosUpdate();
  157. OnSaveAimDeviceInfos();
  158. }
  159. public void SetAimDeviceType(int _aimDeviceType)
  160. {
  161. if (aimDeviceInfo == null) return;
  162. aimDeviceInfo.type = _aimDeviceType;
  163. _AimDeviceInfosUpdate();
  164. OnSaveAimDeviceInfos();
  165. }
  166. //APP连接需进行MAC地址的比对。
  167. //只有再引导初始化页面才保存连接使用的mac地址。
  168. public void SetAimDeviceMac(string _mac) {
  169. if (aimDeviceInfo == null) return;
  170. aimDeviceInfo.setInitMac(_mac);
  171. _AimDeviceInfosUpdate();
  172. OnSaveAimDeviceInfos();
  173. }
  174. //重置mac存储信息
  175. public void ResetAimDeviceMac() {
  176. if (aimDeviceInfo == null) return;
  177. aimDeviceInfo.resetInitMac();
  178. _AimDeviceInfosUpdate();
  179. OnSaveAimDeviceInfos();
  180. }
  181. void _AimDeviceInfosUpdate() {
  182. for (int i = 0; i < aimDeviceInfos.arry.Count; i++)
  183. {
  184. if (aimDeviceInfo.id == aimDeviceInfos.arry[i].id)
  185. {
  186. aimDeviceInfos.arry[i] = aimDeviceInfo;
  187. }
  188. }
  189. }
  190. #region 根据设备1p或者2p 获取HOUYIPRO的状态
  191. public bool isHOUYIPRO(BluetoothPlayer bluetoothPlayer)
  192. {
  193. bool _isHOUYIPRO = false;
  194. foreach (AimDeviceInfo p in AimHandler.ins.aimDeviceInfos.arry)
  195. {
  196. if ((int)bluetoothPlayer == p.id && p.type == (int)AimDeviceType.HOUYIPRO)
  197. {
  198. _isHOUYIPRO = true;
  199. }
  200. }
  201. return _isHOUYIPRO;
  202. }
  203. #endregion
  204. #region 根据设备1p或者2p 获取ARTEMISPro的状态
  205. public bool isARTEMISPro(BluetoothPlayer bluetoothPlayer)
  206. {
  207. bool _isARTEMISPro = false;
  208. foreach (AimDeviceInfo p in ins.aimDeviceInfos.arry)
  209. {
  210. if ((int)bluetoothPlayer == p.id && p.type == (int)AimDeviceType.ARTEMISPRO)
  211. {
  212. _isARTEMISPro = true;
  213. }
  214. }
  215. return _isARTEMISPro;
  216. }
  217. #endregion
  218. public void ReinitAxisHandler()
  219. {
  220. Debug.Log("ReinitAxisHandler");
  221. m_axisHandler.Init();
  222. }
  223. // System.Collections.IEnumerator TestRecord() {
  224. // while (LoginMgr.myUserInfo.id == 0) yield return null;
  225. // UserComp.Instance.saveMac();
  226. // }
  227. [NonSerialized] private Quaternion newRotation = Quaternion.identity;
  228. public void SetNewRotation(Quaternion quat) {
  229. this.newRotation = quat;
  230. }
  231. public void SetNewRotation(o0.Geometry.Quaternion o0Quat) {
  232. Quaternion quat = o0.Bow.Extension.ToUnityQuaternion(o0Quat);
  233. if (float.IsNaN(quat.x) || float.IsNaN(quat.y) || float.IsNaN(quat.z) || float.IsNaN(quat.w)) {
  234. Debug.LogError($"九轴Rotation存在Nan值,double:{o0Quat.ToString()},float:{quat.ToString()}");
  235. return;
  236. }
  237. if (float.IsInfinity(quat.x) || float.IsInfinity(quat.y) || float.IsInfinity(quat.z) || float.IsInfinity(quat.w)) {
  238. Debug.LogError($"九轴Rotation存在Infinity值,double:{o0Quat.ToString()},float:{quat.ToString()}");
  239. return;
  240. }
  241. this.newRotation = quat;
  242. }
  243. [NonSerialized] public bool lerpForRotation = true;
  244. [NonSerialized] public float lerpTimeRate = 7;
  245. public void Update()
  246. {
  247. //&& !InfraredDemo.running
  248. if (m_controlObj && !m_ban9AxisCalculate && bRuning9Axis())
  249. {
  250. if (lerpForRotation)
  251. m_controlObj.localRotation = Quaternion.Lerp(m_controlObj.localRotation, newRotation, Time.deltaTime * lerpTimeRate);
  252. else
  253. m_controlObj.localRotation = newRotation;
  254. }
  255. if (IsMagCompleted())
  256. {
  257. if (!m_magCompleted)
  258. {
  259. StartCoroutine(SaveMag());
  260. PopupMgr.ins.ShowTipTop(TextAutoLanguage2.GetTextByKey("tip_mag-calibrate_success"));
  261. }
  262. m_magCompleted = true;
  263. } else {
  264. m_magCompleted = false;
  265. }
  266. //if (Input.GetKeyDown(KeyCode.Space))
  267. //{
  268. // //AutoResetView.DoIdentity();
  269. // CrossBtnEvent();
  270. //}
  271. }
  272. public void OnDataReceived(byte[] bytes)
  273. {
  274. if (bytes.Length != 27 && bytes.Length != 39)
  275. {
  276. if (bytes.Length == 2)
  277. {
  278. if (bytes[0] == 0x66 && bytes[1] == 0x31)
  279. {
  280. if (bInitOne)
  281. {
  282. bInitOne = false;
  283. if (aimDeviceInfo.type == (int)AimDeviceType.NONE ||
  284. aimDeviceInfo.type == (int)AimDeviceType.HOUYI ||
  285. aimDeviceInfo.type == (int)AimDeviceType.HOUYI2 ||
  286. aimDeviceInfo.type == (int)AimDeviceType.ARTEMIS)
  287. {
  288. AutoResetView.DoIdentity();
  289. }
  290. else
  291. {
  292. //准心开关
  293. CrossBtnEvent();
  294. }
  295. }
  296. else
  297. {
  298. if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked)
  299. {
  300. //模拟鼠标弹出时候
  301. InfraredGuider infraredGuider = FindAnyObjectByType<InfraredGuider>();
  302. if (infraredGuider == null)
  303. {
  304. //视角回正
  305. DoIdentity();
  306. //鼠标居中自然会居中
  307. }
  308. }
  309. else
  310. {
  311. if (aimDeviceInfo.type == (int)AimDeviceType.NONE ||
  312. aimDeviceInfo.type == (int)AimDeviceType.HOUYI ||
  313. aimDeviceInfo.type == (int)AimDeviceType.HOUYI2 ||
  314. aimDeviceInfo.type == (int)AimDeviceType.ARTEMIS)
  315. {
  316. AutoResetView.DoIdentity();
  317. }
  318. else
  319. {
  320. //准心开关
  321. CrossBtnEvent();
  322. }
  323. }
  324. }
  325. }
  326. else if (bytes[0] == 0x66 && bytes[1] == 0x32)
  327. {
  328. //红外部分
  329. if (GlobalData.MyDeviceMode == DeviceMode.Gun || BluetoothAim.ins && BluetoothAim.ins.isMainConnectToInfraredDevice())
  330. {
  331. InfraredGuider infraredGuider = FindAnyObjectByType<InfraredGuider>();
  332. //‘校准'功能的调用,使用原来调出光标的功能键;即在HOUYI Pro使用长按视角归位键;在ARTEMIS Pro使用快速双击按键
  333. if (infraredGuider == null)
  334. {
  335. AutoResetView.DoIdentity();
  336. }
  337. else {
  338. //先判断是否处于校准步骤
  339. infraredGuider.onLongClickDevice();
  340. }
  341. }
  342. else if (SB_EventSystem.ins)
  343. {
  344. // if (SB_EventSystem.ins && !CommonConfig.SpecialVersion1) {
  345. //唤起/隐藏虚拟鼠标
  346. SB_EventSystem.ins.AwakenSimulateMouse();
  347. }
  348. }
  349. else if (bytes[1] == 10)
  350. {
  351. //显示电量
  352. DeviceBatteryView.ins.RenderBattery(1, bytes[0]);
  353. //DeviceView.ins.RenderBattery(1, bytes[0]);
  354. }
  355. }
  356. else if (bytes[0] == 0x5b)
  357. {
  358. //红外射击检测
  359. ShootCheck.ins.ShootByInfrared(bytes);
  360. }
  361. else if (bytes[0] == 0x5C)
  362. {
  363. //00 弹夹分离,01 上弹夹
  364. ShootCheck.ins.UpdateTheMagazine(bytes);
  365. }
  366. else if (bytes[0] == 0x5E)
  367. {
  368. Debug.Log("接收到系统数据:" + BitConverter.ToString(bytes));
  369. //设备类型
  370. switch (bytes[1])
  371. {
  372. case 0x01:
  373. Debug.Log("设备类型:HOUYI Pro");
  374. break;
  375. case 0x02:
  376. Debug.Log("设备类型:ARTEMIS Pro");
  377. break;
  378. case 0x03:
  379. Debug.Log("设备类型:Pistol 1");
  380. break;
  381. }
  382. // 系统类型
  383. switch (bytes[2])
  384. {
  385. case 0x01:
  386. Debug.Log("系统类型:移动手机");
  387. break;
  388. case 0x02:
  389. Debug.Log("系统类型:PC电脑");
  390. break;
  391. case 0x03:
  392. Debug.Log("系统类型:VR设备");
  393. break;
  394. }
  395. }
  396. return;
  397. }
  398. //if (InfraredDemo.running)
  399. //{
  400. // BluetoothAim.ins.WriteData("4"); //关闭九轴
  401. // return;
  402. //}
  403. if (!bRuning9Axis())
  404. {
  405. return;
  406. }
  407. m_axisHandler.Update(bytes);
  408. if (BowQuatDebug.ins) BowQuatDebug.ins.ShowModuleQuat(newRotation.eulerAngles);
  409. if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked) SB_EventSystem.ins.MoveSimulateMouse(newRotation);
  410. }
  411. public byte[] InsertByteAtBeginning(byte[] originalArray, byte newByte)
  412. {
  413. byte[] newArray = new byte[originalArray.Length + 1];
  414. newArray[0] = newByte;
  415. Array.Copy(originalArray, 0, newArray, 1, originalArray.Length);
  416. return newArray;
  417. }
  418. private bool m_magCompleted;
  419. public void CorrectMagCompleted(bool value) { m_magCompleted = value; }
  420. private bool m_ban9AxisCalculate = false;
  421. public void Ban9AxisCalculate(bool ban)
  422. {
  423. // m_ban9AxisCalculate = ban;
  424. // if (!ban)
  425. // {
  426. // SetMsOldDefault();
  427. // if (m_controlObj) m_controlObj.localRotation = newRotation;
  428. // }
  429. }
  430. public void SetMsOldDefault()
  431. {
  432. if (m_axisHandler.GetType() == typeof(Axis9NopackHandler))
  433. (m_axisHandler as Axis9NopackHandler).msOld = default;
  434. }
  435. public void DoIdentity()
  436. {
  437. //if (InfraredDemo.running) return;
  438. m_axisHandler.DoIdentity();
  439. if (!bRuning9Axis()) return;
  440. if (m_controlObj) m_controlObj.localRotation = newRotation;
  441. }
  442. public void NotifyAxisOnShot() { m_axisHandler.NotifyAxisOnShot(); }
  443. public void CalibrateGyr(bool calibration) { m_axisHandler.CalibrateGyr(calibration); }
  444. public void InitGyr(string record) { m_axisHandler.InitGyr(record); }
  445. public void InitMag(string record) { m_axisHandler.InitMag(record); }
  446. public void ResetGyr() { m_axisHandler.ResetGyr(); }
  447. public void ResetMag() { m_axisHandler.ResetMag(); }
  448. public void ApplyImpreciseMag() { m_axisHandler.ApplyImpreciseMag(); }
  449. public bool IsGyrCompleted() { return m_axisHandler.IsGyrCompleted(); }
  450. public bool IsMagCompleted() { return m_axisHandler.IsMagCompleted(); }
  451. public IEnumerator SaveGyr() { return m_axisHandler.SaveGyr(); }
  452. public IEnumerator SaveMag() { return m_axisHandler.SaveMag(); }
  453. public void ResumeCalibrateRecord(string record) { m_axisHandler.ResumeCalibrateRecord(record); }
  454. #region 获取一个连接的设备下,对应的 Archery 是运行9轴的代码处理位置信息判断
  455. public bool bRuning9Axis() {
  456. //连接的设备下,对应的 Archery 是运行9轴的代码处理位置信息判断
  457. //弓箭类型,但是不是HOUYI Pro 情况下。运行9轴代码
  458. bool bRuning = GlobalData.MyDeviceMode == DeviceMode.Archery && !BluetoothAim.ins.isMainConnectToInfraredDevice();
  459. return bRuning;
  460. }
  461. #endregion
  462. /// <summary>
  463. /// 操作准心开关事件
  464. /// </summary>
  465. private void CrossBtnEvent()
  466. {
  467. Debug.Log("CrossBtnEvent");
  468. //准心开关
  469. if (GameAssistUI.ins)
  470. {
  471. InfraredGuider infraredGuider = FindAnyObjectByType<InfraredGuider>();
  472. if (infraredGuider == null)
  473. {
  474. //显示控制准心按钮
  475. Button crossHairBtn = GameAssistUI.ins.transform.Find("Button5").GetComponent<Button>();
  476. crossHairBtn.onClick.Invoke();
  477. }
  478. else {
  479. infraredGuider.onClickDevice();
  480. }
  481. //if (GameMgr.bShowDistance)
  482. //{
  483. // //显示控制准心按钮
  484. // Button crossHairBtn = GameAssistUI.ins.transform.Find("Button5").GetComponent<Button>();
  485. // crossHairBtn.onClick.Invoke();
  486. //}
  487. //else {
  488. // //校准
  489. // InfraredDemo._ins?.OnClick_SetAdjustPointsOffset();
  490. //}
  491. }
  492. else if (DuckHunter.GameUI.Instance)
  493. {
  494. //显示控制准心按钮
  495. Button crossHairBtn = DuckHunter.GameUI.Instance.transform.Find("BtnCrosshair").GetComponent<Button>();
  496. crossHairBtn.onClick.Invoke();
  497. }
  498. else if (HyperspaceGame.UIManager._ins) {
  499. //打枪
  500. Button crossHairBtn = HyperspaceGame.UIManager._ins.transform.Find("BtnCrosshair").GetComponent<Button>();
  501. crossHairBtn.onClick.Invoke();
  502. }
  503. else
  504. {
  505. if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name.StartsWith("FruitMaster")){
  506. //水果
  507. Button crossHairBtn = GameObject.Find("PermanentCanvas/CrossHair_Btn").GetComponent<Button>();
  508. crossHairBtn.onClick.Invoke();
  509. }
  510. }
  511. }
  512. }