Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/text_engine/text.cc @ 6752

Last change on this file since 6752 was 6645, checked in by bensch, 19 years ago

orxonox/trunk: totally remastered the ResourceManager.
Now it takes MultiTypes instead of (void*) as parameters

  1. This is TypeSafe
  2. This is easier to use
  3. This makes much more sense, and is objectOriented

also made some minor adjustments to the MultiType, some comparisons

also fixed the loading in all the Other classes like material md2 and so on

File size: 8.7 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_GRAPHICS
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"
26
27using namespace std;
28
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 textSize)
35{
36  this->init();
37
38  if (fontFile != NULL)
39    this->setFont(fontFile, FONT_DEFAULT_RENDER_SIZE);
40  this->setSizeY2D(textSize);
41}
42
43/**
44 *  deletes a Text out of memory
45 *
46 * This also ereases the text from the textList of the TextEngine
47 */
48Text::~Text()
49{
50  if (this->font != NULL && this->font != Font::getDefaultFont())
51    ResourceManager::getInstance()->unload(this->font);
52
53  if (this->text)
54    delete[] this->text;
55}
56
57/**
58 * initializes Text
59 */
60void Text::init()
61{
62  this->setClassID(CL_TEXT, "Text");
63
64  // initialize this Text
65  this->font = NULL;
66  this->text = NULL;
67  this->externText = NULL;
68  this->setAlignment(TEXT_DEFAULT_ALIGNMENT);
69  this->blending = TEXT_DEFAULT_BLENDING;
70  this->color = TEXT_DEFAULT_COLOR;
71  this->setSize(TEXT_DEFAULT_SIZE);
72  this->setText(NULL);
73}
74
75/**
76 * sets the Font of this Text to font from fontFile
77 * @param fontFile the File to load the Font from.
78 * @param fontSize the Size of the Font
79 */
80void Text::setFont(const char* fontFile, unsigned int fontSize)
81{
82  Font* tmpFont;
83  Text* newText;
84  Vector tmpVec;
85
86  // unloading the Font if we alrady have one loaded.
87  if (this->font != NULL && this->font != Font::getDefaultFont())
88    ResourceManager::getInstance()->unload(this->font);
89  this->font = NULL;
90
91  // load a new Font
92  if (fontFile != NULL)
93  {
94    tmpFont = (Font*)ResourceManager::getInstance()->load(fontFile, TTF, RP_GAME, (int)fontSize);
95    if (tmpFont != NULL)
96      this->font = tmpFont;
97    else
98      PRINTF(2)("Font %s could not be loaded, probably file not found\n", fontFile);
99  }
100}
101
102/**
103 * Sets a new Text to the font
104 * @param text the new text to set
105 */
106void Text::setText(const char* text, bool isExtern)
107{
108  if (isExtern)
109  {
110    this->externText = text;
111
112    if (unlikely(this->text != NULL))
113    {
114      delete[] this->text;
115      this->text = NULL;
116    }
117  }
118  else
119  {
120    this->externText = NULL;
121    if (this->text)
122      delete[] this->text;
123    if (text != NULL)
124    {
125      this->text = new char[strlen(text)+1];
126      strcpy(this->text, text);
127    }
128    else
129      this->text = NULL;
130  }
131
132  // setting up the Text-Width if DYNAMIC
133//  if (this->type & TEXT_RENDER_DYNAMIC && this->getAlignment() != TEXT_ALIGN_LEFT && this->font != NULL)
134  const Font* calcSizeFont = this->font;
135  if (calcSizeFont != NULL || (calcSizeFont = Font::getDefaultFont()) != NULL)
136  {
137    Glyph** glyphArray = calcSizeFont->getGlyphArray();
138
139    float width = 0;
140    const char* tmpText = this->externText;
141    if (this->externText == NULL)
142      tmpText = this->text;
143    if (tmpText != NULL)
144    {
145      while (*tmpText != '\0')
146      {
147        if(glyphArray[*tmpText] != NULL)
148        {
149          width += glyphArray[*tmpText]->advance;
150        }
151        tmpText++;
152      }
153      this->setSizeX2D(width *this->getSizeY2D());
154    }
155  }
156}
157
158/**
159 *  draws the Text
160 */
161void Text::draw() const
162{
163  glPushMatrix();
164  // transform for alignment.
165  if (this->getAlignment() == TEXT_ALIGN_RIGHT)
166    glTranslatef(-this->getSizeX2D(), 0, 0);
167  else if (this->getAlignment() == TEXT_ALIGN_CENTER || this->getAlignment() == TEXT_ALIGN_SCREEN_CENTER)
168    glTranslatef(-this->getSizeX2D()/2, 0, 0);
169
170  // drawing this Text.
171  // setting the Blending effects
172  glColor4f(this->color.x, this->color.y, this->color.z, this->blending);
173  glEnable(GL_BLEND);
174  glEnable(GL_TEXTURE_2D);
175  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
176
177  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GL_MODULATE );
178
179  Glyph** glyphArray;
180  if (likely (this->font != NULL))
181  {
182    glyphArray = this->font->getGlyphArray();
183    glBindTexture(GL_TEXTURE_2D, font->getTexture());
184  }
185  else
186  {
187    if (unlikely(Font::getDefaultFont() == NULL))
188      Font::initDefaultFont();
189    glyphArray = Font::getDefaultFont()->getGlyphArray();
190    glBindTexture(GL_TEXTURE_2D, Font::getDefaultFont()->getTexture());
191  }
192  const char* tmpText = this->externText;
193  if (this->externText == NULL)
194    tmpText = this->text;
195  if (likely(tmpText != NULL))
196  {
197    glTranslatef(getAbsCoor2D().x, getAbsCoor2D().y, 0);
198    glRotatef(this->getAbsDir2D(), 0, 0, 1);
199    Glyph* tmpGlyph;
200    float posX = 0.0f;
201
202    glBegin(GL_QUADS);
203    while (likely(*tmpText != '\0'))
204    {
205      if(likely((tmpGlyph = glyphArray[*tmpText]) != NULL))
206      {
207        glTexCoord2f(tmpGlyph->texCoord[1], tmpGlyph->texCoord[2]);
208        glVertex2d(posX+tmpGlyph->width*this->getSizeY2D(), 0);
209
210        glTexCoord2f(tmpGlyph->texCoord[1], tmpGlyph->texCoord[3]);
211        glVertex2d(posX+tmpGlyph->width*this->getSizeY2D(), this->getSizeY2D());
212
213        glTexCoord2f(tmpGlyph->texCoord[0], tmpGlyph->texCoord[3]);
214        glVertex2d(posX, this->getSizeY2D());
215
216        glTexCoord2f(tmpGlyph->texCoord[0], tmpGlyph->texCoord[2]);
217        glVertex2d(posX, 0);
218
219        posX += tmpGlyph->advance * this->getSizeY2D();
220      }
221      ++tmpText;
222    }
223    glEnd();
224  }
225
226  glPopMatrix();
227}
228
229/**
230 *  prints out some nice debug information about this text
231 */
232void Text::debug() const
233{
234  if (this->externText == NULL)
235    PRINT(0)("=== TEXT: %s ===\n", this->text);
236  else
237    PRINT(0)("=== TEXT: %s ===\n", this->externText);
238
239  if (this->getBindNode())
240    PRINT(0)("is bind to %s; ref=%p\n", this->getBindNode()->getName(), this->getBindNode());
241  PRINT(0)("Color: %0.2f %0.2f %0.2f\n", this->color.x, this->color.y, this->color.z);
242}
243
244
245////////////
246/// UTIL ///
247////////////
248/**
249 * Loads a Font from an SDL_surface into a texture.
250 * @param surface The surface to make the texture of
251 * @param texCoord The texture coordinates of the 4 corners of the texture
252 * @returns the ID of the texture
253 */
254GLuint Text::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
255{
256  GLuint texture;
257  int w, h;
258  SDL_Surface *image;
259  SDL_Rect area;
260  Uint32 saved_flags;
261  Uint8  saved_alpha;
262
263  /* Use the surface width and height expanded to powers of 2 */
264  w = powerOfTwo(surface->w);
265  h = powerOfTwo(surface->h);
266  if (texCoord != NULL)
267  {
268    texCoord->minU = 0.0f;
269    texCoord->minV = 0.0f;
270    texCoord->maxU = (GLfloat)surface->w / w;
271    texCoord->maxV = (GLfloat)surface->h / h;
272  }
273  image = SDL_CreateRGBSurface(SDL_SWSURFACE,
274                               w, h,
275                               32,
276#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
277                               0x000000FF,
278                               0x0000FF00,
279                               0x00FF0000,
280                               0xFF000000
281#else
282                                   0xFF000000,
283                               0x00FF0000,
284                               0x0000FF00,
285                               0x000000FF
286#endif
287                              );
288  if ( image == NULL ) {
289    return 0;
290  }
291
292  /* Save the alpha blending attributes */
293  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
294  saved_alpha = surface->format->alpha;
295  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
296    SDL_SetAlpha(surface, 0, 0);
297  }
298
299  /* Copy the surface into the GL texture image */
300  area.x = 0;
301  area.y = 0;
302  area.w = surface->w;
303  area.h = surface->h;
304  SDL_BlitSurface(surface, &area, image, &area);
305
306  /* Restore the alpha blending attributes */
307  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
308    SDL_SetAlpha(surface, saved_flags, saved_alpha);
309  }
310
311  /* Create an OpenGL texture for the image */
312  glGenTextures(1, &texture);
313  glBindTexture(GL_TEXTURE_2D, texture);
314  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
315  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
316  glTexImage2D(GL_TEXTURE_2D,
317               0,
318               GL_RGBA,
319               w, h,
320               0,
321               GL_RGBA,
322               GL_UNSIGNED_BYTE,
323               image->pixels);
324  SDL_FreeSurface(image); /* No longer needed the data */
325
326  return texture;
327}
328
329/**
330 *  Quick utility function for texture creation
331 * @param input an integer
332 * @returns the next bigger 2^n-integer than input
333 */
334int Text::powerOfTwo(int input)
335{
336  int value = 1;
337
338  while ( value < input )
339    value <<= 1;
340  return value;
341}
Note: See TracBrowser for help on using the repository browser.