1 /**
  2  * The Render Engine
  3  * Vector2DComponent
  4  *
  5  * @fileoverview An extension of the render component which draws 2D
  6  *               wireframe (vector) models to the render context.
  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.render.Vector2D",
 37     "requires":[
 38         "R.components.Render",
 39         "R.collision.ConvexHull",
 40         "R.collision.OBBHull",
 41         "R.collision.CircleHull",
 42         "R.math.Math2D",
 43         "R.math.Point2D",
 44         "R.math.Vector2D",
 45         "R.math.Rectangle2D"
 46     ]
 47 });
 48 
 49 /**
 50  * @class A render component that renders its contents from an <tt>Array</tt> of points.
 51  *
 52  * @param name {String} The name of the component
 53  * @param [priority=0.1] {Number} The priority of the component
 54  * @extends R.components.Render
 55  * @constructor
 56  * @description Creates a 2d vector drawing component
 57  */
 58 R.components.render.Vector2D = function () {
 59     "use strict";
 60     return R.components.Render.extend(/** @scope R.components.render.Vector2D.prototype */{
 61 
 62         strokeStyle:"#ffffff", // Default to white lines
 63         lineWidth:1,
 64         fillStyle:null, // Default to none
 65         points:null,
 66         bBox:null,
 67         closedManifold:null,
 68 
 69         /**
 70          * @private
 71          */
 72         constructor:function (name, priority) {
 73             this.base(name, priority || 0.1);
 74             this.closedManifold = true;
 75             this.points = [];
 76             this.bBox = R.math.Rectangle2D.create(0, 0, 0, 0);
 77         },
 78 
 79         /**
 80          * Destroys the object instance
 81          */
 82         destroy:function () {
 83             this.bBox.destroy();
 84             while (this.points.length > 0) {
 85                 this.points.shift().destroy();
 86             }
 87             this.base();
 88         },
 89 
 90         /**
 91          * Release the component back into the object pool. See {@link PooledObject#release} for
 92          * more information.
 93          */
 94         release:function () {
 95             this.base();
 96             this.strokeStyle = "#ffffff";
 97             this.lineWidth = 1;
 98             this.fillStyle = null;
 99             this.points = null;
100             this.bBox = null;
101             this.closedManifold = null;
102         },
103 
104         /**
105          * Calculate the bounding box from the set of
106          * points which comprise the shape to be rendered.
107          * @private
108          */
109         calculateBoundingBox:function () {
110             R.math.Math2D.getBoundingBox(this.points, this.bBox);
111         },
112 
113         /**
114          * Set the points which comprise the shape of the object to
115          * be rendered to the context.
116          *
117          * @param pointArray {Array} An array of <tt>Point2D</tt> instances
118          * @param noOffset {Boolean} If <code>true</code>, does not offset the points relative to
119          *        their center.  For objects not drawn around a center point, this allows you to
120          *        pass the points literally without translation.
121          */
122         setPoints:function (pointArray, noOffset) {
123             var pc = [];
124             for (var p in pointArray) {
125                 pc.push(R.math.Point2D.create(pointArray[p]));
126             }
127             this.points = pc;
128             this.renderState = null;
129             this.calculateBoundingBox();
130 
131             // Get the center of the bounding box and move all of the points so none are negative
132             if (!noOffset) {
133                 var hP = R.math.Point2D.create(this.bBox.getHalfWidth(), this.bBox.getHalfHeight());
134                 for (p in this.points) {
135                     this.points[p].add(hP);
136                 }
137                 this.calculateBoundingBox();
138             }
139 
140             this.getGameObject().markDirty();
141         },
142 
143         /**
144          * Transform all of the points by the given matrix
145          * @param matrix {Matrix}
146          */
147         transformPoints:function (matrix) {
148             for (var c = 0; c < this.points.length; c++) {
149                 this.points[c].transform(matrix);
150             }
151             this.calculateBoundingBox();
152             this.getGameObject().markDirty();
153         },
154 
155         /**
156          * Get the box which would enclose the shape
157          * @return {R.math.Rectangle2D}
158          */
159         getBoundingBox:function () {
160             return this.bBox;
161         },
162 
163         /**
164          * Get the center point from all of the points
165          * @return {R.math.Point2D}
166          */
167         getCenter:function () {
168             return R.math.Math2D.getCenterOfPoints(this.points);
169         },
170 
171         /**
172          * Get a convex hull that would enclose the points.  The the LOD isn't
173          * specified, it will be assumed to be 4.
174          * @param [lod] {Number} The level of detail for the hull.
175          * @return {R.collision.ConvexHull} A convex hull
176          */
177         getConvexHull:function (lod) {
178             return R.collision.ConvexHull.create(this.points, lod || this.points.length - 1);
179         },
180 
181         /**
182          * Get an Object Bounding Box (OBB) convex hull.
183          * @return {R.collision.OBBHull} A convex hull
184          */
185         getOBBHull:function () {
186             return R.collision.OBBHull.create(this.getBoundingBox());
187         },
188 
189         /**
190          * Get a circular convex hull which encloses the points.
191          * @param radiusPct {Number} A percentage of the calculated radius of the points, or <tt>null</tt>
192          * @return {R.collision.CircleHull} A convex hull
193          */
194         getCircleHull:function (radiusPct) {
195             return R.collision.CircleHull.create(this.points, radiusPct);
196         },
197 
198         /**
199          * Set the color of the lines to be drawn for this shape.
200          *
201          * @param strokeStyle {String} The HTML color of the stroke (lines) of the shape
202          */
203         setLineStyle:function (strokeStyle) {
204             this.strokeStyle = strokeStyle;
205             this.getGameObject().markDirty();
206         },
207 
208         /**
209          * Returns the line style that will be used to draw this shape.
210          * @return {String}
211          */
212         getLineStyle:function () {
213             return this.strokeStyle;
214         },
215 
216         /**
217          * Set the width of lines used to draw this shape.
218          *
219          * @param lineWidth {Number} The width of lines in the shape
220          */
221         setLineWidth:function (lineWidth) {
222             this.lineWidth = lineWidth;
223             this.getGameObject().markDirty();
224         },
225 
226         /**
227          * Returns the width of the lines used to draw the shape.
228          * @return {Number}
229          */
230         getLineWidth:function () {
231             return this.lineWidth;
232         },
233 
234         /**
235          * Set the color used to fill the shape.
236          *
237          * @param fillStyle {String} The HTML color used to fill the shape.
238          */
239         setFillStyle:function (fillStyle) {
240             this.fillStyle = fillStyle;
241             this.getGameObject().markDirty();
242         },
243 
244         /**
245          * Returns the fill style of the shape.
246          * @return {String}
247          */
248         getFillStyle:function () {
249             return this.fillStyle;
250         },
251 
252         /**
253          * Set whether or not we draw a polygon or polyline.  <tt>true</tt>
254          * to draw a polygon (the path formed by the points is a closed loop.
255          *
256          * @param closed {Boolean}
257          */
258         setClosed:function (closed) {
259             this.closedManifold = closed;
260             this.getGameObject().markDirty();
261         },
262 
263         /**
264          * Draw the shape, defined by the points, to the rendering context
265          * using the specified line style and fill style.
266          *
267          * @param renderContext {R.rendercontexts.AbstractRenderContext} The context to render to
268          * @param time {Number} The engine time in milliseconds
269          * @param dt {Number} The delta between the world time and the last time the world was updated
270          *          in milliseconds.
271          */
272         execute:function (renderContext, time, dt) {
273             if (!(this.points && this.base(renderContext, time, dt))) {
274                 return;
275             }
276 
277             // Set the stroke and fill styles
278             if (this.getLineStyle() != null) {
279                 renderContext.setLineStyle(this.strokeStyle);
280             }
281 
282             renderContext.setLineWidth(this.lineWidth);
283 
284             if (this.getFillStyle() != null) {
285                 renderContext.setFillStyle(this.fillStyle);
286             }
287 
288             this.transformOrigin(renderContext, true);
289 
290             // Render out the points
291             if (this.closedManifold) {
292                 renderContext.drawPolygon(this.points);
293             } else {
294                 renderContext.drawPolyline(this.points);
295             }
296 
297             if (this.fillStyle) {
298                 renderContext.drawFilledPolygon(this.points);
299             }
300 
301             this.transformOrigin(renderContext, false);
302 
303         }
304     }, /** @scope R.components.render.Vector2D.prototype */{
305         /**
306          * Get the class name of this object
307          *
308          * @return {String} "R.components.render.Vector2D"
309          */
310         getClassName:function () {
311             return "R.components.render.Vector2D";
312         }
313     });
314 }