1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 Copyright (c) 2012 Scott Lembcke and Howling Moon Software 6 7 http://www.cocos2d-x.org 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ****************************************************************************/ 27 28 /** 29 * Code copied & pasted from SpacePatrol game https://github.com/slembcke/SpacePatrol 30 * 31 * Renamed and added some changes for cocos2d 32 * 33 */ 34 cc.v2fzero = function () { 35 return {x: 0, y: 0}; 36 }; 37 38 cc.v2f = function (x, y) { 39 return {x: x, y: y}; 40 }; 41 42 cc.v2fadd = function (v0, v1) { 43 return cc.v2f(v0.x + v1.x, v0.y + v1.y); 44 }; 45 46 cc.v2fsub = function (v0, v1) { 47 return cc.v2f(v0.x - v1.x, v0.y - v1.y); 48 }; 49 50 cc.v2fmult = function (v, s) { 51 return cc.v2f(v.x * s, v.y * s); 52 }; 53 54 cc.v2fperp = function (p0) { 55 return cc.v2f(-p0.y, p0.x); 56 }; 57 58 cc.v2fneg = function (p0) { 59 return cc.v2f(-p0.x, -p0.y); 60 }; 61 62 cc.v2fdot = function (p0, p1) { 63 return p0.x * p1.x + p0.y * p1.y; 64 }; 65 66 cc.v2fforangle = function (_a_) { 67 return cc.v2f(Math.cos(_a_), Math.sin(_a_)); 68 }; 69 70 cc.v2fnormalize = function (p) { 71 var r = cc.pNormalize(cc.p(p.x, p.y)); 72 return cc.v2f(r.x, r.y); 73 }; 74 75 cc.__v2f = function (v) { 76 return cc.v2f(v.x, v.y); 77 }; 78 79 cc.__t = function (v) { 80 return {u: v.x, v: v.y}; 81 }; 82 83 /** 84 * <p>CCDrawNode <br/> 85 * Node that draws dots, segments and polygons. <br/> 86 * Faster than the "drawing primitives" since they it draws everything in one single batch.</p> 87 * @class 88 * @name cc.DrawNode 89 * @extends cc.Node 90 */ 91 cc.DrawNodeCanvas = cc.Node.extend(/** @lends cc.DrawNode# */{ //TODO need refactor 92 _buffer: null, 93 _blendFunc: null, 94 _lineWidth: 1, 95 _drawColor: null, 96 _className:"DrawNodeCanvas", 97 98 /** 99 * <p>The cc.DrawNodeCanvas's constructor. <br/> 100 * This function will automatically be invoked when you create a node using new construction: "var node = new cc.DrawNodeCanvas()".<br/> 101 * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.</p> 102 */ 103 ctor: function () { 104 cc.Node.prototype.ctor.call(this); 105 var locCmd = this._renderCmd; 106 locCmd._buffer = this._buffer = []; 107 locCmd._drawColor = this._drawColor = cc.color(255, 255, 255, 255); 108 locCmd._blendFunc = this._blendFunc = new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA); 109 110 this.init(); 111 }, 112 113 // ----common function start ---- 114 /** 115 * Gets the blend func 116 * @returns {Object} 117 */ 118 getBlendFunc: function () { 119 return this._blendFunc; 120 }, 121 122 /** 123 * Set the blend func 124 * @param blendFunc 125 * @param dst 126 */ 127 setBlendFunc: function (blendFunc, dst) { 128 if (dst === undefined) { 129 this._blendFunc.src = blendFunc.src; 130 this._blendFunc.dst = blendFunc.dst; 131 } else { 132 this._blendFunc.src = blendFunc; 133 this._blendFunc.dst = dst; 134 } 135 }, 136 137 /** 138 * line width setter 139 * @param {Number} width 140 */ 141 setLineWidth: function (width) { 142 this._lineWidth = width; 143 }, 144 145 /** 146 * line width getter 147 * @returns {Number} 148 */ 149 getLineWidth: function () { 150 return this._lineWidth; 151 }, 152 153 /** 154 * draw color setter 155 * @param {cc.Color} color 156 */ 157 setDrawColor: function (color) { 158 var locDrawColor = this._drawColor; 159 locDrawColor.r = color.r; 160 locDrawColor.g = color.g; 161 locDrawColor.b = color.b; 162 locDrawColor.a = (color.a == null) ? 255 : color.a; 163 }, 164 165 /** 166 * draw color getter 167 * @returns {cc.Color} 168 */ 169 getDrawColor: function () { 170 return cc.color(this._drawColor.r, this._drawColor.g, this._drawColor.b, this._drawColor.a); 171 }, 172 // ----common function end ---- 173 174 175 /** 176 * draws a rectangle given the origin and destination point measured in points. 177 * @param {cc.Point} origin 178 * @param {cc.Point} destination 179 * @param {cc.Color} fillColor 180 * @param {Number} lineWidth 181 * @param {cc.Color} lineColor 182 */ 183 drawRect: function (origin, destination, fillColor, lineWidth, lineColor) { 184 lineWidth = (lineWidth == null) ? this._lineWidth : lineWidth; 185 lineColor = lineColor || this.getDrawColor(); 186 if(lineColor.a == null) 187 lineColor.a = 255; 188 189 var vertices = [ 190 origin, 191 cc.p(destination.x, origin.y), 192 destination, 193 cc.p(origin.x, destination.y) 194 ]; 195 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 196 element.verts = vertices; 197 element.lineWidth = lineWidth; 198 element.lineColor = lineColor; 199 element.isClosePolygon = true; 200 element.isStroke = true; 201 element.lineCap = "butt"; 202 element.fillColor = fillColor; 203 if (fillColor) { 204 if(fillColor.a == null) 205 fillColor.a = 255; 206 element.isFill = true; 207 } 208 this._buffer.push(element); 209 }, 210 211 /** 212 * draws a circle given the center, radius and number of segments. 213 * @override 214 * @param {cc.Point} center center of circle 215 * @param {Number} radius 216 * @param {Number} angle angle in radians 217 * @param {Number} segments 218 * @param {Boolean} drawLineToCenter 219 * @param {Number} lineWidth 220 * @param {cc.Color} color 221 */ 222 drawCircle: function (center, radius, angle, segments, drawLineToCenter, lineWidth, color) { 223 lineWidth = lineWidth || this._lineWidth; 224 color = color || this.getDrawColor(); 225 if (color.a == null) 226 color.a = 255; 227 228 var coef = 2.0 * Math.PI / segments; 229 var vertices = []; 230 for (var i = 0; i <= segments; i++) { 231 var rads = i * coef; 232 var j = radius * Math.cos(rads + angle) + center.x; 233 var k = radius * Math.sin(rads + angle) + center.y; 234 vertices.push(cc.p(j, k)); 235 } 236 if (drawLineToCenter) { 237 vertices.push(cc.p(center.x, center.y)); 238 } 239 240 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 241 element.verts = vertices; 242 element.lineWidth = lineWidth; 243 element.lineColor = color; 244 element.isClosePolygon = true; 245 element.isStroke = true; 246 this._buffer.push(element); 247 }, 248 249 /** 250 * draws a quad bezier path 251 * @override 252 * @param {cc.Point} origin 253 * @param {cc.Point} control 254 * @param {cc.Point} destination 255 * @param {Number} segments 256 * @param {Number} lineWidth 257 * @param {cc.Color} color 258 */ 259 drawQuadBezier: function (origin, control, destination, segments, lineWidth, color) { 260 lineWidth = lineWidth || this._lineWidth; 261 color = color || this.getDrawColor(); 262 if (color.a == null) 263 color.a = 255; 264 265 var vertices = [], t = 0.0; 266 for (var i = 0; i < segments; i++) { 267 var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x; 268 var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y; 269 vertices.push(cc.p(x, y)); 270 t += 1.0 / segments; 271 } 272 vertices.push(cc.p(destination.x, destination.y)); 273 274 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 275 element.verts = vertices; 276 element.lineWidth = lineWidth; 277 element.lineColor = color; 278 element.isStroke = true; 279 element.lineCap = "round"; 280 this._buffer.push(element); 281 }, 282 283 /** 284 * draws a cubic bezier path 285 * @override 286 * @param {cc.Point} origin 287 * @param {cc.Point} control1 288 * @param {cc.Point} control2 289 * @param {cc.Point} destination 290 * @param {Number} segments 291 * @param {Number} lineWidth 292 * @param {cc.Color} color 293 */ 294 drawCubicBezier: function (origin, control1, control2, destination, segments, lineWidth, color) { 295 lineWidth = lineWidth || this._lineWidth; 296 color = color || this.getDrawColor(); 297 if (color.a == null) 298 color.a = 255; 299 300 var vertices = [], t = 0; 301 for (var i = 0; i < segments; i++) { 302 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; 303 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; 304 vertices.push(cc.p(x, y)); 305 t += 1.0 / segments; 306 } 307 vertices.push(cc.p(destination.x, destination.y)); 308 309 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 310 element.verts = vertices; 311 element.lineWidth = lineWidth; 312 element.lineColor = color; 313 element.isStroke = true; 314 element.lineCap = "round"; 315 this._buffer.push(element); 316 }, 317 318 /** 319 * draw a CatmullRom curve 320 * @override 321 * @param {Array} points 322 * @param {Number} segments 323 * @param {Number} lineWidth 324 * @param {cc.Color} color 325 */ 326 drawCatmullRom: function (points, segments, lineWidth, color) { 327 this.drawCardinalSpline(points, 0.5, segments, lineWidth, color); 328 }, 329 330 /** 331 * draw a cardinal spline path 332 * @override 333 * @param {Array} config 334 * @param {Number} tension 335 * @param {Number} segments 336 * @param {Number} lineWidth 337 * @param {cc.Color} color 338 */ 339 drawCardinalSpline: function (config, tension, segments, lineWidth, color) { 340 lineWidth = lineWidth || this._lineWidth; 341 color = color || this.getDrawColor(); 342 if(color.a == null) 343 color.a = 255; 344 345 var vertices = [], p, lt, deltaT = 1.0 / config.length; 346 for (var i = 0; i < segments + 1; i++) { 347 var dt = i / segments; 348 // border 349 if (dt === 1) { 350 p = config.length - 1; 351 lt = 1; 352 } else { 353 p = 0 | (dt / deltaT); 354 lt = (dt - deltaT * p) / deltaT; 355 } 356 357 // Interpolate 358 var newPos = cc.cardinalSplineAt( 359 cc.getControlPointAt(config, p - 1), 360 cc.getControlPointAt(config, p - 0), 361 cc.getControlPointAt(config, p + 1), 362 cc.getControlPointAt(config, p + 2), 363 tension, lt); 364 vertices.push(newPos); 365 } 366 367 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 368 element.verts = vertices; 369 element.lineWidth = lineWidth; 370 element.lineColor = color; 371 element.isStroke = true; 372 element.lineCap = "round"; 373 this._buffer.push(element); 374 }, 375 376 /** 377 * draw a dot at a position, with a given radius and color 378 * @param {cc.Point} pos 379 * @param {Number} radius 380 * @param {cc.Color} color 381 */ 382 drawDot: function (pos, radius, color) { 383 color = color || this.getDrawColor(); 384 if (color.a == null) 385 color.a = 255; 386 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_DOT); 387 element.verts = [pos]; 388 element.lineWidth = radius; 389 element.fillColor = color; 390 this._buffer.push(element); 391 }, 392 393 /** 394 * draws an array of points. 395 * @override 396 * @param {Array} points point of array 397 * @param {Number} radius 398 * @param {cc.Color} color 399 */ 400 drawDots: function(points, radius, color){ 401 if(!points || points.length == 0) 402 return; 403 color = color || this.getDrawColor(); 404 if (color.a == null) 405 color.a = 255; 406 for(var i = 0, len = points.length; i < len; i++) 407 this.drawDot(points[i], radius, color); 408 }, 409 410 /** 411 * draw a segment with a radius and color 412 * @param {cc.Point} from 413 * @param {cc.Point} to 414 * @param {Number} lineWidth 415 * @param {cc.Color} color 416 */ 417 drawSegment: function (from, to, lineWidth, color) { 418 lineWidth = lineWidth || this._lineWidth; 419 color = color || this.getDrawColor(); 420 if (color.a == null) 421 color.a = 255; 422 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 423 element.verts = [from, to]; 424 element.lineWidth = lineWidth * 2; 425 element.lineColor = color; 426 element.isStroke = true; 427 element.lineCap = "round"; 428 this._buffer.push(element); 429 }, 430 431 /** 432 * draw a polygon with a fill color and line color without copying the vertex list 433 * @param {Array} verts 434 * @param {cc.Color} fillColor 435 * @param {Number} lineWidth 436 * @param {cc.Color} color 437 */ 438 drawPoly_: function (verts, fillColor, lineWidth, color) { 439 lineWidth = (lineWidth == null ) ? this._lineWidth : lineWidth; 440 color = color || this.getDrawColor(); 441 if (color.a == null) 442 color.a = 255; 443 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 444 445 element.verts = verts; 446 element.fillColor = fillColor; 447 element.lineWidth = lineWidth; 448 element.lineColor = color; 449 element.isClosePolygon = true; 450 element.isStroke = true; 451 element.lineCap = "round"; 452 if (fillColor) 453 element.isFill = true; 454 this._buffer.push(element); 455 }, 456 457 /** 458 * draw a polygon with a fill color and line color, copying the vertex list 459 * @param {Array} verts 460 * @param {cc.Color} fillColor 461 * @param {Number} lineWidth 462 * @param {cc.Color} color 463 */ 464 drawPoly: function (verts, fillColor, lineWidth, color) { 465 var vertsCopy = []; 466 for (var i=0; i < verts.length; i++) { 467 vertsCopy.push(cc.p(verts[i].x, verts[i].y)); 468 } 469 return this.drawPoly_(vertsCopy, fillColor, lineWidth, color); 470 }, 471 472 /** 473 * Clear the geometry in the node's buffer. 474 */ 475 clear: function () { 476 this._buffer.length = 0; 477 }, 478 479 _createRenderCmd: function(){ 480 return new cc.DrawNode.CanvasRenderCmd(this); 481 } 482 }); 483 484 //Just only a note 485 cc.DrawNodeWebGL = cc.Node.extend({ 486 _bufferCapacity:0, 487 _buffer:null, 488 489 _trianglesArrayBuffer:null, 490 _trianglesWebBuffer:null, 491 _trianglesReader:null, 492 493 _lineWidth: 1, 494 _drawColor: null, 495 496 _blendFunc:null, 497 _dirty:false, 498 _className:"DrawNodeWebGL", 499 500 // ----common function start ---- 501 getBlendFunc:function () { 502 return this._blendFunc; 503 }, 504 505 setBlendFunc:function (blendFunc, dst) { 506 if (dst === undefined) { 507 this._blendFunc.src = blendFunc.src; 508 this._blendFunc.dst = blendFunc.dst; 509 } else { 510 this._blendFunc.src = blendFunc; 511 this._blendFunc.dst = dst; 512 } 513 }, 514 // ----common function end ---- 515 516 ctor:function () { 517 cc.Node.prototype.ctor.call(this); 518 this._buffer = []; 519 this._blendFunc = new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA); 520 this._drawColor = cc.color(255,255,255,255); 521 522 this.init(); 523 }, 524 525 init:function () { 526 if (cc.Node.prototype.init.call(this)) { 527 this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_LENGTHTEXTURECOLOR); 528 this._ensureCapacity(64); 529 this._trianglesWebBuffer = cc._renderContext.createBuffer(); 530 this._dirty = true; 531 return true; 532 } 533 return false; 534 }, 535 536 setLineWidth: function (width) { 537 this._lineWidth = width; 538 }, 539 540 getLineWidth: function () { 541 return this._lineWidth; 542 }, 543 544 setDrawColor: function (color) { 545 var locDrawColor = this._drawColor; 546 locDrawColor.r = color.r; 547 locDrawColor.g = color.g; 548 locDrawColor.b = color.b; 549 locDrawColor.a = color.a; 550 }, 551 552 getDrawColor: function () { 553 return cc.color(this._drawColor.r, this._drawColor.g, this._drawColor.b, this._drawColor.a); 554 }, 555 556 drawRect: function (origin, destination, fillColor, lineWidth, lineColor) { 557 lineWidth = (lineWidth == null) ? this._lineWidth : lineWidth; 558 lineColor = lineColor || this.getDrawColor(); 559 if (lineColor.a == null) 560 lineColor.a = 255; 561 var vertices = [origin, cc.p(destination.x, origin.y), destination, cc.p(origin.x, destination.y)]; 562 if(fillColor == null) 563 this._drawSegments(vertices, lineWidth, lineColor, true); 564 else 565 this.drawPoly(vertices, fillColor, lineWidth, lineColor); 566 }, 567 568 drawCircle: function (center, radius, angle, segments, drawLineToCenter, lineWidth, color) { 569 lineWidth = lineWidth || this._lineWidth; 570 color = color || this.getDrawColor(); 571 if (color.a == null) 572 color.a = 255; 573 var coef = 2.0 * Math.PI / segments, vertices = [], i, len; 574 for (i = 0; i <= segments; i++) { 575 var rads = i * coef; 576 var j = radius * Math.cos(rads + angle) + center.x; 577 var k = radius * Math.sin(rads + angle) + center.y; 578 vertices.push(cc.p(j, k)); 579 } 580 if (drawLineToCenter) 581 vertices.push(cc.p(center.x, center.y)); 582 583 lineWidth *= 0.5; 584 for (i = 0, len = vertices.length; i < len - 1; i++) 585 this.drawSegment(vertices[i], vertices[i + 1], lineWidth, color); 586 }, 587 588 drawQuadBezier: function (origin, control, destination, segments, lineWidth, color) { 589 lineWidth = lineWidth || this._lineWidth; 590 color = color || this.getDrawColor(); 591 if (color.a == null) 592 color.a = 255; 593 var vertices = [], t = 0.0; 594 for (var i = 0; i < segments; i++) { 595 var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x; 596 var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y; 597 vertices.push(cc.p(x, y)); 598 t += 1.0 / segments; 599 } 600 vertices.push(cc.p(destination.x, destination.y)); 601 this._drawSegments(vertices, lineWidth, color, false); 602 }, 603 604 drawCubicBezier: function (origin, control1, control2, destination, segments, lineWidth, color) { 605 lineWidth = lineWidth || this._lineWidth; 606 color = color || this.getDrawColor(); 607 if (color.a == null) 608 color.a = 255; 609 var vertices = [], t = 0; 610 for (var i = 0; i < segments; i++) { 611 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; 612 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; 613 vertices.push(cc.p(x, y)); 614 t += 1.0 / segments; 615 } 616 vertices.push(cc.p(destination.x, destination.y)); 617 this._drawSegments(vertices, lineWidth, color, false); 618 }, 619 620 drawCatmullRom: function (points, segments, lineWidth, color) { 621 this.drawCardinalSpline(points, 0.5, segments, lineWidth, color); 622 }, 623 624 drawCardinalSpline: function (config, tension, segments, lineWidth, color) { 625 lineWidth = lineWidth || this._lineWidth; 626 color = color || this.getDrawColor(); 627 if (color.a == null) 628 color.a = 255; 629 var vertices = [], p, lt, deltaT = 1.0 / config.length; 630 631 for (var i = 0; i < segments + 1; i++) { 632 var dt = i / segments; 633 634 // border 635 if (dt === 1) { 636 p = config.length - 1; 637 lt = 1; 638 } else { 639 p = 0 | (dt / deltaT); 640 lt = (dt - deltaT * p) / deltaT; 641 } 642 643 // Interpolate 644 var newPos = cc.cardinalSplineAt( 645 cc.getControlPointAt(config, p - 1), 646 cc.getControlPointAt(config, p - 0), 647 cc.getControlPointAt(config, p + 1), 648 cc.getControlPointAt(config, p + 2), 649 tension, lt); 650 vertices.push(newPos); 651 } 652 653 lineWidth *= 0.5; 654 for (var j = 0, len = vertices.length; j < len - 1; j++) 655 this.drawSegment(vertices[j], vertices[j + 1], lineWidth, color); 656 }, 657 658 _render:function () { 659 var gl = cc._renderContext; 660 661 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); 662 gl.bindBuffer(gl.ARRAY_BUFFER, this._trianglesWebBuffer); 663 if (this._dirty) { 664 gl.bufferData(gl.ARRAY_BUFFER, this._trianglesArrayBuffer, gl.STREAM_DRAW); 665 this._dirty = false; 666 } 667 var triangleSize = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT; 668 669 // vertex 670 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, triangleSize, 0); 671 // color 672 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, triangleSize, 8); 673 // texcood 674 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, triangleSize, 12); 675 676 gl.drawArrays(gl.TRIANGLES, 0, this._buffer.length * 3); 677 cc.incrementGLDraws(1); 678 //cc.checkGLErrorDebug(); 679 }, 680 681 _ensureCapacity:function(count){ 682 var _t = this; 683 var locBuffer = _t._buffer; 684 if(locBuffer.length + count > _t._bufferCapacity){ 685 var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT; 686 _t._bufferCapacity += Math.max(_t._bufferCapacity, count); 687 //re alloc 688 if((locBuffer == null) || (locBuffer.length === 0)){ 689 //init 690 _t._buffer = []; 691 _t._trianglesArrayBuffer = new ArrayBuffer(TriangleLength * _t._bufferCapacity); 692 _t._trianglesReader = new Uint8Array(_t._trianglesArrayBuffer); 693 } else { 694 var newTriangles = []; 695 var newArrayBuffer = new ArrayBuffer(TriangleLength * _t._bufferCapacity); 696 for(var i = 0; i < locBuffer.length;i++){ 697 newTriangles[i] = new cc.V2F_C4B_T2F_Triangle(locBuffer[i].a,locBuffer[i].b,locBuffer[i].c, 698 newArrayBuffer, i * TriangleLength); 699 } 700 _t._trianglesReader = new Uint8Array(newArrayBuffer); 701 _t._trianglesArrayBuffer = newArrayBuffer; 702 _t._buffer = newTriangles; 703 } 704 } 705 }, 706 707 drawDot:function (pos, radius, color) { 708 color = color || this.getDrawColor(); 709 if (color.a == null) 710 color.a = 255; 711 var c4bColor = {r: 0 | color.r, g: 0 | color.g, b: 0 | color.b, a: 0 | color.a}; 712 var a = {vertices: {x: pos.x - radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: -1.0, v: -1.0}}; 713 var b = {vertices: {x: pos.x - radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: -1.0, v: 1.0}}; 714 var c = {vertices: {x: pos.x + radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: 1.0, v: 1.0}}; 715 var d = {vertices: {x: pos.x + radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: 1.0, v: -1.0}}; 716 717 this._ensureCapacity(2*3); 718 719 this._buffer.push(new cc.V2F_C4B_T2F_Triangle(a, b, c, this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); 720 this._buffer.push(new cc.V2F_C4B_T2F_Triangle(a, c, d, this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); 721 this._dirty = true; 722 }, 723 724 drawDots: function(points, radius,color) { 725 if(!points || points.length === 0) 726 return; 727 color = color || this.getDrawColor(); 728 if (color.a == null) 729 color.a = 255; 730 for(var i = 0, len = points.length; i < len; i++) 731 this.drawDot(points[i], radius, color); 732 }, 733 734 drawSegment:function (from, to, radius, color) { 735 color = color || this.getDrawColor(); 736 if (color.a == null) 737 color.a = 255; 738 radius = radius || (this._lineWidth * 0.5); 739 var vertexCount = 6*3; 740 this._ensureCapacity(vertexCount); 741 742 var c4bColor = {r: 0 | color.r, g: 0 | color.g, b: 0 | color.b, a: 0 | color.a}; 743 var a = cc.__v2f(from), b = cc.__v2f(to); 744 var n = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(b, a))), t = cc.v2fperp(n); 745 var nw = cc.v2fmult(n, radius), tw = cc.v2fmult(t, radius); 746 747 var v0 = cc.v2fsub(b, cc.v2fadd(nw, tw)); 748 var v1 = cc.v2fadd(b, cc.v2fsub(nw, tw)); 749 var v2 = cc.v2fsub(b, nw); 750 var v3 = cc.v2fadd(b, nw); 751 var v4 = cc.v2fsub(a, nw); 752 var v5 = cc.v2fadd(a, nw); 753 var v6 = cc.v2fsub(a, cc.v2fsub(nw, tw)); 754 var v7 = cc.v2fadd(a, cc.v2fadd(nw, tw)); 755 756 var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, triangleBuffer = this._trianglesArrayBuffer, locBuffer = this._buffer; 757 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(cc.v2fadd(n, t)))}, 758 {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, 759 triangleBuffer, locBuffer.length * TriangleLength)); 760 761 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, 762 {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, 763 triangleBuffer, locBuffer.length * TriangleLength)); 764 765 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, 766 {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, 767 triangleBuffer, locBuffer.length * TriangleLength)); 768 769 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, 770 {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, 771 triangleBuffer, locBuffer.length * TriangleLength)); 772 773 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))}, 774 {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, 775 triangleBuffer, locBuffer.length * TriangleLength)); 776 777 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))}, 778 {vertices: v7, colors: c4bColor, texCoords: cc.__t(cc.v2fadd(n, t))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, 779 triangleBuffer, locBuffer.length * TriangleLength)); 780 this._dirty = true; 781 }, 782 783 drawPoly:function (verts, fillColor, borderWidth, borderColor) { 784 if(fillColor == null){ 785 this._drawSegments(verts, borderWidth, borderColor, true); 786 return; 787 } 788 if (fillColor.a == null) 789 fillColor.a = 255; 790 if (borderColor.a == null) 791 borderColor.a = 255; 792 borderWidth = (borderWidth == null)? this._lineWidth : borderWidth; 793 borderWidth *= 0.5; 794 var c4bFillColor = {r: 0 | fillColor.r, g: 0 | fillColor.g, b: 0 | fillColor.b, a: 0 | fillColor.a}; 795 var c4bBorderColor = {r: 0 | borderColor.r, g: 0 | borderColor.g, b: 0 | borderColor.b, a: 0 | borderColor.a}; 796 var extrude = [], i, v0, v1, v2, count = verts.length; 797 for (i = 0; i < count; i++) { 798 v0 = cc.__v2f(verts[(i - 1 + count) % count]); 799 v1 = cc.__v2f(verts[i]); 800 v2 = cc.__v2f(verts[(i + 1) % count]); 801 var n1 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v1, v0))); 802 var n2 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v2, v1))); 803 var offset = cc.v2fmult(cc.v2fadd(n1, n2), 1.0 / (cc.v2fdot(n1, n2) + 1.0)); 804 extrude[i] = {offset: offset, n: n2}; 805 } 806 var outline = (borderWidth > 0.0), triangleCount = 3 * count - 2, vertexCount = 3 * triangleCount; 807 this._ensureCapacity(vertexCount); 808 809 var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer; 810 var locBuffer = this._buffer; 811 var inset = (outline == false ? 0.5 : 0.0); 812 for (i = 0; i < count - 2; i++) { 813 v0 = cc.v2fsub(cc.__v2f(verts[0]), cc.v2fmult(extrude[0].offset, inset)); 814 v1 = cc.v2fsub(cc.__v2f(verts[i + 1]), cc.v2fmult(extrude[i + 1].offset, inset)); 815 v2 = cc.v2fsub(cc.__v2f(verts[i + 2]), cc.v2fmult(extrude[i + 2].offset, inset)); 816 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 817 {vertices: v1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: v2, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 818 trianglesBuffer, locBuffer.length * triangleBytesLen)); 819 } 820 821 for (i = 0; i < count; i++) { 822 var j = (i + 1) % count; 823 v0 = cc.__v2f(verts[i]); 824 v1 = cc.__v2f(verts[j]); 825 826 var n0 = extrude[i].n; 827 var offset0 = extrude[i].offset; 828 var offset1 = extrude[j].offset; 829 var inner0 = outline ? cc.v2fsub(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fsub(v0, cc.v2fmult(offset0, 0.5)); 830 var inner1 = outline ? cc.v2fsub(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fsub(v1, cc.v2fmult(offset1, 0.5)); 831 var outer0 = outline ? cc.v2fadd(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fadd(v0, cc.v2fmult(offset0, 0.5)); 832 var outer1 = outline ? cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fadd(v1, cc.v2fmult(offset1, 0.5)); 833 834 if (outline) { 835 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 836 {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 837 trianglesBuffer, locBuffer.length * triangleBytesLen)); 838 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 839 {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 840 trianglesBuffer, locBuffer.length * triangleBytesLen)); 841 } else { 842 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 843 {vertices: inner1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)}, 844 trianglesBuffer, locBuffer.length * triangleBytesLen)); 845 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 846 {vertices: outer0, colors: c4bFillColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)}, 847 trianglesBuffer, locBuffer.length * triangleBytesLen)); 848 } 849 } 850 extrude = null; 851 this._dirty = true; 852 }, 853 854 _drawSegments: function(verts, borderWidth, borderColor, closePoly){ 855 borderWidth = (borderWidth == null) ? this._lineWidth : borderWidth; 856 borderColor = borderColor || this._drawColor; 857 if(borderColor.a == null) 858 borderColor.a = 255; 859 borderWidth *= 0.5; 860 if (borderWidth <= 0) 861 return; 862 863 var c4bBorderColor = {r: 0 | borderColor.r, g: 0 | borderColor.g, b: 0 | borderColor.b, a: 0 | borderColor.a }; 864 var extrude = [], i, v0, v1, v2, count = verts.length; 865 for (i = 0; i < count; i++) { 866 v0 = cc.__v2f(verts[(i - 1 + count) % count]); 867 v1 = cc.__v2f(verts[i]); 868 v2 = cc.__v2f(verts[(i + 1) % count]); 869 var n1 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v1, v0))); 870 var n2 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v2, v1))); 871 var offset = cc.v2fmult(cc.v2fadd(n1, n2), 1.0 / (cc.v2fdot(n1, n2) + 1.0)); 872 extrude[i] = {offset: offset, n: n2}; 873 } 874 875 var triangleCount = 3 * count - 2, vertexCount = 3 * triangleCount; 876 this._ensureCapacity(vertexCount); 877 878 var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer; 879 var locBuffer = this._buffer; 880 var len = closePoly ? count : count - 1; 881 for (i = 0; i < len; i++) { 882 var j = (i + 1) % count; 883 v0 = cc.__v2f(verts[i]); 884 v1 = cc.__v2f(verts[j]); 885 886 var n0 = extrude[i].n; 887 var offset0 = extrude[i].offset; 888 var offset1 = extrude[j].offset; 889 var inner0 = cc.v2fsub(v0, cc.v2fmult(offset0, borderWidth)); 890 var inner1 = cc.v2fsub(v1, cc.v2fmult(offset1, borderWidth)); 891 var outer0 = cc.v2fadd(v0, cc.v2fmult(offset0, borderWidth)); 892 var outer1 = cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth)); 893 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 894 {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 895 trianglesBuffer, locBuffer.length * triangleBytesLen)); 896 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 897 {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 898 trianglesBuffer, locBuffer.length * triangleBytesLen)); 899 } 900 extrude = null; 901 this._dirty = true; 902 }, 903 904 clear:function () { 905 this._buffer.length = 0; 906 this._dirty = true; 907 }, 908 909 _createRenderCmd: function () { 910 return new cc.DrawNode.WebGLRenderCmd(this); 911 } 912 }); 913 914 cc.DrawNode = cc._renderType === cc._RENDER_TYPE_WEBGL ? cc.DrawNodeWebGL : cc.DrawNodeCanvas; 915 916 /** 917 * Creates a DrawNode 918 * @deprecated since v3.0 please use new cc.DrawNode() instead. 919 * @return {cc.DrawNode} 920 */ 921 cc.DrawNode.create = function () { 922 return new cc.DrawNode(); 923 }; 924 925 cc._DrawNodeElement = function (type, verts, fillColor, lineWidth, lineColor, lineCap, isClosePolygon, isFill, isStroke) { 926 var _t = this; 927 _t.type = type; 928 _t.verts = verts || null; 929 _t.fillColor = fillColor || null; 930 _t.lineWidth = lineWidth || 0; 931 _t.lineColor = lineColor || null; 932 _t.lineCap = lineCap || "butt"; 933 _t.isClosePolygon = isClosePolygon || false; 934 _t.isFill = isFill || false; 935 _t.isStroke = isStroke || false; 936 }; 937 938 cc.DrawNode.TYPE_DOT = 0; 939 cc.DrawNode.TYPE_SEGMENT = 1; 940 cc.DrawNode.TYPE_POLY = 2; 941