/// // Update does the work of mapping the texture onto the triangles // It now doesn't occur the cost of free/alloc data every update cycle. // It also only changes the percentage point but no other points if they have not // been modified. // // It now deals with flipped texture. If you run into this problem, just use the // sprite property and enable the methods flipX, flipY. /// void CCProgressTimer::updateRadial() { if (!m_pSprite) { return; } float alpha = m_fPercentage / 100.f; float angle = 2.f*((float)M_PI) * ( m_bReverseDirection ? alpha : 1.0f - alpha); // We find the vector to do a hit detection based on the percentage // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate // from that by the progress angle around the m_tMidpoint pivot CCPoint topMid = ccp(m_tMidpoint.x, 1.f); CCPoint percentagePt = ccpRotateByAngle(topMid, m_tMidpoint, angle); int index = 0; CCPoint hit = CCPoint::zero; if (alpha == 0.f) { // More efficient since we don't always need to check intersection // If the alpha is zero then the hit point is top mid and the index is 0. hit = topMid; index = 0; } else if (alpha == 1.f) { // More efficient since we don't always need to check intersection // If the alpha is one then the hit point is top mid and the index is 4. hit = topMid; index = 4; } else { // We run a for loop checking the edges of the texture to find the // intersection point // We loop through five points since the top is split in half float min_t = FLT_MAX; for (int i = 0; i <= kProgressTextureCoordsCount; ++i) { int pIndex = (i + (kProgressTextureCoordsCount - 1))%kProgressTextureCoordsCount; CCPoint edgePtA = boundaryTexCoord(i % kProgressTextureCoordsCount); CCPoint edgePtB = boundaryTexCoord(pIndex); // Remember that the top edge is split in half for the 12 o'clock position // Let's deal with that here by finding the correct endpoints if(i == 0){ edgePtB = ccpLerp(edgePtA, edgePtB, 1-m_tMidpoint.x); } else if(i == 4){ edgePtA = ccpLerp(edgePtA, edgePtB, 1-m_tMidpoint.x); } // s and t are returned by ccpLineIntersect float s = 0, t = 0; if(ccpLineIntersect(edgePtA, edgePtB, m_tMidpoint, percentagePt, &s, &t)) { // Since our hit test is on rays we have to deal with the top edge // being in split in half so we have to test as a segment if ((i == 0 || i == 4)) { // s represents the point between edgePtA--edgePtB if (!(0.f <= s && s <= 1.f)) { continue; } } // As long as our t isn't negative we are at least finding a // correct hitpoint from m_tMidpoint to percentagePt. if (t >= 0.f) { // Because the percentage line and all the texture edges are // rays we should only account for the shortest intersection if (t < min_t) { min_t = t; index = i; } } } } // Now that we have the minimum magnitude we can use that to find our intersection hit = ccpAdd(m_tMidpoint, ccpMult(ccpSub(percentagePt, m_tMidpoint),min_t)); } // The size of the vertex data is the index from the hitpoint // the 3 is for the m_tMidpoint, 12 o'clock point and hitpoint position. bool sameIndexCount = true; if(m_nVertexDataCount != index + 3){ sameIndexCount = false; CC_SAFE_FREE(m_pVertexData); m_nVertexDataCount = 0; } if(!m_pVertexData) { m_nVertexDataCount = index + 3; m_pVertexData = (ccV2F_C4B_T2F*)malloc(m_nVertexDataCount * sizeof(ccV2F_C4B_T2F)); CCAssert( m_pVertexData, "CCProgressTimer. Not enough memory"); } updateColor(); if (!sameIndexCount) { // First we populate the array with the m_tMidpoint, then all // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint m_pVertexData[0].texCoords = textureCoordFromAlphaPoint(m_tMidpoint); m_pVertexData[0].vertices = vertexFromAlphaPoint(m_tMidpoint); m_pVertexData[1].texCoords = textureCoordFromAlphaPoint(topMid); m_pVertexData[1].vertices = vertexFromAlphaPoint(topMid); for(int i = 0; i < index; ++i){ CCPoint alphaPoint = boundaryTexCoord(i); m_pVertexData[i+2].texCoords = textureCoordFromAlphaPoint(alphaPoint); m_pVertexData[i+2].vertices = vertexFromAlphaPoint(alphaPoint); } } // hitpoint will go last m_pVertexData[m_nVertexDataCount - 1].texCoords = textureCoordFromAlphaPoint(hit); m_pVertexData[m_nVertexDataCount - 1].vertices = vertexFromAlphaPoint(hit); }
void wyProgressTimer::updateRadial() { // Texture Max is the actual max coordinates to deal with non-power of 2 textures wyTexture2D* tex = m_sprite->getTexture(); wyRect texRect = m_sprite->getTextureRect(); float tOffsetX = texRect.x / tex->getPixelWidth(); float tOffsetY = texRect.y / tex->getPixelHeight(); wyPoint tMax = { texRect.width / tex->getPixelWidth(), texRect.height / tex->getPixelHeight() }; // if texture is get from opengl, it is natural born y-flipped bool flipY = tex->getSource() == SOURCE_OPENGL; if(m_sprite->isFlipY()) flipY = !flipY; // Grab the midpoint wyPoint midpoint = { 0.5f * tMax.x, 0.5f * tMax.y }; // get percentage value in [0, 1] range float alpha = m_percentage / 100.f; // Otherwise we can get the angle from the alpha float angle = 2.0f * M_PI * (m_style == RADIAL_CW ? alpha : (1.0f - alpha)); // We find the vector to do a hit detection based on the percentage // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate // from that by the progress angle around the midpoint pivot wyPoint topMid = { midpoint.x, 0.0f }; wyPoint percentagePt = wypRotateByAngle(topMid, midpoint, angle); // helper variables int index = 0; wyPoint hit = wypZero; // check percentage if(alpha == 0.0f) { // More efficient since we don't always need to check intersection // If the alpha is zero then the hit point is top mid and the index is 0. hit = topMid; index = 0; } else if(alpha == 1.0f) { // More efficient since we don't always need to check intersection // If the alpha is one then the hit point is top mid and the index is 4. hit = topMid; index = 4; } else { // We run a for loop checking the edges of the texture to find the // intersection point // We loop through five points since the top is split in half float min_t = MAX_FLOAT; for(int i = 0; i <= PROGRESS_TEXTURE_COORDS_COUNT; ++i) { int pIndex = (i + (PROGRESS_TEXTURE_COORDS_COUNT - 1)) % PROGRESS_TEXTURE_COORDS_COUNT; wyPoint edgePtA = boundaryTexCoord(i % PROGRESS_TEXTURE_COORDS_COUNT); edgePtA = wypMul(edgePtA, tMax); wyPoint edgePtB = boundaryTexCoord(pIndex); edgePtB = wypMul(edgePtB, tMax); // Remember that the top edge is split in half for the 12 o'clock position // Let's deal with that here by finding the correct endpoints if(i == 0) { edgePtB = wypLerp(edgePtA, edgePtB, .5f); } else if(i == 4) { edgePtA = wypLerp(edgePtA, edgePtB, .5f); } // s and t are returned by lineIntersect float st[] = { 0.0f, 0.0f }; if(wypLineIntersect(edgePtA, edgePtB, midpoint, percentagePt, st)) { float s = st[0]; float t = st[1]; // Since our hit test is on rays we have to deal with the top edge // being in split in half so we have to test as a segment if((i == 0 || i == 4)) { // s represents the point between edgePtA--edgePtB if(!(0.f <= s && s <= 1.f)) { continue; } } // As long as our t isn't negative we are at least finding a // correct hitpoint from midpoint to percentagePt. if(t >= 0.f) { // Because the percentage line and all the texture edges are // rays we should only account for the shortest intersection if(t < min_t) { min_t = t; index = i; } } } } // Now that we have the minimum magnitude we can use that to find our intersection wyPoint tmp1 = wypSub(percentagePt, midpoint); tmp1 = wypMul(tmp1, wyp(min_t, min_t)); hit = wypAdd(midpoint, tmp1); } // The size of the vertex data is the index from the hitpoint // the 3 is for the midpoint, 12 o'clock point and hitpoint position. if(m_vertexCount < index + 3) { resetCapacity(index + 3); updateColor(); } m_vertexCount = index + 3; // First we populate the array with the midpoint, then all // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint int pos = 0; m_texCoords[pos] = midpoint.x; m_texCoords[pos + 1] = midpoint.y; wyPoint vertex = vertexFromTexCoord(midpoint.x, midpoint.y); m_vertices[pos] = vertex.x; m_vertices[pos + 1] = vertex.y; pos += 2; m_texCoords[pos] = midpoint.x; m_texCoords[pos + 1] = 0.0f; vertex = vertexFromTexCoord(midpoint.x, 0.0f); m_vertices[pos] = vertex.x; m_vertices[pos + 1] = vertex.y; pos += 2; for(int i = 0; i < index; ++i) { wyPoint texCoord = boundaryTexCoord(i); texCoord = wypMul(texCoord, tMax); m_texCoords[pos] = texCoord.x; m_texCoords[pos + 1] = texCoord.y; vertex = vertexFromTexCoord(texCoord.x, texCoord.y); m_vertices[pos] = vertex.x; m_vertices[pos + 1] = vertex.y; pos += 2; } // hitpoint will go last index = (m_vertexCount - 1) * 2; m_texCoords[index] = hit.x; m_texCoords[index + 1] = hit.y; vertex = vertexFromTexCoord(hit.x, hit.y); m_vertices[index] = vertex.x; m_vertices[index + 1] = vertex.y; // if sprite is from a rotated zwoptex image, need rotate texture coordinate if(m_sprite->isRotatedZwoptex()) { float t_x = tMax.x; tMax.x = tMax.y; tMax.y = t_x; } // fill all texture coordinates for(int i = 0; i < m_vertexCount; i++) { if(m_sprite->isRotatedZwoptex()) { float t_x = m_texCoords[i * 2]; float t_y = m_texCoords[i * 2 + 1]; m_texCoords[i*2] = t_y / (tMax.x / tMax.y); m_texCoords[i * 2 + 1] = t_x * (tMax.x / tMax.y); } if (flipY || m_sprite->isFlipX()) { if (m_sprite->isFlipX()) { m_texCoords[i * 2] = tMax.x - m_texCoords[i * 2]; } if(flipY) { m_texCoords[i * 2 + 1] = tMax.y - m_texCoords[i * 2 + 1]; } } m_texCoords[i * 2] += tOffsetX; m_texCoords[i * 2 + 1] += tOffsetY; } // The vertices order should be in counter clockwise direction, or else it will be culled if // the director->setCullFace() is enabled. if(RADIAL_CW == m_style) { for(int i = 1; i < m_vertexCount; ++i) { int targetIndex = m_vertexCount - i; if( i < targetIndex) { wyUtils::swap(m_texCoords, i * 2, targetIndex * 2); wyUtils::swap(m_texCoords, i * 2 + 1, targetIndex * 2 + 1); wyUtils::swap(m_vertices, i * 2, targetIndex * 2); wyUtils::swap(m_vertices, i * 2 + 1, targetIndex * 2 + 1); } } } }