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 };