Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hud.cpp
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2001-2002 Daniel Horn & Alan Shieh
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 #include <ctype.h>
22 #include "gfxlib.h"
23 #include "cmd/unit_generic.h"
24 #include "hud.h"
25 #include "lin_time.h"
26 #include "file_main.h"
27 #include "gfx/aux_texture.h"
28 #include "vs_globals.h"
29 #include "config_xml.h"
30 #include "xml_support.h"
31 #include "cmd/base.h"
32 //#include "glut.h"
33 
34 #include "gldrv/gl_globals.h"
35 
36 static bool isInside()
37 {
38  if (BaseInterface::CurrentBase) return true;
39  return false;
40 }
41 
42 const std::string& getStringFont( bool &changed, bool force_inside = false, bool whatinside = false )
43 {
44  static std::string whichfont = vs_config->getVariable( "graphics", "font", "helvetica12" );
45  static std::string whichdockedfont = vs_config->getVariable( "graphics", "basefont", "helvetica12" );
46  bool inside = isInside();
47  if (force_inside)
48  inside = whatinside;
49  static bool lastinside = inside;
50  if (lastinside != inside) {
51  changed = true;
52  lastinside = inside;
53  } else {changed = false; } return inside ? whichdockedfont : whichfont;
54 }
55 
56 const std::string& getStringFontForHeight( bool &changed )
57 {
58  static std::string whichfont = vs_config->getVariable( "graphics", "font", "helvetica12" );
59  static std::string whichdockedfont = vs_config->getVariable( "graphics", "basefont", "helvetica12" );
60  bool inside = isInside();
61  static bool lastinside = inside;
62  if (lastinside != inside) {
63  changed = true;
64  lastinside = inside;
65  } else {changed = false; } return inside ? whichdockedfont : whichfont;
66 }
67 
68 void * getFont( bool forceinside = false, bool whichinside = false )
69 {
70  bool changed = false;
71  std::string whichfont = getStringFont( changed, forceinside, whichinside );
72  static void *retval = NULL;
73  if (changed) retval = NULL;
74  if (retval == NULL) {
75  if (whichfont == "helvetica10")
76  retval = GLUT_BITMAP_HELVETICA_10;
77  else if (whichfont == "helvetica18")
78  retval = GLUT_BITMAP_HELVETICA_18;
79  else if (whichfont == "times24")
80  retval = GLUT_BITMAP_TIMES_ROMAN_24;
81  else if (whichfont == "times10")
82  retval = GLUT_BITMAP_TIMES_ROMAN_10;
83  else if (whichfont == "fixed13")
84  retval = GLUT_BITMAP_8_BY_13;
85  else if (whichfont == "fixed15")
86  retval = GLUT_BITMAP_9_BY_15;
87  else
88  retval = GLUT_BITMAP_HELVETICA_12;
89  }
90  return retval;
91 }
92 
94 {
95  bool changed = false;
96  std::string whichfont = getStringFontForHeight( changed );
97  static float point = 0;
98  if (changed)
99  point = 0;
100  if (point == 0) {
101  if (whichfont == "helvetica10")
102  point = 22;
103  else if (whichfont == "helvetica18")
104  point = 40;
105  else if (whichfont == "times24")
106  point = 50;
107  else if (whichfont == "times10")
108  point = 22;
109  else if (whichfont == "fixed13")
110  point = 30;
111  else if (whichfont == "fixed15")
112  point = 34;
113  else
114  point = 26;
115  }
116  return point/g_game.y_resolution;
117 }
118 
119 TextPlane::TextPlane( const GFXColor &c, const GFXColor &bgcol )
120 {
121  col = c;
122  this->bgcol = bgcol;
123  myDims.i = 2;
124  myDims.j = -2;
125  myFontMetrics.Set( .06, .08, 0 );
126  SetPos( 0, 0 );
127 }
128 
130 
131 int TextPlane::Draw( int offset )
132 {
133  return Draw( myText, offset, true, false, true );
134 }
135 
136 static unsigned int * CreateLists()
137 {
138  static unsigned int lists[256] = {0};
139  void *fnt0 = getFont( true, false );
140  void *fnt1 = getFont( true, true );
141  static bool use_bit = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "high_quality_font", "false" ) );
142  static bool use_display_lists = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "text_display_lists", "true" ) );
143  if (use_display_lists) {
144  for (unsigned int i = 32; i < 256; i++)
145  if ( (i < 128) || (i >= 128+32) ) {
146  lists[i] = GFXCreateList();
147  if (use_bit)
148  glutBitmapCharacter( i < 128 ? fnt0 : fnt1, i%128 );
149  else
150  glutStrokeCharacter( GLUT_STROKE_ROMAN, i%128 );
151  if ( !GFXEndList() )
152  lists[i] = 0;
153  }
154  }
155  return lists;
156 }
157 
158 static unsigned char HexToChar( char a )
159 {
160  if (a >= '0' && a <= '9')
161  return a-'0';
162  else if (a >= 'a' && a <= 'f')
163  return 10+a-'a';
164  else if (a >= 'A' && a <= 'F')
165  return 10+a-'A';
166  return 0;
167 }
168 
169 static unsigned char TwoCharToByte( char a, char b )
170 {
171  return 16*HexToChar( a )+HexToChar( b );
172 }
173 
174 static float TwoCharToFloat( char a, char b )
175 {
176  return TwoCharToByte( a, b )/255.;
177 }
178 
179 void DrawSquare( float left, float right, float top, float bot )
180 {
181  GFXBegin( GFXQUAD );
182  GFXVertex3f( left, top, 0 );
183  GFXVertex3f( left, bot, 0 );
184  GFXVertex3f( right, bot, 0 );
185  GFXVertex3f( right, top, 0 );
186  GFXVertex3f( right, top, 0 );
187  GFXVertex3f( right, bot, 0 );
188  GFXVertex3f( left, bot, 0 );
189  GFXVertex3f( left, top, 0 );
190  GFXEnd();
191 }
192 
193 float charWidth( char c, float myFontMetrics )
194 {
195  static bool use_bit = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "high_quality_font", "false" ) );
196  void *fnt = use_bit ? getFont() : GLUT_STROKE_ROMAN;
197  float charwid = use_bit ? glutBitmapWidth( fnt, c ) : glutStrokeWidth( fnt, c );
198  float dubyawid = use_bit ? glutBitmapWidth( fnt, 'W' ) : glutStrokeWidth( fnt, 'W' );
199  return charwid*myFontMetrics/dubyawid;
200 }
201 
202 bool doNewLine( string::const_iterator begin,
203  string::const_iterator end,
204  float cur_pos,
205  float end_pos,
206  float metrics,
207  bool last_row )
208 {
209  if (*begin == '\n')
210  return true;
211  if (*begin == ' ' && !last_row) {
212  cur_pos += charWidth( *begin, metrics );
213  *begin++;
214  for (; begin != end && cur_pos <= end_pos && !isspace( *begin ); begin++)
215  cur_pos += charWidth( *begin, metrics );
216  return cur_pos > end_pos;
217  }
218  return cur_pos+( (begin+1 != end) ? charWidth( *begin, metrics ) : 0 ) >= end_pos;
219 }
220 
221 int TextPlane::Draw( const string &newText, int offset, bool startlower, bool force_highquality, bool automatte )
222 {
223  int retval = 1;
224  bool drawbg = (bgcol.a != 0);
225  static unsigned int *display_lists = CreateLists();
226  //some stuff to draw the text stuff
227  string::const_iterator text_it = newText.begin();
228  static bool use_bit = force_highquality
229  || XMLSupport::parse_bool( vs_config->getVariable( "graphics", "high_quality_font", "false" ) );
230  static float font_point = XMLSupport::parse_float( vs_config->getVariable( "graphics", "font_point", "16" ) );
231  static bool font_antialias = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "font_antialias", "true" ) );
232  void *fnt = getFont();
233  static float std_wid = glutStrokeWidth( GLUT_STROKE_ROMAN, 'W' );
234  myFontMetrics.i = font_point*std_wid/(119.05+33.33);
235  if (use_bit)
236  myFontMetrics.i = glutBitmapWidth( fnt, 'W' );
237  myFontMetrics.j = font_point;
238  myFontMetrics.i /= .5*g_game.x_resolution;
239  myFontMetrics.j /= .5*g_game.y_resolution;
240  float tmp, row, col;
241  float origcol;
242  GetPos( row, col );
243  GetPos( row, origcol );
244  float rowheight = use_bit ? getFontHeight() : myFontMetrics.j;
245  myFontMetrics.j = rowheight;
246  if (startlower)
247  row -= rowheight;
249  glLineWidth( 1 );
250  if (!use_bit && font_antialias) {
253  glEnable( GL_LINE_SMOOTH );
254  } else {
257  glDisable( GL_LINE_SMOOTH );
258  }
259  GFXColorf( this->col );
261  GFXDisable( CULLFACE );
262  GFXDisable( LIGHTING );
263  GFXDisable( TEXTURE0 );
264  GFXDisable( TEXTURE1 );
265  glPushMatrix();
266  glLoadIdentity();
267  if (!automatte && drawbg) {
268  GFXColorf( this->bgcol );
269  DrawSquare( col, this->myDims.i, row-rowheight*.25, row+rowheight );
270  }
271  GFXColorf( this->col );
272  int entercount = 0;
273  for (; entercount < offset && text_it != newText.end(); text_it++)
274  if (*text_it == '\n')
275  entercount++;
276  glTranslatef( col, row, 0 );
277  glRasterPos2f( 0, 0 );
278  float scalex = 1;
279  float scaley = 1;
280  int potentialincrease = 0;
281  if (!use_bit) {
282  int numplayers = 1;
283  if (_Universe) //_Universe can be NULL during bootstrap.
284  numplayers = ( _Universe->numPlayers() > 3 ? _Universe->numPlayers()/2
285  : _Universe->numPlayers() );
286  scalex = numplayers*myFontMetrics.i/std_wid;
287  scaley = myFontMetrics.j/(119.05+33.33);
288  }
289  glScalef( scalex, scaley, 1 );
290  bool firstThroughLoop = true;
291  GFXColor currentCol( this->col );
292  while ( text_it != newText.end() && (firstThroughLoop || row > myDims.j-rowheight*.25) ) {
293  unsigned char myc = *text_it;
294  if (myc == '_')
295  myc = ' ';
296  float shadowlen = 0;
297  if (myc == '\t') {
298  shadowlen = glutBitmapWidth( fnt, ' ' )*5./(.5*g_game.x_resolution);
299  } else {
300  if (use_bit)
301  shadowlen = glutBitmapWidth( fnt, myc )/(float) (.5*g_game.x_resolution); //need to use myc -- could have transformed '_' to ' '
302  else
303  shadowlen = myFontMetrics.i*glutStrokeWidth( GLUT_STROKE_ROMAN, myc )/std_wid;
304  }
305  if (*text_it == '#') {
306  if (newText.end()-text_it > 6) {
307  float r, g, b;
308  r = TwoCharToFloat( *(text_it+1), *(text_it+2) );
309  g = TwoCharToFloat( *(text_it+3), *(text_it+4) );
310  b = TwoCharToFloat( *(text_it+5), *(text_it+6) );
311  if (r == 0 && g == 0 && b == 0)
312  currentCol = this->col;
313  else
314  currentCol = GFXColor( r, g, b, this->col.a );
315  GFXColorf( currentCol );
316  static bool setRasterPos =
317  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "set_raster_text_color", "true" ) );
318  if (use_bit && setRasterPos)
319  glRasterPos2f( col-origcol, 0 );
320  text_it = text_it+6;
321  } else {
322  break;
323  }
324  text_it++;
325  continue;
326  } else if (*text_it >= 32) {
327  //always true
328  if (automatte) {
329  GFXColorf( this->bgcol );
330  DrawSquare( col-origcol, col-origcol+shadowlen/scalex, -rowheight*.25/scaley, rowheight*.75/scaley );
331  GFXColorf( currentCol );
332  }
333  //glutStrokeCharacter (GLUT_STROKE_ROMAN,*text_it);
334  retval += potentialincrease;
335  potentialincrease = 0;
336  int lists = display_lists[myc+(isInside() ? 128 : 0)];
337  if (lists) {
338  GFXCallList( lists );
339  } else {
340  if (use_bit)
341  glutBitmapCharacter( fnt, myc );
342  else
343  glutStrokeCharacter( GLUT_STROKE_ROMAN, myc );
344  }
345  }
346  if (*text_it == '\t') {
347  if (automatte) {
348  GFXColorf( this->bgcol );
349  DrawSquare( col-origcol,
350  col-origcol+shadowlen*5/(.5*g_game.x_resolution),
351  -rowheight*.25/scaley,
352  rowheight*.75/scaley );
353  GFXColorf( currentCol );
354  }
355  col += shadowlen;
356  glutBitmapCharacter( fnt, ' ' );
357  glutBitmapCharacter( fnt, ' ' );
358  glutBitmapCharacter( fnt, ' ' );
359  glutBitmapCharacter( fnt, ' ' );
360  glutBitmapCharacter( fnt, ' ' );
361  } else {
362  col += shadowlen;
363  }
364  if ( doNewLine( text_it, newText.end(), col, myDims.i, myFontMetrics.i, row-rowheight <= myDims.j ) ) {
365  GetPos( tmp, col );
366  firstThroughLoop = false;
367  row -= rowheight;
368  glPopMatrix();
369  glPushMatrix();
370  glLoadIdentity();
371  if (!automatte && drawbg) {
372  GFXColorf( this->bgcol );
373  DrawSquare( col, this->myDims.i, row-rowheight*.25, row+rowheight*.75 );
374  }
375  if (*text_it == '\n')
376  currentCol = this->col;
377  GFXColorf( currentCol );
378  glTranslatef( col, row, 0 );
379  glScalef( scalex, scaley, 1 );
380  glRasterPos2f( 0, 0 );
381  potentialincrease++;
382  }
383  text_it++;
384  }
386  glDisable( GL_LINE_SMOOTH );
387  glPopMatrix();
388 
389  GFXPopBlendMode();
390  GFXColorf( this->col );
391  return retval;
392 }
393