1 /**************************************************************************** 2 Copyright (c) 2010-2011 cocos2d-x.org 3 Copyright (c) 2010 Lam Pham 4 5 http://www.cocos2d-x.org 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy 8 of this software and associated documentation files (the "Software"), to deal 9 in the Software without restriction, including without limitation the rights 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 copies of the Software, and to permit persons to whom the Software is 12 furnished to do so, subject to the following conditions: 13 14 The above copyright notice and this permission notice shall be included in 15 all copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 THE SOFTWARE. 24 ****************************************************************************/ 25 26 27 /** 28 * Radial Counter-Clockwise 29 * @type Number 30 * @constant 31 */ 32 cc.PROGRESS_TIMER_TYPE_RADIAL = 0; 33 /** 34 * Bar 35 * @type Number 36 * @constant 37 */ 38 cc.PROGRESS_TIMER_TYPE_BAR = 1; 39 40 /** 41 * @constant 42 * @type Number 43 */ 44 cc.PROGRESS_TEXTURE_COORDS_COUNT = 4; 45 46 /** 47 * @constant 48 * @type Number 49 */ 50 cc.PROGRESS_TEXTURE_COORDS = 0x4b; 51 52 /** 53 * cc.Progresstimer is a subclass of cc.Node. <br/> 54 * It renders the inner sprite according to the percentage.<br/> 55 * The progress can be Radial, Horizontal or vertical. 56 * @class 57 * @extends cc.NodeRGBA 58 */ 59 cc.ProgressTimer = cc.NodeRGBA.extend(/** @lends cc.ProgressTimer# */{ 60 _type:null, 61 _percentage:0.0, 62 _sprite:null, 63 64 _midPoint:null, 65 _barChangeRate:null, 66 _reverseDirection:false, 67 68 /** 69 * Midpoint is used to modify the progress start position. 70 * If you're using radials type then the midpoint changes the center point 71 * If you're using bar type the the midpoint changes the bar growth 72 * it expands from the center but clamps to the sprites edge so: 73 * you want a left to right then set the midpoint all the way to cc.p(0,y) 74 * you want a right to left then set the midpoint all the way to cc.p(1,y) 75 * you want a bottom to top then set the midpoint all the way to cc.p(x,0) 76 * you want a top to bottom then set the midpoint all the way to cc.p(x,1) 77 * @return {cc.Point} 78 */ 79 getMidpoint:function () { 80 return cc.p(this._midPoint.x, this._midPoint); 81 }, 82 83 /** 84 * Midpoint setter 85 * @param {cc.Point} mpoint 86 */ 87 setMidpoint:function (mpoint) { 88 this._midPoint = cc.pClamp(mpoint, cc.p(0, 0), cc.p(1, 1)); 89 }, 90 91 /** 92 * This allows the bar type to move the component at a specific rate 93 * Set the component to 0 to make sure it stays at 100%. 94 * For example you want a left to right bar but not have the height stay 100% 95 * Set the rate to be cc.p(0,1); and set the midpoint to = cc.p(0,.5f); 96 * @return {cc.Point} 97 */ 98 getBarChangeRate:function () { 99 return cc.p(this._barChangeRate.x, this._barChangeRate.y); 100 }, 101 102 /** 103 * @param {cc.Point} barChangeRate 104 */ 105 setBarChangeRate:function (barChangeRate) { 106 this._barChangeRate = cc.pClamp(barChangeRate, cc.p(0, 0), cc.p(1, 1)); 107 }, 108 109 /** 110 * Change the percentage to change progress 111 * @return {cc.PROGRESS_TIMER_TYPE_RADIAL|cc.PROGRESS_TIMER_TYPE_BAR} 112 */ 113 getType:function () { 114 return this._type; 115 }, 116 117 /** 118 * Percentages are from 0 to 100 119 * @return {Number} 120 */ 121 getPercentage:function () { 122 return this._percentage; 123 }, 124 125 /** 126 * The image to show the progress percentage, retain 127 * @return {cc.Sprite} 128 */ 129 getSprite:function () { 130 return this._sprite; 131 }, 132 133 /** 134 * from 0-100 135 * @param {Number} percentage 136 */ 137 setPercentage:function (percentage) { 138 if (this._percentage != percentage) { 139 this._percentage = cc.clampf(percentage, 0, 100); 140 this._updateProgress(); 141 } 142 }, 143 144 setOpacityModifyRGB:function (bValue) { 145 }, 146 147 isOpacityModifyRGB:function () { 148 return false; 149 }, 150 151 isReverseDirection:function () { 152 return this._reverseDirection; 153 }, 154 155 _boundaryTexCoord:function (index) { 156 if (index < cc.PROGRESS_TEXTURE_COORDS_COUNT) { 157 var locProTextCoords = cc.PROGRESS_TEXTURE_COORDS; 158 if (this._reverseDirection) 159 return cc.p((locProTextCoords >> (7 - (index << 1))) & 1, (locProTextCoords >> (7 - ((index << 1) + 1))) & 1); 160 else 161 return cc.p((locProTextCoords >> ((index << 1) + 1)) & 1, (locProTextCoords >> (index << 1)) & 1); 162 } 163 return cc.PointZero(); 164 }, 165 166 _origin:null, 167 _startAngle:270, 168 _endAngle:270, 169 _radius:0, 170 _counterClockWise:false, 171 _barRect:null, 172 173 _vertexDataCount:0, 174 _vertexData:null, 175 _vertexArrayBuffer:null, 176 _vertexWebGLBuffer:null, 177 _vertexDataDirty:false, 178 179 ctor: null, 180 181 _ctorForCanvas: function () { 182 cc.NodeRGBA.prototype.ctor.call(this); 183 184 this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; 185 this._percentage = 0.0; 186 this._midPoint = cc.p(0, 0); 187 this._barChangeRate = cc.p(0, 0); 188 this._reverseDirection = false; 189 190 this._sprite = null; 191 192 this._origin = cc.PointZero(); 193 this._startAngle = 270; 194 this._endAngle = 270; 195 this._radius = 0; 196 this._counterClockWise = false; 197 this._barRect = cc.RectZero(); 198 }, 199 200 _ctorForWebGL: function () { 201 cc.NodeRGBA.prototype.ctor.call(this); 202 this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; 203 this._percentage = 0.0; 204 this._midPoint = cc.p(0, 0); 205 this._barChangeRate = cc.p(0, 0); 206 this._reverseDirection = false; 207 208 this._sprite = null; 209 210 this._vertexWebGLBuffer = cc.renderContext.createBuffer(); 211 this._vertexDataCount = 0; 212 this._vertexData = null; 213 this._vertexArrayBuffer = null; 214 this._vertexDataDirty = false; 215 }, 216 217 /** 218 * set color of sprite 219 * @param {cc.Color3B} color 220 */ 221 setColor:function (color) { 222 this._sprite.setColor(color); 223 }, 224 225 /** 226 * Opacity 227 * @param {Number} opacity 228 */ 229 setOpacity:function (opacity) { 230 this._sprite.setOpacity(opacity); 231 }, 232 233 /** 234 * return color of sprite 235 * @return {cc.Color3B} 236 */ 237 getColor:function () { 238 return this._sprite.getColor(); 239 }, 240 241 /** 242 * return Opacity of sprite 243 * @return {Number} 244 */ 245 getOpacity:function () { 246 return this._sprite.getOpacity(); 247 }, 248 249 /** 250 * @param {Boolean} reverse 251 */ 252 setReverseProgress:null, 253 254 _setReverseProgressForCanvas:function (reverse) { 255 if (this._reverseDirection !== reverse) 256 this._reverseDirection = reverse; 257 }, 258 259 _setReverseProgressForWebGL:function (reverse) { 260 if (this._reverseDirection !== reverse) { 261 this._reverseDirection = reverse; 262 263 // release all previous information 264 this._vertexData = null; 265 this._vertexArrayBuffer = null; 266 this._vertexDataCount = 0; 267 } 268 }, 269 270 /** 271 * @param {cc.Sprite} sprite 272 */ 273 setSprite:null, 274 275 _setSpriteForCanvas:function (sprite) { 276 if (this._sprite != sprite) { 277 this._sprite = sprite; 278 this.setContentSize(this._sprite.getContentSize()); 279 } 280 }, 281 282 _setSpriteForWebGL:function (sprite) { 283 if (sprite && this._sprite != sprite) { 284 this._sprite = sprite; 285 this.setContentSize(sprite.getContentSize()); 286 287 // Everytime we set a new sprite, we free the current vertex data 288 if (this._vertexData) { 289 this._vertexData = null; 290 this._vertexArrayBuffer = null; 291 this._vertexDataCount = 0; 292 } 293 } 294 }, 295 296 /** 297 * set Progress type of cc.ProgressTimer 298 * @param {cc.PROGRESS_TIMER_TYPE_RADIAL|cc.PROGRESS_TIMER_TYPE_BAR} type 299 */ 300 setType:null, 301 302 _setTypeForCanvas:function (type) { 303 if (type !== this._type) 304 this._type = type; 305 }, 306 307 _setTypeForWebGL:function (type) { 308 if (type !== this._type) { 309 // release all previous information 310 if (this._vertexData) { 311 this._vertexData = null; 312 this._vertexArrayBuffer = null; 313 this._vertexDataCount = 0; 314 } 315 this._type = type; 316 } 317 }, 318 319 /** 320 * Reverse Progress setter 321 * @param {Boolean} reverse 322 */ 323 setReverseDirection: null, 324 325 _setReverseDirectionForCanvas: function (reverse) { 326 if (this._reverseDirection !== reverse) 327 this._reverseDirection = reverse; 328 }, 329 330 _setReverseDirectionForWebGL: function (reverse) { 331 if (this._reverseDirection !== reverse) { 332 this._reverseDirection = reverse; 333 //release all previous information 334 this._vertexData = null; 335 this._vertexArrayBuffer = null; 336 this._vertexDataCount = 0; 337 } 338 }, 339 340 /** 341 * @param {cc.Point} alpha 342 * @return {cc.Vertex2F | Object} the vertex position from the texture coordinate 343 * @private 344 */ 345 _textureCoordFromAlphaPoint:function (alpha) { 346 var locSprite = this._sprite; 347 if (!locSprite) { 348 return {u:0, v:0}; //new cc.Tex2F(0, 0); 349 } 350 var quad = locSprite.getQuad(); 351 var min = cc.p(quad.bl.texCoords.u, quad.bl.texCoords.v); 352 var max = cc.p(quad.tr.texCoords.u, quad.tr.texCoords.v); 353 354 // Fix bug #1303 so that progress timer handles sprite frame texture rotation 355 if (locSprite.isTextureRectRotated()) { 356 var temp = alpha.x; 357 alpha.x = alpha.y; 358 alpha.y = temp; 359 } 360 return {u: min.x * (1 - alpha.x) + max.x * alpha.x, v: min.y * (1 - alpha.y) + max.y * alpha.y}; 361 }, 362 363 _vertexFromAlphaPoint:function (alpha) { 364 if (!this._sprite) { 365 return {x: 0, y: 0}; 366 } 367 var quad = this._sprite.getQuad(); 368 var min = cc.p(quad.bl.vertices.x, quad.bl.vertices.y); 369 var max = cc.p(quad.tr.vertices.x, quad.tr.vertices.y); 370 return {x: min.x * (1 - alpha.x) + max.x * alpha.x, y: min.y * (1 - alpha.y) + max.y * alpha.y}; 371 }, 372 373 /** 374 * Initializes a progress timer with the sprite as the shape the timer goes through 375 * @param {cc.Sprite} sprite 376 * @return {Boolean} 377 */ 378 initWithSprite:null, 379 380 _initWithSpriteForCanvas:function (sprite) { 381 this.setPercentage(0); 382 this.setAnchorPoint(cc.p(0.5, 0.5)); 383 384 this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; 385 this._reverseDirection = false; 386 this.setMidpoint(cc.p(0.5, 0.5)); 387 this.setBarChangeRate(cc.p(1, 1)); 388 this.setSprite(sprite); 389 390 return true; 391 }, 392 393 _initWithSpriteForWebGL:function (sprite) { 394 this.setPercentage(0); 395 this._vertexData = null; 396 this._vertexArrayBuffer = null; 397 this._vertexDataCount = 0; 398 this.setAnchorPoint(cc.p(0.5, 0.5)); 399 400 this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; 401 this._reverseDirection = false; 402 this.setMidpoint(cc.p(0.5, 0.5)); 403 this.setBarChangeRate(cc.p(1, 1)); 404 this.setSprite(sprite); 405 406 //shader program 407 this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); 408 return true; 409 }, 410 411 /** 412 * stuff gets drawn here 413 * @param {CanvasRenderingContext2D} ctx 414 */ 415 draw:null, 416 417 _drawForCanvas:function (ctx) { 418 var context = ctx || cc.renderContext; 419 420 var locSprite = this._sprite; 421 if (locSprite._isLighterMode) 422 context.globalCompositeOperation = 'lighter'; 423 424 var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX(), locEGL_ScaleY = cc.EGLView.getInstance().getScaleY(); 425 426 context.globalAlpha = locSprite._displayedOpacity / 255; 427 var locRect = locSprite._rect, locContentSize = locSprite._contentSize, locOffsetPosition = locSprite._offsetPosition, locDrawSizeCanvas = locSprite._drawSize_Canvas; 428 var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height, locTextureCoord = locSprite._textureRect_Canvas; 429 locDrawSizeCanvas.width = locRect.width * locEGL_ScaleX; 430 locDrawSizeCanvas.height = locRect.height * locEGL_ScaleY; 431 432 context.save(); 433 if (locSprite._flippedX) { 434 flipXOffset = -locOffsetPosition.x - locRect.width; 435 context.scale(-1, 1); 436 } 437 if (locSprite._flippedY) { 438 flipYOffset = locOffsetPosition.y; 439 context.scale(1, -1); 440 } 441 442 flipXOffset *= locEGL_ScaleX; 443 flipYOffset *= locEGL_ScaleY; 444 445 //clip 446 if (this._type == cc.PROGRESS_TIMER_TYPE_BAR) { 447 var locBarRect = this._barRect; 448 context.beginPath(); 449 context.rect(locBarRect.x * locEGL_ScaleX, locBarRect.y * locEGL_ScaleY, locBarRect.width * locEGL_ScaleX, locBarRect.height * locEGL_ScaleY); 450 context.clip(); 451 context.closePath(); 452 } else if (this._type == cc.PROGRESS_TIMER_TYPE_RADIAL) { 453 var locOriginX = this._origin.x * locEGL_ScaleX; 454 var locOriginY = this._origin.y * locEGL_ScaleY; 455 context.beginPath(); 456 context.arc(locOriginX, locOriginY, this._radius * locEGL_ScaleY, (Math.PI / 180) * this._startAngle, (Math.PI / 180) * this._endAngle, this._counterClockWise); 457 context.lineTo(locOriginX, locOriginY); 458 context.clip(); 459 context.closePath(); 460 } 461 462 //draw sprite 463 if (locSprite._texture && locRect.width > 0) { 464 var image = locSprite._texture.getHtmlElementObj(); 465 if (this._colorized) { 466 context.drawImage(image, 467 0, 0, locTextureCoord.width, locTextureCoord.height, 468 flipXOffset, flipYOffset, locDrawSizeCanvas.width, locDrawSizeCanvas.height); 469 } else { 470 context.drawImage(image, 471 locTextureCoord.x, locTextureCoord.y, locTextureCoord.width, locTextureCoord.height, 472 flipXOffset, flipYOffset, locDrawSizeCanvas.width , locDrawSizeCanvas.height); 473 } 474 } else if (locContentSize.width !== 0) { 475 var curColor = this.getColor(); 476 context.fillStyle = "rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)"; 477 context.fillRect(flipXOffset, flipYOffset, locContentSize.width * locEGL_ScaleX, locContentSize.height * locEGL_ScaleY); 478 } 479 480 context.restore(); 481 cc.INCREMENT_GL_DRAWS(1); 482 }, 483 484 _drawForWebGL:function (ctx) { 485 var context = ctx || cc.renderContext; 486 if (!this._vertexData || !this._sprite) 487 return; 488 489 cc.NODE_DRAW_SETUP(this); 490 491 var blendFunc = this._sprite.getBlendFunc(); 492 cc.glBlendFunc(blendFunc.src, blendFunc.dst); 493 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX); 494 495 if (this._sprite.getTexture()) 496 cc.glBindTexture2D(this._sprite.getTexture()); 497 else 498 cc.glBindTexture2D(null); 499 500 context.bindBuffer(context.ARRAY_BUFFER, this._vertexWebGLBuffer); 501 if(this._vertexDataDirty){ 502 context.bufferData(context.ARRAY_BUFFER, this._vertexArrayBuffer, context.DYNAMIC_DRAW); 503 this._vertexDataDirty = false; 504 } 505 var locVertexDataLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT; 506 context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, context.FLOAT, false, locVertexDataLen, 0); 507 context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.UNSIGNED_BYTE, true, locVertexDataLen, 8); 508 context.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, context.FLOAT, false, locVertexDataLen, 12); 509 510 if (this._type === cc.PROGRESS_TIMER_TYPE_RADIAL) 511 context.drawArrays(context.TRIANGLE_FAN, 0, this._vertexDataCount); 512 else if (this._type == cc.PROGRESS_TIMER_TYPE_BAR) { 513 if (!this._reverseDirection) 514 context.drawArrays(context.TRIANGLE_STRIP, 0, this._vertexDataCount); 515 else { 516 context.drawArrays(context.TRIANGLE_STRIP, 0, this._vertexDataCount / 2); 517 context.drawArrays(context.TRIANGLE_STRIP, 4, this._vertexDataCount / 2); 518 // 2 draw calls 519 cc.g_NumberOfDraws++; 520 } 521 } 522 cc.g_NumberOfDraws++; 523 }, 524 525 /** 526 * <p> 527 * Update does the work of mapping the texture onto the triangles <br/> 528 * It now doesn't occur the cost of free/alloc data every update cycle. <br/> 529 * It also only changes the percentage point but no other points if they have not been modified. <br/> 530 * <br/> 531 * It now deals with flipped texture. If you run into this problem, just use the <br/> 532 * sprite property and enable the methods flipX, flipY. <br/> 533 * </p> 534 * @private 535 */ 536 _updateRadial:function () { 537 if (!this._sprite) 538 return; 539 540 var i, locMidPoint = this._midPoint; 541 var alpha = this._percentage / 100; 542 var angle = 2 * (cc.PI) * ( this._reverseDirection ? alpha : 1.0 - alpha); 543 544 // We find the vector to do a hit detection based on the percentage 545 // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate 546 // from that by the progress angle around the m_tMidpoint pivot 547 var topMid = cc.p(locMidPoint.x, 1); 548 var percentagePt = cc.pRotateByAngle(topMid, locMidPoint, angle); 549 550 var index = 0; 551 var hit; 552 553 if (alpha == 0) { 554 // More efficient since we don't always need to check intersection 555 // If the alpha is zero then the hit point is top mid and the index is 0. 556 hit = topMid; 557 index = 0; 558 } else if (alpha == 1) { 559 // More efficient since we don't always need to check intersection 560 // If the alpha is one then the hit point is top mid and the index is 4. 561 hit = topMid; 562 index = 4; 563 } else { 564 // We run a for loop checking the edges of the texture to find the 565 // intersection point 566 // We loop through five points since the top is split in half 567 568 var min_t = cc.FLT_MAX; 569 var locProTextCoordsCount = cc.PROGRESS_TEXTURE_COORDS_COUNT; 570 for (i = 0; i <= locProTextCoordsCount; ++i) { 571 var pIndex = (i + (locProTextCoordsCount - 1)) % locProTextCoordsCount; 572 573 var edgePtA = this._boundaryTexCoord(i % locProTextCoordsCount); 574 var edgePtB = this._boundaryTexCoord(pIndex); 575 576 // Remember that the top edge is split in half for the 12 o'clock position 577 // Let's deal with that here by finding the correct endpoints 578 if (i == 0) 579 edgePtB = cc.pLerp(edgePtA, edgePtB, 1 - locMidPoint.x); 580 else if (i == 4) 581 edgePtA = cc.pLerp(edgePtA, edgePtB, 1 - locMidPoint.x); 582 583 // retPoint are returned by ccpLineIntersect 584 var retPoint = cc.p(0, 0); 585 if (cc.pLineIntersect(edgePtA, edgePtB, locMidPoint, percentagePt, retPoint)) { 586 // Since our hit test is on rays we have to deal with the top edge 587 // being in split in half so we have to test as a segment 588 if ((i == 0 || i == 4)) { 589 // s represents the point between edgePtA--edgePtB 590 if (!(0 <= retPoint.x && retPoint.x <= 1)) 591 continue; 592 } 593 // As long as our t isn't negative we are at least finding a 594 // correct hitpoint from m_tMidpoint to percentagePt. 595 if (retPoint.y >= 0) { 596 // Because the percentage line and all the texture edges are 597 // rays we should only account for the shortest intersection 598 if (retPoint.y < min_t) { 599 min_t = retPoint.y; 600 index = i; 601 } 602 } 603 } 604 } 605 606 // Now that we have the minimum magnitude we can use that to find our intersection 607 hit = cc.pAdd(locMidPoint, cc.pMult(cc.pSub(percentagePt, locMidPoint), min_t)); 608 } 609 610 // The size of the vertex data is the index from the hitpoint 611 // the 3 is for the m_tMidpoint, 12 o'clock point and hitpoint position. 612 var sameIndexCount = true; 613 if (this._vertexDataCount != index + 3) { 614 sameIndexCount = false; 615 this._vertexData = null; 616 this._vertexArrayBuffer = null; 617 this._vertexDataCount = 0; 618 } 619 620 if (!this._vertexData) { 621 this._vertexDataCount = index + 3; 622 var locCount = this._vertexDataCount, vertexDataLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT; 623 this._vertexArrayBuffer = new ArrayBuffer(locCount * vertexDataLen); 624 var locData = []; 625 for (i = 0; i < locCount; i++) 626 locData[i] = new cc.V2F_C4B_T2F(null, null, null, this._vertexArrayBuffer, i * vertexDataLen); 627 628 this._vertexData = locData; 629 if(!this._vertexData){ 630 cc.log( "cc.ProgressTimer._updateRadial() : Not enough memory"); 631 return; 632 } 633 } 634 635 var locVertexData = this._vertexData; 636 if (!sameIndexCount) { 637 // First we populate the array with the m_tMidpoint, then all 638 // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint 639 locVertexData[0].texCoords = this._textureCoordFromAlphaPoint(locMidPoint); 640 locVertexData[0].vertices = this._vertexFromAlphaPoint(locMidPoint); 641 642 locVertexData[1].texCoords = this._textureCoordFromAlphaPoint(topMid); 643 locVertexData[1].vertices = this._vertexFromAlphaPoint(topMid); 644 645 for (i = 0; i < index; i++) { 646 var alphaPoint = this._boundaryTexCoord(i); 647 locVertexData[i + 2].texCoords = this._textureCoordFromAlphaPoint(alphaPoint); 648 locVertexData[i + 2].vertices = this._vertexFromAlphaPoint(alphaPoint); 649 } 650 } 651 652 // hitpoint will go last 653 locVertexData[this._vertexDataCount - 1].texCoords = this._textureCoordFromAlphaPoint(hit); 654 locVertexData[this._vertexDataCount - 1].vertices = this._vertexFromAlphaPoint(hit); 655 }, 656 657 /** 658 * <p> 659 * Update does the work of mapping the texture onto the triangles for the bar <br/> 660 * It now doesn't occur the cost of free/alloc data every update cycle. <br/> 661 * It also only changes the percentage point but no other points if they have not been modified. <br/> 662 * <br/> 663 * It now deals with flipped texture. If you run into this problem, just use the <br/> 664 * sprite property and enable the methods flipX, flipY. <br/> 665 * </p> 666 * @private 667 */ 668 _updateBar:function () { 669 if (!this._sprite) 670 return; 671 672 var i; 673 var alpha = this._percentage / 100.0; 674 var locBarChangeRate = this._barChangeRate; 675 var alphaOffset = cc.pMult(cc.p((1.0 - locBarChangeRate.x) + alpha * locBarChangeRate.x, 676 (1.0 - locBarChangeRate.y) + alpha * locBarChangeRate.y), 0.5); 677 var min = cc.pSub(this._midPoint, alphaOffset); 678 var max = cc.pAdd(this._midPoint, alphaOffset); 679 680 if (min.x < 0) { 681 max.x += -min.x; 682 min.x = 0; 683 } 684 685 if (max.x > 1) { 686 min.x -= max.x - 1; 687 max.x = 1; 688 } 689 690 if (min.y < 0) { 691 max.y += -min.y; 692 min.y = 0; 693 } 694 695 if (max.y > 1) { 696 min.y -= max.y - 1; 697 max.y = 1; 698 } 699 700 var locVertexData; 701 if (!this._reverseDirection) { 702 if (!this._vertexData) { 703 this._vertexDataCount = 4; 704 var vertexDataLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT, locCount = 4; 705 this._vertexArrayBuffer = new ArrayBuffer(locCount * vertexDataLen); 706 this._vertexData = []; 707 for (i = 0; i < locCount; i++) 708 this._vertexData[i] = new cc.V2F_C4B_T2F(null, null, null, this._vertexArrayBuffer, i * vertexDataLen); 709 } 710 711 locVertexData = this._vertexData; 712 // TOPLEFT 713 locVertexData[0].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, max.y)); 714 locVertexData[0].vertices = this._vertexFromAlphaPoint(cc.p(min.x, max.y)); 715 716 // BOTLEFT 717 locVertexData[1].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, min.y)); 718 locVertexData[1].vertices = this._vertexFromAlphaPoint(cc.p(min.x, min.y)); 719 720 // TOPRIGHT 721 locVertexData[2].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, max.y)); 722 locVertexData[2].vertices = this._vertexFromAlphaPoint(cc.p(max.x, max.y)); 723 724 // BOTRIGHT 725 locVertexData[3].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, min.y)); 726 locVertexData[3].vertices = this._vertexFromAlphaPoint(cc.p(max.x, min.y)); 727 } else { 728 if (!this._vertexData) { 729 this._vertexDataCount = 8; 730 var rVertexDataLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT, rLocCount = 8; 731 this._vertexArrayBuffer = new ArrayBuffer(rLocCount * rVertexDataLen); 732 var rTempData = []; 733 for (i = 0; i < rLocCount; i++) 734 rTempData[i] = new cc.V2F_C4B_T2F(null, null, null, this._vertexArrayBuffer, i * rVertexDataLen); 735 // TOPLEFT 1 736 rTempData[0].texCoords = this._textureCoordFromAlphaPoint(cc.p(0, 1)); 737 rTempData[0].vertices = this._vertexFromAlphaPoint(cc.p(0, 1)); 738 739 // BOTLEFT 1 740 rTempData[1].texCoords = this._textureCoordFromAlphaPoint(cc.p(0, 0)); 741 rTempData[1].vertices = this._vertexFromAlphaPoint(cc.p(0, 0)); 742 743 // TOPRIGHT 2 744 rTempData[6].texCoords = this._textureCoordFromAlphaPoint(cc.p(1, 1)); 745 rTempData[6].vertices = this._vertexFromAlphaPoint(cc.p(1, 1)); 746 747 // BOTRIGHT 2 748 rTempData[7].texCoords = this._textureCoordFromAlphaPoint(cc.p(1, 0)); 749 rTempData[7].vertices = this._vertexFromAlphaPoint(cc.p(1, 0)); 750 751 this._vertexData = rTempData; 752 } 753 754 locVertexData = this._vertexData; 755 // TOPRIGHT 1 756 locVertexData[2].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, max.y)); 757 locVertexData[2].vertices = this._vertexFromAlphaPoint(cc.p(min.x, max.y)); 758 759 // BOTRIGHT 1 760 locVertexData[3].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, min.y)); 761 locVertexData[3].vertices = this._vertexFromAlphaPoint(cc.p(min.x, min.y)); 762 763 // TOPLEFT 2 764 locVertexData[4].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, max.y)); 765 locVertexData[4].vertices = this._vertexFromAlphaPoint(cc.p(max.x, max.y)); 766 767 // BOTLEFT 2 768 locVertexData[5].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, min.y)); 769 locVertexData[5].vertices = this._vertexFromAlphaPoint(cc.p(max.x, min.y)); 770 } 771 }, 772 773 _updateColor:function () { 774 if (!this._sprite || !this._vertexData) 775 return; 776 777 var sc = this._sprite.getQuad().tl.colors; 778 var locVertexData = this._vertexData; 779 for (var i = 0, len = this._vertexDataCount; i < len; ++i) 780 locVertexData[i].colors = sc; 781 this._vertexDataDirty = true; 782 }, 783 784 _updateProgress:null, 785 786 _updateProgressForCanvas:function () { 787 var locSprite = this._sprite; 788 var spriteSize = locSprite.getContentSize(); 789 var locMidPoint = this._midPoint; 790 791 if (this._type == cc.PROGRESS_TIMER_TYPE_RADIAL) { 792 this._radius = Math.round(Math.sqrt(spriteSize.width * spriteSize.width + spriteSize.height * spriteSize.height)); 793 var locStartAngle = 270; 794 var locEndAngle = 270; 795 var locCounterClockWise = false; 796 var locOrigin = this._origin; 797 798 locOrigin.x = spriteSize.width * locMidPoint.x; 799 locOrigin.y = -spriteSize.height * locMidPoint.y; 800 801 if (this._reverseDirection) { 802 locStartAngle = 270 - 3.6 * this._percentage; 803 } else { 804 locEndAngle = 270 + 3.6 * this._percentage; 805 } 806 807 if (locSprite._flippedX) { 808 locOrigin.x -= spriteSize.width * (this._midPoint.x * 2); 809 locStartAngle= -locStartAngle; 810 locEndAngle= -locEndAngle; 811 locStartAngle -= 180; 812 locEndAngle -= 180; 813 locCounterClockWise = !locCounterClockWise; 814 } 815 if (locSprite._flippedY) { 816 locOrigin.y+=spriteSize.height*(this._midPoint.y*2); 817 locCounterClockWise = !locCounterClockWise; 818 locStartAngle= -locStartAngle; 819 locEndAngle= -locEndAngle; 820 } 821 822 this._startAngle = locStartAngle; 823 this._endAngle = locEndAngle; 824 this._counterClockWise = locCounterClockWise; 825 } else { 826 var locBarChangeRate = this._barChangeRate; 827 var percentageF = this._percentage / 100; 828 var locBarRect = this._barRect; 829 830 var drawedSize = cc.size((spriteSize.width * (1 - locBarChangeRate.x)), (spriteSize.height * (1 - locBarChangeRate.y))); 831 var drawingSize = cc.size((spriteSize.width - drawedSize.width) * percentageF, (spriteSize.height - drawedSize.height) * percentageF); 832 var currentDrawSize = cc.size(drawedSize.width + drawingSize.width, drawedSize.height + drawingSize.height); 833 834 var startPoint = cc.p(spriteSize.width * locMidPoint.x, spriteSize.height * locMidPoint.y); 835 836 var needToLeft = startPoint.x - currentDrawSize.width / 2; 837 if (locMidPoint.x > 0.5) { 838 if (currentDrawSize.width / 2 >= spriteSize.width - startPoint.x) { 839 needToLeft = spriteSize.width - currentDrawSize.width; 840 } 841 } 842 843 var needToTop = startPoint.y - currentDrawSize.height / 2; 844 if (locMidPoint.y > 0.5) { 845 if (currentDrawSize.height / 2 >= spriteSize.height - startPoint.y) { 846 needToTop = spriteSize.height - currentDrawSize.height; 847 } 848 } 849 850 //left pos 851 locBarRect.x = 0; 852 var flipXNeed = 1; 853 if (locSprite._flippedX) { 854 locBarRect.x -= currentDrawSize.width; 855 flipXNeed = -1; 856 } 857 858 if (needToLeft > 0) 859 locBarRect.x += needToLeft * flipXNeed; 860 861 //right pos 862 locBarRect.y = 0; 863 var flipYNeed = 1; 864 if (locSprite._flippedY) { 865 locBarRect.y += currentDrawSize.height; 866 flipYNeed = -1; 867 } 868 869 if (needToTop > 0) 870 locBarRect.y -= needToTop * flipYNeed; 871 872 //clip width and clip height 873 locBarRect.width = currentDrawSize.width; 874 locBarRect.height = -currentDrawSize.height; 875 } 876 }, 877 878 _updateProgressForWebGL:function () { 879 var locType = this._type; 880 if(locType === cc.PROGRESS_TIMER_TYPE_RADIAL) 881 this._updateRadial(); 882 else if(locType === cc.PROGRESS_TIMER_TYPE_BAR) 883 this._updateBar(); 884 this._updateColor(); 885 this._vertexDataDirty = true; 886 } 887 }); 888 889 if(cc.Browser.supportWebGL) { 890 cc.ProgressTimer.prototype.ctor = cc.ProgressTimer.prototype._ctorForWebGL; 891 cc.ProgressTimer.prototype.setReverseProgress = cc.ProgressTimer.prototype._setReverseProgressForWebGL; 892 cc.ProgressTimer.prototype.setSprite = cc.ProgressTimer.prototype._setSpriteForWebGL; 893 cc.ProgressTimer.prototype.setType = cc.ProgressTimer.prototype._setTypeForWebGL; 894 cc.ProgressTimer.prototype.setReverseDirection = cc.ProgressTimer.prototype._setReverseDirectionForWebGL; 895 cc.ProgressTimer.prototype.initWithSprite = cc.ProgressTimer.prototype._initWithSpriteForWebGL; 896 cc.ProgressTimer.prototype.draw = cc.ProgressTimer.prototype._drawForWebGL; 897 cc.ProgressTimer.prototype._updateProgress = cc.ProgressTimer.prototype._updateProgressForWebGL; 898 } else { 899 cc.ProgressTimer.prototype.ctor = cc.ProgressTimer.prototype._ctorForCanvas; 900 cc.ProgressTimer.prototype.setReverseProgress = cc.ProgressTimer.prototype._setReverseProgressForCanvas; 901 cc.ProgressTimer.prototype.setSprite = cc.ProgressTimer.prototype._setSpriteForCanvas; 902 cc.ProgressTimer.prototype.setType = cc.ProgressTimer.prototype._setTypeForCanvas; 903 cc.ProgressTimer.prototype.setReverseDirection = cc.ProgressTimer.prototype._setReverseDirectionForCanvas; 904 cc.ProgressTimer.prototype.initWithSprite = cc.ProgressTimer.prototype._initWithSpriteForCanvas; 905 cc.ProgressTimer.prototype.draw = cc.ProgressTimer.prototype._drawForCanvas; 906 cc.ProgressTimer.prototype._updateProgress = cc.ProgressTimer.prototype._updateProgressForCanvas; 907 } 908 909 /** 910 * create a progress timer object with image file name that renders the inner sprite according to the percentage 911 * @param {cc.Sprite} sprite 912 * @return {cc.ProgressTimer} 913 * @example 914 * // Example 915 * var progress = cc.ProgressTimer.create('progress.png') 916 */ 917 cc.ProgressTimer.create = function (sprite) { 918 var progressTimer = new cc.ProgressTimer(); 919 if (progressTimer.initWithSprite(sprite)) 920 return progressTimer; 921 return null; 922 }; 923 924 925