1 /**
  2  * The Render Engine
  3  * VirtualHTMLDivContext
  4  *
  5  * @fileoverview An extension of the HTML div context used to represent a game world larger than
  6  *    the viewport.
  7  *
  8  * @author: Brett Fattori (brettf@renderengine.com)
  9  *
 10  * @author: $Author: bfattori $
 11  * @version: $Revision: 1555 $
 12  *
 13  * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com)
 14  *
 15  * Permission is hereby granted, free of charge, to any person obtaining a copy
 16  * of this software and associated documentation files (the "Software"), to deal
 17  * in the Software without restriction, including without limitation the rights
 18  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 19  * copies of the Software, and to permit persons to whom the Software is
 20  * furnished to do so, subject to the following conditions:
 21  *
 22  * The above copyright notice and this permission notice shall be included in
 23  * all copies or substantial portions of the Software.
 24  *
 25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 26  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 27  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 28  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 29  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 30  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 31  * THE SOFTWARE.
 32  *
 33  */
 34 
 35 // The class this file defines and its required classes
 36 R.Engine.define({
 37     "class":"R.rendercontexts.VirtualHTMLDivContext",
 38     "requires":[
 39         "R.rendercontexts.HTMLDivContext",
 40         "R.math.Math2D"
 41     ]
 42 });
 43 
 44 /**
 45  * @class A HTML element render context whose world boundary is larger than the actual
 46  *        viewport.  This allows the world to be rendered as if viewed through a
 47  *        window into a larger world.  You can set the world position with simple
 48  *        scroll methods, or cause the world to transition to a specific point over
 49  *        a given duration.
 50  *
 51  * @constructor
 52  * @param name {String} The name of the object
 53  * @param windowWidth {Number} The width of the viewable window, in pixels
 54  * @param windowHeight {Number} The height of the viewable window, in pixels
 55  * @param worldWidth {Number} The width of the world, in pixels
 56  * @param worldHeight {Number} The height of the world, in pixels
 57  * @extends R.rendercontexts.CanvasContext
 58  */
 59 R.rendercontexts.VirtualHTMLDivContext = function () {
 60     return R.rendercontexts.HTMLDivContext.extend(/** @scope R.rendercontexts.VirtualHTMLDivContext.prototype */{
 61 
 62         scrollFromPt:null,
 63         scrollToPt:null,
 64         moving:false,
 65         expireTime:0,
 66         duration:0,
 67 
 68         /** @private */
 69         constructor:function (name, windowWidth, windowHeight, worldWidth, worldHeight) {
 70             // Create an element for us to use as our window
 71             this.base(name || "VirtualHTMLDivContext", windowWidth, windowHeight);
 72             this.setWorldBoundary(R.math.Rectangle2D.create(0, 0, worldWidth, worldHeight));
 73 
 74             // To force the element to have scrollable space, we create a div element
 75             // within the context's element which is the size of the world
 76             var shim = $("<div></div>").css({
 77                 width:worldWidth,
 78                 height:worldHeight,
 79                 position:"relative",
 80                 left:0,
 81                 top:0
 82             });
 83             this.jQ().append(shim);
 84 
 85             this.scrollToPt = R.math.Point2D.create(0, 0);
 86             this.scrollFromPt = R.math.Point2D.create(0, 0);
 87             this.moving = false;
 88             this.expireTime = 0;
 89             this.duration = 0;
 90         },
 91 
 92         /**
 93          * Set the horizontal world position in pixels.
 94          *
 95          * @param x {Number} The horizontal scroll in pixels
 96          */
 97         setHorizontalScroll:function (x) {
 98             var maxX = this.getWorldBoundary().w - this.getViewport().w;
 99             x = (x < 0 ? 0 : (x > maxX ? maxX : x));
100             this.getWorldPosition().setX(x);
101             this.getViewport().getTopLeft().setX(x);
102             this.jQ().scrollLeft(x);
103         },
104 
105         /**
106          * Set the vertical world position in pixels.
107          *
108          * @param y {Number} The vertical scroll in pixels
109          */
110         setVerticalScroll:function (y) {
111             var maxY = this.getWorldBoundary().h - this.getViewport().h;
112             y = (y < 0 ? 0 : (y > maxY ? maxY : y));
113             this.getWorldPosition().setY(y);
114             this.getViewport().getTopLeft().setY(y);
115             this.jQ().scrollTop(x);
116         },
117 
118         /**
119          * Set the current world position to a specific point.
120          * @param pt {R.math.Point2D} The point to set the scroll to.
121          */
122         setScroll:function (pt) {
123             this.setHorizontalScroll(pt.x);
124             this.setVerticalScroll(pt.y);
125         },
126 
127         /**
128          * Scroll to the given point, or location, over the given duration.
129          * @param duration {Number} The number of milliseconds for the transition to occur
130          * @param ptOrX {Number|R.math.Point2D} The X coordinate, or point, to scroll to
131          * @param [y] {Number} The Y coordinate, if <tt>ptOrX</tt> is a number
132          */
133         scrollTo:function (duration, ptOrX, y) {
134             this.scrollFromPt.set(this.getWorldPosition());
135             this.scrollToPt.set(ptOrX, y);
136             this.moving = true;
137             this.expireTime = R.Engine.worldTime + duration;
138             this.duration = duration;
139         },
140 
141         /**
142          * Get the horizontal scroll amount in pixels.
143          * @return {Number} The horizontal scroll
144          */
145         getHorizontalScroll:function () {
146             return this.getWorldPosition().x;
147         },
148 
149         /**
150          * Get the vertical scroll amount in pixels.
151          * @return {Number} The vertical scroll
152          */
153         getVerticalScroll:function () {
154             return this.getWorldPosition().y;
155         },
156 
157         /**
158          * If a transition was initiated with {@link #scrollTo},
159          * this will update the viewport accordingly.
160          *
161          * @param worldTime {Number} The current world time
162          * @param dt {Number} The delta between the world time and the last time the world was updated
163          *          in milliseconds.
164          */
165         setupWorld:function (worldTime, dt) {
166             if (this.moving) {
167                 if (worldTime < this.expireTime) {
168                     // Moving
169                     var sc = R.math.Point2D.create(this.scrollToPt).sub(this.scrollFromPt)
170                             .mul((this.duration - (this.expireTime - worldTime)) / this.duration),
171                         sp = R.math.Point2D.create(this.scrollFromPt).add(sc);
172                     this.setScroll(sp);
173                     sc.destroy();
174                     sp.destroy();
175                 } else {
176                     // Arrived
177                     this.moving = false;
178                     this.expireTime = 0;
179                     this.setScroll(this.scrollToPt);
180                 }
181             }
182             this.base(worldTime, dt);
183         }
184 
185     }, /** @scope R.rendercontexts.VirtualHTMLDivContext.prototype */ {
186 
187         /**
188          * Get the class name of this object
189          * @return {String} The string "R.rendercontexts.VirtualHTMLDivContext"
190          */
191         getClassName:function () {
192             return "R.rendercontexts.VirtualHTMLDivContext";
193         }
194     });
195 
196 };
197