1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * <p> 29 * Drawing primitives Utility Class. this class is base class, it contain some render type version: Canvas, WebGL, DOM.<br/> 30 * this class contain some primitive Drawing Method: <br/> 31 * - drawPoint<br/> 32 * - drawLine<br/> 33 * - drawPoly<br/> 34 * - drawCircle<br/> 35 * - drawQuadBezier<br/> 36 * - drawCubicBezier<br/> 37 * You can change the color, width and other property by calling these WebGL API:<br/> 38 * glColor4ub(), glLineWidth(), glPointSize().<br/> 39 * </p> 40 * @class 41 * @extends cc.Class 42 * @warning These functions draws the Line, Point, Polygon, immediately. They aren't batched. <br/> 43 * If you are going to make a game that depends on these primitives, I suggest creating a batch. 44 */ 45 cc.DrawingPrimitive = cc.Class.extend(/** @lends cc.DrawingPrimitive# */{ 46 _renderContext:null, 47 48 /** 49 * set render context of drawing primitive 50 * @param context 51 */ 52 setRenderContext:function (context) { 53 this._renderContext = context; 54 }, 55 56 /** 57 * returns render context of drawing primitive 58 * @return {CanvasRenderingContext2D} 59 */ 60 getRenderContext:function () { 61 return this._renderContext; 62 }, 63 64 /** 65 * Constructor 66 * @param {CanvasRenderingContext2D} renderContext 67 */ 68 ctor:function (renderContext) { 69 this._renderContext = renderContext; 70 }, 71 72 /** 73 * draws a point given x and y coordinate measured in points 74 * @param {cc.Point} point 75 */ 76 drawPoint:function (point) { 77 cc.log("DrawingPrimitive.drawPoint() not implement!"); 78 }, 79 80 /** 81 * draws an array of points. 82 * @param {Array} points point of array 83 * @param {Number} numberOfPoints 84 */ 85 drawPoints:function (points, numberOfPoints) { 86 cc.log("DrawingPrimitive.drawPoints() not implement!"); 87 }, 88 89 /** 90 * draws a line given the origin and destination point measured in points 91 * @param {cc.Point} origin 92 * @param {cc.Point} destination 93 */ 94 drawLine:function (origin, destination) { 95 cc.log("DrawingPrimitive.drawLine() not implement!"); 96 }, 97 98 /** 99 * draws a rectangle given the origin and destination point measured in points. 100 * @param {cc.Point} origin 101 * @param {cc.Point} destination 102 */ 103 drawRect:function (origin, destination) { 104 cc.log("DrawingPrimitive.drawRect() not implement!"); 105 }, 106 107 /** 108 * draws a solid rectangle given the origin and destination point measured in points. 109 * @param {cc.Point} origin 110 * @param {cc.Point} destination 111 * @param {cc.Color} color 112 */ 113 drawSolidRect:function (origin, destination, color) { 114 cc.log("DrawingPrimitive.drawSolidRect() not implement!"); 115 }, 116 117 /** 118 * draws a poligon given a pointer to cc.Point coordiantes and the number of vertices measured in points. 119 * @param {Array} vertices a pointer to cc.Point coordiantes 120 * @param {Number} numOfVertices the number of vertices measured in points 121 * @param {Boolean} closePolygon The polygon can be closed or open 122 * @param {Boolean} fill The polygon can be closed or open and optionally filled with current color 123 */ 124 drawPoly:function (vertices, numOfVertices, closePolygon, fill) { 125 cc.log("DrawingPrimitive.drawPoly() not implement!"); 126 }, 127 128 /** 129 * draws a solid polygon given a pointer to CGPoint coordiantes, the number of vertices measured in points, and a color. 130 * @param {Array} poli 131 * @param {Number} numberOfPoints 132 * @param {cc.Color} color 133 */ 134 drawSolidPoly:function (poli, numberOfPoints, color) { 135 cc.log("DrawingPrimitive.drawSolidPoly() not implement!"); 136 }, 137 138 /** 139 * draws a circle given the center, radius and number of segments. 140 * @param {cc.Point} center center of circle 141 * @param {Number} radius 142 * @param {Number} angle angle in radians 143 * @param {Number} segments 144 * @param {Boolean} drawLineToCenter 145 */ 146 drawCircle:function (center, radius, angle, segments, drawLineToCenter) { 147 cc.log("DrawingPrimitive.drawCircle() not implement!"); 148 }, 149 150 /** 151 * draws a quad bezier path 152 * @param {cc.Point} origin 153 * @param {cc.Point} control 154 * @param {cc.Point} destination 155 * @param {Number} segments 156 */ 157 drawQuadBezier:function (origin, control, destination, segments) { 158 cc.log("DrawingPrimitive.drawQuadBezier() not implement!"); 159 }, 160 161 /** 162 * draws a cubic bezier path 163 * @param {cc.Point} origin 164 * @param {cc.Point} control1 165 * @param {cc.Point} control2 166 * @param {cc.Point} destination 167 * @param {Number} segments 168 */ 169 drawCubicBezier:function (origin, control1, control2, destination, segments) { 170 cc.log("DrawingPrimitive.drawCubicBezier() not implement!"); 171 }, 172 173 /** 174 * draw a catmull rom line 175 * @param {Array} points 176 * @param {Number} segments 177 */ 178 drawCatmullRom:function (points, segments) { 179 cc.log("DrawingPrimitive.drawCardinalSpline() not implement!"); 180 }, 181 182 /** 183 * draw a cardinal spline path 184 * @param {Array} config 185 * @param {Number} tension 186 * @param {Number} segments 187 */ 188 drawCardinalSpline:function (config, tension, segments) { 189 cc.log("DrawingPrimitive.drawCardinalSpline() not implement!"); 190 } 191 }); 192 193 /** 194 * Canvas of DrawingPrimitive implement version 195 * @class 196 * @extends cc.DrawingPrimitive 197 */ 198 cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrimitiveCanvas# */{ 199 _cacheArray:[], 200 /** 201 * draws a point given x and y coordinate measured in points 202 * @override 203 * @param {cc.Point} point 204 * @param {Number} size 205 */ 206 drawPoint:function (point, size) { 207 if (!size) { 208 size = 1; 209 } 210 var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); 211 var newPoint = cc.p(point.x * locScaleX, point.y * locScaleY); 212 this._renderContext.beginPath(); 213 this._renderContext.arc(newPoint.x, -newPoint.y, size * locScaleX, 0, Math.PI * 2, false); 214 this._renderContext.closePath(); 215 this._renderContext.fill(); 216 }, 217 218 /** 219 * draws an array of points. 220 * @override 221 * @param {Array} points point of array 222 * @param {Number} numberOfPoints 223 * @param {Number} size 224 */ 225 drawPoints:function (points, numberOfPoints, size) { 226 if (points == null) { 227 return; 228 } 229 if (!size) { 230 size = 1; 231 } 232 var locContext = this._renderContext,locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); 233 234 locContext.beginPath(); 235 for (var i = 0, len = points.length; i < len; i++) 236 locContext.arc(points[i].x * locScaleX, -points[i].y * locScaleY, size * locScaleX, 0, Math.PI * 2, false); 237 locContext.closePath(); 238 locContext.fill(); 239 }, 240 241 /** 242 * draws a line given the origin and destination point measured in points 243 * @override 244 * @param {cc.Point} origin 245 * @param {cc.Point} destination 246 */ 247 drawLine:function (origin, destination) { 248 var locContext = this._renderContext, locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); 249 locContext.beginPath(); 250 locContext.moveTo(origin.x * locScaleX, -origin.y * locScaleY); 251 locContext.lineTo(destination.x * locScaleX, -destination.y * locScaleY); 252 locContext.closePath(); 253 locContext.stroke(); 254 }, 255 256 /** 257 * draws a rectangle given the origin and destination point measured in points. 258 * @param {cc.Point} origin 259 * @param {cc.Point} destination 260 */ 261 drawRect:function (origin, destination) { 262 this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y)); 263 this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y)); 264 this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y)); 265 this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y)); 266 }, 267 268 /** 269 * draws a solid rectangle given the origin and destination point measured in points. 270 * @param {cc.Point} origin 271 * @param {cc.Point} destination 272 * @param {cc.Color} color 273 */ 274 drawSolidRect:function (origin, destination, color) { 275 var vertices = [ 276 origin, 277 cc.p(destination.x, origin.y), 278 destination, 279 cc.p(origin.x, destination.y) 280 ]; 281 282 this.drawSolidPoly(vertices, 4, color); 283 }, 284 285 /** 286 * draws a polygon given a pointer to cc.Point coordinates and the number of vertices measured in points. 287 * @override 288 * @param {Array} vertices a pointer to cc.Point coordinates 289 * @param {Number} numOfVertices the number of vertices measured in points 290 * @param {Boolean} closePolygon The polygon can be closed or open 291 * @param {Boolean} [fill=] The polygon can be closed or open and optionally filled with current color 292 */ 293 drawPoly:function (vertices, numOfVertices, closePolygon, fill) { 294 fill = fill || false; 295 296 if (vertices == null) 297 return; 298 299 if (vertices.length < 3) 300 throw new Error("Polygon's point must greater than 2"); 301 302 var firstPoint = vertices[0], locContext = this._renderContext; 303 var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); 304 locContext.beginPath(); 305 locContext.moveTo(firstPoint.x * locScaleX, -firstPoint.y * locScaleY); 306 for (var i = 1, len = vertices.length; i < len; i++) 307 locContext.lineTo(vertices[i].x * locScaleX, -vertices[i].y * locScaleY); 308 309 if (closePolygon) 310 locContext.closePath(); 311 312 if (fill) 313 locContext.fill(); 314 else 315 locContext.stroke(); 316 }, 317 318 /** 319 * draws a solid polygon given a pointer to CGPoint coordinates, the number of vertices measured in points, and a color. 320 * @param {Array} polygons 321 * @param {Number} numberOfPoints 322 * @param {cc.Color} color 323 */ 324 drawSolidPoly:function (polygons, numberOfPoints, color) { 325 this.setDrawColor(color.r, color.g, color.b, color.a); 326 this.drawPoly(polygons, numberOfPoints, true, true); 327 }, 328 329 /** 330 * draws a circle given the center, radius and number of segments. 331 * @override 332 * @param {cc.Point} center center of circle 333 * @param {Number} radius 334 * @param {Number} angle angle in radians 335 * @param {Number} segments 336 * @param {Boolean} [drawLineToCenter=] 337 */ 338 drawCircle: function (center, radius, angle, segments, drawLineToCenter) { 339 drawLineToCenter = drawLineToCenter || false; 340 var locContext = this._renderContext; 341 var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); 342 locContext.beginPath(); 343 var endAngle = angle - Math.PI * 2; 344 locContext.arc(0 | (center.x * locScaleX), 0 | -(center.y * locScaleY), radius * locScaleX, -angle, -endAngle, false); 345 if (drawLineToCenter) { 346 locContext.lineTo(0 | (center.x * locScaleX), 0 | -(center.y * locScaleY)); 347 } 348 locContext.stroke(); 349 }, 350 351 /** 352 * draws a quad bezier path 353 * @override 354 * @param {cc.Point} origin 355 * @param {cc.Point} control 356 * @param {cc.Point} destination 357 * @param {Number} segments 358 */ 359 drawQuadBezier:function (origin, control, destination, segments) { 360 //this is OpenGL Algorithm 361 var vertices = this._cacheArray; 362 vertices.length =0; 363 364 var t = 0.0; 365 for (var i = 0; i < segments; i++) { 366 var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x; 367 var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y; 368 vertices.push(cc.p(x, y)); 369 t += 1.0 / segments; 370 } 371 vertices.push(cc.p(destination.x, destination.y)); 372 373 this.drawPoly(vertices, segments + 1, false, false); 374 }, 375 376 /** 377 * draws a cubic bezier path 378 * @override 379 * @param {cc.Point} origin 380 * @param {cc.Point} control1 381 * @param {cc.Point} control2 382 * @param {cc.Point} destination 383 * @param {Number} segments 384 */ 385 drawCubicBezier:function (origin, control1, control2, destination, segments) { 386 //this is OpenGL Algorithm 387 var vertices = this._cacheArray; 388 vertices.length =0; 389 390 var t = 0; 391 for (var i = 0; i < segments; i++) { 392 var x = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x; 393 var y = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y; 394 vertices.push(cc.p(x , y )); 395 t += 1.0 / segments; 396 } 397 vertices.push(cc.p(destination.x , destination.y)); 398 399 this.drawPoly(vertices, segments + 1, false, false); 400 }, 401 402 /** 403 * draw a CatmullRom curve 404 * @override 405 * @param {Array} points 406 * @param {Number} segments 407 */ 408 drawCatmullRom:function (points, segments) { 409 this.drawCardinalSpline(points, 0.5, segments); 410 }, 411 412 /** 413 * draw a cardinal spline path 414 * @override 415 * @param {Array} config 416 * @param {Number} tension 417 * @param {Number} segments 418 */ 419 drawCardinalSpline:function (config, tension, segments) { 420 //lazy_init(); 421 cc._renderContext.strokeStyle = "rgba(255,255,255,1)"; 422 var points = this._cacheArray; 423 points.length = 0; 424 var p, lt; 425 var deltaT = 1.0 / config.length; 426 427 for (var i = 0; i < segments + 1; i++) { 428 var dt = i / segments; 429 430 // border 431 if (dt == 1) { 432 p = config.length - 1; 433 lt = 1; 434 } else { 435 p = 0 | (dt / deltaT); 436 lt = (dt - deltaT * p) / deltaT; 437 } 438 439 // Interpolate 440 var newPos = cc.CardinalSplineAt( 441 cc.getControlPointAt(config, p - 1), 442 cc.getControlPointAt(config, p - 0), 443 cc.getControlPointAt(config, p + 1), 444 cc.getControlPointAt(config, p + 2), 445 tension, lt); 446 points.push(newPos); 447 } 448 this.drawPoly(points, segments + 1, false, false); 449 }, 450 451 /** 452 * draw an image 453 * @override 454 * @param {HTMLImageElement|HTMLCanvasElement} image 455 * @param {cc.Point} sourcePoint 456 * @param {cc.Size} sourceSize 457 * @param {cc.Point} destPoint 458 * @param {cc.Size} destSize 459 */ 460 drawImage:function (image, sourcePoint, sourceSize, destPoint, destSize) { 461 var len = arguments.length; 462 switch (len) { 463 case 2: 464 var height = image.height; 465 this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + height)); 466 break; 467 case 3: 468 this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + sourceSize.height), sourceSize.width, sourceSize.height); 469 break; 470 case 5: 471 this._renderContext.drawImage(image, sourcePoint.x, sourcePoint.y, sourceSize.width, sourceSize.height, destPoint.x, -(destPoint.y + destSize.height), 472 destSize.width, destSize.height); 473 break; 474 default: 475 throw new Error("Argument must be non-nil"); 476 break; 477 } 478 }, 479 480 /** 481 * draw a star 482 * @param {CanvasRenderingContext2D} ctx canvas context 483 * @param {Number} radius 484 * @param {cc.Color} color 485 */ 486 drawStar:function (ctx, radius, color) { 487 var context = ctx || this._renderContext; 488 radius *= cc.view.getScaleX(); 489 var colorStr = "rgba(" + (0 | color.r) + "," + (0 | color.g) + "," + (0 | color.b); 490 context.fillStyle = colorStr + ",1)"; 491 var subRadius = radius / 10; 492 493 context.beginPath(); 494 context.moveTo(-radius, radius); 495 context.lineTo(0, subRadius); 496 context.lineTo(radius, radius); 497 context.lineTo(subRadius, 0); 498 context.lineTo(radius, -radius); 499 context.lineTo(0, -subRadius); 500 context.lineTo(-radius, -radius); 501 context.lineTo(-subRadius, 0); 502 context.lineTo(-radius, radius); 503 context.closePath(); 504 context.fill(); 505 506 var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius); 507 g1.addColorStop(0, colorStr + ", 1)"); 508 g1.addColorStop(0.3, colorStr + ", 0.8)"); 509 g1.addColorStop(1.0, colorStr + ", 0.0)"); 510 context.fillStyle = g1; 511 context.beginPath(); 512 var startAngle_1 = 0; 513 var endAngle_1 = cc.PI2; 514 context.arc(0, 0, radius - subRadius, startAngle_1, endAngle_1, false); 515 context.closePath(); 516 context.fill(); 517 }, 518 519 /** 520 * draw a color ball 521 * @param {CanvasRenderingContext2D} ctx canvas context 522 * @param {Number} radius 523 * @param {cc.Color} color 524 */ 525 drawColorBall:function (ctx, radius, color) { 526 var context = ctx || this._renderContext; 527 radius *= cc.view.getScaleX(); 528 var colorStr = "rgba(" +(0|color.r) + "," + (0|color.g) + "," + (0|color.b); 529 var subRadius = radius / 10; 530 531 var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius); 532 g1.addColorStop(0, colorStr + ", 1)"); 533 g1.addColorStop(0.3, colorStr + ", 0.8)"); 534 g1.addColorStop(0.6, colorStr + ", 0.4)"); 535 g1.addColorStop(1.0, colorStr + ", 0.0)"); 536 context.fillStyle = g1; 537 context.beginPath(); 538 var startAngle_1 = 0; 539 var endAngle_1 = cc.PI2; 540 context.arc(0, 0, radius, startAngle_1, endAngle_1, false); 541 context.closePath(); 542 context.fill(); 543 }, 544 545 /** 546 * fill text 547 * @param {String} strText 548 * @param {Number} x 549 * @param {Number} y 550 */ 551 fillText:function (strText, x, y) { 552 this._renderContext.fillText(strText, x, -y); 553 }, 554 555 /** 556 * set the drawing color with 4 unsigned bytes 557 * @param {Number} r red value (0 to 255) 558 * @param {Number} g green value (0 to 255) 559 * @param {Number} b blue value (0 to 255) 560 * @param {Number} a Alpha value (0 to 255) 561 */ 562 setDrawColor:function (r, g, b, a) { 563 this._renderContext.fillStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")"; 564 this._renderContext.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")"; 565 }, 566 567 /** 568 * set the point size in points. Default 1. 569 * @param {Number} pointSize 570 */ 571 setPointSize:function (pointSize) { 572 }, 573 574 /** 575 * set the line width. Default 1. 576 * @param {Number} width 577 */ 578 setLineWidth:function (width) { 579 this._renderContext.lineWidth = width * cc.view.getScaleX(); 580 } 581 }); 582 583 /** 584 * Canvas of DrawingPrimitive implement version 585 * @class 586 * @extends cc.DrawingPrimitive 587 */ 588 cc.DrawingPrimitiveWebGL = cc.DrawingPrimitive.extend({ 589 _initialized:false, 590 _shader: null, 591 _colorLocation:-1, 592 _colorArray: null, 593 _pointSizeLocation:-1, 594 _pointSize:-1, 595 ctor:function (ctx) { 596 if (ctx == null) 597 ctx = cc._renderContext; 598 599 if (!ctx instanceof WebGLRenderingContext) 600 throw "Can't initialise DrawingPrimitiveWebGL. context need is WebGLRenderingContext"; 601 602 cc.DrawingPrimitive.prototype.ctor.call(this, ctx); 603 this._colorArray = new Float32Array([1.0, 1.0, 1.0, 1.0]); 604 }, 605 606 lazy_init:function () { 607 if (!this._initialized) { 608 // 609 // Position and 1 color passed as a uniform (to similate glColor4ub ) 610 // 611 this._shader = cc.shaderCache.programForKey(cc.SHADER_POSITION_UCOLOR); 612 this._colorLocation = this._renderContext.getUniformLocation(this._shader.getProgram(), "u_color"); 613 this._pointSizeLocation = this._renderContext.getUniformLocation(this._shader.getProgram(), "u_pointSize"); 614 //cc.CHECK_GL_ERROR_DEBUG(); 615 616 this._initialized = true; 617 } 618 }, 619 620 /** 621 * initlialize context 622 */ 623 drawInit:function () { 624 this._initialized = false; 625 }, 626 627 /** 628 * draws a point given x and y coordinate measured in points 629 * @param {cc.Point} point 630 */ 631 drawPoint:function (point) { 632 this.lazy_init(); 633 634 var glContext = this._renderContext; 635 this._shader.use(); 636 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 637 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 638 glContext.uniform4fv(this._colorLocation, this._colorArray); 639 this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize); 640 641 var pointBuffer = glContext.createBuffer(); 642 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 643 glContext.bufferData(glContext.ARRAY_BUFFER, new Float32Array([point.x, point.y]), glContext.STATIC_DRAW); 644 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 645 646 glContext.drawArrays(glContext.POINTS, 0, 1); 647 glContext.deleteBuffer(pointBuffer); 648 649 cc.INCREMENT_GL_DRAWS(1); 650 }, 651 652 /** 653 * draws an array of points. 654 * @param {Array} points point of array 655 * @param {Number} numberOfPoints 656 */ 657 drawPoints:function (points, numberOfPoints) { 658 if (!points || points.length == 0) 659 return; 660 661 this.lazy_init(); 662 663 var glContext = this._renderContext; 664 this._shader.use(); 665 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 666 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 667 glContext.uniform4fv(this._colorLocation, this._colorArray); 668 this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize); 669 670 var pointBuffer = glContext.createBuffer(); 671 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 672 glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(points), glContext.STATIC_DRAW); 673 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 674 675 glContext.drawArrays(glContext.POINTS, 0, points.length); 676 glContext.deleteBuffer(pointBuffer); 677 678 cc.INCREMENT_GL_DRAWS(1); 679 }, 680 681 _pointsToTypeArray:function (points) { 682 var typeArr = new Float32Array(points.length * 2); 683 for (var i = 0; i < points.length; i++) { 684 typeArr[i * 2] = points[i].x; 685 typeArr[i * 2 + 1] = points[i].y; 686 } 687 return typeArr; 688 }, 689 690 /** 691 * draws a line given the origin and destination point measured in points 692 * @param {cc.Point} origin 693 * @param {cc.Point} destination 694 */ 695 drawLine:function (origin, destination) { 696 this.lazy_init(); 697 698 var glContext = this._renderContext; 699 this._shader.use(); 700 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 701 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 702 glContext.uniform4fv(this._colorLocation, this._colorArray); 703 704 var pointBuffer = glContext.createBuffer(); 705 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 706 glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray([origin, destination]), glContext.STATIC_DRAW); 707 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 708 709 glContext.drawArrays(glContext.LINES, 0, 2); 710 glContext.deleteBuffer(pointBuffer); 711 712 cc.INCREMENT_GL_DRAWS(1); 713 }, 714 715 /** 716 * draws a rectangle given the origin and destination point measured in points. 717 * @param {cc.Point} origin 718 * @param {cc.Point} destination 719 */ 720 drawRect:function (origin, destination) { 721 this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y)); 722 this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y)); 723 this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y)); 724 this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y)); 725 }, 726 727 /** 728 * draws a solid rectangle given the origin and destination point measured in points. 729 * @param {cc.Point} origin 730 * @param {cc.Point} destination 731 * @param {cc.Color} color 732 */ 733 drawSolidRect:function (origin, destination, color) { 734 var vertices = [ 735 origin, 736 cc.p(destination.x, origin.y), 737 destination, 738 cc.p(origin.x, destination.y) 739 ]; 740 741 this.drawSolidPoly(vertices, 4, color); 742 }, 743 744 /** 745 * draws a polygon given a pointer to cc.Point coordiantes and the number of vertices measured in points. 746 * @param {Array} vertices a pointer to cc.Point coordiantes 747 * @param {Number} numOfVertices the number of vertices measured in points 748 * @param {Boolean} closePolygon The polygon can be closed or open 749 */ 750 drawPoly:function (vertices, numOfVertices, closePolygon) { 751 this.lazy_init(); 752 753 var glContext = this._renderContext; 754 this._shader.use(); 755 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 756 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 757 glContext.uniform4fv(this._colorLocation, this._colorArray); 758 759 var pointBuffer = glContext.createBuffer(); 760 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 761 glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(vertices), glContext.STATIC_DRAW); 762 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 763 764 if (closePolygon) 765 glContext.drawArrays(glContext.LINE_LOOP, 0, vertices.length); 766 else 767 glContext.drawArrays(glContext.LINE_STRIP, 0, vertices.length); 768 glContext.deleteBuffer(pointBuffer); 769 770 cc.INCREMENT_GL_DRAWS(1); 771 }, 772 773 /** 774 * draws a solid polygon given a pointer to CGPoint coordiantes, the number of vertices measured in points, and a color. 775 * @param {Array} poli 776 * @param {Number} numberOfPoints 777 * @param {cc.Color} color 778 */ 779 drawSolidPoly:function (poli, numberOfPoints, color) { 780 this.lazy_init(); 781 if (color) 782 this.setDrawColor(color.r, color.g, color.b, color.a); 783 784 var glContext = this._renderContext; 785 this._shader.use(); 786 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 787 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 788 glContext.uniform4fv(this._colorLocation, this._colorArray); 789 790 var pointBuffer = glContext.createBuffer(); 791 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 792 glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(poli), glContext.STATIC_DRAW); 793 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 794 glContext.drawArrays(glContext.TRIANGLE_FAN, 0, poli.length); 795 glContext.deleteBuffer(pointBuffer); 796 797 cc.INCREMENT_GL_DRAWS(1); 798 }, 799 800 /** 801 * draws a circle given the center, radius and number of segments. 802 * @param {cc.Point} center center of circle 803 * @param {Number} radius 804 * @param {Number} angle angle in radians 805 * @param {Number} segments 806 * @param {Boolean} drawLineToCenter 807 */ 808 drawCircle:function (center, radius, angle, segments, drawLineToCenter) { 809 this.lazy_init(); 810 811 var additionalSegment = 1; 812 if (drawLineToCenter) 813 additionalSegment++; 814 815 var coef = 2.0 * Math.PI / segments; 816 817 var vertices = new Float32Array((segments + 2) * 2); 818 if (!vertices) 819 return; 820 821 for (var i = 0; i <= segments; i++) { 822 var rads = i * coef; 823 var j = radius * Math.cos(rads + angle) + center.x; 824 var k = radius * Math.sin(rads + angle) + center.y; 825 826 vertices[i * 2] = j; 827 vertices[i * 2 + 1] = k; 828 } 829 vertices[(segments + 1) * 2] = center.x; 830 vertices[(segments + 1) * 2 + 1] = center.y; 831 832 var glContext = this._renderContext; 833 this._shader.use(); 834 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 835 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 836 glContext.uniform4fv(this._colorLocation, this._colorArray); 837 838 var pointBuffer = glContext.createBuffer(); 839 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 840 glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW); 841 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 842 843 glContext.drawArrays(glContext.LINE_STRIP, 0, segments + additionalSegment); 844 glContext.deleteBuffer(pointBuffer); 845 846 cc.INCREMENT_GL_DRAWS(1); 847 }, 848 849 /** 850 * draws a quad bezier path 851 * @param {cc.Point} origin 852 * @param {cc.Point} control 853 * @param {cc.Point} destination 854 * @param {Number} segments 855 */ 856 drawQuadBezier:function (origin, control, destination, segments) { 857 this.lazy_init(); 858 859 var vertices = new Float32Array((segments + 1) * 2); 860 861 var t = 0.0; 862 for (var i = 0; i < segments; i++) { 863 vertices[i * 2] = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x; 864 vertices[i * 2 + 1] = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y; 865 t += 1.0 / segments; 866 } 867 vertices[segments * 2] = destination.x; 868 vertices[segments * 2 + 1] = destination.y; 869 870 var glContext = this._renderContext; 871 this._shader.use(); 872 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 873 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 874 glContext.uniform4fv(this._colorLocation, this._colorArray); 875 876 var pointBuffer = glContext.createBuffer(); 877 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 878 glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW); 879 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 880 881 glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1); 882 glContext.deleteBuffer(pointBuffer); 883 884 cc.INCREMENT_GL_DRAWS(1); 885 }, 886 887 /** 888 * draws a cubic bezier path 889 * @param {cc.Point} origin 890 * @param {cc.Point} control1 891 * @param {cc.Point} control2 892 * @param {cc.Point} destination 893 * @param {Number} segments 894 */ 895 drawCubicBezier:function (origin, control1, control2, destination, segments) { 896 this.lazy_init(); 897 898 var vertices = new Float32Array((segments + 1) * 2); 899 900 var t = 0; 901 for (var i = 0; i < segments; i++) { 902 vertices[i * 2] = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x; 903 vertices[i * 2 + 1] = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y; 904 t += 1.0 / segments; 905 } 906 vertices[segments * 2] = destination.x; 907 vertices[segments * 2 + 1] = destination.y; 908 909 var glContext = this._renderContext; 910 this._shader.use(); 911 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 912 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 913 glContext.uniform4fv(this._colorLocation, this._colorArray); 914 915 var pointBuffer = glContext.createBuffer(); 916 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 917 glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW); 918 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 919 glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1); 920 glContext.deleteBuffer(pointBuffer); 921 922 cc.INCREMENT_GL_DRAWS(1); 923 }, 924 925 /** 926 * draw a catmull rom line 927 * @param {Array} points 928 * @param {Number} segments 929 */ 930 drawCatmullRom:function (points, segments) { 931 this.drawCardinalSpline(points, 0.5, segments); 932 }, 933 934 /** 935 * draw a cardinal spline path 936 * @param {Array} config 937 * @param {Number} tension 938 * @param {Number} segments 939 */ 940 drawCardinalSpline:function (config, tension, segments) { 941 this.lazy_init(); 942 943 var vertices = new Float32Array((segments + 1) * 2); 944 var p, lt, deltaT = 1.0 / config.length; 945 for (var i = 0; i < segments + 1; i++) { 946 var dt = i / segments; 947 948 // border 949 if (dt == 1) { 950 p = config.length - 1; 951 lt = 1; 952 } else { 953 p = 0 | (dt / deltaT); 954 lt = (dt - deltaT * p) / deltaT; 955 } 956 957 var newPos = cc.CardinalSplineAt( 958 cc.getControlPointAt(config, p - 1), 959 cc.getControlPointAt(config, p), 960 cc.getControlPointAt(config, p + 1), 961 cc.getControlPointAt(config, p + 2), 962 tension, lt); 963 // Interpolate 964 965 vertices[i * 2] = newPos.x; 966 vertices[i * 2 + 1] = newPos.y; 967 } 968 969 var glContext = this._renderContext; 970 this._shader.use(); 971 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 972 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 973 glContext.uniform4fv(this._colorLocation, this._colorArray); 974 975 var pointBuffer = glContext.createBuffer(); 976 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 977 glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW); 978 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 979 glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1); 980 glContext.deleteBuffer(pointBuffer); 981 982 cc.INCREMENT_GL_DRAWS(1); 983 }, 984 985 /** 986 * set the drawing color with 4 unsigned bytes 987 * @param {Number} r red value (0 to 255) 988 * @param {Number} g green value (0 to 255) 989 * @param {Number} b blue value (0 to 255) 990 * @param {Number} a Alpha value (0 to 255) 991 */ 992 setDrawColor:function (r, g, b, a) { 993 this._colorArray[0] = r / 255.0; 994 this._colorArray[1] = g / 255.0; 995 this._colorArray[2] = b / 255.0; 996 this._colorArray[3] = a / 255.0; 997 }, 998 999 /** 1000 * set the point size in points. Default 1. 1001 * @param {Number} pointSize 1002 */ 1003 setPointSize:function (pointSize) { 1004 this._pointSize = pointSize * cc.CONTENT_SCALE_FACTOR(); 1005 }, 1006 1007 /** 1008 * set the line width. Default 1. 1009 * @param {Number} width 1010 */ 1011 setLineWidth:function (width) { 1012 if(this._renderContext.lineWidth) 1013 this._renderContext.lineWidth(width); 1014 } 1015 }); 1016 1017 cc.PI2 = Math.PI * 2; 1018