source: OGRE/trunk/ogrenew/OgreMain/src/OgreTextAreaOverlayElement.cpp @ 657

Revision 657, 23.1 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*-------------------------------------------------------------------------
2This source file is a part of OGRE
3(Object-oriented Graphics Rendering Engine)
4
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This library is free software; you can redistribute it and/or modify it
11under the terms of the GNU Lesser General Public License (LGPL) as
12published by the Free Software Foundation; either version 2.1 of the
13License, or (at your option) any later version.
14
15This library is distributed in the hope that it will be useful, but
16WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
18License for more details.
19
20You should have received a copy of the GNU Lesser General Public License
21along with this library; if not, write to the Free Software Foundation,
22Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA or go to
23http://www.gnu.org/copyleft/lesser.txt
24-------------------------------------------------------------------------*/
25#include "OgreStableHeaders.h"
26
27#include "OgreTextAreaOverlayElement.h"
28#include "OgreRoot.h"
29#include "OgreLogManager.h"
30#include "OgreOverlayManager.h"
31#include "OgreHardwareBufferManager.h"
32#include "OgreHardwareVertexBuffer.h"
33#include "OgreException.h"
34#include "OgreStringConverter.h"
35#include "OgreFont.h"
36#include "OgreFontManager.h"
37
38namespace Ogre {
39
40#define DEFAULT_INITIAL_CHARS 12
41    //---------------------------------------------------------------------
42    String TextAreaOverlayElement::msTypeName = "TextArea";
43    TextAreaOverlayElement::CmdCharHeight TextAreaOverlayElement::msCmdCharHeight;
44    TextAreaOverlayElement::CmdSpaceWidth TextAreaOverlayElement::msCmdSpaceWidth;
45    TextAreaOverlayElement::CmdFontName TextAreaOverlayElement::msCmdFontName;
46    TextAreaOverlayElement::CmdColour TextAreaOverlayElement::msCmdColour;
47    TextAreaOverlayElement::CmdColourBottom TextAreaOverlayElement::msCmdColourBottom;
48    TextAreaOverlayElement::CmdColourTop TextAreaOverlayElement::msCmdColourTop;
49    TextAreaOverlayElement::CmdAlignment TextAreaOverlayElement::msCmdAlignment;
50    //---------------------------------------------------------------------
51    #define POS_TEX_BINDING 0
52    #define COLOUR_BINDING 1
53    //---------------------------------------------------------------------
54    TextAreaOverlayElement::TextAreaOverlayElement(const String& name)
55        : OverlayElement(name)
56    {
57        mTransparent = false;
58        mAlignment = Left;
59
60        mColourTop = ColourValue::White;
61        mColourBottom = ColourValue::White;
62        mColoursChanged = true;
63
64        mAllocSize = 0;
65
66        mCharHeight = 0.02;
67                mPixelCharHeight = 12;
68                mSpaceWidth = 0;
69                mPixelSpaceWidth = 0;
70                mViewportAspectCoef = 1;
71
72        if (createParamDictionary("TextAreaOverlayElement"))
73        {
74            addBaseParameters();
75        }
76    }
77
78    void TextAreaOverlayElement::initialise(void)
79    {
80                if (!mInitialised)
81                {
82                        // Set up the render op
83                        // Combine positions and texture coords since they tend to change together
84                        // since character sizes are different
85                        mRenderOp.vertexData = new VertexData();
86                        VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
87                        size_t offset = 0;
88                        // Positions
89                        decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT3, VES_POSITION);
90                        offset += VertexElement::getTypeSize(VET_FLOAT3);
91                        // Texcoords
92                        decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
93                        offset += VertexElement::getTypeSize(VET_FLOAT2);
94                        // Colours - store these in a separate buffer because they change less often
95                        decl->addElement(COLOUR_BINDING, 0, VET_COLOUR, VES_DIFFUSE);
96
97                        mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST;
98                        mRenderOp.useIndexes = false;
99                        mRenderOp.vertexData->vertexStart = 0;
100                        // Vertex buffer will be created in checkMemoryAllocation
101
102                        checkMemoryAllocation( DEFAULT_INITIAL_CHARS );
103
104                        mInitialised = true;
105                }
106
107    }
108
109    void TextAreaOverlayElement::checkMemoryAllocation( size_t numChars )
110    {
111        if( mAllocSize < numChars)
112        {
113            // Create and bind new buffers
114            // Note that old buffers will be deleted automatically through reference counting
115           
116            // 6 verts per char since we're doing tri lists without indexes
117            // Allocate space for positions & texture coords
118            VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
119            VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding;
120
121            mRenderOp.vertexData->vertexCount = numChars * 6;
122
123            // Create dynamic since text tends to change alot
124            // positions & texcoords
125            HardwareVertexBufferSharedPtr vbuf =
126                HardwareBufferManager::getSingleton().
127                    createVertexBuffer(
128                        decl->getVertexSize(POS_TEX_BINDING),
129                        mRenderOp.vertexData->vertexCount,
130                        HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
131            bind->setBinding(POS_TEX_BINDING, vbuf);
132
133            // colours
134            vbuf = HardwareBufferManager::getSingleton().
135                    createVertexBuffer(
136                        decl->getVertexSize(COLOUR_BINDING),
137                        mRenderOp.vertexData->vertexCount,
138                        HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
139            bind->setBinding(COLOUR_BINDING, vbuf);
140
141            mAllocSize = numChars;
142            mColoursChanged = true; // force colour buffer regeneration
143        }
144
145    }
146
147    void TextAreaOverlayElement::updatePositionGeometry()
148    {
149                float *pVert;
150
151                if (mpFont.isNull())
152                {
153                        // not initialised yet, probably due to the order of creation in a template
154                        return;
155                }
156
157                size_t charlen = mCaption.size();
158                checkMemoryAllocation( charlen );
159
160                mRenderOp.vertexData->vertexCount = charlen * 6;
161                // Get position / texcoord buffer
162                HardwareVertexBufferSharedPtr vbuf =
163                        mRenderOp.vertexData->vertexBufferBinding->getBuffer(POS_TEX_BINDING);
164                pVert = static_cast<float*>(
165                        vbuf->lock(HardwareBuffer::HBL_DISCARD) );
166
167                float largestWidth = 0;
168                float left = _getDerivedLeft() * 2.0 - 1.0;
169                float top = -( (_getDerivedTop() * 2.0 ) - 1.0 );
170
171                // Derive space with from a capital A
172                if (mSpaceWidth == 0)
173                {
174                        mSpaceWidth = mpFont->getGlyphAspectRatio( 'A' ) * mCharHeight * 2.0 * mViewportAspectCoef;
175                }
176
177                // Use iterator
178                String::iterator i, iend;
179                iend = mCaption.end();
180                bool newLine = true;
181                for( i = mCaption.begin(); i != iend; ++i )
182                {
183                        if( newLine )
184                        {
185                                Real len = 0.0f;
186                                for( String::iterator j = i; j != iend && *j != '\n'; j++ )
187                                {
188                                        if (*j == ' ')
189                                        {
190                                                len += mSpaceWidth;
191                                        }
192                                        else
193                                        {
194                                                len += mpFont->getGlyphAspectRatio( *j ) * mCharHeight * 2.0 * mViewportAspectCoef;
195                                        }
196                                }
197
198                                if( mAlignment == Right )
199                                        left -= len;
200                                else if( mAlignment == Center )
201                                        left -= len * 0.5;
202
203                                newLine = false;
204                        }
205
206                        if( *i == '\n' )
207                        {
208                                left = _getDerivedLeft() * 2.0 - 1.0;
209                                top -= mCharHeight * 2.0;
210                                newLine = true;
211                                // Also reduce tri count
212                                mRenderOp.vertexData->vertexCount -= 6;
213                                continue;
214                        }
215
216                        if ( *i == ' ')
217                        {
218                                // Just leave a gap, no tris
219                                left += mSpaceWidth;
220                                // Also reduce tri count
221                                mRenderOp.vertexData->vertexCount -= 6;
222                                continue;
223                        }
224
225                        Real horiz_height = mpFont->getGlyphAspectRatio( *i ) * mViewportAspectCoef ;
226                        Real u1, u2, v1, v2;
227                        mpFont->getGlyphTexCoords( *i, u1, v1, u2, v2 );
228
229                        // each vert is (x, y, z, u, v)
230                        //-------------------------------------------------------------------------------------
231                        // First tri
232                        //
233                        // Upper left
234                        *pVert++ = left;
235                        *pVert++ = top;
236                        *pVert++ = -1.0;
237                        *pVert++ = u1;
238                        *pVert++ = v1;
239
240                        top -= mCharHeight * 2.0;
241
242                        // Bottom left
243                        *pVert++ = left;
244                        *pVert++ = top;
245                        *pVert++ = -1.0;
246                        *pVert++ = u1;
247                        *pVert++ = v2;
248
249                        top += mCharHeight * 2.0;
250                        left += horiz_height * mCharHeight * 2.0;
251
252                        // Top right
253                        *pVert++ = left;
254                        *pVert++ = top;
255                        *pVert++ = -1.0;
256                        *pVert++ = u2;
257                        *pVert++ = v1;
258                        //-------------------------------------------------------------------------------------
259
260                        //-------------------------------------------------------------------------------------
261                        // Second tri
262                        //
263                        // Top right (again)
264                        *pVert++ = left;
265                        *pVert++ = top;
266                        *pVert++ = -1.0;
267                        *pVert++ = u2;
268                        *pVert++ = v1;
269
270                        top -= mCharHeight * 2.0;
271                        left -= horiz_height  * mCharHeight * 2.0;
272
273                        // Bottom left (again)
274                        *pVert++ = left;
275                        *pVert++ = top;
276                        *pVert++ = -1.0;
277                        *pVert++ = u1;
278                        *pVert++ = v2;
279
280                        left += horiz_height  * mCharHeight * 2.0;
281
282                        // Bottom right
283                        *pVert++ = left;
284                        *pVert++ = top;
285                        *pVert++ = -1.0;
286                        *pVert++ = u2;
287                        *pVert++ = v2;
288                        //-------------------------------------------------------------------------------------
289
290                        // Go back up with top
291                        top += mCharHeight * 2.0;
292
293                        float currentWidth = (left + 1)/2 - _getDerivedLeft();
294                        if (currentWidth > largestWidth)
295                        {
296                                largestWidth = currentWidth;
297
298                        }
299                }
300                // Unlock vertex buffer
301                vbuf->unlock();
302
303                if (mMetricsMode == GMM_PIXELS)
304                {
305                        // Derive parametric version of dimensions
306                        Real vpWidth;
307                        vpWidth = (Real) (OverlayManager::getSingleton().getViewportWidth());
308
309                        largestWidth *= vpWidth;
310                };
311
312                if (getWidth() < largestWidth)
313                        setWidth(largestWidth);
314    }
315
316        void TextAreaOverlayElement::updateTextureGeometry()
317        {
318                // Nothing to do, we combine positions and textures
319        }
320
321    void TextAreaOverlayElement::setCaption( const String& caption )
322    {
323        mCaption = caption;
324                mGeomPositionsOutOfDate = true;
325                mGeomUVsOutOfDate = true;
326    }
327    const String& TextAreaOverlayElement::getCaption() const
328    {
329        return mCaption;
330    }
331
332    void TextAreaOverlayElement::setFontName( const String& font )
333    {
334        mpFont = FontManager::getSingleton().getByName( font );
335        if (mpFont.isNull())
336                        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, "Could not find font " + font,
337                                "TextAreaOverlayElement::setFontName" );
338        mpFont->load();
339        mpMaterial = mpFont->getMaterial();
340        mpMaterial->setDepthCheckEnabled(false);
341        mpMaterial->setLightingEnabled(false);
342               
343                mGeomPositionsOutOfDate = true;
344                mGeomUVsOutOfDate = true;
345    }
346    const String& TextAreaOverlayElement::getFontName() const
347    {
348        return mpFont->getName();
349    }
350
351    void TextAreaOverlayElement::setCharHeight( Real height )
352    {
353        if (mMetricsMode != GMM_RELATIVE)
354        {
355            mPixelCharHeight = height;
356        }
357        else
358        {
359            mCharHeight = height;
360        }
361        mGeomPositionsOutOfDate = true;
362    }
363        Real TextAreaOverlayElement::getCharHeight() const
364        {
365                if (mMetricsMode == GMM_PIXELS)
366                {
367                        return mPixelCharHeight;
368                }
369                else
370                {
371                        return mCharHeight;
372                }
373        }
374
375    void TextAreaOverlayElement::setSpaceWidth( Real width )
376    {
377        if (mMetricsMode != GMM_RELATIVE)
378        {
379            mPixelSpaceWidth = width;
380        }
381        else
382        {
383            mSpaceWidth = width;
384        }
385
386        mGeomPositionsOutOfDate = true;
387    }
388        Real TextAreaOverlayElement::getSpaceWidth() const
389        {
390                if (mMetricsMode == GMM_PIXELS)
391                {
392                        return mPixelSpaceWidth;
393                }
394                else
395                {
396                        return mSpaceWidth;
397                }
398        }
399
400    //---------------------------------------------------------------------
401    TextAreaOverlayElement::~TextAreaOverlayElement()
402    {
403        delete mRenderOp.vertexData;
404    }
405    //---------------------------------------------------------------------
406    const String& TextAreaOverlayElement::getTypeName(void) const
407    {
408        return msTypeName;
409    }
410    //---------------------------------------------------------------------
411    void TextAreaOverlayElement::getRenderOperation(RenderOperation& op)
412    {
413        op = mRenderOp;
414    }
415    //---------------------------------------------------------------------
416    void TextAreaOverlayElement::setMaterialName(const String& matName)
417    {
418        OverlayElement::setMaterialName(matName);
419    }
420    //---------------------------------------------------------------------
421    void TextAreaOverlayElement::addBaseParameters(void)
422    {
423        OverlayElement::addBaseParameters();
424        ParamDictionary* dict = getParamDictionary();
425
426        dict->addParameter(ParameterDef("char_height",
427            "Sets the height of the characters in relation to the screen."
428            , PT_REAL),
429            &msCmdCharHeight);
430
431        dict->addParameter(ParameterDef("space_width",
432            "Sets the width of a space in relation to the screen."
433            , PT_REAL),
434            &msCmdSpaceWidth);
435
436        dict->addParameter(ParameterDef("font_name",
437            "Sets the name of the font to use."
438            , PT_STRING),
439            &msCmdFontName);
440
441        dict->addParameter(ParameterDef("colour",
442            "Sets the colour of the font (a solid colour)."
443            , PT_STRING),
444            &msCmdColour);
445
446        dict->addParameter(ParameterDef("colour_bottom",
447            "Sets the colour of the font at the bottom (a gradient colour)."
448            , PT_STRING),
449            &msCmdColourBottom);
450
451        dict->addParameter(ParameterDef("colour_top",
452            "Sets the colour of the font at the top (a gradient colour)."
453            , PT_STRING),
454            &msCmdColourTop);
455
456        dict->addParameter(ParameterDef("alignment",
457            "Sets the alignment of the text: 'left', 'center' or 'right'."
458            , PT_STRING),
459            &msCmdAlignment);
460    }
461    //---------------------------------------------------------------------
462    void TextAreaOverlayElement::setColour(const ColourValue& col)
463    {
464        mColourBottom = mColourTop = col;
465        mColoursChanged = true;
466    }
467    //---------------------------------------------------------------------
468    const ColourValue& TextAreaOverlayElement::getColour(void) const
469    {
470        // Either one
471        return mColourTop;
472    }
473    //---------------------------------------------------------------------
474    void TextAreaOverlayElement::setColourBottom(const ColourValue& col)
475    {
476        mColourBottom = col;
477        mColoursChanged = true;
478    }
479    //---------------------------------------------------------------------
480    const ColourValue& TextAreaOverlayElement::getColourBottom(void) const
481    {
482        return mColourBottom;
483    }
484    //---------------------------------------------------------------------
485    void TextAreaOverlayElement::setColourTop(const ColourValue& col)
486    {
487        mColourTop = col;
488        mColoursChanged = true;
489    }
490    //---------------------------------------------------------------------
491    const ColourValue& TextAreaOverlayElement::getColourTop(void) const
492    {
493        return mColourTop;
494    }
495    //---------------------------------------------------------------------
496    void TextAreaOverlayElement::updateColours(void)
497    {
498        // Convert to system-specific
499        RGBA topColour, bottomColour;
500        Root::getSingleton().convertColourValue(mColourTop, &topColour);
501        Root::getSingleton().convertColourValue(mColourBottom, &bottomColour);
502
503        HardwareVertexBufferSharedPtr vbuf =
504            mRenderOp.vertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING);
505
506        RGBA* pDest = static_cast<RGBA*>(
507            vbuf->lock(HardwareBuffer::HBL_DISCARD) );
508
509        for (size_t i = 0; i < mAllocSize; ++i)
510        {
511            // First tri (top, bottom, top)
512            *pDest++ = topColour;
513            *pDest++ = bottomColour;
514            *pDest++ = topColour;
515            // Second tri (top, bottom, bottom)
516            *pDest++ = topColour;
517            *pDest++ = bottomColour;
518            *pDest++ = bottomColour;
519        }
520        vbuf->unlock();
521
522    }
523    //-----------------------------------------------------------------------
524    void TextAreaOverlayElement::setMetricsMode(GuiMetricsMode gmm)
525    {
526        Real vpWidth, vpHeight;
527
528                vpWidth = (Real) (OverlayManager::getSingleton().getViewportWidth());
529        vpHeight = (Real) (OverlayManager::getSingleton().getViewportHeight());
530                mViewportAspectCoef = vpHeight/vpWidth;
531
532                OverlayElement::setMetricsMode(gmm);
533        if (gmm != GMM_RELATIVE)
534        {
535            // Set pixel variables based on viewport multipliers
536            mPixelCharHeight = mCharHeight * vpHeight;
537            mPixelSpaceWidth = mSpaceWidth * vpHeight;
538        }
539    }
540
541    //-----------------------------------------------------------------------
542    void TextAreaOverlayElement::_update(void)
543    {
544        Real vpWidth, vpHeight;
545
546        vpWidth = (Real) (OverlayManager::getSingleton().getViewportWidth());
547        vpHeight = (Real) (OverlayManager::getSingleton().getViewportHeight());
548                mViewportAspectCoef = vpHeight/vpWidth;
549               
550                if (mMetricsMode != GMM_RELATIVE &&
551            (OverlayManager::getSingleton().hasViewportChanged() || mGeomPositionsOutOfDate))
552        {
553            // Recalc character size
554
555            mCharHeight = (Real) mPixelCharHeight / vpHeight;
556            mSpaceWidth = (Real) mPixelSpaceWidth / vpHeight;
557                        mGeomPositionsOutOfDate = true;
558        }
559        OverlayElement::_update();
560
561                if (mColoursChanged && mInitialised)
562                {
563                        updateColours();
564                        mColoursChanged = false;
565                }
566    }
567    //---------------------------------------------------------------------------------------------
568    // Char height command object
569    //
570    String TextAreaOverlayElement::CmdCharHeight::doGet( const void* target ) const
571    {
572        return StringConverter::toString(
573            static_cast< const TextAreaOverlayElement* >( target )->getCharHeight() );
574    }
575    void TextAreaOverlayElement::CmdCharHeight::doSet( void* target, const String& val )
576    {
577        static_cast< TextAreaOverlayElement* >( target )->setCharHeight(
578            StringConverter::parseReal( val ) );
579    }
580    //---------------------------------------------------------------------------------------------
581    // Space width command object
582    //
583    String TextAreaOverlayElement::CmdSpaceWidth::doGet( const void* target ) const
584    {
585        return StringConverter::toString(
586            static_cast< const TextAreaOverlayElement* >( target )->getSpaceWidth() );
587    }
588    void TextAreaOverlayElement::CmdSpaceWidth::doSet( void* target, const String& val )
589    {
590        static_cast< TextAreaOverlayElement* >( target )->setSpaceWidth(
591            StringConverter::parseReal( val ) );
592    }
593    //---------------------------------------------------------------------------------------------
594
595    //---------------------------------------------------------------------------------------------
596    // Font name command object
597    //
598    String TextAreaOverlayElement::CmdFontName::doGet( const void* target ) const
599    {
600        return static_cast< const TextAreaOverlayElement* >( target )->getFontName();
601    }
602    void TextAreaOverlayElement::CmdFontName::doSet( void* target, const String& val )
603    {
604        static_cast< TextAreaOverlayElement* >( target )->setFontName( val );
605    }
606    //---------------------------------------------------------------------------------------------
607    //---------------------------------------------------------------------------------------------
608    // Colour command object
609    //
610    String TextAreaOverlayElement::CmdColour::doGet( const void* target ) const
611    {
612        return StringConverter::toString (
613            static_cast< const TextAreaOverlayElement* >( target )->getColour());
614    }
615    void TextAreaOverlayElement::CmdColour::doSet( void* target, const String& val )
616    {
617        static_cast< TextAreaOverlayElement* >( target )->setColour(
618            StringConverter::parseColourValue(val) );
619    }
620    //---------------------------------------------------------------------------------------------
621    //---------------------------------------------------------------------------------------------
622    //---------------------------------------------------------------------------------------------
623    // Top colour command object
624    //
625    String TextAreaOverlayElement::CmdColourTop::doGet( const void* target ) const
626    {
627        return StringConverter::toString (
628            static_cast< const TextAreaOverlayElement* >( target )->getColourTop());
629    }
630    void TextAreaOverlayElement::CmdColourTop::doSet( void* target, const String& val )
631    {
632        static_cast< TextAreaOverlayElement* >( target )->setColourTop(
633            StringConverter::parseColourValue(val) );
634    }
635    //---------------------------------------------------------------------------------------------
636    //---------------------------------------------------------------------------------------------
637    //---------------------------------------------------------------------------------------------
638    // Bottom colour command object
639    //
640    String TextAreaOverlayElement::CmdColourBottom::doGet( const void* target ) const
641    {
642        return StringConverter::toString (
643            static_cast< const TextAreaOverlayElement* >( target )->getColourBottom());
644    }
645    void TextAreaOverlayElement::CmdColourBottom::doSet( void* target, const String& val )
646    {
647        static_cast< TextAreaOverlayElement* >( target )->setColourBottom(
648            StringConverter::parseColourValue(val) );
649    }
650    //---------------------------------------------------------------------------------------------
651    //---------------------------------------------------------------------------------------------
652    //---------------------------------------------------------------------------------------------
653    // Alignment command object
654    //
655    String TextAreaOverlayElement::CmdAlignment::doGet( const void* target ) const
656    {
657        Alignment align = static_cast< const TextAreaOverlayElement* >( target )->getAlignment();
658        switch (align)
659        {
660            case Left:
661                return "left";
662            case Center:
663                return "center";
664            case Right:
665                return "right";
666               
667        }
668        // To keep compiler happy
669        return "left";
670    }
671    void TextAreaOverlayElement::CmdAlignment::doSet( void* target, const String& val )
672    {
673        if (val == "center")
674        {
675            static_cast< TextAreaOverlayElement* >( target )->setAlignment(Center);
676        }
677        else if (val == "right")
678        {
679            static_cast< TextAreaOverlayElement* >( target )->setAlignment(Right);
680        }
681        else
682        {
683            static_cast< TextAreaOverlayElement* >( target )->setAlignment(Left);
684        }
685    }
686    //---------------------------------------------------------------------------------------------
687}
Note: See TracBrowser for help on using the repository browser.