bool CCSuperAnim::Init(const std::string& theAbsAnimFile, int theId, CCSuperAnimListener *theListener) { // try to load the sprite sheet file mSpriteSheetFileFullPath = theAbsAnimFile.substr(0, theAbsAnimFile.find_last_of('.') + 1) + "plist"; tryLoadSpriteSheet(); mAnimHandler = GetSuperAnimHandler(theAbsAnimFile); if (!mAnimHandler.IsValid()) { char aBuffer[256]; sprintf(aBuffer, "Can't load the SuperAnim %s.", theAbsAnimFile.c_str()); CCMessageBox(aBuffer, "Error"); return false; } setContentSize(CC_SIZE_PIXELS_TO_POINTS(CCSizeMake(mAnimHandler.mWidth, mAnimHandler.mHeight))); mId = theId; mListener = theListener; mAnimState = kAnimStateInitialized; mIsFlipX = mIsFlipY = false; mSpeedFactor = 1.0f; mIsLoop = false; // shader program setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor)); scheduleUpdate(); setAnchorPoint(ccp(0.5f, 0.5f)); return true; }
bool CCTMXLayer::initWithTilesetInfo(CCTMXTilesetInfo *tilesetInfo, CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo) { // XXX: is 35% a good estimate ? CCSize size = layerInfo->m_tLayerSize; float totalNumberOfTiles = size.width * size.height; float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ? CCTexture2D *texture = NULL; if( tilesetInfo ) { texture = CCTextureCache::sharedTextureCache()->addImage(tilesetInfo->m_sSourceImage.c_str()); } if (CCSpriteBatchNode::initWithTexture(texture, (unsigned int)capacity)) { if(tilesetInfo->m_IsNeedFlipX) { layerInfo->m_tOffset.x = layerInfo->m_tLayerSize.width; setScaleX(-1); } // layerInfo m_sLayerName = layerInfo->m_sName; m_tLayerSize = size; m_pTiles = layerInfo->m_pTiles; m_uMinGID = layerInfo->m_uMinGID; m_uMaxGID = layerInfo->m_uMaxGID; m_cOpacity = layerInfo->m_cOpacity; setProperties(CCDictionary::createWithDictionary(layerInfo->getProperties())); m_fContentScaleFactor = CCDirector::sharedDirector()->getContentScaleFactor(); // tilesetInfo m_pTileSet = tilesetInfo; CC_SAFE_RETAIN(m_pTileSet); // mapInfo m_tMapTileSize = mapInfo->getTileSize(); m_uLayerOrientation = mapInfo->getOrientation(); // offset (after layer orientation is set); CCPoint offset = this->calculateLayerOffset(layerInfo->m_tOffset); this->setPosition(CC_POINT_PIXELS_TO_POINTS(offset)); m_pAtlasIndexArray = ccCArrayNew((unsigned int)totalNumberOfTiles); this->setContentSize(CC_SIZE_PIXELS_TO_POINTS(CCSizeMake(m_tLayerSize.width * m_tMapTileSize.width, m_tLayerSize.height * m_tMapTileSize.height))); m_bUseAutomaticVertexZ = false; m_nVertexZvalue = 0; return true; } return false; }
bool TMXLayer::initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo) { // FIXME:: is 35% a good estimate ? Size size = layerInfo->_layerSize; float totalNumberOfTiles = size.width * size.height; float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ? Texture2D *texture = nullptr; if( tilesetInfo ) { texture = Director::getInstance()->getTextureCache()->addImage(tilesetInfo->_sourceImage); } if (nullptr == texture) return false; if (SpriteBatchNode::initWithTexture(texture, static_cast<ssize_t>(capacity))) { // layerInfo _layerName = layerInfo->_name; _layerSize = size; _tiles = layerInfo->_tiles; _opacity = layerInfo->_opacity; setProperties(layerInfo->getProperties()); _contentScaleFactor = Director::getInstance()->getContentScaleFactor(); // tilesetInfo _tileSet = tilesetInfo; CC_SAFE_RETAIN(_tileSet); // mapInfo _mapTileSize = mapInfo->getTileSize(); _layerOrientation = mapInfo->getOrientation(); _staggerAxis = mapInfo->getStaggerAxis(); _staggerIndex = mapInfo->getStaggerIndex(); _hexSideLength = mapInfo->getHexSideLength(); // offset (after layer orientation is set); Vec2 offset = this->calculateLayerOffset(layerInfo->_offset); this->setPosition(CC_POINT_PIXELS_TO_POINTS(offset)); _atlasIndexArray = ccCArrayNew(totalNumberOfTiles); this->setContentSize(CC_SIZE_PIXELS_TO_POINTS(Size(_layerSize.width * _mapTileSize.width, _layerSize.height * _mapTileSize.height))); _useAutomaticVertexZ = false; _vertexZvalue = 0; return true; } return false; }
bool CCSpriteFrame::initWithTextureFilename(const char* filename, const CCRect& rect, bool rotated, const CCPoint& offset, const CCSize& originalSize) { m_pobTexture = NULL; m_strTextureFilename = filename; m_obRectInPixels = rect; m_obRect = CC_RECT_PIXELS_TO_POINTS( rect ); m_obOffsetInPixels = offset; m_obOffset = CC_POINT_PIXELS_TO_POINTS( m_obOffsetInPixels ); m_obOriginalSizeInPixels = originalSize; m_obOriginalSize = CC_SIZE_PIXELS_TO_POINTS( m_obOriginalSizeInPixels ); m_bRotated = rotated; return true; }
bool SpriteFrame::initWithTextureFilename(const std::string& filename, const Rect& rect, bool rotated, const Vec2& offset, const Size& originalSize) { _texture = nullptr; _textureFilename = filename; _rectInPixels = rect; _rect = CC_RECT_PIXELS_TO_POINTS( rect ); _offsetInPixels = offset; _offset = CC_POINT_PIXELS_TO_POINTS( _offsetInPixels ); _originalSizeInPixels = originalSize; _originalSize = CC_SIZE_PIXELS_TO_POINTS( _originalSizeInPixels ); _rotated = rotated; return true; }
bool SpriteFrame::initWithTextureFilename(const char* filename, const Rect& rect, bool rotated, const Point& offset, const Size& originalSize) { _texture = NULL; _textureFilename = filename; _rectInPixels = rect; _rect = CC_RECT_PIXELS_TO_POINTS( rect ); _offsetInPixels = offset; _offset = CC_POINT_PIXELS_TO_POINTS( _offsetInPixels ); _originalSizeInPixels = originalSize; _originalSize = CC_SIZE_PIXELS_TO_POINTS( _originalSizeInPixels ); _rotated = rotated; return true; }
bool SpriteFrame::initWithTextureFilename(const std::string& filename, const Rect& rect, bool rotated, const Vec2& offset, const Size& originalSize) { if (FileUtils::getInstance()->isFileExist(filename)) { _texture = nullptr; _textureFilename = filename; _rectInPixels = rect; _rect = CC_RECT_PIXELS_TO_POINTS( rect ); _offsetInPixels = offset; _offset = CC_POINT_PIXELS_TO_POINTS( _offsetInPixels ); _originalSizeInPixels = originalSize; _originalSize = CC_SIZE_PIXELS_TO_POINTS( _originalSizeInPixels ); _rotated = rotated; _anchorPoint = Vec2(NAN, NAN); _centerRect = Rect(NAN, NAN, NAN, NAN); return true; } return false; }
bool CCSpriteFrame::initWithTexture(CCTexture2D* pobTexture, const CCRect& rect, bool rotated, const CCPoint& offset, const CCSize& originalSize) { m_pobTexture = pobTexture; if (pobTexture) { CC_SAFE_RETAIN(pobTexture); } m_obRectInPixels = rect; m_obRect = CC_RECT_PIXELS_TO_POINTS(rect); m_obOffsetInPixels = offset; m_obOffset = CC_POINT_PIXELS_TO_POINTS( m_obOffsetInPixels ); m_obOriginalSizeInPixels = originalSize; m_obOriginalSize = CC_SIZE_PIXELS_TO_POINTS( m_obOriginalSizeInPixels ); m_bRotated = rotated; return true; }
bool SpriteFrame::initWithTexture(Texture2D* texture, const Rect& rect, bool rotated, const Vec2& offset, const Size& originalSize) { _texture = texture; if (texture) { texture->retain(); } _rectInPixels = rect; _rect = CC_RECT_PIXELS_TO_POINTS(rect); _offsetInPixels = offset; _offset = CC_POINT_PIXELS_TO_POINTS( _offsetInPixels ); _originalSizeInPixels = originalSize; _originalSize = CC_SIZE_PIXELS_TO_POINTS( _originalSizeInPixels ); _rotated = rotated; return true; }
bool TMXLayer::initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo) { if( tilesetInfo ) { _texture = Director::getInstance()->getTextureCache()->addImage(tilesetInfo->_sourceImage); _texture->retain(); } // layerInfo _layerName = layerInfo->_name; _layerSize = layerInfo->_layerSize; _tiles = layerInfo->_tiles; _quadsDirty = true; setOpacity( layerInfo->_opacity ); setProperties(layerInfo->getProperties()); // tilesetInfo _tileSet = tilesetInfo; CC_SAFE_RETAIN(_tileSet); // mapInfo _mapTileSize = mapInfo->getTileSize(); _layerOrientation = mapInfo->getOrientation(); // offset (after layer orientation is set); Vec2 offset = this->calculateLayerOffset(layerInfo->_offset); this->setPosition(CC_POINT_PIXELS_TO_POINTS(offset)); this->setContentSize(CC_SIZE_PIXELS_TO_POINTS(Size(_layerSize.width * _mapTileSize.width, _layerSize.height * _mapTileSize.height))); this->tileToNodeTransform(); // shader, and other stuff setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR)); _useAutomaticVertexZ = false; _vertexZvalue = 0; return true; }
bool EncryptedTMXLayer::initWithInfo(cocos2d::TMXTilesetInfo *tilesetInfo, cocos2d::TMXLayerInfo *layerInfo, cocos2d::TMXMapInfo *mapInfo, const std::string &encryptionKey) { // XXX: is 35% a good estimate ? Size size = layerInfo->_layerSize; float totalNumberOfTiles = size.width * size.height; float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ? this->_encryptionKey = encryptionKey; this->_encryptor = FileEncryptor::create(encryptionKey.c_str()); this->_encryptor->retain(); Texture2D *texture = nullptr; if( tilesetInfo ) { // decrypt first, compatible with Android const std::string &resourcePath = FileUtils::getInstance()->fullPathForFilename(tilesetInfo->_sourceImage); int outSize = 0; unsigned char *data = this->_encryptor->decrypt(resourcePath, &outSize); Image *pImage = new Image(); bool bRet = pImage->initWithImageData(data, outSize); if (!bRet) { return false; } texture = Director::getInstance()->getTextureCache()->addImage(pImage, resourcePath); free(data); } if (SpriteBatchNode::initWithTexture(texture, static_cast<ssize_t>(capacity))) { // layerInfo _layerName = layerInfo->_name; _layerSize = size; _tiles = layerInfo->_tiles; _opacity = layerInfo->_opacity; setProperties(layerInfo->getProperties()); _contentScaleFactor = Director::getInstance()->getContentScaleFactor(); // tilesetInfo _tileSet = tilesetInfo; CC_SAFE_RETAIN(_tileSet); // mapInfo _mapTileSize = mapInfo->getTileSize(); _layerOrientation = mapInfo->getOrientation(); // offset (after layer orientation is set); Point offset = this->calculateLayerOffset(layerInfo->_offset); this->setPosition(CC_POINT_PIXELS_TO_POINTS(offset)); _atlasIndexArray = ccCArrayNew(totalNumberOfTiles); this->setContentSize(CC_SIZE_PIXELS_TO_POINTS(Size(_layerSize.width * _mapTileSize.width, _layerSize.height * _mapTileSize.height))); _useAutomaticVertexZ = false; _vertexZvalue = 0; return true; } return false; }
void TMXLayer::updateTiles(const Rect& culledRect) { Rect visibleTiles = culledRect; Size mapTileSize = CC_SIZE_PIXELS_TO_POINTS(_mapTileSize); Size tileSize = CC_SIZE_PIXELS_TO_POINTS(_tileSet->_tileSize); Mat4 nodeToTileTransform = _tileToNodeTransform.getInversed(); //transform to tile visibleTiles = RectApplyTransform(visibleTiles, nodeToTileTransform); // tile coordinate is upside-down, so we need to make the tile coordinate use top-left for the start point. visibleTiles.origin.y += 1; // if x=0.7, width=9.5, we need to draw number 0~10 of tiles, and so is height. visibleTiles.size.width = ceil(visibleTiles.origin.x + visibleTiles.size.width) - floor(visibleTiles.origin.x); visibleTiles.size.height = ceil(visibleTiles.origin.y + visibleTiles.size.height) - floor(visibleTiles.origin.y); visibleTiles.origin.x = floor(visibleTiles.origin.x); visibleTiles.origin.y = floor(visibleTiles.origin.y); // for the bigger tiles. int tilesOverX = 0; int tilesOverY = 0; // for diagonal oriention tiles float tileSizeMax = std::max(tileSize.width, tileSize.height); if (_layerOrientation == FAST_TMX_ORIENTATION_ORTHO) { tilesOverX = ceil(tileSizeMax / mapTileSize.width) - 1; tilesOverY = ceil(tileSizeMax / mapTileSize.height) - 1; if (tilesOverX < 0) tilesOverX = 0; if (tilesOverY < 0) tilesOverY = 0; } else if(_layerOrientation == FAST_TMX_ORIENTATION_ISO) { Rect overTileRect(0, 0, tileSizeMax - mapTileSize.width, tileSizeMax - mapTileSize.height); if (overTileRect.size.width < 0) overTileRect.size.width = 0; if (overTileRect.size.height < 0) overTileRect.size.height = 0; overTileRect = RectApplyTransform(overTileRect, nodeToTileTransform); tilesOverX = ceil(overTileRect.origin.x + overTileRect.size.width) - floor(overTileRect.origin.x); tilesOverY = ceil(overTileRect.origin.y + overTileRect.size.height) - floor(overTileRect.origin.y); } else { //do nothing, do not support //CCASSERT(0, "TMX invalid value"); } _indicesVertexZNumber.clear(); for(const auto& iter : _indicesVertexZOffsets) { _indicesVertexZNumber[iter.first] = iter.second; } int yBegin = std::max(0.f,visibleTiles.origin.y - tilesOverY); int yEnd = std::min(_layerSize.height,visibleTiles.origin.y + visibleTiles.size.height + tilesOverY); int xBegin = std::max(0.f,visibleTiles.origin.x - tilesOverX); int xEnd = std::min(_layerSize.width,visibleTiles.origin.x + visibleTiles.size.width + tilesOverX); for (int y = yBegin; y < yEnd; ++y) { for (int x = xBegin; x < xEnd; ++x) { int tileIndex = getTileIndexByPos(x, y); if(_tiles[tileIndex] == 0) continue; int vertexZ = getVertexZForPos(Vec2(x,y)); auto iter = _indicesVertexZNumber.find(vertexZ); int offset = iter->second; iter->second++; int quadIndex = _tileToQuadIndex[tileIndex]; CC_ASSERT(-1 != quadIndex); (*_indices)[6 * offset + 0] = quadIndex * 4 + 0; //[CY MOD] (*_indices)[6 * offset + 1] = quadIndex * 4 + 1; //[CY MOD] (*_indices)[6 * offset + 2] = quadIndex * 4 + 2; //[CY MOD] (*_indices)[6 * offset + 3] = quadIndex * 4 + 3; //[CY MOD] (*_indices)[6 * offset + 4] = quadIndex * 4 + 2; //[CY MOD] (*_indices)[6 * offset + 5] = quadIndex * 4 + 1; //[CY MOD] } // for x } // for y for(const auto& iter : _indicesVertexZOffsets) { _indicesVertexZNumber[iter.first] -= iter.second; if(_indicesVertexZNumber[iter.first] == 0) { _indicesVertexZNumber.erase(iter.first); } } }
bool TMXLayer::initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo) { // XXX: is 35% a good estimate ? Size size = layerInfo->_layerSize; float totalNumberOfTiles = size.width * size.height; float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ? Texture2D *texture = nullptr; if( tilesetInfo ) { char tmxFilePath[FILENAME_MAX]; strcpy(tmxFilePath, mapInfo->getTMXFileName().c_str()); for (int i = strlen(tmxFilePath) - 1; i >= 0; --i) { if (tmxFilePath[i] == '\\') { tmxFilePath[i] = '\0'; break; } } char sourceImagePath[FILENAME_MAX]; strcpy(sourceImagePath, tmxFilePath); strcat(sourceImagePath, "\\"); strcat(sourceImagePath, tilesetInfo->_sourceImage.c_str()); texture = Director::getInstance()->getTextureCache()->addImage(sourceImagePath); } if (SpriteBatchNode::initWithTexture(texture, static_cast<ssize_t>(capacity))) { // layerInfo _layerName = layerInfo->_name; _layerSize = size; _tiles = layerInfo->_tiles; _opacity = layerInfo->_opacity; setProperties(layerInfo->getProperties()); _contentScaleFactor = Director::getInstance()->getContentScaleFactor(); // tilesetInfo _tileSet = tilesetInfo; CC_SAFE_RETAIN(_tileSet); // mapInfo _mapTileSize = mapInfo->getTileSize(); _layerOrientation = mapInfo->getOrientation(); // offset (after layer orientation is set); Point offset = this->calculateLayerOffset(layerInfo->_offset); this->setPosition(CC_POINT_PIXELS_TO_POINTS(offset)); _atlasIndexArray = ccCArrayNew(totalNumberOfTiles); this->setContentSize(CC_SIZE_PIXELS_TO_POINTS(Size(_layerSize.width * _mapTileSize.width, _layerSize.height * _mapTileSize.height))); _useAutomaticVertexZ = false; _vertexZvalue = 0; return true; } return false; }
void TMXLayer::updateTotalQuads() { if(_quadsDirty) { Size tileSize = CC_SIZE_PIXELS_TO_POINTS(_tileSet->_tileSize); Size texSize = _tileSet->_imageSize; _tileToQuadIndex.clear(); (*_totalQuads).resize(int(_layerSize.width * _layerSize.height)); //[CY MOD] (*_indices).resize(6 * int(_layerSize.width * _layerSize.height)); //[CY MOD] _tileToQuadIndex.resize(int(_layerSize.width * _layerSize.height),-1); _indicesVertexZOffsets.clear(); int quadIndex = 0; for(int y = 0; y < _layerSize.height; ++y) { for(int x =0; x < _layerSize.width; ++x) { int tileIndex = getTileIndexByPos(x, y); int tileGID = _tiles[tileIndex]; if(tileGID == 0) continue; _tileToQuadIndex[tileIndex] = quadIndex; auto& quad = (*_totalQuads)[quadIndex]; //[CY MOD] Vec3 nodePos(float(x), float(y), 0); _tileToNodeTransform.transformPoint(&nodePos); float left, right, top, bottom, z; z = getVertexZForPos(Vec2(x, y)); auto iter = _indicesVertexZOffsets.find(z); if(iter == _indicesVertexZOffsets.end()) { _indicesVertexZOffsets[z] = 1; } else { iter->second++; } // vertices if (tileGID & kTMXTileDiagonalFlag) { left = nodePos.x; right = nodePos.x + tileSize.height; bottom = nodePos.y + tileSize.width; top = nodePos.y; } else { left = nodePos.x; right = nodePos.x + tileSize.width; bottom = nodePos.y + tileSize.height; top = nodePos.y; } if(tileGID & kTMXTileVerticalFlag) std::swap(top, bottom); if(tileGID & kTMXTileHorizontalFlag) std::swap(left, right); if(tileGID & kTMXTileDiagonalFlag) { // FIXME: not working correcly quad.bl.vertices.x = left; quad.bl.vertices.y = bottom; quad.bl.vertices.z = z; quad.br.vertices.x = left; quad.br.vertices.y = top; quad.br.vertices.z = z; quad.tl.vertices.x = right; quad.tl.vertices.y = bottom; quad.tl.vertices.z = z; quad.tr.vertices.x = right; quad.tr.vertices.y = top; quad.tr.vertices.z = z; } else { quad.bl.vertices.x = left; quad.bl.vertices.y = bottom; quad.bl.vertices.z = z; quad.br.vertices.x = right; quad.br.vertices.y = bottom; quad.br.vertices.z = z; quad.tl.vertices.x = left; quad.tl.vertices.y = top; quad.tl.vertices.z = z; quad.tr.vertices.x = right; quad.tr.vertices.y = top; quad.tr.vertices.z = z; } // texcoords Rect tileTexture = _tileSet->getRectForGID(tileGID); left = (tileTexture.origin.x) / texSize.width; right = (tileTexture.origin.x+tileTexture.size.width) / texSize.width; bottom = (tileTexture.origin.y)/ texSize.height; top = (tileTexture.origin.y+tileTexture.size.height) / texSize.height; quad.bl.texCoords.u = left; quad.bl.texCoords.v = bottom; quad.br.texCoords.u = right; quad.br.texCoords.v = bottom; quad.tl.texCoords.u = left; quad.tl.texCoords.v = top; quad.tr.texCoords.u = right; quad.tr.texCoords.v = top; quad.bl.colors = Color4B::WHITE; quad.br.colors = Color4B::WHITE; quad.tl.colors = Color4B::WHITE; quad.tr.colors = Color4B::WHITE; ++quadIndex; } } int offset = 0; for(auto iter = _indicesVertexZOffsets.begin(); iter != _indicesVertexZOffsets.end(); ++iter) { std::swap(offset, iter->second); offset += iter->second; } updateVertexBuffer(); _quadsDirty = false; } }
bool LabelTextFormatter::createStringSprites(Label *theLabel) { theLabel->_limitShowCount = 0; // check for string int stringLen = theLabel->getStringLength(); if (stringLen <= 0) return false; auto totalHeight = theLabel->_commonLineHeight * theLabel->_currNumLines; auto longestLine = 0.0f; auto nextFontPositionX = 0.0f; auto nextFontPositionY = totalHeight; auto contentScaleFactor = CC_CONTENT_SCALE_FACTOR(); if (theLabel->_labelHeight > 0) { auto labelHeightPixel = theLabel->_labelHeight * contentScaleFactor; if (totalHeight > labelHeightPixel) { int numLines = labelHeightPixel / theLabel->_commonLineHeight; totalHeight = numLines * theLabel->_commonLineHeight; } switch (theLabel->_vAlignment) { case TextVAlignment::TOP: nextFontPositionY = labelHeightPixel; break; case TextVAlignment::CENTER: nextFontPositionY = (labelHeightPixel + totalHeight) / 2.0f; break; case TextVAlignment::BOTTOM: nextFontPositionY = totalHeight; break; default: break; } } int charXOffset = 0; int charYOffset = 0; int charAdvance = 0; auto strWhole = theLabel->_currentUTF16String; auto fontAtlas = theLabel->_fontAtlas; FontLetterDefinition tempDefinition; Vec2 letterPosition; const auto& kernings = theLabel->_horizontalKernings; CCASSERT(kernings, "kernings must's be nullptr!!!"); float clipTop = 0; float clipBottom = 0; int lineIndex = 0; bool lineStart = true; bool clipBlank = false; if (theLabel->_currentLabelType == Label::LabelType::TTF && theLabel->_clipEnabled) { clipBlank = true; } for (int i = 0; i < stringLen; i++) { char16_t c = strWhole[i]; if (fontAtlas->getLetterDefinitionForChar(c, tempDefinition)) { charXOffset = tempDefinition.offsetX; charYOffset = tempDefinition.offsetY; charAdvance = tempDefinition.xAdvance; } else { charXOffset = -1; charYOffset = -1; charAdvance = -1; } if (c == '\n') { lineIndex++; nextFontPositionX = 0; nextFontPositionY -= theLabel->_commonLineHeight; theLabel->recordPlaceholderInfo(i); if(nextFontPositionY < theLabel->_commonLineHeight) break; lineStart = true; continue; } else if (clipBlank && tempDefinition.height > 0.0f) { if (lineStart) { if (lineIndex == 0) { clipTop = charYOffset; } lineStart = false; clipBottom = tempDefinition.clipBottom; } else if(tempDefinition.clipBottom < clipBottom) { clipBottom = tempDefinition.clipBottom; } if (lineIndex == 0 && charYOffset < clipTop) { clipTop = charYOffset; } } letterPosition.x = (nextFontPositionX + charXOffset + kernings[i]) / contentScaleFactor; letterPosition.y = (nextFontPositionY - charYOffset) / contentScaleFactor; if( theLabel->recordLetterInfo(letterPosition, tempDefinition, i) == false) { log("WARNING: can't find letter definition in font file for letter: %c", c); continue; } nextFontPositionX += charAdvance + theLabel->_additionalKerning; auto letterRight = letterPosition.x + tempDefinition.width; if (longestLine < letterRight) { longestLine = letterRight; } } Size tmpSize(longestLine * contentScaleFactor, totalHeight); if (theLabel->_labelHeight > 0) { tmpSize.height = theLabel->_labelHeight * contentScaleFactor; } if (clipBlank) { int clipTotal = (clipTop + clipBottom) / contentScaleFactor; tmpSize.height -= clipTotal * contentScaleFactor; clipBottom /= contentScaleFactor; for (int i = 0; i < theLabel->_limitShowCount; i++) { theLabel->_lettersInfo[i].position.y -= clipBottom; } } theLabel->setContentSize(CC_SIZE_PIXELS_TO_POINTS(tmpSize)); return true; }
void UITextArea::createFontChars() { int nextFontPositionX = 0; int nextFontPositionY = 0; //unsigned short prev = -1; int kerningAmount = 0; CCSize tmpSize = CCSizeZero; int longestLine = 0; unsigned int totalHeight = 0; unsigned int quantityOfLines = 1; if (!m_sString) return; unsigned int stringLen = cc_wcslen(m_sString); if (stringLen == 0) { return; } for (unsigned int i = 0; i < stringLen - 1; ++i) { unsigned short c = m_sString[i]; if (c == '\n') { quantityOfLines++; } } totalHeight = m_pConfiguration->m_nCommonHeight * quantityOfLines; nextFontPositionY = 0-(m_pConfiguration->m_nCommonHeight - m_pConfiguration->m_nCommonHeight * quantityOfLines); for (unsigned int i= 0; i < stringLen; i++) { unsigned short c = m_sString[i]; if (c == '\n') { nextFontPositionX = 0; nextFontPositionY -= m_pConfiguration->m_nCommonHeight; continue; } tFontDefHashElement *element = NULL; // unichar is a short, and an int is needed on HASH_FIND_INT unsigned int key = c; HASH_FIND_INT(m_pConfiguration->m_pFontDefDictionary, &key, element); CCAssert(element, "FontDefinition could not be found!"); ccBMFontDef fontDef = element->fontDef; CCRect rect = fontDef.rect; rect = CC_RECT_PIXELS_TO_POINTS(rect); rect.origin.x += m_tImageOffset.x; rect.origin.y += m_tImageOffset.y; CCSprite *fontChar; fontChar = (CCSprite*)(this->getChildByTag(i)); if( ! fontChar ) { fontChar = new CCSprite(); fontChar->initWithTexture(m_pobTextureAtlas->getTexture(), rect); this->addChild(fontChar, 0, i); fontChar->release(); } else { // reusing fonts fontChar->setTextureRect(rect, false, rect.size); // restore to default in case they were modified fontChar->setVisible(true); fontChar->setOpacity(255); } // See issue 1343. cast( signed short + unsigned integer ) == unsigned integer (sign is lost!) int yOffset = m_pConfiguration->m_nCommonHeight - fontDef.yOffset; CCPoint fontPos = ccp( (float)nextFontPositionX + fontDef.xOffset + fontDef.rect.size.width*0.5f + kerningAmount, (float)nextFontPositionY + yOffset - rect.size.height*0.5f * CC_CONTENT_SCALE_FACTOR() ); fontChar->setPosition(CC_POINT_PIXELS_TO_POINTS(fontPos)); // update kerning nextFontPositionX += fontDef.xAdvance + kerningAmount; //prev = c; // Apply label properties fontChar->setOpacityModifyRGB(m_bIsOpacityModifyRGB); // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on if ( i < colors.size()) { fontChar->setColor(colors.at(i)); } else fontChar->setColor(m_tColor); // only apply opacity if it is different than 255 ) // to prevent modifying the color too (issue #610) if( m_cOpacity != 255 ) { fontChar->setOpacity(m_cOpacity); } if (longestLine < nextFontPositionX) { longestLine = nextFontPositionX; } } tmpSize.width = (float) longestLine; tmpSize.height = (float) totalHeight; this->setContentSize(CC_SIZE_PIXELS_TO_POINTS(tmpSize)); }
bool LabelTextFormatter::createStringSprites(Label *theLabel) { // check for string unsigned int stringLen = theLabel->getStringLength(); theLabel->_limitShowCount = 0; // no string if (stringLen == 0) return false; int longestLine = 0; unsigned int totalHeight = theLabel->_commonLineHeight * theLabel->_currNumLines; int nextFontPositionX = 0; int nextFontPositionY = totalHeight; auto contentScaleFactor = CC_CONTENT_SCALE_FACTOR(); if (theLabel->_labelHeight > 0) { auto labelHeightPixel = theLabel->_labelHeight * contentScaleFactor; if (totalHeight > labelHeightPixel) { int numLines = labelHeightPixel / theLabel->_commonLineHeight; totalHeight = numLines * theLabel->_commonLineHeight; } switch (theLabel->_vAlignment) { case TextVAlignment::TOP: nextFontPositionY = labelHeightPixel; break; case TextVAlignment::CENTER: nextFontPositionY = (labelHeightPixel + totalHeight) / 2.0f; break; case TextVAlignment::BOTTOM: nextFontPositionY = totalHeight; break; default: break; } } Rect charRect; int charXOffset = 0; int charYOffset = 0; int charAdvance = 0; auto strWhole = theLabel->_currentUTF16String; auto fontAtlas = theLabel->_fontAtlas; FontLetterDefinition tempDefinition; Vec2 letterPosition; const auto& kernings = theLabel->_horizontalKernings; float clipTop = 0; float clipBottom = 0; int lineIndex = 0; bool lineStart = true; bool clip = false; if (theLabel->_currentLabelType == Label::LabelType::TTF && theLabel->_clipEnabled) { clip = true; } for (unsigned int i = 0; i < stringLen; i++) { char16_t c = strWhole[i]; if (fontAtlas->getLetterDefinitionForChar(c, tempDefinition)) { charXOffset = tempDefinition.offsetX; charYOffset = tempDefinition.offsetY; charAdvance = tempDefinition.xAdvance; } else { charXOffset = -1; charYOffset = -1; charAdvance = -1; } if (c == '\n') { lineIndex++; nextFontPositionX = 0; nextFontPositionY -= theLabel->_commonLineHeight; theLabel->recordPlaceholderInfo(i); if(nextFontPositionY < theLabel->_commonLineHeight) break; lineStart = true; continue; } else if (clip && tempDefinition.height > 0.0f) { if (lineStart) { if (lineIndex == 0) { clipTop = charYOffset; } lineStart = false; clipBottom = tempDefinition.clipBottom; } else if(tempDefinition.clipBottom < clipBottom) { clipBottom = tempDefinition.clipBottom; } if (lineIndex == 0 && charYOffset < clipTop) { clipTop = charYOffset; } } letterPosition.x = (nextFontPositionX + charXOffset + kernings[i]) / contentScaleFactor; letterPosition.y = (nextFontPositionY - charYOffset) / contentScaleFactor; if( theLabel->recordLetterInfo(letterPosition,tempDefinition,i) == false) { log("WARNING: can't find letter definition in font file for letter: %c", c); continue; } nextFontPositionX += charAdvance + kernings[i] + theLabel->_additionalKerning; if (longestLine < nextFontPositionX) { longestLine = nextFontPositionX; } } float lastCharWidth = tempDefinition.width * contentScaleFactor; Size tmpSize; // If the last character processed has an xAdvance which is less that the width of the characters image, then we need // to adjust the width of the string to take this into account, or the character will overlap the end of the bounding // box if(charAdvance < lastCharWidth) { tmpSize.width = longestLine - charAdvance + lastCharWidth; } else { tmpSize.width = longestLine; } tmpSize.height = totalHeight; if (theLabel->_labelHeight > 0) { tmpSize.height = theLabel->_labelHeight * contentScaleFactor; } if (clip) { int clipTotal = (clipTop + clipBottom) / contentScaleFactor; tmpSize.height -= clipTotal * contentScaleFactor; clipBottom /= contentScaleFactor; for (int i = 0; i < theLabel->_limitShowCount; i++) { theLabel->_lettersInfo[i].position.y -= clipBottom; } } theLabel->setContentSize(CC_SIZE_PIXELS_TO_POINTS(tmpSize)); return true; }