1 /** 2 * The Render Engine 3 * BaseComponent 4 * 5 * @fileoverview The base class from which all components extend. A component 6 * is a single part of the functionality used by a HostObject. 7 * 8 * @author: Brett Fattori (brettf@renderengine.com) 9 * @author: $Author: bfattori $ 10 * @version: $Revision: 1555 $ 11 * 12 * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com) 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a copy 15 * of this software and associated documentation files (the "Software"), to deal 16 * in the Software without restriction, including without limitation the rights 17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 * copies of the Software, and to permit persons to whom the Software is 19 * furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be included in 22 * all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 * THE SOFTWARE. 31 * 32 */ 33 34 // The class this file defines and its required classes 35 R.Engine.define({ 36 "class":"R.components.Base", 37 "requires":[ 38 "R.engine.BaseObject", 39 "R.engine.GameObject" 40 ] 41 }); 42 43 /** 44 * @class All components extend from this object class. A component is one 45 * part of an operating whole object (a {@link R.engine.GameObject}) which is 46 * responsible for only a portion of the overall operation of the 47 * game object. Components are broken down into five major categories: 48 * <ul> 49 * <li><b>TYPE_INPUT</b> - Input from controllers (keyboard, mouse, etc.)</li> 50 * <li><b>TYPE_TRANSFORM</b> - Performs transformations on the host object</li> 51 * <li><b>TYPE_LOGIC</b> - Handles logical operations that are not related to 52 * input and collision</li> 53 * <li><b>TYPE_COLLIDER</b> - Determines what this object is possibly colliding 54 * with, and reports those collisions via callbacks to the host.</li> 55 * <li><b>TYPE_RENDERING</b> - Performs some sort of rendering operation to the context</li> 56 * </ul> 57 * Components are executed in the order listed. First, all inputs are 58 * checked, then logic is performed. Logic may be internal to a game object 59 * itself, but some components perform an object-centric type of logic that 60 * can be reused. Next, collisions are checked. And finally, rendering can 61 * occur. 62 * <p/> 63 * Within each component type set, components can be prioritized so that 64 * one component will execute before others. Such an ordering allows for 65 * multiple components of each type to perform their tasks in an order 66 * that the game object defines. 67 * 68 * 69 * @extends R.engine.BaseObject 70 * @constructor 71 * @description Create a new instance of a component, setting the name, type, and 72 * update priority of this component compared to all other components 73 * within the host. 74 * @param name {String} The name of the component 75 * @param type {Number} The type of the component 76 * @param priority {Number} A value between 0.0 and 1.0. Default: 0.5 77 */ 78 R.components.Base = function () { 79 "use strict"; 80 return R.engine.BaseObject.extend(/** @scope R.components.Base.prototype */{ 81 82 priority:0, 83 84 type:-1, 85 86 host:null, 87 88 /** 89 * @private 90 */ 91 constructor:function (name, type, priority) { 92 Assert((name != null), "You must assign a name to every Component."); 93 name = name.toUpperCase(); 94 95 Assert((type != null && (type >= R.components.Base.TYPE_PRE && type <= R.components.Base.TYPE_POST)), 96 "You must specify a type for component"); 97 98 this.type = type; 99 100 Assert((priority != null && (priority >= 0.0 && priority <= 1.0)), 101 "Priority must be between 0.0 and 1.0 for component"); 102 103 this.priority = priority || 0.5; 104 this.base(name); 105 }, 106 107 /** 108 * Releases the object back into the object pool. See {@link PooledObject#release} 109 * for more information. 110 */ 111 release:function () { 112 this.base(); 113 this.priority = 0; 114 this.type = -1; 115 this.host = null; 116 }, 117 118 /** 119 * Deprecated in favor of {@link #setGameObject} 120 * @deprecated 121 */ 122 setHostObject:function (hostObject) { 123 this.setGameObject(hostObject); 124 }, 125 126 /** 127 * Establishes the link between this component and its game object. 128 * When you assign components to a game object, it will call this method 129 * so that each component can refer to its game object, the same way 130 * a game object can refer to a component with {@link R.engine.GameObject#getComponent}. 131 * 132 * @param gameObject {R.engine.GameObject} The object which hosts this component 133 */ 134 setGameObject:function (gameObject) { 135 this.host = gameObject; 136 }, 137 138 /** 139 * Deprecated in favor of {@link #getGameObject} 140 * @deprecated 141 */ 142 getHostObject:function () { 143 return this.getGameObject(); 144 }, 145 146 /** 147 * Gets the game object this component is a part of. When the component was 148 * assigned to a game object, the game object will have set itself as the container 149 * via {@link #setGameObject}. 150 * 151 * @return {R.engine.GameObject} 152 */ 153 getGameObject:function () { 154 return this.host; 155 }, 156 157 /** 158 * Get the type of this component. The value will be one of: 159 * {@link #TYPE_INPUT}, {@link #TYPE_TRANSFORM}, {@link #TYPE_LOGIC}, 160 * {@link #TYPE_COLLIDER}, or {@link #TYPE_RENDERING} 161 * 162 * @return {Number} The component type Id 163 */ 164 getType:function () { 165 return this.type; 166 }, 167 168 /** 169 * Set the execution priority of this component with 170 * 1.0 being the highest priority and 0.0 being the lowest. Components 171 * within a game object are sorted by type, and then priority. As such, 172 * two components with the same type will be sorted by priority with the 173 * higher value executing before the lower value. This allows you to layer 174 * components like the {@link R.components.Render} component so that one effect 175 * is drawn before another. 176 * 177 * @param priority {Number} A value between 0.0 and 1.0 178 */ 179 setPriority:function (priority) { 180 this.priority = priority; 181 if (this.host) { 182 this.host.sort(); 183 } 184 }, 185 186 /** 187 * Returns the priority of this component. 188 * 189 * @return {Number} A value between 0.0 and 1.0 190 */ 191 getPriority:function () { 192 return this.priority; 193 }, 194 195 /** 196 * [ABSTRACT] This method is called by the game object to run the component, 197 * updating its state. Not all components will need an execute 198 * method. However, it is important to include one if you need to 199 * update the state of the component for each engine cycle. 200 * 201 * @param renderContext {R.rendercontexts.AbstractRenderContext} The context the component will render within. 202 * @param time {Number} The global engine time 203 * @param dt {Number} The delta between the world time and the last time the world was updated 204 * in milliseconds. 205 */ 206 execute:function (renderContext, time, dt) { 207 // ABSTRACT METHOD DECLARATION 208 }, 209 210 /** 211 * Get the type of the component as a string. 212 * @return {String} 213 */ 214 getTypeString:function () { 215 var ts = ""; 216 switch (this.getType()) { 217 case R.components.Base.TYPE_PRE: 218 ts = "TYPE_PRE"; 219 break; 220 case R.components.Base.TYPE_INPUT: 221 ts = "TYPE_INPUT"; 222 break; 223 case R.components.Base.TYPE_TRANSFORM: 224 ts = "TYPE_TRANSFORM"; 225 break; 226 case R.components.Base.TYPE_LOGIC: 227 ts = "TYPE_LOGIC"; 228 break; 229 case R.components.Base.TYPE_COLLIDER: 230 ts = "TYPE_COLLIDER"; 231 break; 232 case R.components.Base.TYPE_RENDERING: 233 ts = "TYPE_RENDERING"; 234 break; 235 case R.components.Base.TYPE_POST: 236 ts = "TYPE_POST"; 237 break; 238 default: 239 ts = "TYPE_UNKNOWN"; 240 } 241 242 return ts; 243 } 244 245 246 }, /** @scope R.components.Base.prototype */{ 247 248 /** 249 * Get the class name of this object 250 * 251 * @return {String} The string "R.components.Base" 252 */ 253 getClassName:function () { 254 return "R.components.Base"; 255 }, 256 257 /** 258 * The constant value for PRE process components. <i>Reserved for internal use.</i> 259 * @type {Number} 260 * @private 261 */ 262 TYPE_PRE:0, 263 264 /** 265 * The constant value for INPUT components. 266 * @type {Number} 267 */ 268 TYPE_INPUT:1, 269 270 /** 271 * The constant value for TRANSFORM (movement) components. 272 * @type {Number} 273 */ 274 TYPE_TRANSFORM:2, 275 276 /** 277 * The constant value for LOGIC components. 278 * @type {Number} 279 */ 280 TYPE_LOGIC:3, 281 282 /** 283 * The constant value for COLLIDER components. 284 * @type {Number} 285 */ 286 TYPE_COLLIDER:4, 287 288 /** 289 * The constant value for RENDERING components. 290 * @type {Number} 291 */ 292 TYPE_RENDERING:5, 293 294 /** 295 * The constant value for POST process components. <i>Reserved for internal use.</i> 296 * @type {Number} 297 * @private 298 */ 299 TYPE_POST:6 300 }); 301 302 };