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 /** 54 * cc.Progresstimer is a subclass of cc.Node.<br/> 55 * It renders the inner sprite according to the percentage.<br/> 56 * The progress can be Radial, Horizontal or vertical. 57 * @class 58 * @extends cc.Node 59 */ 60 cc.ProgressTimer = cc.Node.extend(/** @lends cc.ProgressTimer# */{ 61 RGBAProtocol:true, 62 _type:null, 63 _percentage:0.0, 64 _sprite:null, 65 _vertexDataCount:0, 66 _vertexData:null, 67 68 _midPoint:cc.PointZero(), 69 _barChangeRate:cc.PointZero(), 70 _reverseDirection:false, 71 72 ctor:function () { 73 this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; 74 this._percentage = 0.0; 75 this._midPoint = cc.p(0, 0); 76 this._barChangeRate = cc.p(0, 0); 77 this._reverseDirection = false; 78 }, 79 80 /** 81 * Midpoint is used to modify the progress start position. 82 * If you're using radials type then the midpoint changes the center point 83 * If you're using bar type the the midpoint changes the bar growth 84 * it expands from the center but clamps to the sprites edge so: 85 * you want a left to right then set the midpoint all the way to cc.p(0,y) 86 * you want a right to left then set the midpoint all the way to cc.p(1,y) 87 * you want a bottom to top then set the midpoint all the way to cc.p(x,0) 88 * you want a top to bottom then set the midpoint all the way to cc.p(x,1) 89 * @return {cc.Point} 90 */ 91 getMidpoint:function () { 92 return this._midPoint; 93 }, 94 95 /** 96 * Midpoint setter 97 * @param {cc.Point} mpoint 98 */ 99 setMidpoint:function (mpoint) { 100 this._midPoint = cc.pClamp(mpoint, cc.PointZero(), cc.p(1, 1)); 101 }, 102 103 /** 104 * This allows the bar type to move the component at a specific rate 105 * Set the component to 0 to make sure it stays at 100%. 106 * For example you want a left to right bar but not have the height stay 100% 107 * Set the rate to be cc.p(0,1); and set the midpoint to = cc.p(0,.5f); 108 * @return {cc.Point} 109 */ 110 getBarChangeRate:function () { 111 return this._barChangeRate; 112 }, 113 114 /** 115 * @param {cc.Point} barChangeRate 116 */ 117 setBarChangeRate:function (barChangeRate) { 118 119 this._barChangeRate = cc.pClamp(barChangeRate, cc.PointZero(), cc.p(1, 1)); 120 }, 121 122 /** 123 * Change the percentage to change progress 124 * @return {cc.PROGRESS_TIMER_TYPE_RADIAL|cc.PROGRESS_TIMER_TYPE_BAR} 125 */ 126 getType:function () { 127 return this._type; 128 }, 129 130 /** 131 * Percentages are from 0 to 100 132 * @return {Number} 133 */ 134 getPercentage:function () { 135 return this._percentage; 136 }, 137 138 /** 139 * The image to show the progress percentage, retain 140 * @return {cc.Sprite} 141 */ 142 getSprite:function () { 143 return this._sprite; 144 }, 145 146 /** 147 * Initializes a progress timer with the sprite as the shape the timer goes through 148 * @param {cc.Sprite} sprite 149 * @return {Boolean} 150 */ 151 initWithSprite:function (sprite) { 152 this.setPercentage(0); 153 this._vertexData = null; 154 this._vertexDataCount = 0; 155 this.setAnchorPoint(cc.p(0.5, 0.5)); 156 157 this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; 158 this._reverseDirection = false; 159 this.setMidpoint(cc.p(0.5, 0.5)); 160 this.setBarChangeRate(cc.p(1, 1)); 161 this.setSprite(sprite); 162 163 //shader program 164 //this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(kCCShader_PositionTextureColor)); 165 166 return true; 167 }, 168 169 /** 170 * from 0-100 171 * @param {Number} percentage 172 */ 173 setPercentage:function (percentage) { 174 if (this._percentage != percentage) { 175 this._percentage = cc.clampf(percentage, 0, 100); 176 this._updateProgress(); 177 } 178 }, 179 180 /** 181 * @param {cc.Sprite} sprite 182 */ 183 setSprite:function (sprite) { 184 if (this._sprite != sprite) { 185 this._sprite = sprite; 186 this.setContentSize(this._sprite.getContentSize()); 187 188 // Everytime we set a new sprite, we free the current vertex data 189 if (this._vertexData) { 190 this._vertexData = null; 191 this._vertexDataCount = 0; 192 } 193 } 194 }, 195 196 /** 197 * set Progress type of cc.ProgressTimer 198 * @param {cc.PROGRESS_TIMER_TYPE_RADIAL|cc.PROGRESS_TIMER_TYPE_BAR} type 199 */ 200 setType:function (type) { 201 if (type != this._type) { 202 // release all previous information 203 if (this._vertexData) { 204 this._vertexData = null; 205 this._vertexDataCount = 0; 206 } 207 208 this._type = type; 209 } 210 }, 211 212 /** 213 * set color of sprite 214 * @param {cc.Color3B} color 215 */ 216 setColor:function (color) { 217 this._sprite.setColor(color); 218 this._updateColor(); 219 }, 220 221 /** 222 * return color of sprite 223 * @return {cc.Color3B} 224 */ 225 getColor:function () { 226 return this._sprite.getColor(); 227 }, 228 229 /** 230 * return Opacity of sprite 231 * @return {Number} 232 */ 233 getOpacity:function () { 234 return this._sprite.getOpacity(); 235 }, 236 237 /** 238 * Opacity 239 * @param {Number} opacity 240 */ 241 setOpacity:function (opacity) { 242 this._sprite.setOpacity(opacity); 243 this._updateColor(); 244 }, 245 246 setOpacityModifyRGB:function (bValue) { 247 }, 248 249 isOpacityModifyRGB:function () { 250 return false; 251 }, 252 253 isReverseDirection:function () { 254 return this._reverseDirection; 255 }, 256 257 /** 258 * Reverse Progress setter 259 * @param {Boolean} reverse 260 */ 261 setReverseDirection:function (reverse) { 262 if (this._reverseDirection != reverse) { 263 this._reverseDirection = reverse; 264 //release all previous information 265 this._vertexData = null; 266 this._vertexDataCount = 0; 267 } 268 }, 269 270 /** 271 * stuff gets drawn here 272 * @param {CanvasContext} ctx 273 */ 274 draw:function (ctx) { 275 if (cc.renderContextType == cc.CANVAS) { 276 var context = ctx || cc.renderContext; 277 278 context.globalAlpha = this._sprite._opacity / 255; 279 var centerPoint, mpX = 0, mpY = 0; 280 if (this._sprite._flipX) { 281 centerPoint = cc.p(this._sprite._contentSize.width / 2, this._sprite._contentSize.height / 2); 282 mpX = 0 | (centerPoint.x - this._sprite._anchorPointInPoints.x); 283 context.translate(mpX, 0); 284 context.scale(-1, 1); 285 } 286 287 if (this._sprite._flipY) { 288 centerPoint = cc.p(this._sprite._contentSize.width / 2, this._sprite._contentSize.height / 2); 289 mpY = -(0 | (centerPoint.y - this._sprite._anchorPointInPoints.y)); 290 context.translate(0, mpY); 291 context.scale(1, -1); 292 } 293 294 var pos; 295 if (this._type == cc.PROGRESS_TIMER_TYPE_BAR) { 296 pos = cc.p(( -this._sprite._anchorPointInPoints.x + this._sprite._offsetPosition.x + this._drawPosition.x), 297 ( -this._sprite._anchorPointInPoints.y + this._sprite._offsetPosition.y + this._drawPosition.y)); 298 299 if (this._sprite._texture instanceof HTMLImageElement) { 300 if ((this._originSize.width != 0) && (this._originSize.height != 0)) { 301 context.drawImage(this._sprite._texture, 302 this._sprite._rect.origin.x + this._origin.x, this._sprite._rect.origin.y + this._origin.y, 303 this._originSize.width, this._originSize.height, 304 pos.x, -(pos.y + this._drawSize.height), 305 this._originSize.width, this._originSize.height); 306 } 307 } else if (this._sprite._texture instanceof HTMLCanvasElement) { 308 if ((this._originSize.width != 0) && (this._originSize.height != 0)) { 309 context.drawImage(this._sprite._texture, 310 this._origin.x, this._origin.y, 311 this._originSize.width, this._originSize.height, 312 pos.x, -(pos.y + this._drawSize.height), 313 this._originSize.width, this._originSize.height); 314 } 315 } 316 } else { 317 context.beginPath(); 318 context.arc(this._origin.x, this._origin.y, this._radius, (Math.PI / 180) * this._startAngle, (Math.PI / 180) * this._endAngle, false); 319 context.lineTo(this._origin.x, this._origin.y); 320 context.clip(); 321 context.closePath(); 322 323 var offsetPixels = this._sprite._offsetPosition; 324 pos = cc.p(0 | ( -this._sprite._anchorPointInPoints.x + offsetPixels.x), 325 0 | ( -this._sprite._anchorPointInPoints.y + offsetPixels.y)); 326 327 if (this._sprite._texture instanceof HTMLImageElement) { 328 context.drawImage(this._sprite._texture, 329 this._sprite._rect.origin.x, this._sprite._rect.origin.y, 330 this._sprite._rect.size.width, this._sprite._rect.size.height, 331 pos.x, -(pos.y + this._sprite._rect.size.height), 332 this._sprite._rect.size.width, this._sprite._rect.size.height); 333 } else if (this._sprite._texture instanceof HTMLCanvasElement) { 334 context.drawImage(this._sprite._texture, 335 0, 0, 336 this._sprite._rect.size.width, this._sprite._rect.size.height, 337 pos.x, -(pos.y + this._sprite._rect.size.height), 338 this._sprite._rect.size.width, this._sprite._rect.size.height); 339 } 340 } 341 } else { 342 if (!this._vertexData || !this._sprite) 343 return; 344 } 345 cc.INCREMENT_GL_DRAWS(1); 346 }, 347 348 /** 349 * @param {cc.Point} alpha 350 * @return {cc.Vertex2F} the vertex position from the texture coordinate 351 * @private 352 */ 353 _textureCoordFromAlphaPoint:function (alpha) { 354 var ret = new cc.Tex2F(0, 0); 355 if (!this._sprite) { 356 return ret; 357 } 358 var quad = this._sprite.getQuad(); 359 var min = cc.p(quad.bl.texCoords.u, quad.bl.texCoords.v); 360 var max = cc.p(quad.tr.texCoords.u, quad.tr.texCoords.v); 361 362 // Fix bug #1303 so that progress timer handles sprite frame texture rotation 363 if (this._sprite.isTextureRectRotated()) { 364 var tempX = alpha.x; 365 alpha.x = alpha.y; 366 alpha.y = tempX; 367 } 368 return new cc.Tex2F(min.x * (1 - alpha.x) + max.x * alpha.x, min.y * (1 - alpha.y) + max.y * alpha.y); 369 }, 370 371 _vertexFromAlphaPoint:function (alpha) { 372 var ret = new cc.Tex2F(0, 0); 373 if (!this._sprite) { 374 return ret; 375 } 376 var quad = this._sprite.getQuad(); 377 var min = cc.p(quad.bl.vertices.x, quad.bl.vertices.y); 378 var max = cc.p(quad.tr.vertices.x, quad.tr.vertices.y); 379 ret.x = min.x * (1 - alpha.x) + max.x * alpha.x; 380 ret.y = min.y * (1 - alpha.y) + max.y * alpha.y; 381 return ret; 382 }, 383 384 _origin:cc.PointZero(), 385 _originSize:cc.SizeZero(), 386 _drawSize:cc.SizeZero(), 387 _drawPosition:cc.PointZero(), 388 _startAngle:270, 389 _endAngle:270, 390 _radius:0, 391 _updateProgress:function () { 392 if (cc.renderContextType == cc.CANVAS) { 393 var size = this._sprite.getContentSize(); 394 var textureSize = this._sprite.getTextureRect().size; 395 if (this._type == cc.PROGRESS_TIMER_TYPE_RADIAL) { 396 397 this._origin = cc.p(-(size.width * (0.5 - this._midPoint.x)), -(size.height * (0.5 - this._midPoint.y))); 398 this._radius = Math.round(Math.sqrt(size.width * size.width + size.height * size.height)); 399 if (this._reverseDirection) { 400 this._startAngle = 270 - 3.6 * this._percentage; 401 } else { 402 this._endAngle = 270 + 3.6 * this._percentage; 403 } 404 } else { 405 this._origin = cc.p(0, 0); 406 this._drawPosition = cc.p(0, 0); 407 408 var percentageF = this._percentage / 100; 409 var startPoint = cc.p(size.width * this._midPoint.x, size.height * this._midPoint.y); 410 var startPointTx = cc.p(textureSize.width * this._midPoint.x, textureSize.height * this._midPoint.y); 411 412 var drawedSize = cc.size((size.width * (1 - this._barChangeRate.x)), (size.height * (1 - this._barChangeRate.y))); 413 var drawingSize = cc.size((size.width - drawedSize.width) * percentageF, (size.height - drawedSize.height) * percentageF); 414 this._drawSize = cc.size(drawedSize.width + drawingSize.width, drawedSize.height + drawingSize.height); 415 416 var txDrawedSize = cc.size((textureSize.width * (1 - this._barChangeRate.x)), (textureSize.height * (1 - this._barChangeRate.y))); 417 var txDrawingSize = cc.size((textureSize.width - txDrawedSize.width) * percentageF, (textureSize.height - txDrawedSize.height) * percentageF); 418 this._originSize = cc.size(txDrawedSize.width + txDrawingSize.width, txDrawedSize.height + txDrawingSize.height); 419 420 var needToLeft = startPoint.x * percentageF; 421 var needToLeftTx = startPointTx.x * percentageF; 422 423 if (size.width == this._drawSize.width) { 424 this._origin.x = 0; 425 this._drawPosition.x = 0; 426 } else { 427 this._origin.x = (startPointTx.x - needToLeftTx); 428 this._drawPosition.x = (startPoint.x - needToLeft); 429 } 430 431 var needToTop = (textureSize.height - startPointTx.y) * percentageF; 432 433 if (size.height == this._drawSize.height) { 434 this._origin.y = 0; 435 this._drawPosition.y = 0; 436 } else { 437 this._origin.y = (textureSize.height - startPointTx.y - needToTop); 438 this._drawPosition.y = (startPoint.y - (startPoint.y * percentageF)); 439 } 440 } 441 } else { 442 switch (this._type) { 443 case cc.PROGRESS_TIMER_TYPE_RADIAL: 444 this._updateRadial(); 445 break; 446 case cc.PROGRESS_TIMER_TYPE_BAR: 447 this._updateBar(); 448 break; 449 default: 450 break; 451 } 452 } 453 }, 454 455 _updateBar:function () { 456 if (!this._sprite) { 457 return; 458 } 459 460 var alpha = this._percentage / 100.0; 461 var alphaOffset = cc.pMult(cc.p((1.0 - this._barChangeRate.x) + alpha * this._barChangeRate.x, 462 (1.0 - this._barChangeRate.y) + alpha * this._barChangeRate.y), 0.5); 463 var min = cc.pSub(this._midPoint, alphaOffset); 464 var max = cc.pAdd(this._midPoint, alphaOffset); 465 466 if (min.x < 0) { 467 max.x += -min.x; 468 min.x = 0; 469 } 470 471 if (max.x > 1) { 472 min.x -= max.x - 1; 473 max.x = 1; 474 } 475 476 if (min.y < 0) { 477 max.y += -min.y; 478 min.y = 0; 479 } 480 481 if (max.y > 1) { 482 min.y -= max.y - 1; 483 max.y = 1; 484 } 485 486 if (!this._reverseDirection) { 487 if (!this._vertexData) { 488 this._vertexDataCount = 4; 489 this._vertexData = []; 490 for (i = 0; i < this._vertexDataCount; i++) { 491 this._vertexData[i] = new cc.V2F_C4B_T2F(); 492 } 493 cc.Assert(this._vertexData, "cc.ProgressTimer. Not enough memory"); 494 } 495 496 // TOPLEFT 497 this._vertexData[0].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, max.y)); 498 this._vertexData[0].vertices = this._vertexFromAlphaPoint(cc.p(min.x, max.y)); 499 500 // BOTLEFT 501 this._vertexData[1].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, min.y)); 502 this._vertexData[1].vertices = this._vertexFromAlphaPoint(cc.p(min.x, min.y)); 503 504 // TOPRIGHT 505 this._vertexData[2].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, max.y)); 506 this._vertexData[2].vertices = this._vertexFromAlphaPoint(cc.p(max.x, max.y)); 507 508 // BOTRIGHT 509 this._vertexData[3].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, min.y)); 510 this._vertexData[3].vertices = this._vertexFromAlphaPoint(cc.p(max.x, min.y)); 511 } else { 512 if (!this._vertexData) { 513 this._vertexData = 8; 514 this._vertexData = []; 515 for (i = 0; i < this._vertexDataCount; i++) { 516 this._vertexData[i] = new cc.V2F_C4B_T2F(); 517 } 518 cc.Assert(this._vertexData, "cc.ProgressTimer. Not enough memory"); 519 // TOPLEFT 1 520 this._vertexData[0].texCoords = this._textureCoordFromAlphaPoint(cc.p(0, 1)); 521 this._vertexData[0].vertices = this._vertexFromAlphaPoint(cc.p(0, 1)); 522 523 // BOTLEFT 1 524 this._vertexData[1].texCoords = this._textureCoordFromAlphaPoint(cc.p(0, 0)); 525 this._vertexData[1].vertices = this._vertexFromAlphaPoint(cc.p(0, 0)); 526 527 // TOPRIGHT 2 528 this._vertexData[6].texCoords = this._textureCoordFromAlphaPoint(cc.p(1, 1)); 529 this._vertexData[6].vertices = this._vertexFromAlphaPoint(cc.p(1, 1)); 530 531 // BOTRIGHT 2 532 this._vertexData[7].texCoords = this._textureCoordFromAlphaPoint(cc.p(1, 0)); 533 this._vertexData[7].vertices = this._vertexFromAlphaPoint(cc.p(1, 0)); 534 } 535 536 // TOPRIGHT 1 537 this._vertexData[2].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, max.y)); 538 this._vertexData[2].vertices = this._vertexFromAlphaPoint(cc.p(min.x, max.y)); 539 540 // BOTRIGHT 1 541 this._vertexData[3].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, min.y)); 542 this._vertexData[3].vertices = this._vertexFromAlphaPoint(cc.p(min.x, min.y)); 543 544 // TOPLEFT 2 545 this._vertexData[4].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, max.y)); 546 this._vertexData[4].vertices = this._vertexFromAlphaPoint(cc.p(max.x, max.y)); 547 548 // BOTLEFT 2 549 this._vertexData[5].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, min.y)); 550 this._vertexData[5].vertices = this._vertexFromAlphaPoint(cc.p(max.x, min.y)); 551 } 552 this._updateColor(); 553 }, 554 555 _updateRadial:function () { 556 if (!this._sprite) { 557 return; 558 } 559 var i; 560 var alpha = this._percentage / 100; 561 var angle = 2 * (cc.PI) * ( this._reverseDirection ? alpha : 1.0 - alpha); 562 563 // We find the vector to do a hit detection based on the percentage 564 // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate 565 // from that by the progress angle around the m_tMidpoint pivot 566 var topMid = cc.p(this._midPoint.x, 1); 567 var percentagePt = cc.pRotateByAngle(topMid, this._midPoint, angle); 568 569 var index = 0; 570 var hit = cc.PointZero; 571 572 if (alpha == 0) { 573 // More efficient since we don't always need to check intersection 574 // If the alpha is zero then the hit point is top mid and the index is 0. 575 hit = topMid; 576 index = 0; 577 } else if (alpha == 1) { 578 // More efficient since we don't always need to check intersection 579 // If the alpha is one then the hit point is top mid and the index is 4. 580 hit = topMid; 581 index = 4; 582 } else { 583 // We run a for loop checking the edges of the texture to find the 584 // intersection point 585 // We loop through five points since the top is split in half 586 587 var min_t = cc.FLT_MAX; 588 589 for (i = 0; i <= cc.PROGRESS_TEXTURE_COORDS_COUNT; ++i) { 590 var pIndex = (i + (cc.PROGRESS_TEXTURE_COORDS_COUNT - 1)) % cc.PROGRESS_TEXTURE_COORDS_COUNT; 591 592 var edgePtA = this._boundaryTexCoord(i % cc.PROGRESS_TEXTURE_COORDS_COUNT); 593 var edgePtB = this._boundaryTexCoord(pIndex); 594 595 // Remember that the top edge is split in half for the 12 o'clock position 596 // Let's deal with that here by finding the correct endpoints 597 if (i == 0) { 598 edgePtB = cc.pLerp(edgePtA, edgePtB, 1 - this._midPoint.x); 599 } else if (i == 4) { 600 edgePtA = cc.pLerp(edgePtA, edgePtB, 1 - this._midPoint.x); 601 } 602 603 // s and t are returned by ccpLineIntersect 604 var s = 0, t = 0; 605 var retPoint = cc.p(0, 0); 606 if (cc.pLineIntersect(edgePtA, edgePtB, this._midPoint, percentagePt, retPoint)) { 607 // Since our hit test is on rays we have to deal with the top edge 608 // being in split in half so we have to test as a segment 609 if ((i == 0 || i == 4)) { 610 // s represents the point between edgePtA--edgePtB 611 if (!(0 <= retPoint.width && retPoint.width <= 1)) { 612 continue; 613 } 614 } 615 // As long as our t isn't negative we are at least finding a 616 // correct hitpoint from m_tMidpoint to percentagePt. 617 if (retPoint.height >= 0) { 618 // Because the percentage line and all the texture edges are 619 // rays we should only account for the shortest intersection 620 if (t < min_t) { 621 min_t = t; 622 index = i; 623 } 624 } 625 } 626 } 627 628 // Now that we have the minimum magnitude we can use that to find our intersection 629 hit = cc.pAdd(this._midPoint, cc.pMult(cc.pSub(percentagePt, this._midPoint), min_t)); 630 } 631 632 // The size of the vertex data is the index from the hitpoint 633 // the 3 is for the m_tMidpoint, 12 o'clock point and hitpoint position. 634 var sameIndexCount = true; 635 if (this._vertexDataCount != index + 3) { 636 sameIndexCount = false; 637 this._vertexData = null; 638 this._vertexDataCount = 0; 639 } 640 641 if (!this._vertexData) { 642 this._vertexDataCount = index + 3; 643 this._vertexData = []; 644 for (i = 0; i < this._vertexDataCount; i++) { 645 this._vertexData[i] = new cc.V2F_C4B_T2F(); 646 } 647 cc.Assert(this._vertexData, "cc.ProgressTimer. Not enough memory"); 648 } 649 this._updateColor(); 650 651 if (!sameIndexCount) { 652 // First we populate the array with the m_tMidpoint, then all 653 // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint 654 this._vertexData[0].texCoords = this._textureCoordFromAlphaPoint(this._midPoint); 655 this._vertexData[0].vertices = this._vertexFromAlphaPoint(this._midPoint); 656 657 this._vertexData[1].texCoords = this._textureCoordFromAlphaPoint(topMid); 658 this._vertexData[1].vertices = this._vertexFromAlphaPoint(topMid); 659 660 for (i = 0; i < index; ++i) { 661 var alphaPoint = this._boundaryTexCoord(i); 662 this._vertexData[i + 2].texCoords = this._textureCoordFromAlphaPoint(alphaPoint); 663 this._vertexData[i + 2].vertices = this._vertexFromAlphaPoint(alphaPoint); 664 } 665 } 666 667 // hitpoint will go last 668 this._vertexData[this._vertexDataCount - 1].texCoords = this._textureCoordFromAlphaPoint(hit); 669 this._vertexData[this._vertexDataCount - 1].vertices = this._vertexFromAlphaPoint(hit); 670 }, 671 672 _updateColor:function () { 673 if (!this._sprite) { 674 return; 675 } 676 677 if (this._vertexData) { 678 var sc = this._sprite.getQuad().tl.colors; 679 for (var i = 0; i < this._vertexDataCount; ++i) { 680 this._vertexData[i].colors = sc; 681 } 682 } 683 }, 684 685 _boundaryTexCoord:function (index) { 686 if (index < cc.PROGRESS_TEXTURE_COORDS_COUNT) { 687 if (this._reverseDirection) { 688 return cc.p((cc.PROGRESS_TEXTURE_COORDS >> (7 - (index << 1))) & 1, (cc.PROGRESS_TEXTURE_COORDS >> (7 - ((index << 1) + 1))) & 1); 689 } else { 690 return cc.p((cc.PROGRESS_TEXTURE_COORDS >> ((index << 1) + 1)) & 1, (cc.PROGRESS_TEXTURE_COORDS >> (index << 1)) & 1); 691 } 692 } 693 return cc.PointZero(); 694 } 695 }); 696 697 /** 698 * create a progress timer object with image file name that renders the inner sprite according to the percentage 699 * @param {cc.Sprite} sprite 700 * @return {cc.ProgressTimer} 701 * @example 702 * // Example 703 * var progress = cc.ProgressTimer.create('progress.png') 704 */ 705 cc.ProgressTimer.create = function (sprite) { 706 var progressTimer = new cc.ProgressTimer(); 707 if (progressTimer.initWithSprite(sprite)) { 708 return progressTimer; 709 } else { 710 return null; 711 } 712 }; 713 714