00001 /*------------------------------------------------------------------------- 00002 This source file is a part of OGRE 00003 (Object-oriented Graphics Rendering Engine) 00004 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright © 2000-2002 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This library is free software; you can redistribute it and/or modify it 00011 under the terms of the GNU Lesser General Public License (LGPL) as 00012 published by the Free Software Foundation; either version 2.1 of the 00013 License, or (at your option) any later version. 00014 00015 This library is distributed in the hope that it will be useful, but 00016 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00017 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00018 License for more details. 00019 00020 You should have received a copy of the GNU Lesser General Public License 00021 along with this library; if not, write to the Free Software Foundation, 00022 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or go to 00023 http://www.gnu.org/copyleft/lesser.txt 00024 -------------------------------------------------------------------------*/ 00025 00026 #include "OgreTextAreaGuiElement.h" 00027 #include "OgreRoot.h" 00028 #include "OgreLogManager.h" 00029 #include "OgreOverlayManager.h" 00030 #include "OgreHardwareBufferManager.h" 00031 #include "OgreHardwareVertexBuffer.h" 00032 #include "OgreException.h" 00033 00034 namespace Ogre { 00035 00036 #define DEFAULT_INITIAL_CHARS 12 00037 //--------------------------------------------------------------------- 00038 String TextAreaGuiElement::msTypeName = "TextArea"; 00039 TextAreaGuiElement::CmdCharHeight TextAreaGuiElement::msCmdCharHeight; 00040 TextAreaGuiElement::CmdSpaceWidth TextAreaGuiElement::msCmdSpaceWidth; 00041 TextAreaGuiElement::CmdFontName TextAreaGuiElement::msCmdFontName; 00042 TextAreaGuiElement::CmdColour TextAreaGuiElement::msCmdColour; 00043 TextAreaGuiElement::CmdColourBottom TextAreaGuiElement::msCmdColourBottom; 00044 TextAreaGuiElement::CmdColourTop TextAreaGuiElement::msCmdColourTop; 00045 TextAreaGuiElement::CmdAlignment TextAreaGuiElement::msCmdAlignment; 00046 //--------------------------------------------------------------------- 00047 #define POS_TEX_BINDING 0 00048 #define COLOUR_BINDING 1 00049 //--------------------------------------------------------------------- 00050 TextAreaGuiElement::TextAreaGuiElement(const String& name) 00051 : GuiElement(name) 00052 { 00053 mTransparent = false; 00054 mAlignment = Left; 00055 mpFont = 0; 00056 00057 mColourTop = ColourValue::White; 00058 mColourBottom = ColourValue::White; 00059 mColoursChanged = true; 00060 00061 mAllocSize = 0; 00062 00063 mCharHeight = 0.02; 00064 mPixelCharHeight = 12; 00065 mSpaceWidth = 0; 00066 mPixelSpaceWidth = 0; 00067 00068 if (createParamDictionary("TextAreaGuiElement")) 00069 { 00070 addBaseParameters(); 00071 } 00072 } 00073 00074 void TextAreaGuiElement::initialise(void) 00075 { 00076 // Set up the render op 00077 // Combine positions and texture coords since they tend to change together 00078 // since character sizes are different 00079 mRenderOp.vertexData = new VertexData(); 00080 VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; 00081 size_t offset = 0; 00082 // Positions 00083 decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT3, VES_POSITION); 00084 offset += VertexElement::getTypeSize(VET_FLOAT3); 00085 // Texcoords 00086 decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); 00087 offset += VertexElement::getTypeSize(VET_FLOAT2); 00088 // Colours - store these in a separate buffer because they change less often 00089 decl->addElement(COLOUR_BINDING, 0, VET_COLOUR, VES_DIFFUSE); 00090 00091 mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; 00092 mRenderOp.useIndexes = false; 00093 mRenderOp.vertexData->vertexStart = 0; 00094 // Vertex buffer will be created in checkMemoryAllocation 00095 00096 checkMemoryAllocation( DEFAULT_INITIAL_CHARS ); 00097 00098 } 00099 00100 void TextAreaGuiElement::checkMemoryAllocation( size_t numChars ) 00101 { 00102 if( mAllocSize < numChars) 00103 { 00104 // Create and bind new buffers 00105 // Note that old buffers will be deleted automatically through reference counting 00106 00107 // 6 verts per char since we're doing tri lists without indexes 00108 // Allocate space for positions & texture coords 00109 VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; 00110 VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; 00111 00112 mRenderOp.vertexData->vertexCount = numChars * 6; 00113 00114 // Create dynamic since text tends to change alot 00115 // positions & texcoords 00116 HardwareVertexBufferSharedPtr vbuf = 00117 HardwareBufferManager::getSingleton(). 00118 createVertexBuffer( 00119 decl->getVertexSize(POS_TEX_BINDING), 00120 mRenderOp.vertexData->vertexCount, 00121 HardwareBuffer::HBU_DYNAMIC); 00122 bind->setBinding(POS_TEX_BINDING, vbuf); 00123 00124 // colours 00125 vbuf = HardwareBufferManager::getSingleton(). 00126 createVertexBuffer( 00127 decl->getVertexSize(COLOUR_BINDING), 00128 mRenderOp.vertexData->vertexCount, 00129 HardwareBuffer::HBU_DYNAMIC); 00130 bind->setBinding(COLOUR_BINDING, vbuf); 00131 00132 mAllocSize = numChars; 00133 mColoursChanged = true; // force colour buffer regeneration 00134 } 00135 00136 } 00137 00138 void TextAreaGuiElement::updateGeometry() 00139 { 00140 Real *pVert; 00141 00142 if (!mpFont) 00143 { 00144 // not initialised yet, probably due to the order of creation in a template 00145 return; 00146 } 00147 00148 size_t charlen = mCaption.size(); 00149 checkMemoryAllocation( charlen ); 00150 00151 mRenderOp.vertexData->vertexCount = charlen * 6; 00152 // Get position / texcoord buffer 00153 HardwareVertexBufferSharedPtr vbuf = 00154 mRenderOp.vertexData->vertexBufferBinding->getBuffer(POS_TEX_BINDING); 00155 pVert = static_cast<Real*>( 00156 vbuf->lock(HardwareBuffer::HBL_DISCARD) ); 00157 00158 float largestWidth = 0; 00159 float left = _getDerivedLeft() * 2.0 - 1.0; 00160 float top = -( (_getDerivedTop() * 2.0 ) - 1.0 ); 00161 00162 // Derive space with from a capital A 00163 if (mSpaceWidth == 0) 00164 { 00165 mSpaceWidth = mpFont->getGlyphAspectRatio( 'A' ) * mCharHeight * 2.0; 00166 } 00167 00168 // Use iterator 00169 String::iterator i, iend; 00170 iend = mCaption.end(); 00171 bool newLine = true; 00172 for( i = mCaption.begin(); i != iend; ++i ) 00173 { 00174 if( newLine ) 00175 { 00176 Real len = 0.0f; 00177 for( String::iterator j = i; j != iend && *j != '\n'; j++ ) 00178 { 00179 if (*j == ' ') 00180 { 00181 len += mSpaceWidth; 00182 } 00183 else 00184 { 00185 len += mpFont->getGlyphAspectRatio( *j ) * mCharHeight * 2.0; 00186 } 00187 } 00188 00189 if( mAlignment == Right ) 00190 left -= len; 00191 else if( mAlignment == Center ) 00192 left -= len * 0.5; 00193 00194 newLine = false; 00195 } 00196 00197 if( *i == '\n' ) 00198 { 00199 left = _getDerivedLeft() * 2.0 - 1.0; 00200 top -= mCharHeight * 2.0; 00201 newLine = true; 00202 // Also reduce tri count 00203 mRenderOp.vertexData->vertexCount -= 6; 00204 continue; 00205 } 00206 00207 if ( *i == ' ') 00208 { 00209 // Just leave a gap, no tris 00210 left += mSpaceWidth; 00211 // Also reduce tri count 00212 mRenderOp.vertexData->vertexCount -= 6; 00213 continue; 00214 } 00215 00216 Real horiz_height = mpFont->getGlyphAspectRatio( *i ); 00217 Real u1, u2, v1, v2; 00218 mpFont->getGlyphTexCoords( *i, u1, v1, u2, v2 ); 00219 00220 // each vert is (x, y, z, u, v) 00221 //------------------------------------------------------------------------------------- 00222 // First tri 00223 // 00224 // Upper left 00225 *pVert++ = left; 00226 *pVert++ = top; 00227 *pVert++ = -1.0; 00228 *pVert++ = u1; 00229 *pVert++ = v1; 00230 00231 top -= mCharHeight * 2.0; 00232 00233 // Bottom left 00234 *pVert++ = left; 00235 *pVert++ = top; 00236 *pVert++ = -1.0; 00237 *pVert++ = u1; 00238 *pVert++ = v2; 00239 00240 top += mCharHeight * 2.0; 00241 left += horiz_height * mCharHeight * 2.0; 00242 00243 // Top right 00244 *pVert++ = left; 00245 *pVert++ = top; 00246 *pVert++ = -1.0; 00247 *pVert++ = u2; 00248 *pVert++ = v1; 00249 //------------------------------------------------------------------------------------- 00250 00251 //------------------------------------------------------------------------------------- 00252 // Second tri 00253 // 00254 // Top right (again) 00255 *pVert++ = left; 00256 *pVert++ = top; 00257 *pVert++ = -1.0; 00258 *pVert++ = u2; 00259 *pVert++ = v1; 00260 00261 top -= mCharHeight * 2.0; 00262 left -= horiz_height * mCharHeight * 2.0; 00263 00264 // Bottom left (again) 00265 *pVert++ = left; 00266 *pVert++ = top; 00267 *pVert++ = -1.0; 00268 *pVert++ = u1; 00269 *pVert++ = v2; 00270 00271 left += horiz_height * mCharHeight * 2.0; 00272 00273 // Bottom right 00274 *pVert++ = left; 00275 *pVert++ = top; 00276 *pVert++ = -1.0; 00277 *pVert++ = u2; 00278 *pVert++ = v2; 00279 //------------------------------------------------------------------------------------- 00280 00281 // Go back up with top 00282 top += mCharHeight * 2.0; 00283 00284 float currentWidth = (left + 1)/2 - _getDerivedLeft(); 00285 if (currentWidth > largestWidth) 00286 { 00287 largestWidth = currentWidth; 00288 00289 } 00290 } 00291 // Unlock vertex buffer 00292 vbuf->unlock(); 00293 00294 if (mMetricsMode == GMM_PIXELS) 00295 { 00296 // Derive parametric version of dimensions 00297 Real vpWidth; 00298 vpWidth = (Real) (OverlayManager::getSingleton().getViewportWidth()); 00299 00300 largestWidth *= vpWidth; 00301 }; 00302 00303 if (getWidth() < largestWidth) 00304 setWidth(largestWidth); 00305 updateColours(); 00306 00307 } 00308 00309 void TextAreaGuiElement::updatePositionGeometry() 00310 { 00311 updateGeometry(); 00312 } 00313 00314 void TextAreaGuiElement::setCaption( const String& caption ) 00315 { 00316 mCaption = caption; 00317 updateGeometry(); 00318 00319 } 00320 const String& TextAreaGuiElement::getCaption() const 00321 { 00322 return mCaption; 00323 } 00324 00325 void TextAreaGuiElement::setFontName( const String& font ) 00326 { 00327 mpFont = (Font*)FontManager::getSingleton().getByName( font ); 00328 if (!mpFont) 00329 Except( Exception::ERR_ITEM_NOT_FOUND, "Could not find font " + font, 00330 "TextAreaGuiElement::setFontName" ); 00331 mpFont->load(); 00332 mpMaterial = mpFont->getMaterial(); 00333 mpMaterial->setDepthCheckEnabled(false); 00334 mpMaterial->setLightingEnabled(false); 00335 00336 updateGeometry(); 00337 } 00338 const String& TextAreaGuiElement::getFontName() const 00339 { 00340 return mpFont->getName(); 00341 } 00342 00343 void TextAreaGuiElement::setCharHeight( Real height ) 00344 { 00345 if (mMetricsMode == GMM_PIXELS) 00346 { 00347 mPixelCharHeight = height; 00348 } 00349 else 00350 { 00351 mCharHeight = height; 00352 } 00353 mGeomPositionsOutOfDate = true; 00354 } 00355 Real TextAreaGuiElement::getCharHeight() const 00356 { 00357 if (mMetricsMode == GMM_PIXELS) 00358 { 00359 return mPixelCharHeight; 00360 } 00361 else 00362 { 00363 return mCharHeight; 00364 } 00365 } 00366 00367 void TextAreaGuiElement::setSpaceWidth( Real width ) 00368 { 00369 if (mMetricsMode == GMM_PIXELS) 00370 { 00371 mPixelSpaceWidth = width; 00372 } 00373 else 00374 { 00375 mSpaceWidth = width; 00376 } 00377 00378 mGeomPositionsOutOfDate = true; 00379 } 00380 Real TextAreaGuiElement::getSpaceWidth() const 00381 { 00382 if (mMetricsMode == GMM_PIXELS) 00383 { 00384 return mPixelSpaceWidth; 00385 } 00386 else 00387 { 00388 return mSpaceWidth; 00389 } 00390 } 00391 00392 //--------------------------------------------------------------------- 00393 TextAreaGuiElement::~TextAreaGuiElement() 00394 { 00395 delete mRenderOp.vertexData; 00396 } 00397 //--------------------------------------------------------------------- 00398 const String& TextAreaGuiElement::getTypeName(void) const 00399 { 00400 return msTypeName; 00401 } 00402 //--------------------------------------------------------------------- 00403 void TextAreaGuiElement::getRenderOperation(RenderOperation& op) 00404 { 00405 op = mRenderOp; 00406 } 00407 //--------------------------------------------------------------------- 00408 void TextAreaGuiElement::setMaterialName(const String& matName) 00409 { 00410 GuiElement::setMaterialName(matName); 00411 updateGeometry(); 00412 } 00413 //--------------------------------------------------------------------- 00414 void TextAreaGuiElement::addBaseParameters(void) 00415 { 00416 GuiElement::addBaseParameters(); 00417 ParamDictionary* dict = getParamDictionary(); 00418 00419 dict->addParameter(ParameterDef("char_height", 00420 "Sets the height of the characters in relation to the screen." 00421 , PT_REAL), 00422 &msCmdCharHeight); 00423 00424 dict->addParameter(ParameterDef("space_width", 00425 "Sets the width of a space in relation to the screen." 00426 , PT_REAL), 00427 &msCmdSpaceWidth); 00428 00429 dict->addParameter(ParameterDef("font_name", 00430 "Sets the name of the font to use." 00431 , PT_STRING), 00432 &msCmdFontName); 00433 00434 dict->addParameter(ParameterDef("colour", 00435 "Sets the colour of the font (a solid colour)." 00436 , PT_STRING), 00437 &msCmdColour); 00438 00439 dict->addParameter(ParameterDef("colour_bottom", 00440 "Sets the colour of the font at the bottom (a gradient colour)." 00441 , PT_STRING), 00442 &msCmdColourBottom); 00443 00444 dict->addParameter(ParameterDef("colour_top", 00445 "Sets the colour of the font at the top (a gradient colour)." 00446 , PT_STRING), 00447 &msCmdColourTop); 00448 00449 dict->addParameter(ParameterDef("alignment", 00450 "Sets the alignment of the text: 'left', 'center' or 'right'." 00451 , PT_STRING), 00452 &msCmdAlignment); 00453 } 00454 //--------------------------------------------------------------------- 00455 void TextAreaGuiElement::setColour(const ColourValue& col) 00456 { 00457 mColourBottom = mColourTop = col; 00458 mColoursChanged = true; 00459 updateColours(); 00460 } 00461 //--------------------------------------------------------------------- 00462 const ColourValue& TextAreaGuiElement::getColour(void) const 00463 { 00464 // Either one 00465 return mColourTop; 00466 } 00467 //--------------------------------------------------------------------- 00468 void TextAreaGuiElement::setColourBottom(const ColourValue& col) 00469 { 00470 mColourBottom = col; 00471 mColoursChanged = true; 00472 updateColours(); 00473 } 00474 //--------------------------------------------------------------------- 00475 const ColourValue& TextAreaGuiElement::getColourBottom(void) const 00476 { 00477 return mColourBottom; 00478 } 00479 //--------------------------------------------------------------------- 00480 void TextAreaGuiElement::setColourTop(const ColourValue& col) 00481 { 00482 mColourTop = col; 00483 mColoursChanged = true; 00484 updateColours(); 00485 } 00486 //--------------------------------------------------------------------- 00487 const ColourValue& TextAreaGuiElement::getColourTop(void) const 00488 { 00489 return mColourTop; 00490 } 00491 //--------------------------------------------------------------------- 00492 void TextAreaGuiElement::updateColours(void) 00493 { 00494 if (!mColoursChanged) return; // do nothing if colours haven't changed 00495 00496 // Convert to system-specific 00497 RGBA topColour, bottomColour; 00498 Root::getSingleton().convertColourValue(mColourTop, &topColour); 00499 Root::getSingleton().convertColourValue(mColourBottom, &bottomColour); 00500 00501 HardwareVertexBufferSharedPtr vbuf = 00502 mRenderOp.vertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING); 00503 00504 RGBA* pDest = static_cast<RGBA*>( 00505 vbuf->lock(HardwareBuffer::HBL_DISCARD) ); 00506 00507 for (size_t i = 0; i < mAllocSize; ++i) 00508 { 00509 // First tri (top, bottom, top) 00510 *pDest++ = topColour; 00511 *pDest++ = bottomColour; 00512 *pDest++ = topColour; 00513 // Second tri (top, bottom, bottom) 00514 *pDest++ = topColour; 00515 *pDest++ = bottomColour; 00516 *pDest++ = bottomColour; 00517 } 00518 vbuf->unlock(); 00519 00520 mColoursChanged = false; 00521 00522 } 00523 //----------------------------------------------------------------------- 00524 void TextAreaGuiElement::setMetricsMode(GuiMetricsMode gmm) 00525 { 00526 GuiElement::setMetricsMode(gmm); 00527 if (gmm == GMM_PIXELS) 00528 { 00529 mPixelCharHeight = mCharHeight; 00530 mPixelSpaceWidth = mSpaceWidth; 00531 } 00532 } 00533 //----------------------------------------------------------------------- 00534 void TextAreaGuiElement::_update(void) 00535 { 00536 if (mMetricsMode == GMM_PIXELS && 00537 (OverlayManager::getSingleton().hasViewportChanged() || mGeomPositionsOutOfDate)) 00538 { 00539 // Recalc character size 00540 Real vpHeight; 00541 vpHeight = (Real) (OverlayManager::getSingleton().getViewportHeight()); 00542 00543 mCharHeight = (Real) mPixelCharHeight / vpHeight; 00544 mSpaceWidth = (Real) mPixelSpaceWidth / vpHeight; 00545 mGeomPositionsOutOfDate = true; 00546 } 00547 GuiElement::_update(); 00548 } 00549 //--------------------------------------------------------------------------------------------- 00550 // Char height command object 00551 // 00552 String TextAreaGuiElement::CmdCharHeight::doGet( const void* target ) const 00553 { 00554 return StringConverter::toString( 00555 static_cast< const TextAreaGuiElement* >( target )->getCharHeight() ); 00556 } 00557 void TextAreaGuiElement::CmdCharHeight::doSet( void* target, const String& val ) 00558 { 00559 static_cast< TextAreaGuiElement* >( target )->setCharHeight( 00560 StringConverter::parseReal( val ) ); 00561 } 00562 //--------------------------------------------------------------------------------------------- 00563 // Space width command object 00564 // 00565 String TextAreaGuiElement::CmdSpaceWidth::doGet( const void* target ) const 00566 { 00567 return StringConverter::toString( 00568 static_cast< const TextAreaGuiElement* >( target )->getSpaceWidth() ); 00569 } 00570 void TextAreaGuiElement::CmdSpaceWidth::doSet( void* target, const String& val ) 00571 { 00572 static_cast< TextAreaGuiElement* >( target )->setSpaceWidth( 00573 StringConverter::parseReal( val ) ); 00574 } 00575 //--------------------------------------------------------------------------------------------- 00576 00577 //--------------------------------------------------------------------------------------------- 00578 // Font name command object 00579 // 00580 String TextAreaGuiElement::CmdFontName::doGet( const void* target ) const 00581 { 00582 return static_cast< const TextAreaGuiElement* >( target )->getFontName(); 00583 } 00584 void TextAreaGuiElement::CmdFontName::doSet( void* target, const String& val ) 00585 { 00586 static_cast< TextAreaGuiElement* >( target )->setFontName( val ); 00587 } 00588 //--------------------------------------------------------------------------------------------- 00589 //--------------------------------------------------------------------------------------------- 00590 // Colour command object 00591 // 00592 String TextAreaGuiElement::CmdColour::doGet( const void* target ) const 00593 { 00594 return StringConverter::toString ( 00595 static_cast< const TextAreaGuiElement* >( target )->getColour()); 00596 } 00597 void TextAreaGuiElement::CmdColour::doSet( void* target, const String& val ) 00598 { 00599 static_cast< TextAreaGuiElement* >( target )->setColour( 00600 StringConverter::parseColourValue(val) ); 00601 } 00602 //--------------------------------------------------------------------------------------------- 00603 //--------------------------------------------------------------------------------------------- 00604 //--------------------------------------------------------------------------------------------- 00605 // Top colour command object 00606 // 00607 String TextAreaGuiElement::CmdColourTop::doGet( const void* target ) const 00608 { 00609 return StringConverter::toString ( 00610 static_cast< const TextAreaGuiElement* >( target )->getColourTop()); 00611 } 00612 void TextAreaGuiElement::CmdColourTop::doSet( void* target, const String& val ) 00613 { 00614 static_cast< TextAreaGuiElement* >( target )->setColourTop( 00615 StringConverter::parseColourValue(val) ); 00616 } 00617 //--------------------------------------------------------------------------------------------- 00618 //--------------------------------------------------------------------------------------------- 00619 //--------------------------------------------------------------------------------------------- 00620 // Bottom colour command object 00621 // 00622 String TextAreaGuiElement::CmdColourBottom::doGet( const void* target ) const 00623 { 00624 return StringConverter::toString ( 00625 static_cast< const TextAreaGuiElement* >( target )->getColourBottom()); 00626 } 00627 void TextAreaGuiElement::CmdColourBottom::doSet( void* target, const String& val ) 00628 { 00629 static_cast< TextAreaGuiElement* >( target )->setColourBottom( 00630 StringConverter::parseColourValue(val) ); 00631 } 00632 //--------------------------------------------------------------------------------------------- 00633 //--------------------------------------------------------------------------------------------- 00634 //--------------------------------------------------------------------------------------------- 00635 // Alignment command object 00636 // 00637 String TextAreaGuiElement::CmdAlignment::doGet( const void* target ) const 00638 { 00639 Alignment align = static_cast< const TextAreaGuiElement* >( target )->getAlignment(); 00640 switch (align) 00641 { 00642 case Left: 00643 return "left"; 00644 case Center: 00645 return "center"; 00646 case Right: 00647 return "right"; 00648 00649 } 00650 // To keep compiler happy 00651 return "left"; 00652 } 00653 void TextAreaGuiElement::CmdAlignment::doSet( void* target, const String& val ) 00654 { 00655 if (val == "center") 00656 { 00657 static_cast< TextAreaGuiElement* >( target )->setAlignment(Center); 00658 } 00659 else if (val == "right") 00660 { 00661 static_cast< TextAreaGuiElement* >( target )->setAlignment(Right); 00662 } 00663 else 00664 { 00665 static_cast< TextAreaGuiElement* >( target )->setAlignment(Left); 00666 } 00667 } 00668 //--------------------------------------------------------------------------------------------- 00669 }
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:30 2004