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
base_interface.cpp
Go to the documentation of this file.
1 #include "config.h"
2 #include <Python.h>
3 #include "base.h"
4 #include "gldrv/winsys.h"
5 #include "vsfilesystem.h"
6 #include "lin_time.h"
7 #include "audiolib.h"
8 #include "gfx/camera.h"
9 #include "gfx/cockpit_generic.h"
10 #include "python/init.h"
11 #include "python/python_compile.h"
12 #include "planet_generic.h"
13 #include <algorithm>
14 #include "base_util.h"
15 #include "config_xml.h"
16 #include "save_util.h"
17 #include "unit_util.h"
18 #include "networking/netclient.h"
19 #include "gfx/cockpit.h"
20 #include "gfx/ani_texture.h"
21 #include "music.h"
22 #include "lin_time.h"
23 #include "load_mission.h"
24 #include "universe_util.h"
25 #include "gui/guidefs.h"
26 #ifdef RENDER_FROM_TEXTURE
27 #include "gfx/stream_texture.h"
28 #endif
29 #include "main_loop.h"
30 #include "in_mouse.h"
31 #include "in_kb.h"
32 
33 #include "audio/SceneManager.h"
34 
35 
36 static unsigned int& getMouseButtonMask()
37 {
38  static unsigned int mask = 0;
39  return mask;
40 }
41 
42 static void biModifyMouseSensitivity( int &x, int &y, bool invert )
43 {
44  int xrez = g_game.x_resolution;
45  static int whentodouble = XMLSupport::parse_int( vs_config->getVariable( "joystick", "double_mouse_position", "1280" ) );
46  static float factor = XMLSupport::parse_float( vs_config->getVariable( "joystick", "double_mouse_factor", "2" ) );
47  if (xrez >= whentodouble) {
48  x -= g_game.x_resolution/2;
49  y -= g_game.y_resolution/2;
50  if (invert) {
51  x = int(x/factor);
52  y = int(y/factor);
53  } else {
54  x = int(x*factor);
55  y = int(y*factor);
56  }
57  x += g_game.x_resolution/2;
58  y += g_game.y_resolution/2;
59  if (x > g_game.x_resolution)
60  x = g_game.x_resolution;
61  if (y > g_game.y_resolution)
62  y = g_game.y_resolution;
63  if (x < 0) x = 0;
64  if (y < 0) y = 0;
65  }
66 }
67 
68 static bool createdbase = false;
69 static int createdmusic = -1;
70 
71 void ModifyMouseSensitivity( int &x, int &y )
72 {
73  biModifyMouseSensitivity( x, y, false );
74 }
75 #ifdef BASE_MAKER
76  #include <stdio.h>
77  #ifdef _WIN32
78  #ifndef NOMINMAX
79  #define NOMINMAX
80  #endif //tells VCC not to generate min/max macros
81  #include <windows.h>
82  #endif
83 static char makingstate = 0;
84 #endif
85 extern const char *mission_key; //defined in main.cpp
87 using namespace VSFileSystem;
88 #define NEW_GUI
89 
90 #ifdef NEW_GUI
91 #include "basecomputer.h"
92 #include "../gui/eventmanager.h"
93 #endif
94 std::vector< unsigned int >base_keyboard_queue;
95 static void CalculateRealXAndY( int xbeforecalc, int ybeforecalc, float *x, float *y )
96 {
97  (*x) = ( ( (float) (xbeforecalc*2) )/g_game.x_resolution )-1;
98  (*y) = -( ( (float) (ybeforecalc*2) )/g_game.y_resolution )+1;
99 }
100 #define mymin( a, b ) ( ( (a) < (b) ) ? (a) : (b) )
101 static void SetupViewport()
102 {
103  static int base_max_width = XMLSupport::parse_int( vs_config->getVariable( "graphics", "base_max_width", "0" ) );
104  static int base_max_height = XMLSupport::parse_int( vs_config->getVariable( "graphics", "base_max_height", "0" ) );
105  if (base_max_width && base_max_height) {
106  int xrez = mymin( g_game.x_resolution, base_max_width );
107  int yrez = mymin( g_game.y_resolution, base_max_height );
108  int offsetx = (g_game.x_resolution-xrez)/2;
109  int offsety = (g_game.y_resolution-yrez)/2;
110  glViewport( offsetx, offsety, xrez, yrez );
111  }
112 }
113 #undef mymin
115 {
116  size_t i;
117  for (i = 0; i < links.size(); i++)
118  if (links[i])
119  delete links[i];
120  for (i = 0; i < objs.size(); i++)
121  if (objs[i])
122  delete objs[i];
123 }
124 
126 {
127 //Do nothing...
128 }
129 
131 {
132 //Do nothing...
133 }
134 
136 {
137  static bool blur_bases = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "blur_bases", "true" ) );
138  return blur_bases ? BILINEAR : NEAREST;
139 }
140 
141 BaseInterface::Room::BaseVSSprite::BaseVSSprite( const std::string &spritefile, const std::string &ind ) :
142  BaseObj( ind )
143  , spr( spritefile.c_str(), BlurBases(), GFXTRUE )
144 {
145 }
146 
148 {
149  if (soundsource.get() != NULL)
150  BaseUtil::DestroyVideoSoundStream(soundsource, soundscene);
151  spr.ClearTimeSource();
152 }
153 
154 
155 BaseInterface::Room::BaseVSMovie::BaseVSMovie( const std::string &moviefile, const std::string &ind ) :
156  BaseVSSprite( ind, VSSprite( AnimatedTexture::CreateVideoTexture( moviefile ), 0, 0, 2, 2, 0, 0, true ) )
157 {
158  playing = false;
159  soundscene = "video";
160  if (g_game.sound_enabled && spr.LoadSuccess()) {
163  } else {
164  spr.Reset();
165  }
166  SetHidePointer(true);
167 }
168 
170 {
171  hidePointer = hide;
172  hidePointerTime = realTime();
173 }
174 
175 void BaseInterface::Room::BaseVSSprite::SetSprite( const std::string &spritefile )
176 {
177  //Destroy SPR
178  spr.~VSSprite();
179  //Re-create it (in case you don't know the following syntax,
180  //which is a weird but standard syntax,
181  //it initializes spr instead of allocating memory for it)
182  //PS: I hope it doesn't break many compilers ;)
183  //(if it does, spr will have to become a pointer)
184  new (&spr)VSSprite( spritefile.c_str(), BlurBases(), GFXTRUE );
185 }
186 
187 void BaseInterface::Room::BaseVSMovie::SetMovie( const std::string &moviefile )
188 {
189  //Get sprite position and size so that we can preserve them
190  float x, y, w, h, rot;
191  spr.GetPosition( x, y );
192  spr.GetSize( w, h );
193  spr.GetRotation( rot );
194 
195  //See notes above
196  spr.~VSSprite();
197  new (&spr)VSSprite( AnimatedTexture::CreateVideoTexture( moviefile ), x, y, w, h, 0, 0, true );
198  spr.SetRotation( rot );
199 
200  if (soundsource.get() != NULL)
201  BaseUtil::DestroyVideoSoundStream(soundsource, soundscene);
202  soundscene = "video";
203  playing = false;
204  if (g_game.sound_enabled) {
205  soundsource = BaseUtil::CreateVideoSoundStream( moviefile, soundscene );
206  spr.SetTimeSource( soundsource );
207  } else {
208  spr.Reset();
209  }
210 }
211 
213 {
214  return spr.getTexture()->curTime();
215 }
216 
218 {
219  spr.getTexture()->setTime( t );
220 }
221 
223 {
224  static float AlphaTestingCutoff =
225  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_alpha_test_cutoff", "0" ) );
226  GFXAlphaTest( GREATER, AlphaTestingCutoff );
228  GFXEnable( TEXTURE0 );
229  spr.Draw();
230  GFXAlphaTest( ALWAYS, 0 );
231 
232  // Play the associated source if it isn't playing
233  if (soundsource.get() != NULL) {
234  if (!soundsource->isPlaying())
235  soundsource->startPlaying();
236  }
237 }
238 
240 {
241  if (soundsource.get() == NULL) {
242  // If it's not playing, mark as playing, and reset the sprite's animation
243  // (it's not automatic without a time source)
244  if (!playing) {
245  playing = true;
246  spr.Reset();
247  }
248  }
249 
250  // Hide mouse pointer
251  if (base && hidePointer && base->mousePointerStyle != MOUSE_POINTER_NONE) {
252  double time = realTime();
253  if (hidePointerTime < 0.0) {
254  hidePointerTime = time + 1.0;
255  } else if (time > hidePointerTime) {
256  base->mousePointerStyle = MOUSE_POINTER_NONE;
257  hidePointerTime = -1.0;
258  }
259  }
260 
262 
263  if (soundsource.get() == NULL) {
264  // If there is no sound source, and the sprite is an animated sprite, and
265  // it's finished, then we must invoke the callback
266  if (!getCallback().empty() && spr.Done()) {
267  RunPython(getCallback().c_str());
268  playing = false;
269  }
270  }
271 }
272 
274 {
275  return soundsource.get() != NULL
276  && soundsource->isPlaying();
277 }
278 
280 {
281  Unit *un = base->caller.GetUnit();
282  if (un) {
283  GFXHudMode( GFXFALSE );
284  float tmp = g_game.fov;
285  static float standard_fov = XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_fov", "90" ) );
286  g_game.fov = standard_fov;
287  float tmp1 = _Universe->AccessCamera()->GetFov();
288  _Universe->AccessCamera()->SetFov( standard_fov );
289  Vector p, q, r;
290  _Universe->AccessCamera()->GetOrientation( p, q, r );
291  float co = _Universe->AccessCamera()->getCockpitOffset();
295  Matrix cam( p.i, p.j, p.k, q.i, q.j, q.k, r.i, r.j, r.k, pos );
296  Matrix final;
297  Matrix newmat = mat;
298  newmat.p.k *= un->rSize();
299  newmat.p += QVector( 0, 0, g_game.znear );
300  newmat.p.i *= newmat.p.k;
301  newmat.p.j *= newmat.p.k;
302  MultMatrix( final, cam, newmat );
303  SetupViewport();
304  GFXClear( GFXFALSE ); //clear the zbuf
305 
306  GFXEnable( DEPTHTEST );
308  GFXEnable( LIGHTING );
309  int light = 0;
310  GFXCreateLight( light,
311  GFXLight( true,
312  GFXColor( 1, 1, 1, 1 ),
313  GFXColor( 1, 1, 1, 1 ),
314  GFXColor( 1, 1, 1, 1 ),
315  GFXColor( 0.1, 0.1, 0.1, 1 ),
316  GFXColor( 1, 0, 0 ),
317  GFXColor( 1, 1, 1, 0 ),
318  24 ),
319  true );
320 
321  (un)->DrawNow( final, FLT_MAX );
322  GFXDeleteLight( light );
325  GFXDisable( LIGHTING );
326  GFXDisable( TEXTURE1 );
327  GFXEnable( TEXTURE0 );
330  SetupViewport();
331  GFXHudMode( GFXTRUE );
332  g_game.fov = tmp;
333  _Universe->AccessCamera()->SetFov( tmp1 );
334  }
335 }
336 
338 {
339  size_t i;
340  for (i = 0; i < objs.size(); i++)
341  if (objs[i]) {
343  objs[i]->Draw( base );
344  }
346  //draw location markers
347  //<!-- config options in the "graphics" section -->
348  //<var name="base_enable_locationmarkers" value="true"/>
349  //<var name="base_locationmarker_sprite" value="base_locationmarker.spr"/>
350  //<var name="base_draw_locationtext" value="true"/>
351  //<var name="base_locationmarker_textoffset_x" value="0.025"/>
352  //<var name="base_locationmarker_textoffset_y" value="0.025"/>
353  //<var name="base_locationmarker_drawalways" value="false"/>
354  //<var name="base_locationmarker_distance" value="0.5"/>
355  //<var name="base_locationmarker_textcolor_r" value="1.0"/>
356  //<var name="base_locationmarker_textcolor_g" value="1.0"/>
357  //<var name="base_locationmarker_textcolor_b" value="1.0"/>
358  //<var name="base_drawlocationborders" value="false"/>
359  static bool enable_markers =
360  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "base_enable_locationmarkers", "false" ) );
361  static bool draw_text = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "base_draw_locationtext", "false" ) );
362  static bool draw_always =
363  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "base_locationmarker_drawalways", "false" ) );
364  static float y_lower = -0.9; //shows the offset on the lower edge of the screen (for the textline there) -> Should be defined globally somewhere
365  static float base_text_background_alpha =
366  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_text_background_alpha", "0.0625" ) );
367  if (enable_markers) {
368  float x, y, text_wid, text_hei;
369  //get offset from config;
370  static float text_offset_x =
371  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_locationmarker_textoffset_x", "0" ) );
372  static float text_offset_y =
373  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_locationmarker_textoffset_y", "0" ) );
374  static float text_color_r =
375  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_locationmarker_textcolor_r", "1" ) );
376  static float text_color_g =
377  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_locationmarker_textcolor_g", "1" ) );
378  static float text_color_b =
379  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_locationmarker_textcolor_b", "1" ) );
380  for (size_t i = 0; i < links.size(); i++) //loop through all links and draw a marker for each
381  if (links[i]) {
382  if ( (links[i]->alpha < 1) || (draw_always) ) {
383  if (draw_always) links[i]->alpha = 1; //set all alphas to visible
384  x = ( links[i]->x+(links[i]->wid/2) ); //get the center of the location
385  y = ( links[i]->y+(links[i]->hei/2) ); //get the center of the location
386 
387  /* draw marker */
388  static string spritefile_marker = vs_config->getVariable( "graphics", "base_locationmarker_sprite", "" );
389  if ( spritefile_marker.length() && links[i]->text.find("XXX") != 0 ) {
390  static VSSprite *spr_marker = new VSSprite( spritefile_marker.c_str() );
391  float wid, hei;
392  spr_marker->GetSize( wid, hei );
393  //check if the sprite is near a screenedge and correct its position if necessary
394  if ( ( x+(wid/2) ) >= 1 ) x = ( 1-(wid/2) );
395  if ( ( y+(hei/2) ) >= 1 ) y = ( 1-(hei/2) );
396  if ( ( x-(wid/2) ) <= -1 ) x = ( -1+(wid/2) );
397  if ( ( y-(hei/2) ) <= y_lower ) y = ( y_lower+(hei/2) );
398  spr_marker->SetPosition( x, y );
399  GFXDisable( TEXTURE1 );
400  GFXEnable( TEXTURE0 );
401  GFXColor4f( 1, 1, 1, links[i]->alpha );
402  spr_marker->Draw();
403  } //if spritefile
404  if (draw_text) {
405  GFXDisable( TEXTURE0 );
406  TextPlane text_marker;
407  text_marker.SetText( links[i]->text );
408  text_marker.GetCharSize( text_wid, text_hei ); //get average charactersize
409  float text_pos_x = x+text_offset_x; //align right ...
410  float text_pos_y = y+text_offset_y+text_hei; //...and on top
411  text_wid = text_wid*links[i]->text.length()*0.25; //calc ~width of text (=multiply the average characterwidth with the number of characters)
412  if ( (text_pos_x+text_offset_x+text_wid) >= 1 ) //check right screenborder
413  text_pos_x = (x-fabs( text_offset_x )-text_wid); //align left
414  if ( (text_pos_y+text_offset_y) >= 1 ) //check upper screenborder
415  text_pos_y = ( y-fabs( text_offset_y ) ); //align on bottom
416  if ( (text_pos_y+text_offset_y-text_hei) <= y_lower ) //check lower screenborder
417  text_pos_y = (y+fabs( text_offset_y )+text_hei); //align on top
418  text_marker.col = GFXColor( text_color_r, text_color_g, text_color_b, links[i]->alpha );
419  text_marker.SetPos( text_pos_x, text_pos_y );
420  if (links[i]->pythonfile != "#" && text_marker.GetText().find( "XXX" ) != 0) {
421  GFXColor tmpbg = text_marker.bgcol;
422  bool automatte = (0 == tmpbg.a);
423  if (automatte) text_marker.bgcol = GFXColor( 0, 0, 0, base_text_background_alpha );
424  text_marker.Draw( text_marker.GetText(), 0, true, false, automatte );
425  text_marker.bgcol = tmpbg;
426  }
427  GFXEnable( TEXTURE0 );
428  } //if draw_text
429  }
430  }
431  //if link
432  //for i
433  } //enable_markers
434 
435  static bool draw_borders = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "base_drawlocationborders", "false" ) );
436  static bool debug_markers = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "base_enable_debugmarkers", "false" ) );
437  if (draw_borders || debug_markers) {
438  float x, y, text_wid, text_hei;
439  //get offset from config;
440  static float text_offset_x =
441  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_locationmarker_textoffset_x", "0" ) );
442  static float text_offset_y =
443  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_locationmarker_textoffset_y", "0" ) );
444  for (size_t i = 0; i < links.size(); i++) //loop through all links and draw a marker for each
445  if (links[i]) {
446  //Debug marker
447  if (debug_markers) {
448  //compute label position
449  x = ( links[i]->x+(links[i]->wid/2) ); //get the center of the location
450  y = ( links[i]->y+(links[i]->hei/2) ); //get the center of the location
451  TextPlane text_marker;
452  text_marker.SetText( links[i]->index );
453  text_marker.GetCharSize( text_wid, text_hei ); //get average charactersize
454  float text_pos_x = x+text_offset_x; //align right ...
455  float text_pos_y = y+text_offset_y+text_hei; //...and on top
456  text_wid = text_wid*links[i]->text.length()*0.25; //calc ~width of text (=multiply the average characterwidth with the number of characters)
457  if ( (text_pos_x+text_offset_x+text_wid) >= 1 ) //check right screenborder
458  text_pos_x = (x-fabs( text_offset_x )-text_wid); //align left
459  if ( (text_pos_y+text_offset_y) >= 1 ) //check upper screenborder
460  text_pos_y = ( y-fabs( text_offset_y ) ); //align on bottom
461  if ( (text_pos_y+text_offset_y-text_hei) <= y_lower ) //check lower screenborder
462  text_pos_y = (y+fabs( text_offset_y )+text_hei); //align on top
463  if (enable_markers)
464  text_pos_y += text_hei;
465  text_marker.col = GFXColor( 1, 1, 1, 1 );
466  text_marker.SetPos( text_pos_x, text_pos_y );
467 
468  GFXDisable( TEXTURE0 );
469  GFXColor tmpbg = text_marker.bgcol;
470  bool automatte = (0 == tmpbg.a);
471  if (automatte) text_marker.bgcol = GFXColor( 0, 0, 0, base_text_background_alpha );
472  text_marker.Draw( text_marker.GetText(), 0, true, false, automatte );
473  text_marker.bgcol = tmpbg;
474  GFXEnable( TEXTURE0 );
475  }
476  //link border
477  GFXColor4f( 1, 1, 1, 1 );
478  Vector c1( links[i]->x, links[i]->y, 0 );
479  Vector c3( links[i]->wid+c1.i, links[i]->hei+c1.j, 0 );
480  Vector c2( c1.i, c3.j, 0 );
481  Vector c4( c3.i, c1.j, 0 );
482  GFXDisable( TEXTURE0 );
484  GFXVertexf( c1 );
485  GFXVertexf( c2 );
486  GFXVertexf( c3 );
487  GFXVertexf( c4 );
488  GFXVertexf( c1 );
489  GFXEnd();
490  GFXEnable( TEXTURE0 );
491  }
492  //if link
493  //for i
494  } //if draw_borders
495 }
496 static std::vector< BaseInterface::Room::BaseTalk* >active_talks;
497 
498 BaseInterface::Room::BaseTalk::BaseTalk( const std::string &msg, const std::string &ind, bool only_one ) : BaseObj( ind )
499  , curchar( 0 )
500  , curtime( 0 )
501  , message( msg )
502 {
503  if (only_one)
504  active_talks.clear();
505  active_talks.push_back( this );
506 }
507 
509 {
510  int tmpx = g_game.x_resolution;
511  int tmpy = g_game.y_resolution;
512  static int base_max_width = XMLSupport::parse_int( vs_config->getVariable( "graphics", "base_max_width", "0" ) );
513  static int base_max_height = XMLSupport::parse_int( vs_config->getVariable( "graphics", "base_max_height", "0" ) );
514  if (base_max_width && base_max_height) {
515  if (base_max_width < tmpx)
516  g_game.x_resolution = base_max_width;
517  if (base_max_height < tmpy)
518  g_game.y_resolution = base_max_height;
519  }
520  static float base_text_background_alpha =
521  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_text_background_alpha", "0.0625" ) );
522  GFXColor tmpbg = text.bgcol;
523  bool automatte = (0 == tmpbg.a);
524  if (automatte)
525  text.bgcol = GFXColor( 0, 0, 0, base_text_background_alpha );
526  if ( !automatte && text.GetText().empty() ) {
527  float posx, posy, wid, hei;
528  text.GetPos( posy, posx );
529  text.GetSize( wid, hei );
530 
531  GFXColorf( text.bgcol );
532  GFXBegin( GFXQUAD );
533  GFXVertex3f( posx, hei, 0.0f );
534  GFXVertex3f( wid, hei, 0.0f );
535  GFXVertex3f( wid, posy, 0.0f );
536  GFXVertex3f( posx, posy, 0.0f );
537  GFXEnd();
538  } else {
539  text.Draw( text.GetText(), 0, true, false, automatte );
540  }
541  text.bgcol = tmpbg;
542  g_game.x_resolution = tmpx;
543  g_game.y_resolution = tmpy;
544 }
545 
546 void RunPython( const char *filnam )
547 {
548 #ifdef DEBUG_RUN_PYTHON
549  printf( "Run python:\n%s\n", filnam );
550 #endif
551  if (filnam[0]) {
552  if (filnam[0] == '#' && filnam[1] != '\0') {
553  ::Python::reseterrors();
554  PyRun_SimpleString( const_cast< char* > (filnam) );
555  ::Python::reseterrors();
556  } else {
557  CompileRunPython( filnam );
558  }
559  }
560 }
561 
563 {
564  timeleft += GetElapsedTime()/getTimeCompression();
565  if (timeleft >= maxtime) {
566  timeleft = 0;
567  VSFileSystem::vs_dprintf( 2, "Running python script... " );
568  RunPython( this->pythonfile.c_str() );
569  return; //do not do ANYTHING with 'this' after the previous statement...
570  }
571 }
572 
573 void BaseInterface::Room::BasePython::Relink( const std::string &python )
574 {
575  pythonfile = python;
576 }
577 
579 {
580  //FIXME: should be called from draw()
581  if (hastalked) return;
582  curtime += GetElapsedTime()/getTimeCompression();
583  static float delay = XMLSupport::parse_float( vs_config->getVariable( "graphics", "text_delay", ".05" ) );
584  if ( ( std::find( active_talks.begin(), active_talks.end(),
585  this ) == active_talks.end() )
586  || ( curchar >= message.size() && curtime > ( ( delay*message.size() )+2 ) ) ) {
587  curtime = 0;
588  std::vector< BaseObj* >::iterator ind = std::find( base->rooms[base->curroom]->objs.begin(),
589  base->rooms[base->curroom]->objs.end(),
590  this );
591  if ( ind != base->rooms[base->curroom]->objs.end() )
592  *ind = NULL;
593  std::vector< BaseTalk* >::iterator ind2 = std::find( active_talks.begin(), active_talks.end(), this );
594  if ( ind2 != active_talks.end() )
595  *ind2 = NULL;
596  base->othtext.SetText( "" );
597  delete this;
598  return; //do not do ANYTHING with 'this' after the previous statement...
599  }
600  if ( curchar < message.size() ) {
601  static float inbetween = XMLSupport::parse_float( vs_config->getVariable( "graphics", "text_speed", ".025" ) );
602  if (curtime > inbetween) {
603  base->othtext.SetText( message.substr( 0, ++curchar ) );
604  curtime = 0;
605  }
606  }
607  hastalked = true;
608 }
609 
611 {
612  for (size_t i = 0; i < links.size(); i++)
613  if (links[i]) {
614  if ( x >= links[i]->x
615  && x <= (links[i]->x+links[i]->wid)
616  && y >= links[i]->y
617  && y <= (links[i]->y+links[i]->hei) )
618  return i;
619  }
620  return -1;
621 }
622 
624 
625 bool RefreshGUI( void )
626 {
627  bool retval = false;
628  if ( _Universe->AccessCockpit() ) {
632 #ifdef NEW_GUI
634  return true;
635 
636 #else
637  return RefreshInterface();
638 #endif
639  } else {
641  }
642  retval = true;
643  }
644  }
645  }
646  return retval;
647 }
648 
650 {
651  UpdateTime();
653  if (Network != NULL)
654  for (size_t jj = 0; jj < _Universe->numPlayers(); jj++)
655  Network[jj].checkMsg( NULL );
656  GFXBeginScene();
657  if (createdbase) {
658  createdbase = false;
660  }
661  if ( !RefreshGUI() ) {
663  } else {
664  GFXEndScene();
665  micro_sleep( 1000 );
666  }
667  BaseComputer::dirty = false;
668 }
669 
670 void BaseInterface::Room::Click( BaseInterface *base, float x, float y, int button, int state )
671 {
672  if (button == WS_LEFT_BUTTON) {
673  int linknum = MouseOver( base, x, y );
674  if (linknum >= 0) {
675  Link *link = links[linknum];
676  if (link)
677  link->Click( base, x, y, button, state );
678  }
679  } else {
680 #ifdef BASE_MAKER
681  if (state == WS_MOUSE_UP) {
682  char input[201];
683  char *str;
684  if (button == WS_RIGHT_BUTTON)
685  str = "Please create a file named stdin.txt and type\nin the sprite file that you wish to use.";
686  else if (button == WS_MIDDLE_BUTTON)
687  str =
688  "Please create a file named stdin.txt and type\nin the type of room followed by arguments for the room followed by text in quotations:\n1 ROOM# \"TEXT\"\n2 \"TEXT\"\n3 vector<MODES>.size vector<MODES> \"TEXT\"";
689  else
690  return;
691 #ifdef _WIN32
692  int ret = MessageBox( NULL, str, "Input", MB_OKCANCEL );
693 #else
694  printf( "\n%s\n", str );
695  int ret = 1;
696 #endif
697  int index;
698  int rmtyp;
699  if (ret == 1) {
700  if (button == WS_RIGHT_BUTTON) {
701 #ifdef _WIN32
702  FILE *fp = VSFileSystem::vs_open( "stdin.txt", "rt" );
703 #else
704  FILE *fp = stdin;
705 #endif
706  VSFileSystem::vs_fscanf( fp, "%200s", input );
707 #ifdef _WIN32
709 #endif
710  } else if (button == WS_MIDDLE_BUTTON && makingstate == 0) {
711  int i;
712 #ifdef _WIN32
713  FILE *fp = VSFileSystem::vs_open( "stdin.txt", "rt" );
714 #else
715  FILE *fp = stdin;
716 #endif
717  VSFileSystem::vs_fscanf( fp, "%d", &rmtyp );
718  switch (rmtyp)
719  {
720  case 1:
721  links.push_back( new Goto( "linkind", "link" ) );
722  VSFileSystem::vs_fscanf( fp, "%d", &( (Goto*) links.back() )->index );
723  break;
724  case 2:
725  links.push_back( new Launch( "launchind", "launch" ) );
726  break;
727  case 3:
728  links.push_back( new Comp( "compind", "comp" ) );
729  VSFileSystem::vs_fscanf( fp, "%d", &index );
730  for (i = 0; i < index && ( !VSFileSystem::vs_feof( fp ) ); i++) {
731  VSFileSystem::vs_fscanf( fp, "%d", &ret );
732  ( (Comp*) links.back() )->modes.push_back( (BaseComputer::DisplayMode) ret );
733  }
734  break;
735  default:
736 #ifdef _WIN32
738  MessageBox( NULL, "warning: invalid basemaker option", "Error", MB_OK );
739 #endif
740  printf( "warning: invalid basemaker option: %d", rmtyp );
741  return;
742  }
743  VSFileSystem::vs_fscanf( fp, "%200s", input );
744  input[200] = input[199] = '\0';
745  links.back()->text = string( input );
746 #ifdef _WIN32
748 #endif
749  }
750  if (button == WS_RIGHT_BUTTON) {
751  input[200] = input[199] = '\0';
752  objs.push_back( new BaseVSSprite( input, "tex" ) );
753  ( (BaseVSSprite*) objs.back() )->texfile = string( input );
754  ( (BaseVSSprite*) objs.back() )->spr.SetPosition( x, y );
755  } else if (button == WS_MIDDLE_BUTTON && makingstate == 0) {
756  links.back()->x = x;
757  links.back()->y = y;
758  links.back()->wid = 0;
759  links.back()->hei = 0;
760  makingstate = 1;
761  } else if (button == WS_MIDDLE_BUTTON && makingstate == 1) {
762  links.back()->wid = x-links.back()->x;
763  if (links.back()->wid < 0)
764  links.back()->wid = -links.back()->wid;
765  links.back()->hei = y-links.back()->y;
766  if (links.back()->hei < 0)
767  links.back()->hei = -links.back()->hei;
768  makingstate = 0;
769  }
770  }
771  }
772 #else
773  if ( state == WS_MOUSE_UP && links.size() ) {
774  size_t count = 0;
775  while ( count++ < links.size() ) {
776  Link *curlink = links[base->curlinkindex++%links.size()];
777  if (curlink) {
778  int x = int( ( ( ( curlink->x+(curlink->wid/2) )+1 )/2 )*g_game.x_resolution );
779  int y = -int( ( ( ( curlink->y+(curlink->hei/2) )-1 )/2 )*g_game.y_resolution );
780  biModifyMouseSensitivity( x, y, true );
781  winsys_warp_pointer( x, y );
782  PassiveMouseOverWin( x, y );
783  break;
784  }
785  }
786  }
787 #endif
788  }
789 }
790 
791 void BaseInterface::MouseOver( int xbeforecalc, int ybeforecalc )
792 {
793  float x, y;
794  CalculateRealXAndY( xbeforecalc, ybeforecalc, &x, &y );
795  int i = rooms[curroom]->MouseOver( this, x, y ); //FIXME Whatever this is, it shouldn't be named just "i"; & possibly should be size_t
796  Room::Link *link = 0;
797  Room::Link *hotlink = 0;
798  if (i >= 0)
799  link = rooms[curroom]->links[i];
800  if ( lastmouseindex >= 0 && lastmouseindex < static_cast<int>(rooms[curroom]->links.size()) )
801  hotlink = rooms[curroom]->links[lastmouseindex];
802  if ( hotlink && (lastmouseindex != i) )
803  hotlink->MouseLeave( this, x, y, getMouseButtonMask() );
804  if ( link && (lastmouseindex != i) )
805  link->MouseEnter( this, x, y, getMouseButtonMask() );
806  if (link)
807  link->MouseMove( this, x, y, getMouseButtonMask() );
808  lastmouseindex = i;
809  static float overcolor[4] = {1, .666666667, 0, 1};
810  static float inactivecolor[4] = {0, 1, 0, 1};
811  if (link)
812  curtext.SetText( link->text );
813  else
814  curtext.SetText( rooms[curroom]->deftext );
815  if (link && link->pythonfile != "#") {
816  curtext.col = GFXColor( overcolor[0], overcolor[1], overcolor[2], overcolor[3] );
817  mousePointerStyle = MOUSE_POINTER_HOVER;
818  } else {
819  curtext.col = GFXColor( inactivecolor[0], inactivecolor[1], inactivecolor[2], inactivecolor[3] );
820  mousePointerStyle = MOUSE_POINTER_NORMAL;
821  }
822  static bool draw_always =
823  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "base_locationmarker_drawalways", "false" ) );
824  static float defined_distance =
825  fabs( XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_locationmarker_distance", "0.5" ) ) );
826  if (!draw_always) {
827  float cx, cy;
828  float dist_cur2link;
829  for (i = 0; i < static_cast<int>(rooms[curroom]->links.size()); i++) {
830  cx = ( rooms[curroom]->links[i]->x+(rooms[curroom]->links[i]->wid/2) ); //get the x center of the location
831  cy = ( rooms[curroom]->links[i]->y+(rooms[curroom]->links[i]->hei/2) ); //get the y center of the location
832  dist_cur2link = sqrt( pow( (cx-x), 2 )+pow( (cy-y), 2 ) );
833  if (dist_cur2link < defined_distance)
834  rooms[curroom]->links[i]->alpha = ( 1-(dist_cur2link/defined_distance) );
835  else
836  rooms[curroom]->links[i]->alpha = 1;
837  }
838  }
839 }
840 
841 void BaseInterface::Click( int xint, int yint, int button, int state )
842 {
843  float x, y;
844  CalculateRealXAndY( xint, yint, &x, &y );
845  rooms[curroom]->Click( this, x, y, button, state );
846 }
847 
848 void BaseInterface::ClickWin( int button, int state, int x, int y )
849 {
850  ModifyMouseSensitivity( x, y );
851  if (state == WS_MOUSE_DOWN)
852  getMouseButtonMask() |= ( 1<<(button-1) );
853 
854  else if (state == WS_MOUSE_UP)
855  getMouseButtonMask() &= ~( 1<<(button-1) );
856  if (CurrentBase) {
857  if (CurrentBase->CallComp) {
858 #ifdef NEW_GUI
859  EventManager::
860 #else
861  UpgradingInfo::
862 #endif
863  ProcessMouseClick( button, state, x, y );
864  } else {
865  CurrentBase->Click( x, y, button, state );
866  }
867  } else {
868  NavigationSystem::mouseClick( button, state, x, y );
869  }
870 }
871 
873 {
874  ModifyMouseSensitivity( x, y );
875  SetSoftwareMousePosition( x, y );
876  if (CurrentBase) {
877  if (CurrentBase->CallComp) {
878 #ifdef NEW_GUI
879  EventManager::
880 #else
881  UpgradingInfo::
882 #endif
883  ProcessMousePassive( x, y );
884  } else {
885  CurrentBase->MouseOver( x, y );
886  }
887  } else {
889  }
890 }
891 
893 {
894  ModifyMouseSensitivity( x, y );
895  SetSoftwareMousePosition( x, y );
896  if (CurrentBase) {
897  if (CurrentBase->CallComp) {
898 #ifdef NEW_GUI
899  EventManager::
900 #else
901  UpgradingInfo::
902 #endif
903  ProcessMouseActive( x, y );
904  } else {
905  CurrentBase->MouseOver( x, y );
906  }
907  } else {
909  }
910 }
911 
912 void BaseInterface::Key( unsigned int ch, unsigned int mod, bool release, int x, int y )
913 {
914  if ( !python_kbhandler.empty() ) {
915  const std::string *evtype;
916  if (release) {
917  static const std::string release_evtype( "keyup" );
918  evtype = &release_evtype;
919  } else {
920  static const std::string press_evtype( "keydown" );
921  evtype = &press_evtype;
922  }
923  BaseUtil::SetKeyEventData( *evtype, ch );
924  RunPython( python_kbhandler.c_str() );
925  }
926 }
927 
928 void BaseInterface::GotoLink( int linknum )
929 {
930  othtext.SetText( "" );
931  if (static_cast<int>(rooms.size()) > linknum && linknum >= 0) {
932  curlinkindex = 0;
933  curroom = linknum;
934  curtext.SetText( rooms[curroom]->deftext );
935  mousePointerStyle = MOUSE_POINTER_NORMAL;
936  } else {
937 #ifndef BASE_MAKER
938  VSFileSystem::vs_fprintf( stderr, "\nWARNING: base room #%d tried to go to an invalid index: #%d", curroom, linknum );
939  assert( 0 );
940 #else
941  while (rooms.size() <= linknum) {
942  rooms.push_back( new Room() );
943  char roomnum[50];
944  sprintf( roomnum, "Room #%d", linknum );
945  rooms.back()->deftext = roomnum;
946  }
947  GotoLink( linknum );
948 #endif
949  }
950 }
951 
953 {
954 #ifdef BASE_MAKER
955  FILE *fp = VSFileSystem::vs_open( "bases/NEW_BASE" BASE_EXTENSION, "wt" );
956  if (fp) {
957  EndXML( fp );
959  }
960 #endif
961  CurrentBase = 0;
963  for (size_t i = 0; i < rooms.size(); i++)
964  delete rooms[i];
965 }
966 
967 void base_main_loop();
968 int shiftup( int );
969 
970 static void base_keyboard_cb( unsigned int ch, unsigned int mod, bool release, int x, int y )
971 {
972  //Set modifiers
973  unsigned int amods = 0;
974  amods |= ( mod&(WSK_MOD_LSHIFT|WSK_MOD_RSHIFT) ) ? KB_MOD_SHIFT : 0;
975  amods |= ( mod&(WSK_MOD_LCTRL|WSK_MOD_RCTRL) ) ? KB_MOD_CTRL : 0;
976  amods |= ( mod&(WSK_MOD_LALT|WSK_MOD_RALT) ) ? KB_MOD_ALT : 0;
977  setActiveModifiers( amods );
978  unsigned int shiftedch =
979  ( ( WSK_MOD_LSHIFT == (mod&WSK_MOD_LSHIFT) ) || ( WSK_MOD_RSHIFT == (mod&WSK_MOD_RSHIFT) ) ) ? shiftup( ch ) : ch;
981  //Flush buffer
982  if ( base_keyboard_queue.size() )
984  //Send directly to base interface handlers
985  BaseInterface::CurrentBase->Key( shiftedch, amods, release, x, y );
986  } else
987  //Queue keystroke
988  if (!release) {
989  base_keyboard_queue.push_back( shiftedch );
990  }
991 }
992 
994 {
999  CurrentBase = this;
1000  CallComp = false;
1001  static bool simulate_while_at_base =
1002  XMLSupport::parse_bool( vs_config->getVariable( "physics", "simulate_while_docked", "false" ) );
1003  if ( !(simulate_while_at_base || _Universe->numPlayers() > 1) )
1005 }
1006 
1007 BaseInterface::Room::Talk::Talk( const std::string &ind, const std::string &pythonfile ) :
1008  BaseInterface::Room::Link( ind, pythonfile ), index(-1)
1009 {
1010 #ifndef BASE_MAKER
1011  gameMessage last;
1012  int i = 0;
1013  vector< std::string >who;
1014  string newmsg;
1015  string newsound;
1016  who.push_back( "bar" );
1017  while ( ( mission->msgcenter->last( i++, last, who ) ) ) {
1018  newmsg = last.message;
1019  newsound = "";
1020  string::size_type first = newmsg.find_first_of( "[" );
1021  {
1022  string::size_type last = newmsg.find_first_of( "]" );
1023  if ( first != string::npos && (first+1) < newmsg.size() ) {
1024  newsound = newmsg.substr( first+1, last-first-1 );
1025  newmsg = newmsg.substr( 0, first );
1026  }
1027  }
1028  this->say.push_back( newmsg );
1029  this->soundfiles.push_back( newsound );
1030  }
1031 #endif
1032 }
1033 
1034 double compute_light_dot( Unit *base, Unit *un )
1035 {
1036  StarSystem *ss = base->getStarSystem();
1037  double ret = -1;
1038  Unit *st;
1039  Unit *base_owner = NULL;
1040  if (ss) {
1042  un_iter ui = ss->getUnitList().createIterator();
1043  for (; (st = *ui); ++ui)
1044  if ( st->isPlanet() ) {
1045  if ( ( (Planet*) st )->hasLights() ) {
1046  QVector v1 = ( un->Position()-base->Position() ).Normalize();
1047  QVector v2 = ( st->Position()-base->Position() ).Normalize();
1048 #ifdef VS_DEBUG
1049  double dot = v1.Dot( v2 );
1050  if (dot > ret) {
1051  VSFileSystem::vs_fprintf( stderr, "dot %lf", dot );
1052  ret = dot;
1053  }
1054 #endif
1055  } else {
1056  un_iter ui = ( (Planet*) st )->satellites.createIterator();
1057  Unit *ownz = NULL;
1058  for (; (ownz = *ui); ++ui)
1059  if (ownz == base)
1060  base_owner = st;
1061  }
1062  }
1064  } else {return 1; } if (base_owner == NULL || base->isUnit() == PLANETPTR)
1065  return ret;
1066  else
1067  return compute_light_dot( base_owner, un );
1068 }
1069 
1070 const char * compute_time_of_day( Unit *base, Unit *un )
1071 {
1072  if (!base || !un)
1073  return "day";
1074  float rez = compute_light_dot( base, un );
1075  if (rez > .2)
1076  return "day";
1077  if (rez < -.1)
1078  return "night";
1079  return "sunset";
1080 }
1081 
1082 extern void ExecuteDirector();
1083 
1084 BaseInterface::BaseInterface( const char *basefile, Unit *base, Unit *un ) :
1085  curtext( getConfigColor( "Base_Text_Color_Foreground",
1086  GFXColor( 0, 1, 0, 1 ) ), getConfigColor( "Base_Text_Color_Background", GFXColor( 0, 0, 0, 1 ) ) )
1087  , othtext( getConfigColor( "Fixer_Text_Color_Foreground",
1088  GFXColor( 1, 1, .5, 1 ) ), getConfigColor( "FixerTextColor_Background", GFXColor( 0, 0, 0, 1 ) ) )
1089 {
1090  CurrentBase = this;
1091  CallComp = false;
1092  lastmouseindex = 0;
1093  enabledj = true;
1094  createdbase = true;
1095  midloop = false;
1096  terminate_scheduled = false;
1097  createdmusic = -1;
1098  caller = un;
1099  curroom = 0;
1100  curlinkindex = 0;
1101  this->baseun = base;
1102  float x, y;
1103  curtext.GetCharSize( x, y );
1104  curtext.SetCharSize( x*2, y*2 );
1105  curtext.SetSize( 1-.01, -2 );
1106  othtext.GetCharSize( x, y );
1107  othtext.SetCharSize( x*2, y*2 );
1108  othtext.SetSize( 1-.01, -.75 );
1109 
1110  std::string fac = base ? FactionUtil::GetFaction( base->faction ) : "neutral";
1111  if (base && fac == "neutral")
1113  Load( basefile, compute_time_of_day( base, un ), fac.c_str() );
1115  if (base && un) {
1116  vector< string >vec;
1117  vec.push_back( base->name );
1118  int cpt = UnitUtil::isPlayerStarship( un );
1119  if (cpt >= 0)
1120  saveStringList( cpt, mission_key, vec );
1121  }
1122  if ( !rooms.size() ) {
1123  VSFileSystem::vs_fprintf( stderr,
1124  "ERROR: there are no rooms in basefile \"%s%s%s\" ...\n",
1125  basefile,
1126  compute_time_of_day( base, un ),
1127  BASE_EXTENSION );
1128  rooms.push_back( new Room() );
1129  rooms.back()->deftext = "ERROR: No rooms specified...";
1130 #ifndef BASE_MAKER
1131  rooms.back()->objs.push_back( new Room::BaseShip( -1, 0, 0, 0, 0, -1, 0, 1, 0, QVector( 0, 0, 2 ), "default room" ) );
1132  BaseUtil::Launch( 0, "default room", -1, -1, 1, 2, "ERROR: No rooms specified... - Launch" );
1133  BaseUtil::Comp( 0, "default room", 0, -1, 1, 2, "ERROR: No rooms specified... - Computer",
1134  "Cargo Upgrade Info ShipDealer News Missions" );
1135 #endif
1136  }
1137  GotoLink( 0 );
1138  {
1139  for (unsigned int i = 0; i < 16; ++i)
1140  ExecuteDirector();
1141  }
1142 }
1143 
1144 //Need this for NEW_GUI. Can't ifdef it out because it needs to link.
1145 void InitCallbacks( void )
1146 {
1149 }
1150 
1152 {
1156  }
1157 }
1158 
1160 {
1163 }
1164 //end NEW_GUI.
1165 
1166 void BaseInterface::Room::Comp::Click( BaseInterface *base, float x, float y, int button, int state )
1167 {
1168  if (state == WS_MOUSE_UP) {
1169  Link::Click( base, x, y, button, state );
1170  Unit *un = base->caller.GetUnit();
1171  Unit *baseun = base->baseun.GetUnit();
1172  if (un && baseun) {
1173  base->CallComp = true;
1174 #ifdef NEW_GUI
1175  BaseComputer *bc = new BaseComputer( un, baseun, modes );
1176  bc->init();
1177  bc->run();
1178 #else
1179  UpgradeCompInterface( un, baseun, modes );
1180 #endif //NEW_GUI
1181  }
1182  }
1183 }
1184 
1186 {
1187  if (midloop) {
1188  terminate_scheduled = true;
1189  } else {
1190  Unit *un = caller.GetUnit();
1191  int cpt = UnitUtil::isPlayerStarship( un );
1192  if (un && cpt >= 0) {
1193  vector< string >vec;
1194  vec.push_back( string() );
1195  saveStringList( cpt, mission_key, vec );
1196  }
1199  delete this;
1200  }
1201 }
1202 
1203 extern void abletodock( int dock );
1204 #include "ai/communication.h"
1205 
1206 void BaseInterface::Room::Launch::Click( BaseInterface *base, float x, float y, int button, int state )
1207 {
1208  if (state == WS_MOUSE_UP) {
1209  Link::Click( base, x, y, button, state );
1210  static bool auto_undock_var = XMLSupport::parse_bool( vs_config->getVariable( "physics", "AutomaticUnDock", "true" ) );
1211  bool auto_undock = auto_undock_var;
1212  Unit *bas = base->baseun.GetUnit();
1213  Unit *playa = base->caller.GetUnit();
1214  if (Network != NULL && auto_undock && playa && bas) {
1215  cerr<<"Sending an undock notification"<<endl;
1216  int playernum = _Universe->whichPlayerStarship( playa );
1217  if (playernum >= 0) {
1218  Network[playernum].undockRequest( bas->GetSerial() );
1219  auto_undock = false;
1220  }
1221  }
1222  if (playa && bas) {
1223  if ( ( (playa->name == "eject") || (playa->name == "ejecting") || (playa->name == "pilot")
1224  || (playa->name == "Pilot") || (playa->name == "Eject") ) && (bas->faction == playa->faction) )
1225  playa->name = "return_to_cockpit";
1226  }
1227  if ( (playa && bas) && ( auto_undock || (playa->name == "return_to_cockpit") ) ) {
1228  playa->UnDock( bas );
1229  CommunicationMessage c( bas, playa, NULL, 0 );
1230  c.SetCurrentState( c.fsm->GetUnDockNode(), NULL, 0 );
1231  if ( playa->getAIState() )
1232  playa->getAIState()->Communicate( c );
1233  abletodock( 5 );
1234  if (playa->name == "return_to_cockpit")
1235  if (playa->faction == playa->faction)
1236  playa->owner = bas;
1237  }
1238  base->Terminate();
1239  }
1240 }
1241 
1242 inline float aynrand( float min, float max )
1243 {
1244  return ( (float) ( rand() )/RAND_MAX )*(max-min)+min;
1245 }
1246 
1247 inline QVector randyVector( float min, float max )
1248 {
1249  return QVector( aynrand( min, max ),
1250  aynrand( min, max ),
1251  aynrand( min, max ) );
1252 }
1253 
1254 void BaseInterface::Room::Eject::Click( BaseInterface *base, float x, float y, int button, int state )
1255 {
1256  if (state == WS_MOUSE_UP) {
1257  Link::Click( base, x, y, button, state );
1258  XMLSupport::parse_bool( vs_config->getVariable( "physics", "AutomaticUnDock", "true" ) );
1259  Unit *bas = base->baseun.GetUnit();
1260  Unit *playa = base->caller.GetUnit();
1261  if (playa && bas) {
1262  if (playa->name == "return_to_cockpit") {
1263  playa->name = "ejecting";
1264  Vector tmpvel = bas->Velocity* -1;
1265  if (tmpvel.MagnitudeSquared() < .00001) {
1266  tmpvel = randyVector( -( bas->rSize() ), bas->rSize() ).Cast();
1267  if (tmpvel.MagnitudeSquared() < .00001)
1268  tmpvel = Vector( 1, 1, 1 );
1269  }
1270  tmpvel.Normalize();
1271  playa->SetPosAndCumPos( bas->Position()+tmpvel*1.5*bas->rSize()+randyVector( -.5*bas->rSize(), .5*bas->rSize() ) );
1272  playa->SetAngularVelocity( bas->AngularVelocity );
1273  playa->SetOwner( bas );
1274  static float velmul = XMLSupport::parse_float( vs_config->getVariable( "physics", "eject_cargo_speed", "1" ) );
1275  playa->SetVelocity( bas->Velocity*velmul+randyVector( -.25, .25 ).Cast() );
1276  }
1277  playa->UnDock( bas );
1278  CommunicationMessage c( bas, playa, NULL, 0 );
1279  c.SetCurrentState( c.fsm->GetUnDockNode(), NULL, 0 );
1280  if ( playa->getAIState() )
1281  playa->getAIState()->Communicate( c );
1282  abletodock( 5 );
1283  playa->EjectCargo( (unsigned int) -1 );
1284  if ( (playa->name == "return_to_cockpit") || (playa->name == "ejecting") || (playa->name == "eject")
1285  || (playa->name == "Eject") || (playa->name == "Pilot") || (playa->name == "pilot") )
1286  playa->Kill();
1287  }
1288  base->Terminate();
1289  }
1290 }
1291 
1292 void BaseInterface::Room::Goto::Click( BaseInterface *base, float x, float y, int button, int state )
1293 {
1294  if (state == WS_MOUSE_UP) {
1295  Link::Click( base, x, y, button, state );
1296  base->GotoLink( index );
1297  }
1298 }
1299 
1300 void BaseInterface::Room::Talk::Click( BaseInterface *base, float x, float y, int button, int state )
1301 {
1302  if (state == WS_MOUSE_UP) {
1303  Link::Click( base, x, y, button, state );
1304  if (index >= 0) {
1305  delete base->rooms[curroom]->objs[index];
1306  base->rooms[curroom]->objs[index] = NULL;
1307  index = -1;
1308  base->othtext.SetText( "" );
1309  } else if ( say.size() ) {
1310  curroom = base->curroom;
1311  int sayindex = rand()%say.size();
1312  base->rooms[curroom]->objs.push_back( new Room::BaseTalk( say[sayindex], "currentmsg", true ) );
1313  if (soundfiles[sayindex].size() > 0) {
1314  int sound = AUDCreateSoundWAV( soundfiles[sayindex], false );
1315  if (sound == -1) {
1316  VSFileSystem::vs_fprintf( stderr, "\nCan't find the sound file %s\n", soundfiles[sayindex].c_str() );
1317  } else {
1318  AUDStartPlaying( sound );
1319  AUDDeleteSound( sound ); //won't actually toast it until it stops
1320  }
1321  }
1322  } else {
1323  VSFileSystem::vs_fprintf( stderr, "\nThere are no things to say...\n" );
1324  assert( 0 );
1325  }
1326  }
1327 }
1328 
1329 void BaseInterface::Room::Link::Click( BaseInterface *base, float x, float y, int button, int state )
1330 {
1331  unsigned int buttonmask = getMouseButtonMask();
1332  if (state == WS_MOUSE_UP) {
1333  if (eventMask&UpEvent) {
1334  static std::string evtype( "up" );
1335  BaseUtil::SetMouseEventData( evtype, x, y, buttonmask );
1336  RunPython( this->pythonfile.c_str() );
1337  }
1338  }
1339  if (state == WS_MOUSE_UP) {
1340  //For now, the same. Eventually, we'll want click & double-click
1341  if (eventMask&ClickEvent) {
1342  static std::string evtype( "click" );
1343  BaseUtil::SetMouseEventData( evtype, x, y, buttonmask );
1344  RunPython( this->pythonfile.c_str() );
1345  }
1346  }
1347  if (state == WS_MOUSE_DOWN) {
1348  if (eventMask&DownEvent) {
1349  static std::string evtype( "down" );
1350  BaseUtil::SetMouseEventData( evtype, x, y, buttonmask );
1351  RunPython( this->pythonfile.c_str() );
1352  }
1353  }
1354 }
1355 
1356 void BaseInterface::Room::Link::MouseMove( ::BaseInterface *base, float x, float y, int buttonmask )
1357 {
1358  //Compiling Python code each mouse movement == Bad idea!!!
1359  //If this support is needed we will need to use Python-C++ inheritance.
1360  //Like the Execute() method of AI and Mission classes.
1361  //Even better idea: Rewrite the entire BaseInterface python interface.
1362  if (eventMask&MoveEvent) {
1363  static std::string evtype( "move" );
1364  BaseUtil::SetMouseEventData( evtype, x, y, buttonmask );
1365  RunPython( this->pythonfile.c_str() );
1366  }
1367 }
1368 
1369 void BaseInterface::Room::Link::MouseEnter( ::BaseInterface *base, float x, float y, int buttonmask )
1370 {
1371  if (eventMask&EnterEvent) {
1372  static std::string evtype( "enter" );
1373  BaseUtil::SetMouseEventData( evtype, x, y, buttonmask );
1374  RunPython( this->pythonfile.c_str() );
1375  }
1376 }
1377 
1378 void BaseInterface::Room::Link::MouseLeave( ::BaseInterface *base, float x, float y, int buttonmask )
1379 {
1380  if (eventMask&LeaveEvent) {
1381  static std::string evtype( "leave" );
1382  BaseUtil::SetMouseEventData( evtype, x, y, buttonmask );
1383  RunPython( this->pythonfile.c_str() );
1384  }
1385  clickbtn = -1;
1386 }
1387 
1388 void BaseInterface::Room::Link::Relink( const std::string &pfile )
1389 {
1390  pythonfile = pfile;
1391 }
1392 
1394 {
1395  unsigned char r, g, b, a;
1396 };
1397 static void AnimationDraw()
1398 {
1399 #ifdef RENDER_FROM_TEXTURE
1400  static StreamTexture T( 512, 256, NEAREST, NULL );
1401  BaseColor( *data )[512] = reinterpret_cast< BaseColor(*)[512] > ( T.Map() );
1402  bool counter = false;
1403  srand( time( NULL ) );
1404  for (int i = 0; i < 256; ++i)
1405  for (int j = 0; j < 512; ++j) {
1406  data[i][j].r = rand()&0xff;
1407  data[i][j].g = rand()&0xff;
1408  data[i][j].b = rand()&0xff;
1409  data[i][j].a = rand()&0xff;
1410  }
1411  T.UnMap();
1412  T.MakeActive();
1414  GFXEnable( TEXTURE0 );
1415  GFXDisable( TEXTURE1 );
1416  GFXDisable( CULLFACE );
1417  GFXBegin( GFXQUAD );
1418  GFXTexCoord2f( 0, 0 );
1419  GFXVertex3f( -1.0, -1.0, 0.0 );
1420  GFXTexCoord2f( 1, 0 );
1421  GFXVertex3f( 1.0, -1.0, 0.0 );
1422  GFXTexCoord2f( 1, 1 );
1423  GFXVertex3f( 1.0, 1.0, 0.0 );
1424  GFXTexCoord2f( 0, 1 );
1425  GFXVertex3f( -1.0, 1.0, 0.0 );
1426  GFXEnd();
1427 #endif
1428 }
1430 {
1431  // Some operations cannot be performed in the middle of a Draw() loop
1432  midloop = true;
1433 
1434  GFXColor( 0, 0, 0, 0 );
1435  SetupViewport();
1437  if (GetElapsedTime() < 1) {
1439  }
1440  Room::BaseTalk::hastalked = false;
1441  rooms[curroom]->Draw( this );
1442  AnimationDraw();
1443 
1444  float x, y;
1445  glViewport( 0, 0, g_game.x_resolution, g_game.y_resolution );
1446  static float base_text_background_alpha =
1447  XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_text_background_alpha", "0.0625" ) );
1448 
1449  curtext.GetCharSize( x, y );
1450  curtext.SetPos( -.99, -1+(y*1.5) );
1451 
1452  if (curtext.GetText().find( "XXX" ) != 0) {
1453  GFXColor tmpbg = curtext.bgcol;
1454  bool automatte = (0 == tmpbg.a);
1455  if (automatte) curtext.bgcol = GFXColor( 0, 0, 0, base_text_background_alpha );
1456  curtext.Draw( curtext.GetText(), 0, true, false, automatte );
1457  curtext.bgcol = tmpbg;
1458  }
1459  othtext.SetPos( -.99, 1 );
1460 
1461  if (othtext.GetText().length() != 0) {
1462  GFXColor tmpbg = othtext.bgcol;
1463  bool automatte = (0 == tmpbg.a);
1464  if (automatte) othtext.bgcol = GFXColor( 0, 0, 0, base_text_background_alpha );
1465  othtext.Draw( othtext.GetText(), 0, true, false, automatte );
1466  othtext.bgcol = tmpbg;
1467  }
1468  SetupViewport();
1469  EndGUIFrame( mousePointerStyle );
1470  glViewport( 0, 0, g_game.x_resolution, g_game.y_resolution );
1471  Unit *un = caller.GetUnit();
1472  Unit *base = baseun.GetUnit();
1473  if ( un && (!base) ) {
1474  VSFileSystem::vs_fprintf( stderr, "Error: Base NULL" );
1475  mission->msgcenter->add( "game", "all", "[Computer] Docking unit destroyed. Emergency launch initiated." );
1476  for (size_t i = 0; i < un->pImage->dockedunits.size(); i++)
1477  if (un->pImage->dockedunits[i]->uc.GetUnit() == base)
1478  un->FreeDockingPort( i );
1479  Terminate();
1480  }
1481 
1482  //Commit audio scene status to renderer
1483  if (g_game.sound_enabled)
1485 
1486  // Some operations cannot be performed in the middle of a Draw() loop
1487  // If any of them are scheduled for deferred execution, do so now
1488  midloop = false;
1489  if (terminate_scheduled)
1490  Terminate();
1491 }
1492 
1494 {
1495  if (CurrentBase) {
1496  if (!CurrentBase->CallComp) {
1497  for (std::vector< unsigned int >::iterator it = base_keyboard_queue.begin(); it != base_keyboard_queue.end();
1498  ++it) {
1499  CurrentBase->Key( *it, 0, false, 0, 0 );
1500  CurrentBase->Key( *it, 0, true, 0, 0 );
1501  }
1502  base_keyboard_queue.clear();
1503  }
1504  }
1505 }
1506 
1508 {
1509  enabledj = enabled;
1510 }