kick
|
00001 // 00002 // Created by morten on 30/06/14. 00003 // 00004 00005 #include "label.h" 00006 #include <iostream> 00007 #include "kick/mesh/mesh.h" 00008 #include "glm/gtx/string_cast.hpp" 00009 00010 using namespace std; 00011 using namespace glm; 00012 00013 namespace kick { 00014 00015 Label::Label(GameObject *gameObject, std::shared_ptr<Canvas> canvas) 00016 : Component2D(gameObject, canvas), 00017 mBounds{vec2{0,0},vec2{0,0}} { 00018 mMesh = new Mesh(); 00019 mMeshData = make_shared<MeshData>(); 00020 mMaterial = new Material(); 00021 mMesh->setMeshData(mMeshData); 00022 } 00023 00024 std::string const &Label::text() const { 00025 return mText; 00026 } 00027 00028 void Label::setText(std::string const &text) { 00029 Label::mText = text; 00030 updateVertexBuffer(); 00031 } 00032 00033 void Label::render(EngineUniforms *engineUniforms) { 00034 if (!mFont) return; 00035 auto shader = mMaterial->shader(); 00036 assert(shader); 00037 mMesh->bind(shader.get()); 00038 shader->bind_uniforms(mMaterial, engineUniforms, transform().get()); 00039 mMesh->render(0); 00040 } 00041 00042 void Label::setFont(std::shared_ptr<Font>& font) { 00043 if (!font->initialized()){ 00044 font->loadFntFile(); 00045 } 00046 Label::mFont = font; 00047 auto setupFont = [&](Font* f){ 00048 mMaterial->setShader(f->getShader()); 00049 mMaterial->setUniform("mainTexture", f->texture()); 00050 }; 00051 setupFont(font.get()); 00052 mEventListener = font->fontListener.createListener(setupFont); 00053 updateVertexBuffer(); 00054 } 00055 00056 std::shared_ptr<Font> Label::font() const { 00057 return mFont; 00058 } 00059 00060 void Label::updateVertexBuffer() { 00061 if (!mFont || mText.length() ==0) { 00062 mMeshData->setSubmesh(0, {}, MeshType::Triangles); 00063 mMesh->setMeshData(mMeshData); 00064 return; 00065 } 00066 vector<vec3> position; 00067 vector<vec2> textureCoords; 00068 vector<GLushort> indices; 00069 vec2 caret{-mFont->width(mText) * mAnchor.x, -mFont->height() * mAnchor.y}; 00070 00071 if (mText.length()>0){ // if first char is x-offset, then undo offset to fix horizontal alignment 00072 const FontChar fc = mFont->getChar(mText[0]); 00073 caret.x -= fc.xoffset; 00074 } 00075 00076 mBounds.max = vec2{-FLT_MAX}; 00077 mBounds.min = vec2{FLT_MAX}; 00078 GLushort vertexCount = 0; 00079 int lastChar = -1; 00080 for (unsigned short i=0;i< mText.length();i++){ 00081 const FontChar fc = mFont->getChar(mText[i]); 00082 00083 caret.x += mFont->getKerning(lastChar, mText[i]); 00084 bool visibleCharacter = fc.width > 0; 00085 if (visibleCharacter) { 00086 vec2 basePoint = caret + vec2{fc.xoffset, mFont->height()-fc.height-fc.yoffset}; 00087 position.push_back(vec3{basePoint,0}); 00088 position.push_back(vec3{basePoint+vec2{fc.width,0},0}); 00089 position.push_back(vec3{basePoint+vec2{fc.width,fc.height},0}); 00090 position.push_back(vec3{basePoint+vec2{0 ,fc.height},0}); 00091 00092 mBounds.min = glm::min(mBounds.min, basePoint); 00093 mBounds.max = glm::max(mBounds.max, (vec2)position[position.size()-2]); 00094 00095 vec2 scale{1.0f / mFont->scaleW(), 1.0f / mFont->scaleH()}; 00096 00097 textureCoords.push_back(vec2{fc.x , mFont->scaleH()-fc.y-fc.height}*scale); 00098 textureCoords.push_back(vec2{fc.x+fc.width, mFont->scaleH()-fc.y-fc.height}*scale); 00099 textureCoords.push_back(vec2{fc.x+fc.width, mFont->scaleH()-fc.y}*scale); 00100 textureCoords.push_back(vec2{fc.x , mFont->scaleH()-fc.y}*scale); 00101 00102 // push two triangles 00103 indices.push_back(vertexCount); 00104 indices.push_back(vertexCount + (GLushort)1); 00105 indices.push_back(vertexCount + (GLushort)2); 00106 indices.push_back(vertexCount + (GLushort)2); 00107 indices.push_back(vertexCount + (GLushort)3); 00108 indices.push_back(vertexCount); 00109 00110 vertexCount += 4; 00111 } 00112 caret.x += fc.xadvance; 00113 lastChar = mText[i]; 00114 } 00115 00116 mMeshData->setPosition(position); 00117 mMeshData->setTexCoord0(textureCoords); 00118 mMeshData->setSubmesh(0,indices, MeshType::Triangles); 00119 mMesh->setMeshData(mMeshData); 00120 } 00121 00122 Bounds2 Label::bounds() const { 00123 return mBounds; 00124 } 00125 00126 Material *Label::material() const { 00127 return mMaterial; 00128 } 00129 00130 void Label::setMaterial(Material *material) { 00131 assert(material); 00132 Label::mMaterial = material; 00133 material->setShader(mFont->getShader()); 00134 material->setUniform("mainTexture", mFont->texture()); 00135 } 00136 00137 int Label::renderOrder() { 00138 return mMaterial->renderOrder(); 00139 } 00140 00141 void Label::setAnchor(glm::vec2 anchor) { 00142 if (anchor != Label::mAnchor){ 00143 Label::mAnchor = anchor; 00144 updateVertexBuffer(); 00145 } 00146 } 00147 00148 glm::vec2 Label::anchor() const { 00149 return mAnchor; 00150 } 00151 00152 Shader *Label::shader() const { 00153 if (mMaterial){ 00154 return mMaterial->shader().get(); 00155 } 00156 return nullptr; 00157 } 00158 00159 void Label::setBounds(Bounds2 bounds) { 00160 cout << "Implement" << endl; 00161 } 00162 }