PageRenderTime 41ms CodeModel.GetById 16ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

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