1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga 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# */{ 92 _buffer: null, 93 _blendFunc: null, 94 _lineWidth: 0, 95 _drawColor: null, 96 _className:"DrawNodeCanvas", 97 ctor: function () { 98 cc.Node.prototype.ctor.call(this); 99 this._buffer = []; 100 this._lineWidth = 1; 101 this._drawColor = cc.color(255, 255, 255, 255); 102 this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); 103 }, 104 105 // ----common function start ---- 106 getBlendFunc: function () { 107 return this._blendFunc; 108 }, 109 110 setBlendFunc: function (blendFunc) { 111 this._blendFunc = blendFunc; 112 }, 113 114 /** 115 * line width setter 116 * @param {Number} width 117 */ 118 setLineWidth: function (width) { 119 this._lineWidth = width; 120 }, 121 122 /** 123 * line width getter 124 * @returns {Number} 125 */ 126 getLineWidth: function () { 127 return this._lineWidth; 128 }, 129 130 /** 131 * draw color setter 132 * @param {cc.Color} color 133 */ 134 setDrawColor: function (color) { 135 this._drawColor.r = color.r; 136 this._drawColor.g = color.g; 137 this._drawColor.b = color.b; 138 this._drawColor.a = color.a; 139 }, 140 141 /** 142 * draw color getter 143 * @returns {cc.Color} 144 */ 145 getDrawColor: function () { 146 return cc.color(this._drawColor.r, this._drawColor.g, this._drawColor.b, this._drawColor.a); 147 }, 148 // ----common function end ---- 149 150 151 /** 152 * draws a rectangle given the origin and destination point measured in points. 153 * @param {cc.Point} origin 154 * @param {cc.Point} destination 155 * @param {cc.Color} fillColor 156 * @param {Number} lineWidth 157 * @param {cc.Color} lineColor 158 */ 159 drawRect: function (origin, destination, fillColor, lineWidth, lineColor) { 160 lineWidth = lineWidth || this._lineWidth; 161 lineColor = lineColor || this.getDrawColor(); 162 var vertices = [ 163 origin, 164 cc.p(destination.x, origin.y), 165 destination, 166 cc.p(origin.x, destination.y) 167 ]; 168 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 169 element.verts = vertices; 170 element.lineWidth = lineWidth; 171 element.lineColor = lineColor; 172 element.isClosePolygon = true; 173 element.isStroke = true; 174 element.lineCap = "butt"; 175 element.fillColor = fillColor; 176 if (fillColor) { 177 element.isFill = true; 178 } 179 this._buffer.push(element); 180 }, 181 182 /** 183 * draws a circle given the center, radius and number of segments. 184 * @override 185 * @param {cc.Point} center center of circle 186 * @param {Number} radius 187 * @param {Number} angle angle in radians 188 * @param {Number} segments 189 * @param {Boolean} drawLineToCenter 190 * @param {Number} lineWidth 191 * @param {cc.Color} color 192 */ 193 drawCircle: function (center, radius, angle, segments, drawLineToCenter, lineWidth, color) { 194 lineWidth = lineWidth || this._lineWidth; 195 color = color || this.getDrawColor(); 196 197 var coef = 2.0 * Math.PI / segments; 198 var vertices = []; 199 for (var i = 0; i <= segments; i++) { 200 var rads = i * coef; 201 var j = radius * Math.cos(rads + angle) + center.x; 202 var k = radius * Math.sin(rads + angle) + center.y; 203 vertices.push(cc.p(j, k)); 204 } 205 if (drawLineToCenter) { 206 vertices.push(cc.p(center.x, center.y)); 207 } 208 209 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 210 element.verts = vertices; 211 element.lineWidth = lineWidth; 212 element.lineColor = color; 213 element.isClosePolygon = true; 214 element.isStroke = true; 215 this._buffer.push(element); 216 }, 217 218 /** 219 * draws a quad bezier path 220 * @override 221 * @param {cc.Point} origin 222 * @param {cc.Point} control 223 * @param {cc.Point} destination 224 * @param {Number} segments 225 * @param {Number} lineWidth 226 * @param {cc.Color} color 227 */ 228 drawQuadBezier: function (origin, control, destination, segments, lineWidth, color) { 229 lineWidth = lineWidth || this._lineWidth; 230 color = color || this.getDrawColor(); 231 232 var vertices = []; 233 var t = 0.0; 234 for (var i = 0; i < segments; i++) { 235 var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x; 236 var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y; 237 vertices.push(cc.p(x, y)); 238 t += 1.0 / segments; 239 } 240 vertices.push(cc.p(destination.x, destination.y)); 241 242 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 243 element.verts = vertices; 244 element.lineWidth = lineWidth; 245 element.lineColor = color; 246 element.isStroke = true; 247 element.lineCap = "round"; 248 this._buffer.push(element); 249 }, 250 251 /** 252 * draws a cubic bezier path 253 * @override 254 * @param {cc.Point} origin 255 * @param {cc.Point} control1 256 * @param {cc.Point} control2 257 * @param {cc.Point} destination 258 * @param {Number} segments 259 * @param {Number} lineWidth 260 * @param {cc.Color} color 261 */ 262 drawCubicBezier: function (origin, control1, control2, destination, segments, lineWidth, color) { 263 lineWidth = lineWidth || this._lineWidth; 264 color = color || this.getDrawColor(); 265 266 var vertices = []; 267 var t = 0; 268 for (var i = 0; i < segments; i++) { 269 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; 270 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; 271 vertices.push(cc.p(x, y)); 272 t += 1.0 / segments; 273 } 274 vertices.push(cc.p(destination.x, destination.y)); 275 276 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 277 element.verts = vertices; 278 element.lineWidth = lineWidth; 279 element.lineColor = color; 280 element.isStroke = true; 281 element.lineCap = "round"; 282 this._buffer.push(element); 283 }, 284 285 /** 286 * draw a CatmullRom curve 287 * @override 288 * @param {Array} points 289 * @param {Number} segments 290 * @param {Number} lineWidth 291 * @param {cc.Color} color 292 */ 293 drawCatmullRom: function (points, segments, lineWidth, color) { 294 this.drawCardinalSpline(points, 0.5, segments, lineWidth, color); 295 }, 296 297 /** 298 * draw a cardinal spline path 299 * @override 300 * @param {Array} config 301 * @param {Number} tension 302 * @param {Number} segments 303 * @param {Number} lineWidth 304 * @param {cc.Color} color 305 */ 306 drawCardinalSpline: function (config, tension, segments, lineWidth, color) { 307 lineWidth = lineWidth || this._lineWidth; 308 color = color || this.getDrawColor(); 309 310 var vertices = []; 311 var p, lt; 312 var deltaT = 1.0 / config.length; 313 314 for (var i = 0; i < segments + 1; i++) { 315 var dt = i / segments; 316 317 // border 318 if (dt == 1) { 319 p = config.length - 1; 320 lt = 1; 321 } else { 322 p = 0 | (dt / deltaT); 323 lt = (dt - deltaT * p) / deltaT; 324 } 325 326 // Interpolate 327 var newPos = cc.CardinalSplineAt( 328 cc.getControlPointAt(config, p - 1), 329 cc.getControlPointAt(config, p - 0), 330 cc.getControlPointAt(config, p + 1), 331 cc.getControlPointAt(config, p + 2), 332 tension, lt); 333 vertices.push(newPos); 334 } 335 336 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 337 element.verts = vertices; 338 element.lineWidth = lineWidth; 339 element.lineColor = color; 340 element.isStroke = true; 341 element.lineCap = "round"; 342 this._buffer.push(element); 343 }, 344 345 /** 346 * draw a dot at a position, with a given radius and color 347 * @param {cc.Point} pos 348 * @param {Number} radius 349 * @param {cc.Color} color 350 */ 351 drawDot: function (pos, radius, color) { 352 color = color || this.getDrawColor(); 353 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_DOT); 354 element.verts = [pos]; 355 element.lineWidth = radius; 356 element.fillColor = color; 357 this._buffer.push(element); 358 }, 359 360 /** 361 * draw a segment with a radius and color 362 * @param {cc.Point} from 363 * @param {cc.Point} to 364 * @param {Number} lineWidth 365 * @param {cc.Color} color 366 */ 367 drawSegment: function (from, to, lineWidth, color) { 368 lineWidth = lineWidth || this._lineWidth; 369 color = color || this.getDrawColor(); 370 371 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 372 element.verts = [from, to]; 373 element.lineWidth = lineWidth; 374 element.lineColor = color; 375 element.isStroke = true; 376 element.lineCap = "round"; 377 this._buffer.push(element); 378 }, 379 380 /** 381 * draw a polygon with a fill color and line color without copying the vertex list 382 * @param {Array} verts 383 * @param {cc.Color} fillColor 384 * @param {Number} lineWidth 385 * @param {cc.Color} color 386 */ 387 drawPoly_: function (verts, fillColor, lineWidth, color) { 388 lineWidth = lineWidth || this._lineWidth; 389 color = color || this.getDrawColor(); 390 var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY); 391 392 element.verts = verts; 393 element.fillColor = fillColor; 394 element.lineWidth = lineWidth; 395 element.lineColor = color; 396 element.isClosePolygon = true; 397 element.isStroke = true; 398 element.lineCap = "round"; 399 if (fillColor) { 400 element.isFill = true; 401 } 402 this._buffer.push(element); 403 }, 404 405 /** 406 * draw a polygon with a fill color and line color, copying the vertex list 407 * @param {Array} verts 408 * @param {cc.Color} fillColor 409 * @param {Number} lineWidth 410 * @param {cc.Color} color 411 */ 412 drawPoly: function (verts, fillColor, lineWidth, color) { 413 var vertsCopy = []; 414 for (var i=0; i < verts.length; i++) { 415 vertsCopy.push(cc.p(verts[i].x, verts[i].y)); 416 } 417 return this.drawPoly_(vertsCopy, fillColor, lineWidth, color); 418 }, 419 420 draw: function (ctx) { 421 var context = ctx || cc._renderContext; 422 if ((this._blendFunc && (this._blendFunc.src == cc.SRC_ALPHA) && (this._blendFunc.dst == cc.ONE))) 423 context.globalCompositeOperation = 'lighter'; 424 425 for (var i = 0; i < this._buffer.length; i++) { 426 var element = this._buffer[i]; 427 switch (element.type) { 428 case cc.DrawNode.TYPE_DOT: 429 this._drawDot(context, element); 430 break; 431 case cc.DrawNode.TYPE_SEGMENT: 432 this._drawSegment(context, element); 433 break; 434 case cc.DrawNode.TYPE_POLY: 435 this._drawPoly(context, element); 436 break; 437 } 438 } 439 }, 440 441 _drawDot: function (ctx, element) { 442 var locColor = element.fillColor; 443 var locPos = element.verts[0]; 444 var locRadius = element.lineWidth; 445 var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); 446 447 ctx.fillStyle = "rgba(" + (0 | locColor.r) + "," + (0 | locColor.g) + "," + (0 | locColor.b) + "," + locColor.a / 255 + ")"; 448 ctx.beginPath(); 449 ctx.arc(locPos.x * locScaleX, -locPos.y * locScaleY, locRadius * locScaleX, 0, Math.PI * 2, false); 450 ctx.closePath(); 451 ctx.fill(); 452 }, 453 454 _drawSegment: function (ctx, element) { 455 var locColor = element.lineColor; 456 var locFrom = element.verts[0]; 457 var locTo = element.verts[1]; 458 var locLineWidth = element.lineWidth; 459 var locLineCap = element.lineCap; 460 var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); 461 462 ctx.strokeStyle = "rgba(" + (0 | locColor.r) + "," + (0 | locColor.g) + "," + (0 | locColor.b) + "," + locColor.a / 255 + ")"; 463 ctx.lineWidth = locLineWidth * locScaleX; 464 ctx.beginPath(); 465 ctx.lineCap = locLineCap; 466 ctx.moveTo(locFrom.x * locScaleX, -locFrom.y * locScaleY); 467 ctx.lineTo(locTo.x * locScaleX, -locTo.y * locScaleY); 468 ctx.stroke(); 469 }, 470 471 _drawPoly: function (ctx, element) { 472 var locVertices = element.verts; 473 var locLineCap = element.lineCap; 474 var locFillColor = element.fillColor; 475 var locLineWidth = element.lineWidth; 476 var locLineColor = element.lineColor; 477 var locIsClosePolygon = element.isClosePolygon; 478 var locIsFill = element.isFill; 479 var locIsStroke = element.isStroke; 480 if (locVertices == null) 481 return; 482 483 var firstPoint = locVertices[0]; 484 var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); 485 486 ctx.lineCap = locLineCap; 487 488 if (locFillColor) { 489 ctx.fillStyle = "rgba(" + (0 | locFillColor.r) + "," + (0 | locFillColor.g) + "," 490 + (0 | locFillColor.b) + "," + locFillColor.a / 255 + ")"; 491 } 492 493 if (locLineWidth) { 494 ctx.lineWidth = locLineWidth * locScaleX; 495 } 496 if (locLineColor) { 497 ctx.strokeStyle = "rgba(" + (0 | locLineColor.r) + "," + (0 | locLineColor.g) + "," 498 + (0 | locLineColor.b) + "," + locLineColor.a / 255 + ")"; 499 } 500 ctx.beginPath(); 501 ctx.moveTo(firstPoint.x * locScaleX, -firstPoint.y * locScaleY); 502 for (var i = 1, len = locVertices.length; i < len; i++) 503 ctx.lineTo(locVertices[i].x * locScaleX, -locVertices[i].y * locScaleY); 504 505 if (locIsClosePolygon) 506 ctx.closePath(); 507 508 if (locIsFill) 509 ctx.fill(); 510 if (locIsStroke) 511 ctx.stroke(); 512 }, 513 514 /** 515 * Clear the geometry in the node's buffer. 516 */ 517 clear: function () { 518 this._buffer.length = 0; 519 } 520 }); 521 522 cc.DrawNodeWebGL = cc.Node.extend({ 523 _bufferCapacity:0, 524 _buffer:null, 525 526 _trianglesArrayBuffer:null, 527 _trianglesWebBuffer:null, 528 _trianglesReader:null, 529 530 _blendFunc:null, 531 _dirty:false, 532 _className:"DrawNodeWebGL", 533 534 // ----common function start ---- 535 getBlendFunc:function () { 536 return this._blendFunc; 537 }, 538 539 setBlendFunc:function (blendFunc) { 540 this._blendFunc = blendFunc; 541 }, 542 // ----common function end ---- 543 544 ctor:function () { 545 cc.Node.prototype.ctor.call(this); 546 this._buffer = []; 547 this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); 548 }, 549 550 init:function () { 551 if (cc.Node.prototype.init.call(this)) { 552 this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_LENGTHTEXTURECOLOR); 553 this._ensureCapacity(512); 554 this._trianglesWebBuffer = cc._renderContext.createBuffer(); 555 this._dirty = true; 556 return true; 557 } 558 return false; 559 }, 560 561 _render:function () { 562 var gl = cc._renderContext; 563 564 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); 565 gl.bindBuffer(gl.ARRAY_BUFFER, this._trianglesWebBuffer); 566 if (this._dirty) { 567 gl.bufferData(gl.ARRAY_BUFFER, this._trianglesArrayBuffer, gl.STREAM_DRAW); 568 this._dirty = false; 569 } 570 var triangleSize = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT; 571 572 // vertex 573 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, triangleSize, 0); 574 // color 575 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, triangleSize, 8); 576 // texcood 577 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, triangleSize, 12); 578 579 gl.drawArrays(gl.TRIANGLES, 0, this._buffer.length * 3); 580 cc.INCREMENT_GL_DRAWS(1); 581 //cc.CHECK_GL_ERROR_DEBUG(); 582 }, 583 584 _ensureCapacity:function(count){ 585 if(this._buffer.length + count > this._bufferCapacity){ 586 var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT; 587 this._bufferCapacity += Math.max(this._bufferCapacity, count); 588 //re alloc 589 if((this._buffer == null) || (this._buffer.length === 0)){ 590 //init 591 this._buffer = []; 592 this._trianglesArrayBuffer = new ArrayBuffer(TriangleLength * this._bufferCapacity); 593 this._trianglesReader = new Uint8Array(this._trianglesArrayBuffer); 594 } else { 595 var newTriangles = this._buffer; 596 newTriangles.length = 0; 597 var newArrayBuffer = new ArrayBuffer(TriangleLength * this._bufferCapacity); 598 599 for(var i = 0; i < this._buffer.length;i++){ 600 newTriangles[i] = new cc.V2F_C4B_T2F_Triangle(this._buffer[i].a,this._buffer[i].b,this._buffer[i].c, 601 newArrayBuffer,i * TriangleLength); 602 } 603 this._trianglesReader = new Uint8Array(newArrayBuffer); 604 this._trianglesArrayBuffer = newArrayBuffer; 605 } 606 } 607 }, 608 609 draw:function () { 610 cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); 611 this._shaderProgram.use(); 612 this._shaderProgram.setUniformsForBuiltins(); 613 this._render(); 614 }, 615 616 drawDot:function (pos, radius, color) { 617 var c4bColor = {r: 0 | color.r, g: 0 | color.g, b: 0 | color.b, a: 0 | color.a}; 618 var a = {vertices: {x: pos.x - radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: -1.0, v: -1.0}}; 619 var b = {vertices: {x: pos.x - radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: -1.0, v: 1.0}}; 620 var c = {vertices: {x: pos.x + radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: 1.0, v: 1.0}}; 621 var d = {vertices: {x: pos.x + radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: 1.0, v: -1.0}}; 622 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)); 623 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)); 624 this._dirty = true; 625 }, 626 627 drawSegment:function (from, to, radius, color) { 628 var vertexCount = 6*3; 629 this._ensureCapacity(vertexCount); 630 631 var c4bColor = {r: 0 | color.r, g: 0 | color.g, b: 0 | color.b, a: 0 | color.a}; 632 var a = cc.__v2f(from); 633 var b = cc.__v2f(to); 634 635 var n = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(b, a))); 636 var t = cc.v2fperp(n); 637 638 var nw = cc.v2fmult(n, radius); 639 var tw = cc.v2fmult(t, radius); 640 var v0 = cc.v2fsub(b, cc.v2fadd(nw, tw)); 641 var v1 = cc.v2fadd(b, cc.v2fsub(nw, tw)); 642 var v2 = cc.v2fsub(b, nw); 643 var v3 = cc.v2fadd(b, nw); 644 var v4 = cc.v2fsub(a, nw); 645 var v5 = cc.v2fadd(a, nw); 646 var v6 = cc.v2fsub(a, cc.v2fsub(nw, tw)); 647 var v7 = cc.v2fadd(a, cc.v2fadd(nw, tw)); 648 649 var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, triangleBuffer = this._trianglesArrayBuffer; 650 this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(cc.v2fadd(n, t)))}, 651 {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, 652 triangleBuffer, this._buffer.length * TriangleLength)); 653 654 this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, 655 {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, 656 triangleBuffer, this._buffer.length * TriangleLength)); 657 658 this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, 659 {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, 660 triangleBuffer, this._buffer.length * TriangleLength)); 661 662 this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, 663 {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, 664 triangleBuffer, this._buffer.length * TriangleLength)); 665 666 this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))}, 667 {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, 668 triangleBuffer, this._buffer.length * TriangleLength)); 669 670 this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))}, 671 {vertices: v7, colors: c4bColor, texCoords: cc.__t(cc.v2fadd(n, t))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, 672 triangleBuffer, this._buffer.length * TriangleLength)); 673 this._dirty = true; 674 }, 675 676 drawPoly:function (verts, fillColor, borderWidth, borderColor) { 677 var c4bFillColor = {r: 0 | fillColor.r, g: 0 | fillColor.g, b: 0 | fillColor.b, a: 0 | fillColor.a}; 678 var c4bBorderColor = {r: 0 | borderColor.r, g: 0 | borderColor.g, b: 0 | borderColor.b, a: 0 | borderColor.a}; 679 var extrude = [], i; 680 var v0, v1, v2; 681 var count = verts.length; 682 for (i = 0; i < count; i++) { 683 v0 = cc.__v2f(verts[(i - 1 + count) % count]); 684 v1 = cc.__v2f(verts[i]); 685 v2 = cc.__v2f(verts[(i + 1) % count]); 686 var n1 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v1, v0))); 687 var n2 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v2, v1))); 688 var offset = cc.v2fmult(cc.v2fadd(n1, n2), 1.0 / (cc.v2fdot(n1, n2) + 1.0)); 689 extrude[i] = {offset: offset, n: n2}; 690 } 691 var outline = (borderWidth > 0.0); 692 693 var triangleCount = 3 * count -2; 694 var vertexCount = 3 * triangleCount; 695 this._ensureCapacity(vertexCount); 696 697 var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer; 698 var locBuffer = this._buffer; 699 var inset = (outline == false ? 0.5 : 0.0); 700 for (i = 0; i < count - 2; i++) { 701 v0 = cc.v2fsub(cc.__v2f(verts[0]), cc.v2fmult(extrude[0].offset, inset)); 702 v1 = cc.v2fsub(cc.__v2f(verts[i + 1]), cc.v2fmult(extrude[i + 1].offset, inset)); 703 v2 = cc.v2fsub(cc.__v2f(verts[i + 2]), cc.v2fmult(extrude[i + 2].offset, inset)); 704 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 705 {vertices: v1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: v2, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 706 trianglesBuffer, locBuffer.length * triangleBytesLen)); 707 } 708 709 for (i = 0; i < count; i++) { 710 var j = (i + 1) % count; 711 v0 = cc.__v2f(verts[i]); 712 v1 = cc.__v2f(verts[j]); 713 714 var n0 = extrude[i].n; 715 var offset0 = extrude[i].offset; 716 var offset1 = extrude[j].offset; 717 var inner0 = outline ? cc.v2fsub(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fsub(v0, cc.v2fmult(offset0, 0.5)); 718 var inner1 = outline ? cc.v2fsub(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fsub(v1, cc.v2fmult(offset1, 0.5)); 719 var outer0 = outline ? cc.v2fadd(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fadd(v0, cc.v2fmult(offset0, 0.5)); 720 var outer1 = outline ? cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fadd(v1, cc.v2fmult(offset1, 0.5)); 721 722 if (outline) { 723 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 724 {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 725 trianglesBuffer, locBuffer.length * triangleBytesLen)); 726 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, 727 {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, 728 trianglesBuffer, locBuffer.length * triangleBytesLen)); 729 } else { 730 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 731 {vertices: inner1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)}, 732 trianglesBuffer, locBuffer.length * triangleBytesLen)); 733 locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, 734 {vertices: outer0, colors: c4bFillColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)}, 735 trianglesBuffer, locBuffer.length * triangleBytesLen)); 736 } 737 } 738 extrude = null; 739 this._dirty = true; 740 }, 741 742 clear:function () { 743 this._buffer.length = 0; 744 this._dirty = true; 745 } 746 }); 747 748 cc.DrawNode = cc._renderType == cc._RENDER_TYPE_WEBGL ? cc.DrawNodeWebGL : cc.DrawNodeCanvas; 749 750 /** 751 * Creates a DrawNode 752 * @return {cc.DrawNode} 753 */ 754 cc.DrawNode.create = function () { 755 var ret = new cc.DrawNode(); 756 if (ret && ret.init()) 757 return ret; 758 return null; 759 }; 760 761 cc._DrawNodeElement = function (type, verts, fillColor, lineWidth, lineColor, lineCap, isClosePolygon, isFill, isStroke) { 762 this.type = type; 763 this.verts = verts || null; 764 this.fillColor = fillColor || null; 765 this.lineWidth = lineWidth || 0; 766 this.lineColor = lineColor || null; 767 this.lineCap = lineCap || "butt"; 768 this.isClosePolygon = isClosePolygon || false; 769 this.isFill = isFill || false; 770 this.isStroke = isStroke || false; 771 }; 772 773 cc.DrawNode.TYPE_DOT = 0; 774 cc.DrawNode.TYPE_SEGMENT = 1; 775 cc.DrawNode.TYPE_POLY = 2; 776