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 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|null} fillColor Fill color or `null` for a hollow polygon. 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|null} fillColor Fill color or `null` for a hollow polygon. 492 * @param {Number} [lineWidth] 493 * @param {cc.Color} [lineColor] 494 */ 495 drawPoly: function (verts, fillColor, lineWidth, lineColor) { 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, lineColor); 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 gl.bindBuffer(gl.ARRAY_BUFFER, this._trianglesWebBuffer); 653 if (this._dirty) { 654 gl.bufferData(gl.ARRAY_BUFFER, this._trianglesArrayBuffer, gl.STREAM_DRAW); 655 this._dirty = false; 656 } 657 var triangleSize = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT; 658 659 gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); 660 gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR); 661 gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS); 662 663 // vertex 664 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, triangleSize, 0); 665 // color 666 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, triangleSize, 8); 667 // texcood 668 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, triangleSize, 12); 669 670 gl.drawArrays(gl.TRIANGLES, 0, this._buffer.length * 3); 671 cc.incrementGLDraws(1); 672 //cc.checkGLErrorDebug(); 673 }, 674 675 _ensureCapacity:function(count){ 676 var _t = this; 677 var locBuffer = _t._buffer; 678 if(locBuffer.length + count > _t._bufferCapacity){ 679 var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT; 680 _t._bufferCapacity += Math.max(_t._bufferCapacity, count); 681 //re alloc 682 if((locBuffer == null) || (locBuffer.length === 0)){ 683 //init 684 _t._buffer = []; 685 _t._trianglesArrayBuffer = new ArrayBuffer(TriangleLength * _t._bufferCapacity); 686 _t._trianglesReader = new Uint8Array(_t._trianglesArrayBuffer); 687 } else { 688 var newTriangles = []; 689 var newArrayBuffer = new ArrayBuffer(TriangleLength * _t._bufferCapacity); 690 for(var i = 0; i < locBuffer.length;i++){ 691 newTriangles[i] = new cc.V2F_C4B_T2F_Triangle(locBuffer[i].a,locBuffer[i].b,locBuffer[i].c, 692 newArrayBuffer, i * TriangleLength); 693 } 694 _t._trianglesReader = new Uint8Array(newArrayBuffer); 695 _t._trianglesArrayBuffer = newArrayBuffer; 696 _t._buffer = newTriangles; 697 } 698 } 699 }, 700 701 drawDot:function (pos, radius, color) { 702 color = color || this.getDrawColor(); 703 if (color.a == null) 704 color.a = 255; 705 var c4bColor = {r: 0 | color.r, g: 0 | color.g, b: 0 | color.b, a: 0 | color.a}; 706 var a = {vertices: {x: pos.x - radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: -1.0, v: -1.0}}; 707 var b = {vertices: {x: pos.x - radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: -1.0, v: 1.0}}; 708 var c = {vertices: {x: pos.x + radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: 1.0, v: 1.0}}; 709 var d = {vertices: {x: pos.x + radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: 1.0, v: -1.0}}; 710 711 this._ensureCapacity(2*3); 712 713 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)); 714 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)); 715 this._dirty = true; 716 }, 717 718 drawDots: function(points, radius,color) { 719 if(!points || points.length === 0) 720 return; 721 color = color || this.getDrawColor(); 722 if (color.a == null) 723 color.a = 255; 724 for(var i = 0, len = points.length; i < len; i++) 725 this.drawDot(points[i], radius, color); 726 }, 727 728 drawSegment:function (from, to, radius, color) { 729 color = color || this.getDrawColor(); 730 if (color.a == null) 731 color.a = 255; 732 radius = radius || (this._lineWidth * 0.5); 733 var vertexCount = 6*3; 734 this._ensureCapacity(vertexCount); 735 736 var c4bColor = {r: 0 | color.r, g: 0 | color.g, b: 0 | color.b, a: 0 | color.a}; 737 var a = cc.__v2f(from), b = cc.__v2f(to); 738 var n = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(b, a))), t = cc.v2fperp(n); 739 var nw = cc.v2fmult(n, radius), tw = cc.v2fmult(t, radius); 740 741 var v0 = cc.v2fsub(b, cc.v2fadd(nw, tw)); 742 var v1 = cc.v2fadd(b, cc.v2fsub(nw, tw)); 743 var v2 = cc.v2fsub(b, nw); 744 var v3 = cc.v2fadd(b, nw); 745 var v4 = cc.v2fsub(a, nw); 746 var v5 = cc.v2fadd(a, nw); 747 var v6 = cc.v2fsub(a, cc.v2fsub(nw, tw)); 748 var v7 = cc.v2fadd(a, cc.v2fadd(nw, tw)); 749 750 var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, triangleBuffer = this._trianglesArrayBuffer, locBuffer = this._buffer; 751 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(cc.v2fadd(n, t)))}, 752 {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, 753 triangleBuffer, locBuffer.length * TriangleLength)); 754 755 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, 756 {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, 757 triangleBuffer, locBuffer.length * TriangleLength)); 758 759 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, 760 {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, 761 triangleBuffer, locBuffer.length * TriangleLength)); 762 763 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, 764 {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, 765 triangleBuffer, locBuffer.length * TriangleLength)); 766 767 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))}, 768 {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, 769 triangleBuffer, locBuffer.length * TriangleLength)); 770 771 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))}, 772 {vertices: v7, colors: c4bColor, texCoords: cc.__t(cc.v2fadd(n, t))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, 773 triangleBuffer, locBuffer.length * TriangleLength)); 774 this._dirty = true; 775 }, 776 777 drawPoly:function (verts, fillColor, borderWidth, borderColor) { 778 if(fillColor == null){ 779 this._drawSegments(verts, borderWidth, borderColor, true); 780 return; 781 } 782 if (fillColor.a == null) 783 fillColor.a = 255; 784 if (borderColor.a == null) 785 borderColor.a = 255; 786 borderWidth = (borderWidth == null)? this._lineWidth : borderWidth; 787 borderWidth *= 0.5; 788 var c4bFillColor = {r: 0 | fillColor.r, g: 0 | fillColor.g, b: 0 | fillColor.b, a: 0 | fillColor.a}; 789 var c4bBorderColor = {r: 0 | borderColor.r, g: 0 | borderColor.g, b: 0 | borderColor.b, a: 0 | borderColor.a}; 790 var extrude = [], i, v0, v1, v2, count = verts.length; 791 for (i = 0; i < count; i++) { 792 v0 = cc.__v2f(verts[(i - 1 + count) % count]); 793 v1 = cc.__v2f(verts[i]); 794 v2 = cc.__v2f(verts[(i + 1) % count]); 795 var n1 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v1, v0))); 796 var n2 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v2, v1))); 797 var offset = cc.v2fmult(cc.v2fadd(n1, n2), 1.0 / (cc.v2fdot(n1, n2) + 1.0)); 798 extrude[i] = {offset: offset, n: n2}; 799 } 800 var outline = (borderWidth > 0.0), triangleCount = 3 * count - 2, vertexCount = 3 * triangleCount; 801 this._ensureCapacity(vertexCount); 802 803 var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer; 804 var locBuffer = this._buffer; 805 var inset = (outline == false ? 0.5 : 0.0); 806 for (i = 0; i < count - 2; i++) { 807 v0 = cc.v2fsub(cc.__v2f(verts[0]), cc.v2fmult(extrude[0].offset, inset)); 808 v1 = cc.v2fsub(cc.__v2f(verts[i + 1]), cc.v2fmult(extrude[i + 1].offset, inset)); 809 v2 = cc.v2fsub(cc.__v2f(verts[i + 2]), cc.v2fmult(extrude[i + 2].offset, inset)); 810 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 811 {vertices: v1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: v2, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 812 trianglesBuffer, locBuffer.length * triangleBytesLen)); 813 } 814 815 for (i = 0; i < count; i++) { 816 var j = (i + 1) % count; 817 v0 = cc.__v2f(verts[i]); 818 v1 = cc.__v2f(verts[j]); 819 820 var n0 = extrude[i].n; 821 var offset0 = extrude[i].offset; 822 var offset1 = extrude[j].offset; 823 var inner0 = outline ? cc.v2fsub(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fsub(v0, cc.v2fmult(offset0, 0.5)); 824 var inner1 = outline ? cc.v2fsub(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fsub(v1, cc.v2fmult(offset1, 0.5)); 825 var outer0 = outline ? cc.v2fadd(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fadd(v0, cc.v2fmult(offset0, 0.5)); 826 var outer1 = outline ? cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fadd(v1, cc.v2fmult(offset1, 0.5)); 827 828 if (outline) { 829 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 830 {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 831 trianglesBuffer, locBuffer.length * triangleBytesLen)); 832 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 833 {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 834 trianglesBuffer, locBuffer.length * triangleBytesLen)); 835 } else { 836 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 837 {vertices: inner1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)}, 838 trianglesBuffer, locBuffer.length * triangleBytesLen)); 839 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 840 {vertices: outer0, colors: c4bFillColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)}, 841 trianglesBuffer, locBuffer.length * triangleBytesLen)); 842 } 843 } 844 extrude = null; 845 this._dirty = true; 846 }, 847 848 _drawSegments: function(verts, borderWidth, borderColor, closePoly){ 849 borderWidth = (borderWidth == null) ? this._lineWidth : borderWidth; 850 borderColor = borderColor || this._drawColor; 851 if(borderColor.a == null) 852 borderColor.a = 255; 853 borderWidth *= 0.5; 854 if (borderWidth <= 0) 855 return; 856 857 var c4bBorderColor = {r: 0 | borderColor.r, g: 0 | borderColor.g, b: 0 | borderColor.b, a: 0 | borderColor.a }; 858 var extrude = [], i, v0, v1, v2, count = verts.length; 859 for (i = 0; i < count; i++) { 860 v0 = cc.__v2f(verts[(i - 1 + count) % count]); 861 v1 = cc.__v2f(verts[i]); 862 v2 = cc.__v2f(verts[(i + 1) % count]); 863 var n1 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v1, v0))); 864 var n2 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v2, v1))); 865 var offset = cc.v2fmult(cc.v2fadd(n1, n2), 1.0 / (cc.v2fdot(n1, n2) + 1.0)); 866 extrude[i] = {offset: offset, n: n2}; 867 } 868 869 var triangleCount = 3 * count - 2, vertexCount = 3 * triangleCount; 870 this._ensureCapacity(vertexCount); 871 872 var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer; 873 var locBuffer = this._buffer; 874 var len = closePoly ? count : count - 1; 875 for (i = 0; i < len; i++) { 876 var j = (i + 1) % count; 877 v0 = cc.__v2f(verts[i]); 878 v1 = cc.__v2f(verts[j]); 879 880 var n0 = extrude[i].n; 881 var offset0 = extrude[i].offset; 882 var offset1 = extrude[j].offset; 883 var inner0 = cc.v2fsub(v0, cc.v2fmult(offset0, borderWidth)); 884 var inner1 = cc.v2fsub(v1, cc.v2fmult(offset1, borderWidth)); 885 var outer0 = cc.v2fadd(v0, cc.v2fmult(offset0, borderWidth)); 886 var outer1 = cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth)); 887 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 888 {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 889 trianglesBuffer, locBuffer.length * triangleBytesLen)); 890 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 891 {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 892 trianglesBuffer, locBuffer.length * triangleBytesLen)); 893 } 894 extrude = null; 895 this._dirty = true; 896 }, 897 898 clear:function () { 899 this._buffer.length = 0; 900 this._dirty = true; 901 }, 902 903 _createRenderCmd: function () { 904 return new cc.DrawNode.WebGLRenderCmd(this); 905 } 906 }); 907 } 908 }); 909