Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 5343 in orxonox.OLD for trunk/src/lib/graphics/text_engine/text.cc


Ignore:
Timestamp:
Oct 10, 2005, 12:16:19 AM (19 years ago)
Author:
bensch
Message:

orxonox/trunk: split open the text-engine

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/graphics/text_engine/text.cc

    r5330 r5343  
    1010
    1111   ### File Specific:
    12    main-programmer: ...
     12   main-programmer: Benjamin Grauer
    1313   co-programmer: ...
    1414*/
    1515
    16 //#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
    17 
    18 #include "proto_class.h"
     16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_FONT
     17
     18#include "text.h"
     19#include "font.h"
     20
     21#include "graphics_engine.h"
     22#include "resource_manager.h"
     23#include "class_list.h"
     24#include "debug.h"
     25#include "p_node.h"
    1926
    2027using namespace std;
    2128
    22 
    23 /**
    24  * standard constructor
    25  * @todo this constructor is not jet implemented - do it
    26 */
    27 ProtoClass::ProtoClass ()
    28 {
    29    this->setClassID(CL_PROTO_ID, "ProtoClass");
    30 
    31    /* If you make a new class, what is most probably the case when you write this file
    32       don't forget to:
    33        1. Add the new file new_class.cc to the ./src/Makefile.am
    34        2. Add the class identifier to ./src/class_id.h eg. CL_NEW_CLASS
    35 
    36       Advanced Topics:
    37       - if you want to let your object be managed via the ObjectManager make sure to read
    38         the object_manager.h header comments. You will use this most certanly only if you
    39         make many objects of your class, like a weapon bullet.
    40    */
    41 }
    42 
    43 
    44 /**
    45  * standard deconstructor
    46 */
    47 ProtoClass::~ProtoClass ()
    48 {
    49   // delete what has to be deleted here
    50 }
     29/**
     30 *  creates a new Text Element
     31 * @param fontFile the Font to render this text in
     32 * @param type The renderType to display this font in
     33 */
     34Text::Text(const char* fontFile, unsigned int fontSize, TEXT_RENDER_TYPE type)
     35{
     36  this->init();
     37
     38  if (fontFile != NULL)
     39    this->setFont(fontFile, fontSize);
     40  this->setType(type);
     41}
     42
     43/**
     44 *  creates a new Text Element
     45 * @param font the Font to render this text in
     46 * @param type The renderType to display this font in
     47 *
     48 * this constructor is private, because the user should initialize
     49 * a text with the TextEngine.
     50 */
     51Text::Text(Font* font, TEXT_RENDER_TYPE type)
     52{
     53  this->init();
     54
     55  this->font = font;
     56  this->setType(type);
     57}
     58
     59/**
     60 *  deletes a Text out of memory
     61 *
     62 * This also ereases the text from the textList of the TextEngine
     63 */
     64Text::~Text()
     65{
     66  if (this->font != NULL)
     67    ResourceManager::getInstance()->unload(this->font);
     68
     69  if (this->text)
     70    delete[] this->text;
     71}
     72
     73void Text::init()
     74{
     75  this->setClassID(CL_TEXT, "Text");
     76
     77  // initialize this Text
     78  this->font = NULL;
     79  this->text = NULL;
     80  this->externText = NULL;
     81  this->setAlignment(TEXT_DEFAULT_ALIGNMENT);
     82  this->texture = 0;
     83  this->blending = TEXT_DEFAULT_BLENDING;
     84  this->color = TEXT_DEFAULT_COLOR;
     85  this->setType(TEXT_RENDER_DYNAMIC);
     86
     87  this->setText(NULL);
     88}
     89
     90/**
     91 * sets the Font of this Text to font
     92 * @param font the Font (normaly from the ResourceManager) to allocate to this Text
     93 */
     94void Text::setFont(Font* font)
     95{
     96  if (this->font != NULL)
     97    ResourceManager::getInstance()->unload(this->font);
     98  this->font = font;
     99}
     100
     101/**
     102 * sets the Font of this Text to font from fontFile
     103 * @param fontFile the File to load the Font from.
     104 * @param fontSize the Size of the Font
     105 */
     106void Text::setFont(const char* fontFile, unsigned int fontSize)
     107{
     108  Font* tmpFont;
     109  Text* newText;
     110  Vector tmpVec;
     111
     112  tmpFont = (Font*)ResourceManager::getInstance()->load(fontFile, TTF, RP_GAME, &fontSize);
     113  if (tmpFont == NULL)
     114  {
     115    PRINTF(2)("Font %s could not be loaded, probably file not found\n", fontFile);
     116    this->setFont(NULL);
     117  }
     118  else
     119    this->setFont(tmpFont);
     120}
     121
     122/**
     123 *  sets the Type of this Text
     124 * @param type the type to set.
     125 */
     126void Text::setType(TEXT_RENDER_TYPE type)
     127{
     128  if (this->font != NULL && this->font->font)
     129    this->type = type;
     130  else
     131    this->type = TEXT_RENDER_DYNAMIC;
     132}
     133
     134/**
     135 *  Sets a new Text to the font
     136 * @param text the new text to set
     137 */
     138void Text::setText(const char* text, bool isExtern)
     139{
     140  if (isExtern)
     141  {
     142    this->externText = text;
     143
     144    if (unlikely(this->text != NULL))
     145    {
     146      delete[] this->text;
     147      this->text = NULL;
     148    }
     149  }
     150  else
     151  {
     152    this->externText = NULL;
     153    if (this->text)
     154      delete[] this->text;
     155    if (text != NULL)
     156    {
     157      this->text = new char[strlen(text)+1];
     158      strcpy(this->text, text);
     159    }
     160    else
     161      this->text = NULL;
     162  }
     163
     164  // setting up the Text-Width if DYNAMIC
     165  if (this->type & TEXT_RENDER_DYNAMIC && this->getAlignment() != TEXT_ALIGN_LEFT && this->font != NULL)
     166  {
     167    Glyph** glyphArray = this->font->getGlyphArray();
     168
     169    int width = 0;
     170    const char* tmpText = this->externText;
     171    if (this->externText == NULL)
     172      tmpText = this->text;
     173    if (tmpText != NULL)
     174    {
     175      while (*tmpText != '\0')
     176      {
     177        if(glyphArray[*tmpText])
     178        {
     179          width += glyphArray[*tmpText]->width;
     180        }
     181        tmpText++;
     182      }
     183      this->width = width;
     184    }
     185  }
     186}
     187
     188/**
     189 *  creates a texture out of the given parameters
     190
     191   this has to be called every time by the user, to if changes were made.
     192   this is only for TEXT_STATIC-mode
     193 */
     194void Text::createTexture()
     195{
     196  SDL_Surface* tmpSurf;
     197  if (this->texture)
     198    glDeleteTextures(1, &this->texture);
     199  if (likely(this->font != NULL))
     200  {
     201    SDL_Color theColor = { (int)(this->color.x*255), (int)(this->color.y*255), (int)(this->color.z*255) };
     202    tmpSurf = TTF_RenderText_Blended(this->font->font,
     203                                     this->text,
     204                                     theColor);
     205  }
     206  if (tmpSurf)
     207    this->texture = loadTexture(tmpSurf, &this->texCoord);
     208
     209  this->width = tmpSurf->w;
     210  this->height = tmpSurf->h;
     211  SDL_FreeSurface(tmpSurf);
     212}
     213
     214/**
     215 *  draws the Text
     216 */
     217void Text::draw() const
     218{
     219  glPushMatrix();
     220  // transform for alignment.
     221  if (this->getAlignment() == TEXT_ALIGN_RIGHT)
     222    glTranslatef(-this->width, 0, 0);
     223  else if (this->getAlignment() == TEXT_ALIGN_CENTER || this->getAlignment() == TEXT_ALIGN_SCREEN_CENTER)
     224    glTranslatef(-this->width/2, 0, 0);
     225
     226  // drawing this Text.
     227  // setting the Blending effects
     228  glColor4f(this->color.x, this->color.y, this->color.z, this->blending);
     229  glEnable(GL_BLEND);
     230  glEnable(GL_TEXTURE_2D);
     231  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
     232
     233  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GL_MODULATE );
     234
     235  if(likely(type & TEXT_RENDER_DYNAMIC ))
     236  {
     237    Glyph** glyphArray;
     238    if (likely (this->font != NULL))
     239    {
     240      glyphArray = this->font->getGlyphArray();
     241      glBindTexture(GL_TEXTURE_2D, font->getFastTextureID());
     242    }
     243    else
     244    {
     245      if (unlikely(Font::getDefaultFont() == NULL))
     246        Font::initDefaultFont();
     247      glyphArray = Font::getDefaultFont()->getGlyphArray();
     248      glBindTexture(GL_TEXTURE_2D, Font::getDefaultFont()->getFastTextureID());
     249    }
     250    glTranslatef(getAbsCoor2D().x, getAbsCoor2D().y, 0);
     251//      glRotatef(this->getAbsDir2D(), 0,0,1);
     252    const char* tmpText = this->externText;
     253    if (this->externText == NULL)
     254      tmpText = this->text;
     255    if (likely(tmpText != NULL))
     256    {
     257      while (likely(*tmpText != '\0'))
     258      {
     259        if(likely(glyphArray[*tmpText] != NULL))
     260        {
     261          glCallList(glyphArray[*tmpText]->displayList);
     262          glTranslatef(glyphArray[*tmpText]->width, 0, 0);
     263        }
     264        tmpText++;
     265      }
     266    }
     267  }
     268  else //(if type & TEXT_RENDER_STATIC)
     269  {
     270    glBindTexture(GL_TEXTURE_2D, this->texture);
     271    glBegin(GL_QUADS);
     272
     273    glTexCoord2f(this->texCoord.minU, this->texCoord.minV);
     274    glVertex2f(this->getAbsCoor2D().x,   this->getAbsCoor2D().y  );
     275
     276    glTexCoord2f(this->texCoord.maxU, this->texCoord.minV);
     277    glVertex2f(this->getAbsCoor2D().x + this->width, this->getAbsCoor2D().y  );
     278
     279    glTexCoord2f(this->texCoord.maxU, this->texCoord.maxV);
     280    glVertex2f(this->getAbsCoor2D().x + this->width, getAbsCoor2D().y + this->height);
     281
     282    glTexCoord2f(this->texCoord.minU, this->texCoord.maxV);
     283    glVertex2f(getAbsCoor2D().x, getAbsCoor2D().y + this->height);
     284
     285    glEnd();
     286
     287  }
     288  glPopMatrix();
     289}
     290
     291/**
     292 *  prints out some nice debug information about this text
     293 */
     294void Text::debug() const
     295{
     296  if (this->externText == NULL)
     297    PRINT(0)("=== TEXT: %s ===\n", this->text);
     298  else
     299    PRINT(0)("=== TEXT: %s ===\n", this->externText);
     300
     301  if (this->getBindNode())
     302    PRINT(0)("is bind to %s; ref=%p\n", this->getBindNode()->getName(), this->getBindNode());
     303  PRINT(0)("Color: %0.2f %0.2f %0.2f\n", this->color.x, this->color.y, this->color.z);
     304}
     305
     306
     307////////////
     308/// UTIL ///
     309////////////
     310/**
     311 *  Loads a Font from an SDL_surface into a texture.
     312 * @param surface The surface to make the texture of
     313 * @param texCoord The texture coordinates of the 4 corners of the texture
     314 * @returns the ID of the texture
     315 */
     316GLuint Text::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
     317{
     318  GLuint texture;
     319  int w, h;
     320  SDL_Surface *image;
     321  SDL_Rect area;
     322  Uint32 saved_flags;
     323  Uint8  saved_alpha;
     324
     325  /* Use the surface width and height expanded to powers of 2 */
     326  w = powerOfTwo(surface->w);
     327  h = powerOfTwo(surface->h);
     328  if (texCoord != NULL)
     329  {
     330    texCoord->minU = 0.0f;
     331    texCoord->minV = 0.0f;
     332    texCoord->maxU = (GLfloat)surface->w / w;
     333    texCoord->maxV = (GLfloat)surface->h / h;
     334  }
     335  image = SDL_CreateRGBSurface(SDL_SWSURFACE,
     336                               w, h,
     337                               32,
     338#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
     339                               0x000000FF,
     340                               0x0000FF00,
     341                               0x00FF0000,
     342                               0xFF000000
     343#else
     344                                   0xFF000000,
     345                               0x00FF0000,
     346                               0x0000FF00,
     347                               0x000000FF
     348#endif
     349                              );
     350  if ( image == NULL ) {
     351    return 0;
     352  }
     353
     354  /* Save the alpha blending attributes */
     355  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
     356  saved_alpha = surface->format->alpha;
     357  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
     358    SDL_SetAlpha(surface, 0, 0);
     359  }
     360
     361  /* Copy the surface into the GL texture image */
     362  area.x = 0;
     363  area.y = 0;
     364  area.w = surface->w;
     365  area.h = surface->h;
     366  SDL_BlitSurface(surface, &area, image, &area);
     367
     368  /* Restore the alpha blending attributes */
     369  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
     370    SDL_SetAlpha(surface, saved_flags, saved_alpha);
     371  }
     372
     373  /* Create an OpenGL texture for the image */
     374  glGenTextures(1, &texture);
     375  glBindTexture(GL_TEXTURE_2D, texture);
     376  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     377  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     378  glTexImage2D(GL_TEXTURE_2D,
     379               0,
     380               GL_RGBA,
     381               w, h,
     382               0,
     383               GL_RGBA,
     384               GL_UNSIGNED_BYTE,
     385               image->pixels);
     386  SDL_FreeSurface(image); /* No longer needed the data */
     387
     388  return texture;
     389}
     390
     391/**
     392 *  Quick utility function for texture creation
     393 * @param input an integer
     394 * @returns the next bigger 2^n-integer than input
     395 */
     396int Text::powerOfTwo(int input)
     397{
     398  int value = 1;
     399
     400  while ( value < input )
     401    value <<= 1;
     402  return value;
     403}
Note: See TracChangeset for help on using the changeset viewer.