/Resources/ui/screens/ARScreen.js

https://bitbucket.org/dharmik/dharmik · JavaScript · 618 lines · 412 code · 36 blank · 170 comment · 23 complexity · 77ba1a8505e40b792c9c9bbf22d5b131 MD5 · raw file

  1. /*
  2. * ARScreen
  3. * ==========
  4. *
  5. * This file contains the Augmented Reality window.
  6. *
  7. * It displays the data from google place.
  8. *
  9. * Using callbacks to process the next stage of the build
  10. *
  11. */
  12. /*
  13. * Load the required modules for this function
  14. */
  15. var layout = require('/ui/layout');
  16. var images = require('/ui/images');
  17. var common = require('/tools/common');
  18. var persHandler = require('/tools/persHandler');
  19. var augmentedReality = require('/tools/augmentedReality');
  20. var androidPlatform = null;
  21. /*
  22. * The variables needed to pass views around for changes...
  23. */
  24. var arWin = null;
  25. var arBaseView = null;
  26. var arRadarImg = null;
  27. var googleData = null;
  28. var cameraView = null;
  29. var poiView1 = null;
  30. var poiView2 = null;
  31. var poiView3 = null;
  32. var poiView4 = null;
  33. var screenWidth = parseInt(persHandler.retPersData({
  34. type : 'width'
  35. }), 10);
  36. var screenHeight = parseInt(persHandler.retPersData({
  37. type : 'height'
  38. }), 10);
  39. /*
  40. * The required flags to only allow processing when the processing is not already happening
  41. */
  42. var rotateFlag = true;
  43. /*
  44. * showARDetail
  45. * ============
  46. *
  47. * This function create a view of the POI's data and then displays it over
  48. * the AR view. When closed it cleans up the View and variables.
  49. *
  50. */
  51. function showARDetail(inParam)
  52. {
  53. var arDetailView = Ti.UI.createView({
  54. top : 0,
  55. left : 0,
  56. right : 0,
  57. bottom : 0,
  58. backgroundColor : layout.css.ar.detail.bkc,
  59. opacity : 0.75,
  60. zIndex : 125
  61. });
  62. var arDetailTitle = Ti.UI.createLabel({
  63. top : '75dp',
  64. height : '50dp',
  65. left : '30dp',
  66. right : '30dp',
  67. text : inParam.TITLE,
  68. textAlign : 'center',
  69. color : layout.css.ar.detail.fc,
  70. font : {
  71. fontFamily : layout.css.hs.tbfnf,
  72. fontWeight : layout.css.hs.tbfnw,
  73. fontSize : layout.css.hs.tbfns
  74. }
  75. });
  76. var arDetailDesc = Ti.UI.createTextArea({
  77. top : '130dp',
  78. height : '300dp',
  79. left : '30dp',
  80. right : '30dp',
  81. backgroundColor : 'transparent',
  82. editable : false,
  83. value : inParam.DESC,
  84. textAlign : 'center',
  85. color : layout.css.ar.detail.fc,
  86. font : {
  87. fontFamily : layout.css.hs.tbfnf,
  88. fontWeight : layout.css.hs.tbfnw,
  89. fontSize : layout.css.hs.tbfns
  90. }
  91. });
  92. arDetailView.add(arDetailTitle);
  93. arDetailView.add(arDetailDesc);
  94. /*
  95. * The close button
  96. */
  97. var arDetailClose = Ti.UI.createLabel({
  98. bottom : '25dp',
  99. width : layout.css.butt.wi,
  100. height : layout.css.butt.hi,
  101. text : Ti.Locale.getString('butt_close'),
  102. textAlign : layout.css.butt.ta,
  103. backgroundColor : layout.css.butt.bkc,
  104. color : layout.css.butt.fc,
  105. borderRadius : layout.css.butt.br,
  106. borderWidth : layout.css.butt.bw,
  107. borderColor : layout.css.butt.bc,
  108. font : {
  109. fontFamily : layout.css.butt.ff,
  110. fontWeight : layout.css.butt.fw,
  111. fontSize : layout.css.butt.fs
  112. },
  113. zIndex : 150
  114. });
  115. arDetailView.add(arDetailClose);
  116. /*
  117. * The event listeners to facilitate actions
  118. */
  119. arDetailClose.addEventListener('touchstart', function()
  120. {
  121. arDetailClose.backgroundColor = layout.css.butt.tbkc;
  122. arDetailClose.borderColor = layout.css.butt.tbc;
  123. arDetailClose.color = layout.css.butt.tfc;
  124. });
  125. arDetailClose.addEventListener('touchend', function()
  126. {
  127. arDetailClose.backgroundColor = layout.css.butt.bkc;
  128. arDetailClose.borderColor = layout.css.butt.bc;
  129. arDetailClose.color = layout.css.butt.fc;
  130. arBaseView.remove(arDetailView);
  131. arDetailView = null;
  132. });
  133. arBaseView.add(arDetailView);
  134. }
  135. /*
  136. * rotateDisplay
  137. * =============
  138. *
  139. * These function rotates the Augmented Reality Display as the device is rotated
  140. *
  141. * The right is set as opposed to the left as it rotates the screen correctly. If the
  142. * left position of the view is set it rotates the display in the opposite direction.
  143. *
  144. */
  145. function removeFlag()
  146. {
  147. rotateFlag = false;
  148. }
  149. function rotateDisplay()
  150. {
  151. if(!rotateFlag) {
  152. rotateFlag = true;
  153. var currBearing = parseInt(persHandler.retPersData({
  154. type : 'bearing'
  155. }), 10);
  156. if(currBearing <= 90) {
  157. poiView1.right = ((currBearing - 0) * (screenWidth / 90)) + (screenWidth * 3);
  158. poiView2.right = poiView1.right - screenWidth;
  159. poiView3.right = poiView2.right - screenWidth;
  160. poiView4.right = poiView1.right + screenWidth;
  161. }
  162. else
  163. if(currBearing <= 180) {
  164. poiView2.right = ((currBearing - 90) * (screenWidth / 90)) + (screenWidth * 3);
  165. poiView3.right = poiView2.right - screenWidth;
  166. poiView4.right = poiView3.right - screenWidth;
  167. poiView1.right = poiView2.right + screenWidth;
  168. }
  169. else
  170. if(currBearing <= 270) {
  171. poiView3.right = ((currBearing - 180) * (screenWidth / 90)) + (screenWidth * 3);
  172. poiView4.right = poiView3.right - screenWidth;
  173. poiView1.right = poiView4.right - screenWidth;
  174. poiView2.right = poiView3.right + screenWidth;
  175. }
  176. else {
  177. poiView4.right = ((currBearing - 270) * (screenWidth / 90)) + (screenWidth * 3);
  178. poiView1.right = poiView4.right - screenWidth;
  179. poiView2.right = poiView1.right - screenWidth;
  180. poiView3.right = poiView4.right + screenWidth;
  181. }
  182. arRadarImg.transform = Ti.UI.create2DMatrix().rotate(-augmentedReality.toDegree(augmentedReality.toRadius(currBearing)));
  183. removeFlag();
  184. }
  185. }
  186. /*
  187. * displayOverlay
  188. * ==============
  189. *
  190. * This function displays the AR view either through the camera or
  191. */
  192. function displayOverlay()
  193. {
  194. /*
  195. * camearView
  196. * ==========
  197. *
  198. * This section displays the view through the camera, using the overlay created.
  199. *
  200. * If there is no camera, it adds the overlay to the base window.
  201. */
  202. //if (androidPlatform) { cameraView = false ;}
  203. if(cameraView) {
  204. Ti.Media.showCamera({
  205. success : function(event)
  206. {
  207. },
  208. cancel : function()
  209. {
  210. },
  211. error : function(error)
  212. {
  213. if(error.code == Ti.Media.NO_CAMERA) {
  214. common.launchEvent({
  215. TYPE : 'ERROR',
  216. MESS : 'E0006'
  217. });
  218. }
  219. else {
  220. common.launchEvent({
  221. TYPE : 'ERROR',
  222. MESS : 'E0006'
  223. });
  224. }
  225. },
  226. mediaTypes : [Ti.Media.MEDIA_TYPE_VIDEO, Ti.Media.MEDIA_TYPE_PHOTO],
  227. showControls : false,
  228. autohide : false,
  229. autofocus : "off",
  230. animated : false,
  231. overlay : arBaseView
  232. });
  233. }
  234. else {
  235. arWin.add(arBaseView);
  236. }
  237. }
  238. /*
  239. * startMovement
  240. * =============
  241. *
  242. * This function starts the movement of the display and places the radar blips
  243. * and display panels in the right position.
  244. *
  245. */
  246. function startMovement()
  247. {
  248. /*
  249. * Now set the screen position of blips and POI's
  250. */
  251. displayOverlay();
  252. rotateFlag = false;
  253. rotateDisplay();
  254. }
  255. /*
  256. * addPOIEvent
  257. * ===========
  258. *
  259. * This function creates and event listener for each POI.
  260. *
  261. * It has been separated from the loop as it is bad practice to add
  262. * event listeners in the loop.
  263. *
  264. */
  265. function addPOIEvent(inParam)
  266. {
  267. inParam.VIEW.addEventListener('click', function()
  268. {
  269. showARDetail({
  270. TITLE : googleData[inParam.POS].name,
  271. DESC : googleData[inParam.POS].vicinity
  272. });
  273. });
  274. }
  275. /*
  276. * buildARData
  277. * ==========
  278. *
  279. * This function builds the AR Data.
  280. *
  281. * It takes the passed google data shows the POI's icon and positions it onto the relevant
  282. * view in relation to its heading.
  283. *
  284. * It also scales the Icon depending on the distance away from the current location.
  285. *
  286. * Finally creating the blips for the radar display.
  287. */
  288. function buildARData(callBack)
  289. {
  290. for(var iPos = 0; iPos < googleData.length; iPos++) {
  291. // The POI's
  292. var scale = (10 / googleData[iPos].distance).toFixed(2);
  293. if(scale >= 1) {
  294. scale = 1.00;
  295. }
  296. if(scale <= 0.35) {
  297. scale = 0.35;
  298. }
  299. var tmpDegCal = 0;
  300. var tmpView = null;
  301. if(googleData[iPos].degree <= 45 || googleData[iPos].degree >= 315) {
  302. tmpDegCal = -45;
  303. tmpView = poiView1;
  304. }
  305. else
  306. if(googleData[iPos].degree <= 135) {
  307. tmpDegCal = 45;
  308. tmpView = poiView2;
  309. }
  310. else
  311. if(googleData[iPos].degree <= 225) {
  312. tmpDegCal = 135;
  313. tmpView = poiView3;
  314. }
  315. else {
  316. tmpDegCal = 225;
  317. tmpView = poiView4;
  318. }
  319. var tmpLeft = ((googleData[iPos].degree - tmpDegCal) * (screenWidth / 90)) - ((layout.css.ar.detail.ics * scale) / 2);
  320. var tmpTop = (screenHeight / 2) * scale;
  321. if((tmpLeft + ((layout.css.ar.detail.ics * scale / 2))) >= screenWidth) {
  322. tmpLeft = screenWidth - (layout.css.ar.detail.ics * scale);
  323. }
  324. if(tmpLeft <= 0) {
  325. tmpLeft = 0;
  326. }
  327. var poiItem = Ti.UI.createImageView({
  328. height : layout.css.ar.detail.ics * scale,
  329. width : layout.css.ar.detail.ics * scale,
  330. left : tmpLeft,
  331. top : tmpTop,
  332. image : googleData[iPos].icon
  333. });
  334. addPOIEvent({
  335. VIEW : poiItem,
  336. POS : iPos
  337. });
  338. tmpView.add(poiItem);
  339. tmpView = null;
  340. // The Radar Blips ....
  341. var ro = ((images.file.radar.wCalc) * (googleData[iPos].distance.toFixed(4) / 1000) / 2);
  342. var centerX = ((images.file.radar.wCalc) / 2) + (ro * Math.sin(googleData[iPos].bearing));
  343. var centerY = ((images.file.radar.wCalc) / 2) - (ro * Math.cos(googleData[iPos].bearing));
  344. var displayBlip = Ti.UI.createView({
  345. height : layout.css.ar.blip.height,
  346. width : layout.css.ar.blip.width,
  347. backgroundColor : layout.css.ar.blip.color,
  348. borderRadius : 2,
  349. top : centerY - 1,
  350. left : centerX - 1,
  351. lat : googleData[iPos].location.lat,
  352. lng : googleData[iPos].location.lng
  353. });
  354. arRadarImg.add(displayBlip);
  355. }
  356. startMovement();
  357. }
  358. /*
  359. * buildARDisplay
  360. * ==============
  361. *
  362. * This function builds the main display panels and adds the data to the screen.
  363. *
  364. * This function requires some explanation as to why it is done this way.
  365. *
  366. * In AR most solutions display all the POI's on the screen and then moves them
  367. * around hiding and showing the ones required.
  368. *
  369. * This takes a lot of processing and means that you get a jerky display.
  370. *
  371. * The solution below uses 4 views each representing a 90degree angle. The POI's
  372. * are then positioned within these views and the views moved.
  373. *
  374. */
  375. function buildARDisplay(callBack)
  376. {
  377. var poiDisplay = Ti.UI.createView({
  378. top : 0,
  379. height : screenHeight,
  380. left : 0 - (screenWidth * 3),
  381. width : (screenWidth * 7),
  382. backgroundColor : 'transparent',
  383. zIndex : 50
  384. });
  385. poiView1 = Ti.UI.createView({
  386. top : 0,
  387. height : screenHeight,
  388. right : 0,
  389. width : screenWidth
  390. });
  391. poiView2 = Ti.UI.createView({
  392. top : 0,
  393. height : screenHeight,
  394. right : screenWidth,
  395. width : screenWidth
  396. });
  397. poiView3 = Ti.UI.createView({
  398. top : 0,
  399. height : screenHeight,
  400. right : (screenWidth * 2),
  401. width : screenWidth
  402. });
  403. poiView4 = Ti.UI.createView({
  404. top : 0,
  405. height : screenHeight,
  406. right : -screenWidth,
  407. width : screenWidth
  408. });
  409. poiDisplay.add(poiView1);
  410. poiDisplay.add(poiView2);
  411. poiDisplay.add(poiView3);
  412. poiDisplay.add(poiView4);
  413. arBaseView.add(poiDisplay);
  414. if(callBack) {
  415. callBack();
  416. }
  417. }
  418. function buildAROverlay()
  419. {
  420. /*
  421. * Build the parent AR view
  422. *
  423. * This view is crucial to how the whole AR display works as you will see as the display is
  424. * developed.
  425. *
  426. * We initially have a single screen sized view with a transparent background containing the
  427. * Radar image. This is set with a zIndex of 10 and will always be behind the other views.
  428. *
  429. */
  430. arBaseView = Ti.UI.createView({
  431. top : 0,
  432. left : 0,
  433. right : 0,
  434. bottom : 0,
  435. backgroundColor : 'transparent',
  436. zIndex : 10
  437. });
  438. /*
  439. * The radar image
  440. *
  441. * The radar displays blips of the POI's giving an indication of the direction of
  442. * the POI's
  443. *
  444. * Positioned top right.
  445. *
  446. */
  447. var arRadarBck = Ti.UI.createView({
  448. top : '10dp',
  449. right : '10dp',
  450. height : images.file.radar.height,
  451. width : images.file.radar.width,
  452. backgroundImage : images.file.radar.file,
  453. zIndex : 30
  454. });
  455. /*
  456. * The radar view to rotate the blips...
  457. */
  458. arRadarImg = Ti.UI.createView({
  459. top : 0,
  460. left : 0,
  461. height : images.file.radar.height,
  462. width : images.file.radar.width,
  463. backgroundcolor : 'transparent',
  464. zIndex : 31
  465. });
  466. /*
  467. * Add the window components
  468. */
  469. arRadarBck.add(arRadarImg);
  470. arBaseView.add(arRadarBck);
  471. /*
  472. * The close button
  473. */
  474. var closeButton = Ti.UI.createLabel({
  475. bottom : '25dp',
  476. width : layout.css.butt.wi,
  477. height : layout.css.butt.hi,
  478. text : Ti.Locale.getString('butt_close'),
  479. textAlign : layout.css.butt.ta,
  480. backgroundColor : layout.css.butt.bkc,
  481. color : layout.css.butt.fc,
  482. borderRadius : layout.css.butt.br,
  483. borderWidth : layout.css.butt.bw,
  484. borderColor : layout.css.butt.bc,
  485. font : {
  486. fontFamily : layout.css.butt.ff,
  487. fontWeight : layout.css.butt.fw,
  488. fontSize : layout.css.butt.fs
  489. },
  490. zIndex : 75
  491. });
  492. arBaseView.add(closeButton);
  493. /*
  494. * The event listeners to facilitate actions
  495. */
  496. closeButton.addEventListener('touchstart', function()
  497. {
  498. closeButton.backgroundColor = layout.css.butt.tbkc;
  499. closeButton.borderColor = layout.css.butt.tbc;
  500. closeButton.color = layout.css.butt.tfc;
  501. });
  502. closeButton.addEventListener('touchend', function()
  503. {
  504. closeButton.backgroundColor = layout.css.butt.bkc;
  505. closeButton.borderColor = layout.css.butt.bc;
  506. closeButton.color = layout.css.butt.fc;
  507. if(cameraView) {
  508. if(!androidPlatform) {
  509. Ti.Media.hideCamera();
  510. }
  511. }
  512. cameraView = null;
  513. /*
  514. * Now return control to the controller.
  515. */
  516. common.launchEvent({
  517. TYPE : 'startApp'
  518. });
  519. });
  520. /*
  521. * Making it legal adding the google logo as required for using places.
  522. */
  523. var googleLogo = Ti.UI.createImageView({
  524. bottom : '5dp',
  525. right : '5dp',
  526. height : images.file.google.height,
  527. width : images.file.google.width,
  528. image : images.file.google.file
  529. });
  530. arBaseView.add(googleLogo);
  531. /*
  532. * build the radar blips
  533. */
  534. buildARDisplay(function()
  535. {
  536. buildARData();
  537. });
  538. return;
  539. }
  540. function loadARScreen(inParams)
  541. {
  542. /*
  543. * Load the data in
  544. */
  545. googleData = inParams.DATA;
  546. cameraView = inParams.SERVICES.camera;
  547. androidPlatform = inParams.ANDROID;
  548. arWin = Ti.UI.createWindow({
  549. backgroundColor : layout.css.sbkc.hs,
  550. navBarHidden : true,
  551. exitOnClose : false,
  552. orientationModes : [Ti.UI.PORTRAIT]
  553. });
  554. /*
  555. * Set orientation fixed for Android
  556. */
  557. arWin.orientationModes = [Ti.UI.PORTRAIT];
  558. /*
  559. * Add a close event listener to clean everything up nicely.
  560. */
  561. arWin.addEventListener('close', function()
  562. {
  563. arWin = null;
  564. arBaseView = null;
  565. arRadarImg = null;
  566. googleData = null;
  567. });
  568. /*
  569. * Open the window here so we can process the data separately.
  570. */
  571. arWin.open();
  572. /*
  573. * Build the data display
  574. */
  575. buildAROverlay();
  576. return arWin;
  577. }
  578. /*
  579. * Export the required functions for access
  580. */
  581. exports.loadARScreen = loadARScreen;
  582. exports.rotateDisplay = rotateDisplay;