1 /* 2 *Copyright (c) 2009, TellurianRing.com 3 *All rights reserved. 4 * 5 *Redistribution and use in source and binary forms, with or without modification, 6 *are permitted provided that the following conditions are met: 7 * 8 * Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * Neither the name of the Organization (TellurianRing.com) nor the names of 14 * its contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 *ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 *WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 *DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 21 *ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 *(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 *LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 *ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @class SceneContent represents any object which can be placed in the 31 * "content" field of any group node of a Scene. This object defines the methods 32 * and attributes, which are expected to be implemented by any scene content. 33 * @author <a href="mailto:elberry@tellurianring.com">Eric Berry</a> 34 * 35 * @param _details All SceneContent takes a JSON object in it's factory 36 * function with the following properties: 37 * Expected but not required properties: 38 * <table cellpadding="0" cellspacing="1" border="0" class="constructor_details"> 39 * <tr><th>Property</th> <th>Required</th> <th>Default</th></tr> 40 * <tr><td>active</td> <td>no</td> <td>true</td></tr> 41 * <tr><td>h</td> <td>no</td> <td>0</td></tr> 42 * <tr><td>visible</td> <td>no</td> <td>true</td></tr> 43 * <tr><td>w</td> <td>no</td> <td>0</td></tr> 44 * <tr><td>x</td> <td>no</td> <td>0</td></tr> 45 * <tr><td>y</td> <td>no</td> <td>0</td></tr> 46 * <tr><td>name</td> <td>no</td> <td></td></tr> 47 * </table> 48 * This is a base set of properties. Any object that extends SceneContent should 49 * be expected to handle this set of properties. Some exceptions include the 50 * Graphic object which sets the width and height properties after the image has 51 * been loaded. The Sound object, which doesn't have any use of coordinates or 52 * size. And Groups, their width and height attributes are based on their 53 * content. 54 * @example 55 * // Creates a new SceneContent object. 56 * var myContent = SceneContent({x: 10, y: 10, w: 100, h: 100, name: "my_content"}); 57 * @example 58 * // Your content can be retrieved from the scene using its name. 59 * myScene["my content"] 60 * @constructs 61 */ 62 function SceneContent(_details) { // {{{ 63 /** @constructs */ 64 function _SceneContent(_details) { // {{{ 65 // private variables {{{ 66 var active = check(_details.active, true); 67 var h = check(_details.h, 0); 68 var name = _details.name; 69 var parent = null; 70 var scene = null; 71 var stage = null; 72 var visible = check(_details.visible, true); 73 var w = check(_details.w, 0); 74 var x = check(_details.x, 0); 75 var y = check(_details.y, 0); 76 77 // used as a prototype for the clone function below. 78 function Clone() {} 79 // }}} 80 81 // public variables {{{ 82 /** 83 * The public details field should refer to the original object passed in to the 84 * creation function. Users should always be able to attach their own details to 85 * any scene content object and retrieve it again using the public details 86 * field. 87 */ 88 this.details = _details; 89 // }}} 90 91 // public functions {{{ 92 /** 93 * The draw function is responsible for drawing this content to the given 94 * canvas context. It is called after the update function. 95 * @param _context The canvas context this content should be drawn to. 96 */ 97 this.draw = function(_context) {} 98 /** 99 * This extends the provided child function with this instance. 100 * @param _child The child function to be extended. 101 */ 102 this.extend = function(_child) { // {{{ 103 _child.prototype = this; 104 } // }}} extend 105 /** 106 * The getBounds function should return the location and size of this 107 * content relative to it's parent. 108 * @example 109 * var myGraphic = Graphic({ x: 13, y: 13, url: "./images/ball.png" }); 110 * var myGrp = Group({ x: 10, y: 10, content: [myGraphic] }); 111 * alert(myGraphic.getBounds().x); // alerts 13 112 * <script type="text/javascript"> 113 * function scenecontent_bounds() { 114 * var myGraphic = Graphic({ x: 13, y: 13, url: "./images/ball.png" }); 115 * var myGrp = Group({ x: 10, y: 10, content: [myGraphic] }); 116 * alert(myGraphic.getBounds().x); // alerts 13 117 * } 118 * </script> 119 * <button onclick="scenecontent_bounds()">Prove It!</button> 120 * @return {Bounds} with 4 fields, x, y, w, and h. 121 */ 122 this.getBounds = function() { // {{{ 123 return Bounds({x: x, y: y, w: w, h: h}); 124 } // }}} getBounds 125 /** 126 * Gets the name of this SceneContent as it was passed in the original 127 * _details object. 128 * @return The name of this SceneContent 129 */ 130 this.getName = function() { // {{{ 131 return name; 132 } // }}} getName 133 /** 134 * The getParent function returns the parent of this content. This usually 135 * returns another SceneContent object, except when this object is the 136 * first child of the Scene object. In which case, the Scene itself is 137 * returned. 138 * @return {SceneContent|Scene} The parent of this content. 139 */ 140 this.getParent = function() { // {{{ 141 return parent; 142 } // }}} getParent 143 /** 144 * The getScene function returns the scene this content belongs to. The scene 145 * is passed in to the load function. 146 * @return {Scene} The Scene Object this content belongs to. 147 */ 148 this.getScene = function() { // {{{ 149 return scene; 150 } // }}} getScene 151 /** 152 * The getStage function returns the stage this content belongs to. The stage 153 * can originally be retrieved by the Scene object which is passed in to the 154 * load function. 155 * @return {Stage} The Stage Object this content belongs to. 156 */ 157 this.getStage = function() { // {{{ 158 return stage; 159 } // }}} getStage 160 /** 161 * isActive Is this content currently active. This field tells the Scene 162 * that this content needs to be updated and drawn. If content is not 163 * active then it will not be updated or drawn. 164 * @function 165 * @returns true if this content is active, false otherwise. 166 */ 167 this.isActive = function() { // {{{ 168 return active; 169 } // }}} isActive 170 /** 171 * isVisible Is this content currently visible. This field tells the Scene 172 * that this content needs to be drawn. If the content is not visible then 173 * it will not be drawn. 174 * @function 175 * @returns true if this content is visible, false otherwise. 176 */ 177 this.isVisible = function() { // {{{ 178 return visible; 179 } // }}} 180 /** 181 * The load function gets called after all the stage objects and content have 182 * been initialized. It's only called once when the Scene's load method is 183 * called. 184 * @param {Scene} _scene The Scene this content belongs to. 185 * @param {SceneContent|Scene} _parent The parent of this content. 186 */ 187 this.load = function(_scene, _parent) { // {{{ 188 this.loadBase(_scene, _parent); 189 } // }}} load 190 /** 191 * Sets the scene, parent and stage for this content. Also adds this object 192 * to the scene by name. 193 */ 194 this.loadBase = function(_scene, _parent) { // {{{ 195 scene = _scene; 196 parent = _parent; 197 stage = scene.getStage(); 198 scene[name] = this; 199 } // }}} loadBase 200 /** 201 * The moveBy function moves this content's relative x, y position by the 202 * the given distances. This is equivalent to an instant translation, vs. 203 * the use of a Translation Transform node. The function should work on 204 * partial data, and a lack of data should signify non-action. 205 * @example 206 * var myImage = Graphic({ x: 10, y: 10, url: "./images/ball.png" }); 207 * alert(myImage.getBounds().x); // alerts 10 208 * myImage.moveBy({x: 5}); 209 * alert(myImage.getBounds().x); // alerts 15 210 * <script type="text/javascript"> 211 * function scenecontent_moveby() { 212 * var myImage = Graphic({ x: 10, y: 10, url: "./images/ball.png" }); 213 * alert(myImage.getBounds().x); // alerts 10 214 * myImage.moveBy({x: 5}); 215 * alert(myImage.getBounds().x); // alerts 15 216 * } 217 * </script> 218 * <button onclick="scenecontent_moveby()">Prove It!</button> 219 * @param {Number} _distance A Distance object with two fields, x, and y. 220 */ 221 this.moveBy = function(_distance) { // {{{ 222 if(exists(_distance.x)) { 223 x += _distance.x; 224 } 225 if(exists(_distance.y)) { 226 y += _distance.y; 227 } 228 } // }}} moveBy 229 /** 230 * The moveTo function moves this content's relative x, y position to the 231 * values provided in the point object. The function should work on partial 232 * data, and a lack of data should signify non-action. 233 * @example 234 * var myImage = Graphic({ x: 10, y: 10, url: "./images/ball.png" }); 235 * alert(myImage.getBounds().x); // alerts 10 236 * myImage.moveTo({x: 15}); 237 * alert(myImage.getBounds().x); // alerts 15 238 * <script type="text/javascript"> 239 * function scenecontent_moveto() { 240 * var myImage = Graphic({ x: 10, y: 10, url: "./images/ball.png" }); 241 * alert(myImage.getBounds().x); // alerts 10 242 * myImage.moveTo({x: 15}); 243 * alert(myImage.getBounds().x); // alerts 15 244 * } 245 * </script> 246 * <button onclick="scenecontent_moveto()">Prove It!</button> 247 * @param {Point} _point Point object with two fields, x, and y. 248 */ 249 this.moveTo = function(_point) { // {{{ 250 if(exists(_point.x)) { 251 x = _point.x; 252 } 253 if(exists(_point.y)) { 254 y = _point.y; 255 } 256 } // }}} moveTo 257 /** 258 * setActive Sets this content's active status flag. 259 * @function 260 * @param {Boolean} _active true or false 261 */ 262 this.setActive = function(_active) { // {{{ 263 active = _active; 264 } // }}} setActive 265 /** 266 * The setSize function sets this content's width and height. The function 267 * should work on partial data, and a lack of data should signify 268 * non-action. 269 * @example // Only updates the width of the SceneContent. 270 * var rect = Rectangle({ x: 10, y: 10, w: 10, h: 10 }); 271 * rect.setSize({w: 15 }); 272 * alert(rect.getBounds().w == 15) // alerts true. 273 * <script type="text/javascript"> 274 * function scenecontent_setsize() { 275 * var rect = Rectangle({ x: 10, y: 10, w: 10, h: 10 }); 276 * rect.setSize({w: 15 }); 277 * alert(rect.getBounds().w == 15) // alerts true. 278 * } 279 * </script> 280 * <button onclick="scenecontent_setsize()">Prove It!</button> 281 * @param {Bounds} _dimension A Dimension object with two fields, w, and h. 282 */ 283 this.setSize = function(_dimension) { // {{{ 284 if(exists(_dimension.w)) { 285 w = _dimension.w; 286 } 287 if(exists(_dimension.h)) { 288 h = _dimension.h; 289 } 290 } // }}} setSize 291 /** 292 * setVisible Sets this content's visible status flag. 293 * @function 294 * @param {Boolean} _visible true or false 295 */ 296 this.setVisible = function(_visible) { // {{{ 297 visible = _visible; 298 } // }}} setVisible 299 /** 300 * The update function is called after the load function has been called 301 * and before the draw function is called. It's called repeatedly with the 302 * total time passed since the Scene's load time. 303 * @param {Number} _runtime The total time passed since the Scene's load time. 304 */ 305 this.update = function(_runtime) { 306 this.updateBase(_runtime); 307 } 308 /** 309 * The updateBase function should be called by subclasses overriding the 310 * update function. This function automatically hides SceneContent if it 311 * goes outside the boundaries of the stage. This method can be extended 312 * by supplying an update function in the initialization data. 313 * @example // Supplying your own update function 314 * Graphic({ 315 * x: 10, y: 10, url: "./images/ball.png", 316 * update: function(_runtime) { 317 * // do something 318 * } 319 * }) 320 * @param {Number} _runtime The total time passed since the Scene's load time. 321 */ 322 this.updateBase = function(_runtime) { 323 var bounds = this.getBounds(); 324 var stage_size = this.getStage().getSize(); 325 if(stage_size.contains(bounds)) { 326 this.setVisible(true); 327 } else { 328 this.setVisible(false); 329 } 330 if(exists(this.details.update)) { 331 this.details.update.apply(this, arguments); 332 } 333 } 334 // }}} public functions 335 } // }}} _SceneContent 336 var theSceneContent = new _SceneContent(_details); 337 return theSceneContent; 338 } // }}} SceneContent 339 // These properties are for jEdit - Programmer's Text Editor. 340 // Load this file in jEdit to see what they do. 341 // ::folding=explicit:mode=javascript:noTabs=true:collapseFolds=4:: 342