TargetPod::TargetPod(const char* podFile, const char* name, lw::Sounds* pSndHit) :_score(0.f), _angle(0.f), _pSndHit(pSndHit){ _pMdlSpt = lw::ModelSprite::create(podFile, name); lwassert(_pMdlSpt); const std::vector<lw::Sprite::Vertex>& vec = _pMdlSpt->getVertexVec(); lwassert(vec.size()%3 == 0); b2Vec2 b2v[3]; float scale = B2_SCALE*.9f; for ( int i = 0; i < (int)vec.size(); ){ b2v[0].Set(vec[i].x*scale, vec[i].y*scale); ++i; b2v[1].Set(vec[i].x*scale, vec[i].y*scale); ++i; b2v[2].Set(vec[i].x*scale, vec[i].y*scale); ++i; b2PolygonShape shape; shape.Set(b2v, 3); _shapes.push_back(shape); } _pSpt = lw::Sprite::create("alpha1.png"); _pSpt->setUV(506, 0, 6, 66); _pSpt->setAnchor(3.f, 4.f); _pos.x = _pos.y = 0.f; }
//=============================================== Sprite9* Sprite9::create(const char* file, int u, int v, int w1, int w2, int w3, int h1, int h2, int h3){ lwassert(file); bool ok = false; Sprite9* pSprite9 = new Sprite9(file, u, v, w1, w2, w3, h1, h2, h3, ok); lwassert(pSprite9); if ( !ok ){ delete pSprite9; return NULL; } return pSprite9; }
Sprite9* Sprite9::create(const char* atlasKey, int w1, int w2, int w3, int h1, int h2, int h3){ lwassert(atlasKey); bool ok = false; Sprite9* pSprite9 = new Sprite9(atlasKey, w1, w2, w3, h1, h2, h3, ok); lwassert(pSprite9); if ( !ok ){ delete pSprite9; return NULL; } return pSprite9; }
void PODModel::setParent(PODModel* pParent, unsigned char nodeIndex){ _parentNodeIndex = nodeIndex; if ( pParent != _pParent ){ if ( _pParent == NULL ){ std::list<PODModel*>::iterator it = _sRootChildren.begin(); std::list<PODModel*>::iterator itEnd = _sRootChildren.end(); for ( ; it != itEnd; ++it ){ if ( *it == this ){ _sRootChildren.erase(it); break; } } }else{ std::list<PODModel*>::iterator it = _pParent->_pChildren->begin(); std::list<PODModel*>::iterator itEnd = _pParent->_pChildren->end(); for ( ; it != itEnd; ++it ){ if ( *it == this ){ _pParent->_pChildren->erase(it); break; } } } if ( pParent == NULL ){ _sRootChildren.push_back(this); }else{ if ( pParent->_pChildren == NULL ){ pParent->_pChildren = new std::list<PODModel*>; lwassert(pParent->_pChildren); } pParent->_pChildren->push_back(this); } _pParent = pParent; } }
Font* Font::create(const char* fileName){ FontRes* pRes = FontRes::create(fileName); if ( pRes == NULL ){ return NULL; } Font* pFont = new Font(pRes); lwassert(pFont); return pFont; }
TextureRes* TextureRes::create(int w, int h, const char* pData, bool hasAlpha, bool reserveData, bool revertY){ lwassert(pData); TextureRes* p = new TextureRes(w, h, pData, hasAlpha, reserveData, revertY); if ( p && p->_glId == -1 ){ delete p; return NULL; }else{ return p; } }
int PODModel::getTextureIndex(const char* name){ lwassert(name); CPVRTModelPOD& pod = _pRes->getPOD(); for ( int i = 0; i < (int)pod.nNumTexture; ++i ){ if ( strcmp(pod.pTexture[i].pszName, name) == 0 ){ return i; } } return -1; }
ModelSprite* ModelSprite::create(const char* podFileName, const char* nodeName){ bool ok = false; ModelSprite* p = new ModelSprite(podFileName, nodeName, ok); lwassert(p); if ( p && !ok ){ lwerror("new ModelSprite failed"); delete p; return NULL; } return p; }
Sprite* Sprite::create(const char* texFileName, bool reserveData){ lwassert(texFileName); bool ok; Sprite* p = new Sprite(texFileName, reserveData, ok); if ( p && !ok ){ lwerror("Sprite construct failed"); delete p; p = NULL; } return p; }
EffectsRes* EffectsRes::create(const char *file) { lwassert(file); std::map<std::string, EffectsRes*>::iterator it = _resMap.find(file); if ( it != _resMap.end() ) { it->second->retain(); return it->second; } bool ok = false; EffectsRes *p = new EffectsRes(file, ok); if ( p && !ok ) { lwerror("new EffectsRes failed"); delete p; return NULL; } _resMap[file] = p; return p; }
FontRes* FontRes::create(const char* fileName){ std::map<std::string, FontRes*>::iterator it = _sResMap.find(fileName); if ( it != _sResMap.end() ){ it->second->addRef(); return it->second; } bool ok = false; FontRes* pRes = new FontRes(fileName, ok); lwassert(pRes); if ( !ok ){ lwerror("new FontRes error"); delete pRes; return NULL; } _sResMap[fileName] = pRes; return pRes; }
void Sprite::collectModel(PODModel* pModel, int nodeIndex, lw::Color color){ lwassert(pModel); stepZ(); ImageStaticData& d = g_imageStaticData; if ( d.currVertexOffset == -2 ){ BatchInfo& batchInfo = d.batchInfoVec.back(); batchInfo.vertexOffset = -1; batchInfo.pModle = pModel; batchInfo.nodeIndex = (char)nodeIndex; batchInfo.color = color; d.currVertexOffset = -1; }else{ BatchInfo batchInfo; batchInfo.vertexOffset = -1; batchInfo.pModle = pModel; batchInfo.nodeIndex = (char)nodeIndex; batchInfo.color = color; d.currVertexOffset = -1; d.batchInfoVec.push_back(batchInfo); } }
bool PODModel::replaceTexture(int textureIndex, const char* textureName){ lwassert(textureIndex >= 0 && textureIndex < (int)_pRes->getPOD().nNumTexture); std::map<int, PODTextureRes*>::iterator it = _replaceTextureMap.find(textureIndex); if ( it != _replaceTextureMap.end() ){ if ( strcmp(it->second->getFileName(), textureName) == 0 ){ return true; } } PODTextureRes* pTextrueRes = PODTextureRes::create(textureName); if ( pTextrueRes == NULL ){ lwerror("PODTextureRes::create failed: textureName=" << textureName); return false; } if ( it != _replaceTextureMap.end() ){ it->second->release(); _replaceTextureMap.erase(it); } _replaceTextureMap[textureIndex] = pTextrueRes; return true; }
TextureRes* TextureRes::create(const char* fileName, bool reserveData, bool revertY){ lwassert(fileName); std::string strFileName = fileName; std::map<std::string, TextureRes*>::iterator it = _resMap.find(strFileName); if ( it == _resMap.end() ){ TextureRes* p = new TextureRes(fileName, reserveData, revertY); if ( p && p->_glId == -1 ){ delete p; return NULL; }else{ _resMap[strFileName] = p; return p; } }else{ it->second->addRef(); if ( reserveData ){ it->second->reserveData(); } return it->second; } }
TextureRes::TextureRes(int w, int h, const char* pData, bool hasAlpha, bool reserveData, bool revertY) : _glId(-1), _pImgData(NULL){ lwassert(pData); _w = w; _h = h; _numChannels = hasAlpha?4:3; int sz = w*h*_numChannels; _pImgData = new unsigned char[sz]; memcpy(_pImgData, pData, sz); _glId = SOIL_internal_create_OGL_texture(_pImgData, w, h, _numChannels, SOIL_CREATE_NEW_ID, revertY ? SOIL_FLAG_INVERT_Y:0, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_MAX_TEXTURE_SIZE); if ( !reserveData ){ delete [] _pImgData; _pImgData = NULL; } if ( _glId == 0 ){ lwerror("Failed to create texture"); _glId = -1; } }
void HTTPClient::sendMsg(HTTPMsg* pMsg){ lwassert(pMsg); if ( !_isConnected ){ connect(); } if ( !_isConnected ){ return; } HINTERNET hRequest = WinHttpOpenRequest( _hConnect, L"POST", pMsg->getObjName(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0 ); pMsg->setHRequest(hRequest); //WinHttpSetOption(hRequest, // WINHTTP_OPTION_CONTEXT_VALUE, // pMsg, // sizeof(pMsg)); WinHttpSetStatusCallback(hRequest, requestCallback, WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS | WINHTTP_CALLBACK_FLAG_HANDLES, // to listen to the HANDLE_CLOSING event 0); DWORD size = pMsg->getBuff()->getSize(); bool bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, pMsg->getBuff()->getBuff(), size, size, (DWORD_PTR)pMsg ) != 0; if ( bResults ){ _msgs.push_back(pMsg); }else{ delete pMsg; } }
PODModel::~PODModel(){ if (_pRes){ _pRes->release(); } if (_pChildren){ std::list<PODModel*>::iterator it = _pChildren->begin(); std::list<PODModel*>::iterator itEnd = _pChildren->end(); for ( ; it != itEnd; ++it ){ _sRootChildren.push_back(*it); (*it)->_pParent = NULL; } delete _pChildren; } std::list<PODModel*>* pParentChildren = NULL; if ( _pParent ){ pParentChildren = _pParent->_pChildren; }else{ pParentChildren = &_sRootChildren; } lwassert(pParentChildren); std::list<PODModel*>::iterator it = pParentChildren->begin(); std::list<PODModel*>::iterator itEnd = pParentChildren->end(); for ( ; it != itEnd; ++it ){ if ( (*it) == this ){ pParentChildren->erase(it); break; } } { std::map<int, PODTextureRes*>::iterator it = _replaceTextureMap.begin(); std::map<int, PODTextureRes*>::iterator itEnd = _replaceTextureMap.end(); for ( ; it != itEnd; ++it ){ it->second->release(); } } }
TextureRes::TextureRes(const char* fileName, bool reserveData, bool revertY) : _glId(-1), _pImgData(NULL){ lwassert(fileName); _fileName = fileName; size_t len = strlen(fileName); if ( len < 4 ){ lwerror("texture file name too short: filepath = " << _f(fileName)); _glId = -1; return; } _f fpath(fileName); if ( fileName[len-4] == '.' && fileName[len-3] == 'p' && fileName[len-2] == 'n' && fileName[len-1] == 'g'){ if ( fpath.isValid() ){ loadPNG(fpath, reserveData); }else{ lwerror("texture is not exist: " << fileName); return; } }else{ lwerror("only support PNG file: " << fileName); return; } }
MsgLogin::MsgLogin(const char *gcid, const char *gcname) { lwassert(gcid && gcname); std::stringstream ss; ss << HOST_AUTH << "/gclogin_e0252334753c435db65e9726544b6596?gcid=" << gcid << "&gcname=" << gcname; setURL(ss.str().c_str()); }
void Sprite::draw(){ ImageStaticData& d = g_imageStaticData; if ( d.vertexVec.empty() && d.batchInfoVec.empty() ){ return; } #ifdef USEVBO if ( d.vbo == -1 ){ glGenBuffers(1, &d.vbo); } #endif glDisable(GL_LIGHTING); glDepthMask(GL_FALSE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); const App::Config conf = App::getConfig(); float w = (float)conf.width; float h = (float)conf.height; #ifdef __APPLE__ float rotDegree = 0; const App::Orientation orient = App::getConfig().orientation; switch (orient) { case App::ORIENTATION_LEFT: rotDegree = 90; break; case App::ORIENTATION_RIGHT: rotDegree = -90; break; default: break; } glRotatef(rotDegree, 0, 0, 1); #endif #ifdef WIN32 int dOrient = (App::getConfig().orientation-App::getConfig().orientation0); float rotDegree = -dOrient * 90.f; glRotatef(rotDegree, 0, 0, 1); //if ( abs(dOrient) == 1 ){ // float temp = h; // h = w; // w = temp; //} #endif cml::Matrix44 m; cml::matrix_orthographic_RH(m, 0.f, w, -h, 0.f, Z_BEGIN, Z_END, cml::z_clip_neg_one); glMultMatrixf(m.data()); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); #ifdef USEVBO glBindBuffer(GL_ARRAY_BUFFER, d.vbo); glBufferData(GL_ARRAY_BUFFER, (int)d.vertexVec.size()*sizeof(Vertex), &(d.vertexVec[0]), GL_DYNAMIC_DRAW); glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (GLvoid*)0); glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid*)(sizeof(float)*3)); #else if ( !d.vertexVec.empty() ){ glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &(d.vertexVec[0])); char* p = (char*)&(d.vertexVec[0]); glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), p+(sizeof(float)*3)); } #endif bool blendEnabled = false; for ( size_t i = 0; i < d.batchInfoVec.size(); ++i ){ BatchInfo& batchInfo = d.batchInfoVec[i]; glColor4f(batchInfo.color.r/255.f, batchInfo.color.g/255.f, batchInfo.color.b/255.f, batchInfo.color.a/255.f); if ( !batchInfo.rsObjs.empty() ){ std::vector<RanderStateObj*>::iterator it = batchInfo.rsObjs.begin(); std::vector<RanderStateObj*>::iterator itEnd = batchInfo.rsObjs.end(); for ( ; it != itEnd; ++it ){ (*it)->set(); } } if ( batchInfo.vertexOffset == -2 ){ if ( !batchInfo.rsObjs.empty() ){ std::vector<RanderStateObj*>::iterator it = batchInfo.rsObjs.begin(); std::vector<RanderStateObj*>::iterator itEnd = batchInfo.rsObjs.end(); for ( ; it != itEnd; ++it ){ delete (*it); } } batchInfo.rsObjs.clear(); continue; } //model if ( batchInfo.vertexOffset == -1 ){ batchInfo.pModle->drawAsSprite(batchInfo.nodeIndex); if ( blendEnabled ){ glEnable(GL_BLEND); //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }else{ glDisable(GL_BLEND); } if ( !d.vertexVec.empty() && i < d.batchInfoVec.size()-1 ){ glEnable(GL_TEXTURE_2D); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &(d.vertexVec[0])); char* p = (char*)&(d.vertexVec[0]); glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), p+(sizeof(float)*3)); } if ( !batchInfo.rsObjs.empty() ){ std::vector<RanderStateObj*>::iterator it = batchInfo.rsObjs.begin(); std::vector<RanderStateObj*>::iterator itEnd = batchInfo.rsObjs.end(); for ( ; it != itEnd; ++it ){ delete (*it); } } batchInfo.rsObjs.clear(); continue; } bool shouldBlend = batchInfo.hasAlpha || batchInfo.color.a != 255; if ( shouldBlend != blendEnabled ){ blendEnabled = shouldBlend; if ( blendEnabled ){ glEnable(GL_BLEND); //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }else{ glDisable(GL_BLEND); } } glBindTexture(GL_TEXTURE_2D, batchInfo.textureId); lwassert(glGetError()==GL_NO_ERROR); //find next sprite batch int sz = 0; bool find = false; for ( size_t idx = i+1; idx < d.batchInfoVec.size(); ++idx ){ if ( d.batchInfoVec[idx].vertexOffset != -1 ){ sz = d.batchInfoVec[idx].vertexOffset - batchInfo.vertexOffset; find = true; break; } } if ( !find ){ sz = (int)d.vertexVec.size()-batchInfo.vertexOffset; } //if ( i == d.batchInfoVec.size() - 1 ){ // sz = (int)d.vertexVec.size()-batchInfo.vertexOffset; //}else{ // sz = d.batchInfoVec[i+1].vertexOffset - batchInfo.vertexOffset; //} glDrawArrays(GL_TRIANGLES, batchInfo.vertexOffset, sz); if ( !batchInfo.rsObjs.empty() ){ std::vector<RanderStateObj*>::iterator it = batchInfo.rsObjs.begin(); std::vector<RanderStateObj*>::iterator itEnd = batchInfo.rsObjs.end(); for ( ; it != itEnd; ++it ){ delete (*it); } batchInfo.rsObjs.clear(); } } glDepthMask(GL_TRUE); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); if ( blendEnabled ){ glDisable(GL_BLEND); } d.vertexVec.clear(); d.batchInfoVec.clear(); d.currTextureId = -1; //float z = g_currZ; g_currZ = Z_BEGIN+1.f; }
HTTPMsg::HTTPMsg(const wchar_t* objName, HTTPClient* pClient) :_pClient(pClient), _buff(BUFF_SIZE), _hRequest(0){ lwassert(objName); _objName = objName; }
EffectsRes::EffectsRes(const char *file, bool &ok) { lwassert(file); _file = file; tinyxml2::XMLDocument doc; doc.LoadFile(_f(file)); const tinyxml2::XMLElement *pElemLwfx = doc.RootElement(); const tinyxml2::XMLElement *pElemVS = pElemLwfx->FirstChildElement("vs"); lwassert(pElemVS); const char *vsSource = pElemVS->GetText(); const tinyxml2::XMLElement *pElemFS = pElemLwfx->FirstChildElement("fs"); lwassert(pElemFS); const char *fsSource = pElemFS->GetText(); GLuint vertShader, fragShader; if ( !compileShader(vertShader, GL_VERTEX_SHADER, vsSource) ) { ok = false; return; } if ( !compileShader(fragShader, GL_FRAGMENT_SHADER, fsSource) ) { ok = false; return; } _program = glCreateProgram(); glAttachShader(_program, vertShader); glAttachShader(_program, fragShader); if (!linkProgram(_program)) { lwerror("Failed to link program: " << _program); if (vertShader) { glDeleteShader(vertShader); vertShader = 0; } if (fragShader) { glDeleteShader(fragShader); fragShader = 0; } ok = false; return; } if (vertShader) { glDetachShader(_program, vertShader); glDeleteShader(vertShader); } if (fragShader) { glDetachShader(_program, fragShader); glDeleteShader(fragShader); } const const tinyxml2::XMLElement *pElemAttr = pElemLwfx->FirstChildElement("attribute"); while (pElemAttr) { LocSmt locSmt; const char *name = pElemAttr->Attribute("name"); const char *semantic = pElemAttr->Attribute("semantic"); locSmt.location = glGetAttribLocation(_program, name); if ( locSmt.location == -1 ) { lwerror("glGetAttribLocation failed"); } else { if ( strcmp(semantic, "POSITION") == 0 ) { locSmt.semantic = POSITION; } else if ( strcmp(semantic, "NORMAL") == 0 ) { locSmt.semantic = NORMAL; } else if ( strcmp(semantic, "BINORMAL") == 0 ) { locSmt.semantic = BINORMAL; } else if ( strcmp(semantic, "TANGENT") == 0 ) { locSmt.semantic = TANGENT; } else if ( strcmp(semantic, "UV0") == 0 ) { locSmt.semantic = UV0; } else if ( strcmp(semantic, "UV1") == 0 ) { locSmt.semantic = UV1; } else if ( strcmp(semantic, "UV2") == 0 ) { locSmt.semantic = UV2; } else if ( strcmp(semantic, "UV3") == 0 ) { locSmt.semantic = UV3; } else { locSmt.semantic = UNKNOWN; } if ( locSmt.semantic != UNKNOWN ) { _locSmts.push_back(locSmt); } } pElemAttr = pElemAttr->NextSiblingElement("attribute"); } const const tinyxml2::XMLElement *pElemUniform = pElemLwfx->FirstChildElement("uniform"); while (pElemUniform) { LocSmt locSmt; const char *name = pElemUniform->Attribute("name"); const char *semantic = pElemUniform->Attribute("semantic"); locSmt.location = glGetUniformLocation(_program, name); if ( locSmt.location == -1 ) { lwerror("glGetUniformLocation failed"); } else { if ( strcmp(semantic, "WORLDVIEW") == 0 ) { locSmt.semantic = WORLDVIEW; } else if ( strcmp(semantic, "WORLDVIEWPROJ") == 0 ) { locSmt.semantic = WORLDVIEWPROJ; } else if ( strcmp(semantic, "WORLDVIEWIT") == 0 ) { locSmt.semantic = WORLDVIEWIT; } else { locSmt.semantic = UNKNOWN; } if ( locSmt.semantic != UNKNOWN ) { _locSmts.push_back(locSmt); } } pElemUniform = pElemUniform->NextSiblingElement("uniform"); } ok = true; }
ModelSprite::ModelSprite(const char* podFileName, const char* nodeName, bool& ok){ ok = false; lwassert(podFileName && nodeName); CPVRTModelPOD pod; if(pod.ReadFromFile(_f(podFileName)) != PVR_SUCCESS){ lwerror("Failed to load pod file. file=" << podFileName); return; } //find node SPODNode* pNode = NULL; for ( int i = 0; i < (int)pod.nNumNode; ++i ){ if ( strcmp(pod.pNode[i].pszName, nodeName) == 0 ){ pNode = pod.pNode + i; } } if ( pNode == NULL ){ lwerror("node is not found: nodeName=" << nodeName); return; } if ( pNode->nIdx >= (int)pod.nNumMesh ){ lwerror("invalid mesh index"); return; } SPODMesh* pMesh = pod.pMesh+pNode->nIdx; char* bp = (char*)pMesh->sVertex.pData; unsigned int stride = pMesh->sVertex.nStride; unsigned short* pIndex = (unsigned short*)pMesh->sFaces.pData; char* bpUV = (char*)pMesh->psUVW[0].pData; unsigned int strideUV = pMesh->psUVW[0].nStride; float* pv = NULL; Sprite::Vertex vtx; for ( unsigned int j = 0; j < pMesh->nNumFaces; ++j ){ for ( int ii = 0; ii < 3; ++ii ){ pv = (float*)(bp + (*pIndex)*stride); vtx.x = *pv; vtx.y = *(pv+1); vtx.z = 0; pv = (float*)(bpUV + (*pIndex)*strideUV); vtx.u = *pv; vtx.v = *(pv+1); _vertexVec.push_back(vtx); ++pIndex; } } SPODMaterial* pMaterial = &pod.pMaterial[pNode->nIdxMaterial]; int textureIndex = pMaterial->nIdxTexDiffuse; if ( textureIndex == -1 ){ _glId = 0; _hasAlpha = false; }else{ const char* textureName = pod.pTexture[textureIndex].pszName; if ( textureName == NULL ){ lwerror("textureName == NULL"); return; } const char* p = strrchr(textureName, '.'); std::string str = textureName; if ( p ){ str.resize(p-textureName); } str.append(".png"); _pTextureRes = PODTextureRes::create(str.c_str()); if ( _pTextureRes == NULL ){ lwerror("PODTextureRes::create failed"); return; } _glId = _pTextureRes->getGlId(); _hasAlpha = _pTextureRes->getHeader()->dwAlphaBitMask != 0; } ok = true; }
void PODModel::collectAsSprite(unsigned char nodeIndex){ lwassert(0 || "not implemented"); }
void Font::collect(){ if ( _needUpdate ){ update(); } const wchar_t* text = _text.c_str(); size_t len = _text.size(); const wchar_t* p = text; float currX = _posX; if ( !_linesOffset.empty() ){ currX += _linesOffset[0]; } float currY = _y0; int currLine = 1; const FontRes::CommonInfo& comInfo = _pRes->getCommonInfo(); const std::map<wchar_t, FontRes::CharInfo>& charInfoMap = _pRes->getCharInfoMap(); const std::vector<Sprite*> sprites = _pRes->getSprites(); while ( p < text+len ){ if ( *p == '\n' ){ currY += comInfo.lineHeight*_scaleY; currX = _posX; if ( currLine < (int)_linesOffset.size() ){ currX += _linesOffset[currLine]; } ++currLine; }else{ std::map<wchar_t, FontRes::CharInfo>::const_iterator it = charInfoMap.find(*p); if ( it == charInfoMap.end() ){ it = charInfoMap.find(' '); if ( it == charInfoMap.end() ){ currX += 3; ++p; continue; } } const FontRes::CharInfo& charInfo = it->second; lwassert(charInfo.page < sprites.size()); Sprite* pSprite = sprites[charInfo.page]; pSprite->setUV(charInfo.x, charInfo.y, charInfo.w, charInfo.h); if ( _rotate == 0 ){ pSprite->setPos((float)currX+charInfo.xoffset, (float)currY+charInfo.yoffset*_scaleY); pSprite->setScale(_scaleX, _scaleY); pSprite->setColor(_color); pSprite->setRotate(0); pSprite->collect(); }else{ cml::Vector2 v2; v2[0] = (float)currX+charInfo.xoffset-_posX; v2[1] = (float)currY+charInfo.yoffset-_posY; v2 = cml::rotate_vector_2D(v2, _rotate); pSprite->setPos(_posX+v2[0], _posY+v2[1]); pSprite->setScale(_scaleX, _scaleY); pSprite->setRotate(_rotate); pSprite->setColor(_color); pSprite->collect(); } currX += charInfo.xadvance*_scaleX; } ++p; } }
FontRes::FontRes(const char* fileName, bool& ok){ ok = false; lwassert(fileName); _fileName = fileName; FILE* pf = fopen(_f(fileName), "rb"); if ( pf == NULL ){ lwerror("fopen failed: fileName=" << fileName); return; } //"BMF" and version char bmfAndVersion[4]; fread(bmfAndVersion, sizeof(bmfAndVersion), 1, pf); if ( bmfAndVersion[0] != 'B' && bmfAndVersion[1] != 'M' && bmfAndVersion[2] != 'F' ){ lwerror("not BMF head"); fclose(pf); } if ( bmfAndVersion[3] != 3 ){ lwerror("version 3 needed: this file version=" << (int)(bmfAndVersion[3])); fclose(pf); } //Block type 1: info char blockType = 0; int blockSize = 0; fread(&blockType, sizeof(blockType), 1, pf); lwassert(blockType == 1); fread(&blockSize, sizeof(blockSize), 1, pf); fseek(pf, blockSize, SEEK_CUR); //Block type 2: common fread(&blockType, sizeof(blockType), 1, pf); lwassert(blockType == 2); fread(&blockSize, sizeof(blockSize), 1, pf); fread(&_commonInfo, blockSize, 1, pf); //Block type 3: pages fread(&blockType, sizeof(blockType), 1, pf); lwassert(blockType == 3); fread(&blockSize, sizeof(blockSize), 1, pf); char* buf = new char[blockSize]; fread(buf, blockSize, 1, pf); char* p = buf; int strSize = 0; while ( p < buf + blockSize ){ strSize = (int)strlen(p); Sprite* pSprite = Sprite::create(p); if ( pSprite == NULL ){ lwerror("font create sprite failed: fileName=" << p); delete [] buf; fclose(pf); return; } _sprites.push_back(pSprite); p += strSize + 1; } delete [] buf; //Block type 4: chars fread(&blockType, sizeof(blockType), 1, pf); lwassert(blockType == 4); fread(&blockSize, sizeof(blockSize), 1, pf); int numChars = blockSize/20; CharInfo cf; for ( int i = 0; i < numChars; ++i ){ fread(&cf, sizeof(cf), 1, pf); wchar_t wc = cf.id; _charInfoMap[wc] = cf; } fclose(pf); ok = true; }