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