1 /**
  2  * The Render Engine
  3  * ImageLoader
  4  *
  5  * @fileoverview A resource loader for images.
  6  *
  7  * @author: Brett Fattori (brettf@renderengine.com)
  8  * @author: $Author: bfattori $
  9  * @version: $Revision: 1555 $
 10  *
 11  * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com)
 12  *
 13  * Permission is hereby granted, free of charge, to any person obtaining a copy
 14  * of this software and associated documentation files (the "Software"), to deal
 15  * in the Software without restriction, including without limitation the rights
 16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 17  * copies of the Software, and to permit persons to whom the Software is
 18  * furnished to do so, subject to the following conditions:
 19  *
 20  * The above copyright notice and this permission notice shall be included in
 21  * all copies or substantial portions of the Software.
 22  *
 23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 26  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 28  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 29  * THE SOFTWARE.
 30  *
 31  */
 32 
 33 // The class this file defines and its required classes
 34 R.Engine.define({
 35     "class":"R.resources.loaders.ImageLoader",
 36     "requires":[
 37         "R.resources.loaders.RemoteLoader",
 38         "R.resources.types.Image",
 39         "R.math.Point2D",
 40         "R.lang.OneShotTimeout"
 41     ]
 42 });
 43 
 44 /**
 45  * @class Loads images and stores the reference to those images.  Images
 46  *        are stored on the client-side in a simple cache for faster re-use.
 47  *        When loading images, you assign a name to the image.  This would allow
 48  *        you to re-use the image without having to load it again for another
 49  *        purpose.
 50  *        <p/>
 51  *        Loading images is fairly simple.  You only need to create an instance
 52  *        of an image loader (multiple images can be loaded by the same resource
 53  *        loader) and then use it to load the images:
 54  <pre>
 55  this.imageLoader = R.resourceloaders.ImageLoader.create();
 56 
 57  // Load an image
 58  this.imageLoader.load("keys", this.getFilePath("resources/fingerboard.png"), 220, 171);
 59  </pre>
 60  *        In the example above, <tt>this</tt> refers to a {@link R.engine.Game} object which
 61  *        implements the {@link R.engine.Game#getFilePath getFilePath()} method which is
 62  *        used to get a path relative to where the game is located on the server.
 63  *
 64  * @constructor
 65  * @param name {String=ImageLoader} The name of the resource loader
 66  * @extends R.resources.loaders.RemoteLoader
 67  */
 68 R.resources.loaders.ImageLoader = function () {
 69     return R.resources.loaders.RemoteLoader.extend(/** @scope R.resources.loaders.ImageLoader.prototype */{
 70 
 71         /** @private */
 72         constructor:function (name) {
 73             this.base(name || "ImageLoader");
 74 
 75             // Create the area if it doesn't exist which will
 76             // be used to load the images from their URL
 77             if (this.getElement() == null) {
 78                 var div = jQuery("<div/>").css({
 79                     background:"black",
 80                     display:"none"
 81                 });
 82 
 83                 this.setElement(div[0]);
 84             }
 85         },
 86 
 87         /**
 88          * Load an image resource from a URL.  Images are cached within the page
 89          * in an invisible object for fast retrieval.
 90          *
 91          * @param name {String} The name of the resource
 92          * @param url {String} The URL where the resource is located
 93          * @param width {Number} The width of this resource, in pixels
 94          * @param height {Number} The height of this resource, in pixels
 95          */
 96         load:function (name, url, width, height) {
 97             // Create an image element
 98             var imageInfo = null;
 99             if (url != null) {
100                 imageInfo = this.loadImageResource(name, url, width, height);
101             }
102 
103             this.base(name, url, imageInfo);
104         },
105 
106         /**
107          * Lazy loads an image resource when the information for it becomes available.  It
108          * is best to specify the width and height of the resource, but it isn't necessary
109          * to load the image.
110          *
111          * @param name {String} The name of the resource
112          * @param url {String} The URL where the resource is located
113          * @param width {Number} The width of this resource, in pixels, or <tt>null</tt>
114          * @param height {Number} The height of this resource, in pixels, or <tt>null</tt>
115          * @return {HTMLImage} The image loaded
116          */
117         loadImageResource:function (name, url, width, height) {
118             var image = null;
119             if (width && height) {
120                 image = $("<img/>").attr("src", url).attr("width", width).attr("height", height);
121             }
122             else {
123                 image = $("<img/>").attr("src", url);
124             }
125 
126             var thisObj = this;
127             if (!R.browser.Wii) {
128                 image.bind("load", function () {
129                     thisObj.setReady(name, true);
130                 });
131             }
132             else {
133                 // Calculate an approximate wait time based on dimensions
134                 R.lang.OneShotTimeout.create("readyImg", (width * height) * ImageLoader.loadAdjust, function () {
135                     thisObj.setReady(name, true);
136                 });
137             }
138 
139             // Append it to the container so it can load the image
140             $(this.getElement()).append(image);
141             var info = {
142                 width:width,
143                 height:height,
144                 image:image
145             };
146             return info;
147         },
148 
149         /**
150          * Get the image from the resource stored with the specified name, or <tt>null</tt>
151          * if no such image exists.
152          *
153          * @param name {String} The name of the image resource
154          * @return {HTMLImage} The image
155          */
156         get:function (name) {
157             var imgInfo = this.base(name);
158             return imgInfo ? imgInfo.image[0] : null;
159         },
160 
161         /**
162          * Get an {@link R.resources.types.Image} object from the resource which represents the image, or <tt>null</tt>
163          * if no such image exists.
164          * @param name {String} The name of the image resource
165          * @return {R.resources.types.Image}
166          */
167         getImage:function (name) {
168             return R.resources.types.Image.create("Image", name, this);
169         },
170 
171         /**
172          * Get the specific image resource by name.
173          * @param name {String} The name of the resource
174          * @return {R.resources.types.Image}
175          */
176         getResourceObject:function (name) {
177             return this.getImage(name);
178         },
179 
180         /**
181          * Get the dimensions of an image from the resource stored with
182          * the specified name, or <tt>null</tt> if no such image exists.
183          *
184          * @param name {String} The name of the image resource
185          * @return {R.math.Point2D} A point which represents the width and height of the image
186          */
187         getDimensions:function (name) {
188             var imgInfo = this.getCachedObjects()[name] ? this.getCachedObjects()[name].data : null;
189             return imgInfo ? R.math.Point2D.create(imgInfo.width, imgInfo.height) : null;
190         },
191 
192         /**
193          * The name of the resource this loader will get.
194          * @return {String} The string "image"
195          */
196         getResourceType:function () {
197             return "image";
198         }
199 
200     }, /** @scope R.resources.loaders.ImageLoader.prototype */ {
201         /**
202          * Get the class name of this object
203          * @return {String} The string "R.resources.loaders.ImageLoader"
204          */
205         getClassName:function () {
206             return "R.resources.loaders.ImageLoader";
207         },
208 
209         /**
210          * The ratio by which to scale image load times when loading on the Wii
211          */
212         loadAdjust:0.05
213 
214     });
215 
216 }