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.Color4F} 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.Color4F} 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 /** 200 * draws a point given x and y coordinate measured in points 201 * @override 202 * @param {cc.Point} point 203 * @param {Number} size 204 */ 205 drawPoint:function (point, size) { 206 if (!size) { 207 size = 1; 208 } 209 var newPoint = cc.p(point.x * cc.CONTENT_SCALE_FACTOR(), point.y * cc.CONTENT_SCALE_FACTOR()); 210 this._renderContext.beginPath(); 211 this._renderContext.arc(newPoint.x, -newPoint.y, size * cc.CONTENT_SCALE_FACTOR(), 0, Math.PI * 2, false); 212 this._renderContext.closePath(); 213 this._renderContext.fill(); 214 }, 215 216 /** 217 * draws an array of points. 218 * @override 219 * @param {Array} points point of array 220 * @param {Number} numberOfPoints 221 * @param {Number} size 222 */ 223 drawPoints:function (points, numberOfPoints, size) { 224 if (points == null) { 225 return; 226 } 227 if (!size) { 228 size = 1; 229 } 230 231 this._renderContext.beginPath(); 232 for (var i = 0; i < points.length; i++) { 233 this._renderContext.arc(points[i].x * cc.CONTENT_SCALE_FACTOR(), -points[i].y * cc.CONTENT_SCALE_FACTOR(), 234 size * cc.CONTENT_SCALE_FACTOR(), 0, Math.PI * 2, false); 235 } 236 this._renderContext.closePath(); 237 this._renderContext.fill(); 238 }, 239 240 /** 241 * draws a line given the origin and destination point measured in points 242 * @override 243 * @param {cc.Point} origin 244 * @param {cc.Point} destination 245 */ 246 drawLine:function (origin, destination) { 247 this._renderContext.beginPath(); 248 this._renderContext.moveTo(origin.x * cc.CONTENT_SCALE_FACTOR(), -origin.y * cc.CONTENT_SCALE_FACTOR()); 249 this._renderContext.lineTo(destination.x * cc.CONTENT_SCALE_FACTOR(), -destination.y * cc.CONTENT_SCALE_FACTOR()); 250 this._renderContext.closePath(); 251 this._renderContext.stroke(); 252 }, 253 254 /** 255 * draws a rectangle given the origin and destination point measured in points. 256 * @param {cc.Point} origin 257 * @param {cc.Point} destination 258 */ 259 drawRect:function (origin, destination) { 260 this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y)); 261 this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y)); 262 this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y)); 263 this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y)); 264 }, 265 266 /** 267 * draws a solid rectangle given the origin and destination point measured in points. 268 * @param {cc.Point} origin 269 * @param {cc.Point} destination 270 * @param {cc.Color4F} color 271 */ 272 drawSolidRect:function (origin, destination, color) { 273 var vertices = [ 274 origin, 275 cc.p(destination.x, origin.y), 276 destination, 277 cc.p(origin.x, destination.y) 278 ]; 279 280 this.drawSolidPoly(vertices, 4, color); 281 }, 282 283 /** 284 * draws a poligon given a pointer to cc.Point coordiantes and the number of vertices measured in points. 285 * @override 286 * @param {Array} vertices a pointer to cc.Point coordiantes 287 * @param {Number} numOfVertices the number of vertices measured in points 288 * @param {Boolean} closePolygon The polygon can be closed or open 289 * @param {Boolean} fill The polygon can be closed or open and optionally filled with current color 290 */ 291 drawPoly:function (vertices, numOfVertices, closePolygon, fill) { 292 if (fill == 'undefined') { 293 fill = false; 294 } 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 303 var firstPoint = vertices[0]; 304 this._renderContext.beginPath(); 305 this._renderContext.moveTo(firstPoint.x * cc.CONTENT_SCALE_FACTOR(), -firstPoint.y * cc.CONTENT_SCALE_FACTOR()); 306 for (var i = 1; i < vertices.length; i++) { 307 this._renderContext.lineTo(vertices[i].x * cc.CONTENT_SCALE_FACTOR(), -vertices[i].y * cc.CONTENT_SCALE_FACTOR()); 308 } 309 if (closePolygon) { 310 this._renderContext.closePath(); 311 } 312 313 if (fill) { 314 this._renderContext.fill(); 315 } else { 316 this._renderContext.stroke(); 317 } 318 }, 319 320 /** 321 * draws a solid polygon given a pointer to CGPoint coordiantes, the number of vertices measured in points, and a color. 322 * @param {Array} poli 323 * @param {Number} numberOfPoints 324 * @param {cc.Color4F} color 325 */ 326 drawSolidPoly:function (poli, numberOfPoints, color) { 327 this.setDrawColor4F(color.r, color.g, color.b, color.a); 328 this.drawPoly(poli, numberOfPoints, true, true); 329 }, 330 331 /** 332 * draws a circle given the center, radius and number of segments. 333 * @override 334 * @param {cc.Point} center center of circle 335 * @param {Number} radius 336 * @param {Number} angle angle in radians 337 * @param {Number} segments 338 * @param {Boolean} drawLineToCenter 339 */ 340 drawCircle:function (center, radius, angle, segments, drawLineToCenter) { 341 this._renderContext.beginPath(); 342 var endAngle = angle - Math.PI * 2; 343 this._renderContext.arc(0 | center.x, 0 | -(center.y), radius, -angle, -endAngle, false); 344 if (drawLineToCenter) { 345 this._renderContext.lineTo(0 | center.x, 0 | -(center.y)); 346 } 347 this._renderContext.stroke(); 348 }, 349 350 /** 351 * draws a quad bezier path 352 * @override 353 * @param {cc.Point} origin 354 * @param {cc.Point} control 355 * @param {cc.Point} destination 356 * @param {Number} segments 357 */ 358 drawQuadBezier:function (origin, control, destination, segments) { 359 //this is OpenGL Algorithm 360 var vertices = []; 361 362 var t = 0.0; 363 for (var i = 0; i < segments; i++) { 364 var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x; 365 var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y; 366 vertices.push(cc.p(x * cc.CONTENT_SCALE_FACTOR(), y * cc.CONTENT_SCALE_FACTOR())); 367 t += 1.0 / segments; 368 } 369 vertices.push(cc.p(destination.x * cc.CONTENT_SCALE_FACTOR(), destination.y * cc.CONTENT_SCALE_FACTOR())); 370 371 this.drawPoly(vertices, segments + 1, false, false); 372 }, 373 374 /** 375 * draws a cubic bezier path 376 * @override 377 * @param {cc.Point} origin 378 * @param {cc.Point} control1 379 * @param {cc.Point} control2 380 * @param {cc.Point} destination 381 * @param {Number} segments 382 */ 383 drawCubicBezier:function (origin, control1, control2, destination, segments) { 384 //this is OpenGL Algorithm 385 var vertices = []; 386 387 var t = 0; 388 for (var i = 0; i < segments; i++) { 389 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; 390 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; 391 vertices.push(cc.p(x * cc.CONTENT_SCALE_FACTOR(), y * cc.CONTENT_SCALE_FACTOR())); 392 t += 1.0 / segments; 393 } 394 vertices.push(cc.p(destination.x * cc.CONTENT_SCALE_FACTOR(), destination.y * cc.CONTENT_SCALE_FACTOR())); 395 396 this.drawPoly(vertices, segments + 1, false, false); 397 }, 398 399 /** 400 * draw a CatmullRom curve 401 * @override 402 * @param {Array} points 403 * @param {Number} segments 404 */ 405 drawCatmullRom:function (points, segments) { 406 this.drawCardinalSpline(points, 0.5, segments); 407 }, 408 409 /** 410 * draw a cardinal spline path 411 * @override 412 * @param {Array} config 413 * @param {Number} tension 414 * @param {Number} segments 415 */ 416 drawCardinalSpline:function (config, tension, segments) { 417 //lazy_init(); 418 cc.renderContext.strokeStyle = "rgba(255,255,255,1)"; 419 var points = []; 420 var p, lt; 421 var deltaT = 1.0 / config.length; 422 423 for (var i = 0; i < segments + 1; i++) { 424 var dt = i / segments; 425 426 // border 427 if (dt == 1) { 428 p = config.length - 1; 429 lt = 1; 430 } else { 431 p = 0 | (dt / deltaT); 432 lt = (dt - deltaT * p) / deltaT; 433 } 434 435 // Interpolate 436 var newPos = cc.CardinalSplineAt( 437 cc.getControlPointAt(config, p - 1), 438 cc.getControlPointAt(config, p - 0), 439 cc.getControlPointAt(config, p + 1), 440 cc.getControlPointAt(config, p + 2), 441 tension, lt); 442 points.push(newPos); 443 } 444 this.drawPoly(points, segments + 1, false, false); 445 }, 446 447 /** 448 * draw an image 449 * @override 450 * @param {HTMLImageElement|HTMLCanvasElement} image 451 * @param {cc.Point} sourcePoint 452 * @param {cc.Size} sourceSize 453 * @param {cc.Point} destPoint 454 * @param {cc.Size} destSize 455 */ 456 drawImage:function (image, sourcePoint, sourceSize, destPoint, destSize) { 457 var len = arguments.length; 458 switch (len) { 459 case 2: 460 var height = image.height; 461 this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + height)); 462 break; 463 case 3: 464 this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + sourceSize.height), sourceSize.width, sourceSize.height); 465 break; 466 case 5: 467 this._renderContext.drawImage(image, sourcePoint.x, sourcePoint.y, sourceSize.width, sourceSize.height, destPoint.x, -(destPoint.y + destSize.height), 468 destSize.width, destSize.height); 469 break; 470 default: 471 throw new Error("Argument must be non-nil"); 472 break; 473 } 474 }, 475 476 /** 477 * draw a star 478 * @param {CanvasRenderingContext2D} ctx canvas context 479 * @param {Number} radius 480 * @param {cc.Color3B|cc.Color4B|cc.Color4F} color 481 */ 482 drawStar:function (ctx, radius, color) { 483 var context = ctx || this._renderContext; 484 if (color instanceof cc.Color4F) 485 color = new cc.Color3B(0 | (color.r * 255), 0 | (color.g * 255), 0 | (color.b * 255)); 486 var colorStr = "rgba(" + color.r + "," + color.g + "," + color.b; 487 context.fillStyle = colorStr + ",1)"; 488 var subRadius = radius / 10; 489 490 context.beginPath(); 491 context.moveTo(-radius, radius); 492 context.lineTo(0, subRadius); 493 context.lineTo(radius, radius); 494 context.lineTo(subRadius, 0); 495 context.lineTo(radius, -radius); 496 context.lineTo(0, -subRadius); 497 context.lineTo(-radius, -radius); 498 context.lineTo(-subRadius, 0); 499 context.lineTo(-radius, radius); 500 context.closePath(); 501 context.fill(); 502 503 var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius); 504 g1.addColorStop(0, colorStr + ", 1)"); 505 g1.addColorStop(0.3, colorStr + ", 0.8)"); 506 g1.addColorStop(1.0, colorStr + ", 0.0)"); 507 context.fillStyle = g1; 508 context.beginPath(); 509 var startAngle_1 = 0; 510 var endAngle_1 = cc.PI2; 511 context.arc(0, 0, radius - subRadius, startAngle_1, endAngle_1, false); 512 context.closePath(); 513 context.fill(); 514 }, 515 516 /** 517 * draw a color ball 518 * @param {CanvasRenderingContext2D} ctx canvas context 519 * @param {Number} radius 520 * @param {cc.Color3B|cc.Color4B|cc.Color4F} color 521 */ 522 drawColorBall:function (ctx, radius, color) { 523 var context = ctx || this._renderContext; 524 if (color instanceof cc.Color4F) 525 color = new cc.Color3B(0 | (color.r * 255), 0 | (color.g * 255), 0 | (color.b * 255)); 526 var colorStr = "rgba(" + color.r + "," + color.g + "," + color.b; 527 var subRadius = radius / 10; 528 529 var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius); 530 g1.addColorStop(0, colorStr + ", 1)"); 531 g1.addColorStop(0.3, colorStr + ", 0.8)"); 532 g1.addColorStop(0.6, colorStr + ", 0.4)"); 533 g1.addColorStop(1.0, colorStr + ", 0.0)"); 534 context.fillStyle = g1; 535 context.beginPath(); 536 var startAngle_1 = 0; 537 var endAngle_1 = cc.PI2; 538 context.arc(0, 0, radius, startAngle_1, endAngle_1, false); 539 context.closePath(); 540 context.fill(); 541 }, 542 543 /** 544 * fill text 545 * @param {String} strText 546 * @param {Number} x 547 * @param {Number} y 548 */ 549 fillText:function (strText, x, y) { 550 this._renderContext.fillText(strText, x, -y); 551 }, 552 553 /** 554 * set the drawing color with 4 unsigned bytes 555 * @param {Number} r red value (0 to 255) 556 * @param {Number} g green value (0 to 255) 557 * @param {Number} b blue value (0 to 255) 558 * @param {Number} a Alpha value (0 to 255) 559 */ 560 setDrawColor4B:function (r, g, b, a) { 561 this._renderContext.fillStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")"; 562 this._renderContext.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")"; 563 }, 564 565 /** 566 * set the drawing color with 4 floats 567 * @param {Number} r red value (0 to 1) 568 * @param {Number} g green value (0 to 1) 569 * @param {Number} b blue value (0 to 1) 570 * @param {Number} a Alpha value (0 to 1) 571 */ 572 setDrawColor4F:function (r, g, b, a) { 573 this._renderContext.fillStyle = "rgba(" + (0 | (r * 255)) + "," + (0 | (g * 255)) + "," + (0 | (b * 255)) + "," + a + ")"; 574 this._renderContext.strokeStyle = "rgba(" + (0 | (r * 255)) + "," + (0 | (g * 255)) + "," + (0 | (b * 255)) + "," + a + ")"; 575 }, 576 577 /** 578 * set the point size in points. Default 1. 579 * @param {Number} pointSize 580 */ 581 setPointSize:function (pointSize) { 582 }, 583 584 /** 585 * set the line width. Default 1. 586 * @param {Number} width 587 */ 588 setLineWidth:function (width) { 589 this._renderContext.lineWidth = width; 590 } 591 }); 592 593 /** 594 * Canvas of DrawingPrimitive implement version 595 * @class 596 * @extends cc.DrawingPrimitive 597 */ 598 cc.DrawingPrimitiveWebGL = cc.DrawingPrimitive.extend({ 599 _initialized:false, 600 _shader: null, 601 _colorLocation:-1, 602 _color: null, 603 _pointSizeLocation:-1, 604 _pointSize:-1, 605 606 ctor:function (ctx) { 607 if (ctx == null) 608 ctx = cc.renderContext; 609 610 if (!ctx instanceof WebGLRenderingContext) 611 throw "Can't initialise DrawingPrimitiveWebGL. context need is WebGLRenderingContext"; 612 613 cc.DrawingPrimitive.prototype.ctor.call(this, ctx); 614 this._color = new cc.Color4F(1.0, 1.0, 1.0, 1.0); 615 }, 616 617 lazy_init:function () { 618 if (!this._initialized) { 619 // 620 // Position and 1 color passed as a uniform (to similate glColor4ub ) 621 // 622 this._shader = cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_UCOLOR); 623 this._colorLocation = this._renderContext.getUniformLocation(this._shader.getProgram(), "u_color"); 624 this._pointSizeLocation = this._renderContext.getUniformLocation(this._shader.getProgram(), "u_pointSize"); 625 //cc.CHECK_GL_ERROR_DEBUG(); 626 627 this._initialized = true; 628 } 629 }, 630 631 /** 632 * initlialize context 633 */ 634 drawInit:function () { 635 this._initialized = false; 636 }, 637 638 /** 639 * draws a point given x and y coordinate measured in points 640 * @param {cc.Point} point 641 */ 642 drawPoint:function (point) { 643 this.lazy_init(); 644 645 this._shader.use(); 646 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 647 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 648 this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1); 649 this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize); 650 651 var glContext = this._renderContext; 652 var pointBuffer = glContext.createBuffer(); 653 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 654 glContext.bufferData(glContext.ARRAY_BUFFER, new Float32Array([point.x, point.y]), glContext.STATIC_DRAW); 655 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 656 657 glContext.drawArrays(glContext.POINTS, 0, 1); 658 glContext.deleteBuffer(pointBuffer); 659 660 cc.INCREMENT_GL_DRAWS(1); 661 }, 662 663 /** 664 * draws an array of points. 665 * @param {Array} points point of array 666 * @param {Number} numberOfPoints 667 */ 668 drawPoints:function (points, numberOfPoints) { 669 if (!points || points.length == 0) 670 return; 671 672 this.lazy_init(); 673 674 this._shader.use(); 675 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 676 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 677 this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1); 678 this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize); 679 680 var glContext = this._renderContext; 681 var pointBuffer = glContext.createBuffer(); 682 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 683 glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(points), glContext.STATIC_DRAW); 684 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 685 686 glContext.drawArrays(glContext.POINTS, 0, points.length); 687 glContext.deleteBuffer(pointBuffer); 688 689 cc.INCREMENT_GL_DRAWS(1); 690 }, 691 692 _pointsToTypeArray:function (points) { 693 var typeArr = new Float32Array(points.length * 2); 694 for (var i = 0; i < points.length; i++) { 695 typeArr[i * 2] = points[i].x; 696 typeArr[i * 2 + 1] = points[i].y; 697 } 698 return typeArr; 699 }, 700 701 /** 702 * draws a line given the origin and destination point measured in points 703 * @param {cc.Point} origin 704 * @param {cc.Point} destination 705 */ 706 drawLine:function (origin, destination) { 707 this.lazy_init(); 708 709 this._shader.use(); 710 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 711 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 712 this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1); 713 714 var glContext = this._renderContext; 715 var pointBuffer = glContext.createBuffer(); 716 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 717 glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray([origin, destination]), glContext.STATIC_DRAW); 718 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 719 720 glContext.drawArrays(glContext.LINES, 0, 2); 721 glContext.deleteBuffer(pointBuffer); 722 723 cc.INCREMENT_GL_DRAWS(1); 724 }, 725 726 /** 727 * draws a rectangle given the origin and destination point measured in points. 728 * @param {cc.Point} origin 729 * @param {cc.Point} destination 730 */ 731 drawRect:function (origin, destination) { 732 this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y)); 733 this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y)); 734 this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y)); 735 this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y)); 736 }, 737 738 /** 739 * draws a solid rectangle given the origin and destination point measured in points. 740 * @param {cc.Point} origin 741 * @param {cc.Point} destination 742 * @param {cc.Color4F} color 743 */ 744 drawSolidRect:function (origin, destination, color) { 745 var vertices = [ 746 origin, 747 cc.p(destination.x, origin.y), 748 destination, 749 cc.p(origin.x, destination.y) 750 ]; 751 752 this.drawSolidPoly(vertices, 4, color); 753 }, 754 755 /** 756 * draws a polygon given a pointer to cc.Point coordiantes and the number of vertices measured in points. 757 * @param {Array} vertices a pointer to cc.Point coordiantes 758 * @param {Number} numOfVertices the number of vertices measured in points 759 * @param {Boolean} closePolygon The polygon can be closed or open 760 */ 761 drawPoly:function (vertices, numOfVertices, closePolygon) { 762 this.lazy_init(); 763 764 this._shader.use(); 765 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 766 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 767 this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1); 768 769 var glContext = this._renderContext; 770 var pointBuffer = glContext.createBuffer(); 771 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 772 glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(vertices), glContext.STATIC_DRAW); 773 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 774 775 if (closePolygon) 776 glContext.drawArrays(glContext.LINE_LOOP, 0, vertices.length); 777 else 778 glContext.drawArrays(glContext.LINE_STRIP, 0, vertices.length); 779 glContext.deleteBuffer(pointBuffer); 780 781 cc.INCREMENT_GL_DRAWS(1); 782 }, 783 784 /** 785 * draws a solid polygon given a pointer to CGPoint coordiantes, the number of vertices measured in points, and a color. 786 * @param {Array} poli 787 * @param {Number} numberOfPoints 788 * @param {cc.Color4F} color 789 */ 790 drawSolidPoly:function (poli, numberOfPoints, color) { 791 this.lazy_init(); 792 if (!color) 793 color = this._color; 794 795 this._shader.use(); 796 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 797 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 798 this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(color._arrayBuffer,0,4), 1); 799 800 var glContext = this._renderContext; 801 var pointBuffer = glContext.createBuffer(); 802 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 803 glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(poli), glContext.STATIC_DRAW); 804 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 805 glContext.drawArrays(glContext.TRIANGLE_FAN, 0, poli.length); 806 glContext.deleteBuffer(pointBuffer); 807 808 cc.INCREMENT_GL_DRAWS(1); 809 }, 810 811 /** 812 * draws a circle given the center, radius and number of segments. 813 * @param {cc.Point} center center of circle 814 * @param {Number} radius 815 * @param {Number} angle angle in radians 816 * @param {Number} segments 817 * @param {Boolean} drawLineToCenter 818 */ 819 drawCircle:function (center, radius, angle, segments, drawLineToCenter) { 820 this.lazy_init(); 821 822 var additionalSegment = 1; 823 if (drawLineToCenter) 824 additionalSegment++; 825 826 var coef = 2.0 * Math.PI / segments; 827 828 var vertices = new Float32Array((segments + 2) * 2); 829 if (!vertices) 830 return; 831 832 for (var i = 0; i <= segments; i++) { 833 var rads = i * coef; 834 var j = radius * Math.cos(rads + angle) + center.x; 835 var k = radius * Math.sin(rads + angle) + center.y; 836 837 vertices[i * 2] = j; 838 vertices[i * 2 + 1] = k; 839 } 840 vertices[(segments + 1) * 2] = center.x; 841 vertices[(segments + 1) * 2 + 1] = center.y; 842 843 this._shader.use(); 844 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 845 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 846 this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1); 847 848 var glContext = this._renderContext; 849 var pointBuffer = glContext.createBuffer(); 850 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 851 glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW); 852 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 853 854 glContext.drawArrays(glContext.LINE_STRIP, 0, segments + additionalSegment); 855 glContext.deleteBuffer(pointBuffer); 856 857 cc.INCREMENT_GL_DRAWS(1); 858 }, 859 860 /** 861 * draws a quad bezier path 862 * @param {cc.Point} origin 863 * @param {cc.Point} control 864 * @param {cc.Point} destination 865 * @param {Number} segments 866 */ 867 drawQuadBezier:function (origin, control, destination, segments) { 868 this.lazy_init(); 869 870 var vertices = new Float32Array((segments + 1) * 2); 871 872 var t = 0.0; 873 for (var i = 0; i < segments; i++) { 874 vertices[i * 2] = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x; 875 vertices[i * 2 + 1] = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y; 876 t += 1.0 / segments; 877 } 878 vertices[segments * 2] = destination.x; 879 vertices[segments * 2 + 1] = destination.y; 880 881 this._shader.use(); 882 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 883 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 884 this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1); 885 886 var glContext = this._renderContext; 887 var pointBuffer = glContext.createBuffer(); 888 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 889 glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW); 890 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 891 892 glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1); 893 glContext.deleteBuffer(pointBuffer); 894 895 cc.INCREMENT_GL_DRAWS(1); 896 }, 897 898 /** 899 * draws a cubic bezier path 900 * @param {cc.Point} origin 901 * @param {cc.Point} control1 902 * @param {cc.Point} control2 903 * @param {cc.Point} destination 904 * @param {Number} segments 905 */ 906 drawCubicBezier:function (origin, control1, control2, destination, segments) { 907 this.lazy_init(); 908 909 var vertices = new Float32Array((segments + 1) * 2); 910 911 var t = 0; 912 for (var i = 0; i < segments; i++) { 913 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; 914 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; 915 t += 1.0 / segments; 916 } 917 vertices[segments * 2] = destination.x; 918 vertices[segments * 2 + 1] = destination.y; 919 920 this._shader.use(); 921 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 922 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 923 this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1); 924 925 var glContext = this._renderContext; 926 var pointBuffer = glContext.createBuffer(); 927 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 928 glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW); 929 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 930 glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1); 931 glContext.deleteBuffer(pointBuffer); 932 933 cc.INCREMENT_GL_DRAWS(1); 934 }, 935 936 /** 937 * draw a catmull rom line 938 * @param {Array} points 939 * @param {Number} segments 940 */ 941 drawCatmullRom:function (points, segments) { 942 this.drawCardinalSpline(points, 0.5, segments); 943 }, 944 945 /** 946 * draw a cardinal spline path 947 * @param {Array} config 948 * @param {Number} tension 949 * @param {Number} segments 950 */ 951 drawCardinalSpline:function (config, tension, segments) { 952 this.lazy_init(); 953 954 var vertices = new Float32Array((segments + 1) * 2); 955 var p, lt, deltaT = 1.0 / config.length; 956 for (var i = 0; i < segments + 1; i++) { 957 var dt = i / segments; 958 959 // border 960 if (dt == 1) { 961 p = config.length - 1; 962 lt = 1; 963 } else { 964 p = 0 | (dt / deltaT); 965 lt = (dt - deltaT * p) / deltaT; 966 } 967 968 var newPos = cc.CardinalSplineAt( 969 cc.getControlPointAt(config, p - 1), 970 cc.getControlPointAt(config, p), 971 cc.getControlPointAt(config, p + 1), 972 cc.getControlPointAt(config, p + 2), 973 tension, lt); 974 // Interpolate 975 976 vertices[i * 2] = newPos.x; 977 vertices[i * 2 + 1] = newPos.y; 978 } 979 980 this._shader.use(); 981 this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); 982 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); 983 this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1); 984 985 var glContext = this._renderContext; 986 var pointBuffer = glContext.createBuffer(); 987 glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer); 988 glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW); 989 glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0); 990 glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1); 991 glContext.deleteBuffer(pointBuffer); 992 993 cc.INCREMENT_GL_DRAWS(1); 994 }, 995 996 /** 997 * set the drawing color with 4 unsigned bytes 998 * @param {Number} r red value (0 to 255) 999 * @param {Number} g green value (0 to 255) 1000 * @param {Number} b blue value (0 to 255) 1001 * @param {Number} a Alpha value (0 to 255) 1002 */ 1003 setDrawColor4B:function (r, g, b, a) { 1004 this._color.r = r / 255.0; 1005 this._color.g = g / 255.0; 1006 this._color.b = b / 255.0; 1007 this._color.a = a / 255.0; 1008 }, 1009 1010 /** 1011 * set the drawing color with 4 floats 1012 * @param {Number} r red value (0 to 1) 1013 * @param {Number} g green value (0 to 1) 1014 * @param {Number} b blue value (0 to 1) 1015 * @param {Number} a Alpha value (0 to 1) 1016 */ 1017 setDrawColor4F:function (r, g, b, a) { 1018 this._color.r = r; 1019 this._color.g = g; 1020 this._color.b = b; 1021 this._color.a = a; 1022 }, 1023 1024 /** 1025 * set the point size in points. Default 1. 1026 * @param {Number} pointSize 1027 */ 1028 setPointSize:function (pointSize) { 1029 this._pointSize = pointSize * cc.CONTENT_SCALE_FACTOR(); 1030 }, 1031 1032 /** 1033 * set the line width. Default 1. 1034 * @param {Number} width 1035 */ 1036 setLineWidth:function (width) { 1037 if(this._renderContext.lineWidth) 1038 this._renderContext.lineWidth(width); 1039 } 1040 }); 1041 1042 cc.PI2 = Math.PI * 2; 1043