naev 0.12.6
gui.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <stdlib.h>
11
12#include "physfs.h"
13
14#include "naev.h"
16
17#include "gui.h"
18
19#include "ai.h"
20#include "array.h"
21#include "camera.h"
22#include "conf.h"
23#include "font.h"
24#include "gui_omsg.h"
25#include "gui_osd.h"
26#include "input.h"
27#include "land.h"
28#include "log.h"
29#include "map_overlay.h"
30#include "menu.h"
31#include "ndata.h"
32#include "nlua.h"
33#include "nlua_gfx.h"
34#include "nlua_gui.h"
35#include "nlua_tk.h"
36#include "nstring.h"
37#include "ntracing.h"
38#include "opengl.h"
39#include "pause.h"
40#include "pilot.h"
41#include "player.h"
42#include "player_gui.h"
43#include "render.h"
44#include "space.h"
45#include "spfx.h"
46#include "start.h"
47#include "toolkit.h"
48
49#define XML_GUI_ID "GUIs"
50#define XML_GUI_TAG "gui"
51
52#define RADAR_BLINK_PILOT 0.5
53#define RADAR_BLINK_SPOB 1.
54
55/* some blinking stuff. */
56static double blink_pilot = 0.;
57static double blink_spob = 0.;
58static double animation_dt = 0.;
59
60/* for VBO. */
61static gl_vbo *gui_radar_select_vbo = NULL;
62
63static int gui_getMessage =
64 1;
65static char *gui_name = NULL;
67
68extern unsigned int land_wid;
69
73static nlua_env gui_env = LUA_NOREF;
74static int gui_L_mclick = 0;
75static int gui_L_mmove = 0;
76
80static double gui_viewport_x = 0.;
81static double gui_viewport_y = 0.;
82static double gui_viewport_w = 0.;
83static double gui_viewport_h = 0.;
84
90typedef struct Radar_ {
91 double w;
92 double h;
93 double x;
94 double y;
95 RadarShape shape;
96 double res;
97} Radar;
98/* radar resolutions */
99#define RADAR_RES_MAX 300.
100#define RADAR_RES_REF 100.
101#define RADAR_RES_MIN 10.
102#define RADAR_RES_INTERVAL \
103 10.
104static Radar gui_radar;
105
106/* needed to render properly */
107static double gui_xoff = 0.;
108static double gui_yoff = 0.;
109
110/* messages */
111static const int mesg_max = 128;
112static int mesg_pointer =
113 0;
114static int mesg_viewpoint = -1;
115static const double mesg_timeout = 15.;
121typedef struct Mesg_ {
122 int dup;
123 char *str;
124 char *dstr;
125 double t;
127} Mesg;
129 NULL;
130static int gui_mesg_w = 0;
131static int gui_mesg_x = 0;
132static int gui_mesg_y = 0;
133
134/* Calculations to speed up borders. */
135static double gui_tr = 0.;
136static double gui_br = 0.;
137static double gui_tl = 0.;
138static double gui_bl = 0.;
139
140/* Intrinsic graphical stuff. */
141static glTexture *gui_ico_hail = NULL;
144
145/* Lua Stuff. */
146static int gui_lua_create = LUA_NOREF;
147static int gui_lua_render = LUA_NOREF;
148static int gui_lua_render_cooldown = LUA_NOREF;
149static int gui_lua_cooldown_end = LUA_NOREF;
150static int gui_lua_mouse_move = LUA_NOREF;
151static int gui_lua_mouse_click = LUA_NOREF;
152static int gui_lua_update_cargo = LUA_NOREF;
153static int gui_lua_update_nav = LUA_NOREF;
154static int gui_lua_update_target = LUA_NOREF;
155static int gui_lua_update_ship = LUA_NOREF;
156static int gui_lua_update_system = LUA_NOREF;
157static int gui_lua_update_faction = LUA_NOREF;
158static int gui_lua_update_effects = LUA_NOREF;
159
160/*
161 * prototypes
162 */
163/*
164 * external
165 */
166extern void weapon_minimap( const double res, const double w, const double h,
167 const RadarShape shape,
168 double alpha );
169/*
170 * internal
171 */
172/* gui */
173static void gui_renderTargetReticles( const SimpleShader *shd, double x,
174 double y, double radius, double angle,
175 const glColour *c );
176static void gui_borderIntersection( double *cx, double *cy, double rx,
177 double ry, double hw, double hh );
178/* Render GUI. */
179static void gui_renderPilotTarget( void );
180static void gui_renderSpobTarget( void );
181static void gui_renderBorder( double dt );
182static void gui_renderMessages( double dt );
183static const glColour *gui_getSpobColour( int i );
184static void gui_renderRadarOutOfRange( RadarShape sh, int w, int h, int cx,
185 int cy, const glColour *col );
186static void gui_blink( double cx, double cy, double vr, const glColour *col,
187 double blinkInterval, double blinkVar );
188static const glColour *gui_getPilotColour( const Pilot *p );
189static void gui_calcBorders( void );
190/* Lua GUI. */
191static int gui_doFunc( int func_ref, const char *func_name );
192static int gui_prepFunc( int func_ref, const char *func_name );
193static int gui_runFunc( const char *func, int nargs, int nret );
194
198void gui_setDefaults( void )
199{
200 gui_setRadarResolution( player.radar_res );
202}
203
211void gui_messageInit( int width, int x, int y )
212{
213 gui_mesg_w = width;
214 gui_mesg_x = x;
215 gui_mesg_y = y;
216}
217
223void gui_messageScrollUp( int lines )
224{
225 int o;
226
227 /* Handle hacks. */
228 if ( mesg_viewpoint == -1 ) {
230 return;
231 }
232
233 /* Get offset. */
235 if ( o < 0 )
236 o += mesg_max;
237 o = mesg_max - 2 * conf.mesg_visible - o;
238
239 /* Calculate max line movement. */
240 if ( lines > o )
241 lines = o;
242
243 /* Move viewpoint. */
244 const int new_point = ( mesg_max + mesg_viewpoint - lines ) % mesg_max;
245 if ( mesg_stack && mesg_stack[new_point].str )
246 mesg_viewpoint = new_point;
247}
248
254void gui_messageScrollDown( int lines )
255{
256 int o;
257
258 /* Handle hacks. */
259 if ( mesg_viewpoint == mesg_pointer ) {
260 mesg_viewpoint = -1;
261 return;
262 } else if ( mesg_viewpoint == -1 )
263 return;
264
265 /* Get offset. */
267 if ( o < 0 )
268 o += mesg_max;
269
270 /* Calculate max line movement. */
271 if ( lines > o )
272 lines = o;
273
274 /* Move viewpoint. */
275 mesg_viewpoint = ( mesg_viewpoint + lines ) % mesg_max;
276}
277
283void player_messageToggle( int enable )
284{
285 gui_getMessage = enable;
286}
287
293void player_messageRaw( const char *str )
294{
296
297 /* Must be receiving messages. */
298 if ( !gui_getMessage )
299 return;
300
302 gui_mesg_w - ( ( str[0] == '\t' ) ? 45 : 15 ) );
303 while ( gl_printLineIteratorNext( &iter ) ) {
305
306 /* See if same message. */
307 if ( ( m->t > 0. ) && strcmp( mesg_stack[mesg_pointer].str, str ) == 0 ) {
308 free( m->dstr );
309 m->dup++;
310 SDL_asprintf( &m->dstr, p_( "player_message", "%s x%d" ), str,
311 m->dup );
312 if ( gl_printWidthRaw( &gl_smallFont, m->dstr ) <=
313 gui_mesg_w - ( ( str[0] == '\t' ) ? 45 : 15 ) ) {
314 m->t = mesg_timeout; /* Reset time out. */
315 return;
316 }
317 free( m->dstr );
318 m->dstr = NULL;
319 }
320
321 /* Move pointer. */
323 if ( mesg_viewpoint != -1 )
326
327 /* Add the new one */
328 free( m->str );
329 free( m->dstr );
330 m->dstr = NULL;
331 if ( iter.l_begin == 0 ) {
332 m->str = strndup( &str[iter.l_begin], iter.l_end - iter.l_begin );
334 } else {
335 m->str = malloc( iter.l_end - iter.l_begin + 2 );
336 snprintf( m->str, iter.l_end - iter.l_begin + 2, "\t%s",
337 &str[iter.l_begin] );
338 gl_printStoreMax( &m->restore, str, iter.l_begin );
339 }
340 m->t = mesg_timeout;
341 m->dup = 1;
342
343 iter.width =
344 gui_mesg_w - 45; /* Remaining lines are tabbed so it's shorter. */
345 }
346}
347
353void player_message( const char *fmt, ... )
354{
355 va_list ap;
356 char *buf;
357
358 /* Must be receiving messages. */
359 if ( !gui_getMessage )
360 return;
361
362 /* Add the new one */
363 va_start( ap, fmt );
364 /* Requires SDL2 >=2.0.18 */
365 SDL_vasprintf( &buf, fmt, ap );
366 va_end( ap );
367 player_messageRaw( buf );
368 free( buf );
369}
370
374static void gui_renderSpobTarget( void )
375{
376 double x, y, r;
377 const glColour *c;
378
379 /* no need to draw if pilot is dead */
380 if ( player_isFlag( PLAYER_DESTROYED ) || player_isFlag( PLAYER_CREATING ) ||
381 ( player.p == NULL ) || pilot_isFlag( player.p, PILOT_DEAD ) )
382 return;
383
384 /* Make sure target exists. */
385 if ( ( player.p->nav_spob < 0 ) && ( player.p->nav_hyperspace < 0 ) &&
386 ( player.p->nav_asteroid < 0 ) )
387 return;
388
389 /* Make sure targets are still in range. */
390#if 0
391 if (!pilot_inRangeSpob( player.p, player.p->nav_spob )) {
393 return;
394 }
395#endif
396
397 /* Draw spob and jump point target graphics. */
398 if ( player.p->nav_hyperspace >= 0 ) {
399 const JumpPoint *jp = &cur_system->jumps[player.p->nav_hyperspace];
400 if ( jp_isKnown( jp ) ) {
401 c = &cGreen;
402 x = jp->pos.x;
403 y = jp->pos.y;
404 r = jumppoint_gfx->sw * 0.5;
405 gui_renderTargetReticles( &shaders.targetspob, x, y, r, 0., c );
406 }
407 }
408 if ( player.p->nav_spob >= 0 ) {
409 const Spob *spob = cur_system->spobs[player.p->nav_spob];
410 c = spob_getColour( spob );
411 x = spob->pos.x;
412 y = spob->pos.y;
413 r = spob->radius;
414 gui_renderTargetReticles( &shaders.targetspob, x, y, r, 0., c );
415 }
416 if ( player.p->nav_asteroid >= 0 ) {
417 const AsteroidAnchor *field =
418 &cur_system->asteroids[player.p->nav_anchor];
419 const Asteroid *ast = &field->asteroids[player.p->nav_asteroid];
420 c = &cWhite;
421
422 x = ast->sol.pos.x;
423 y = ast->sol.pos.y;
424 r = ast->gfx->sw * 0.5;
425 gui_renderTargetReticles( &shaders.targetship, x, y, r, 0., c );
426 }
427}
428
439static void gui_renderTargetReticles( const SimpleShader *shd, double x,
440 double y, double radius, double angle,
441 const glColour *c )
442{
443 double rx, ry, r;
444 /* Must not be NULL. */
445 if ( gui_target_spob == NULL )
446 return;
447
448 gl_gameToScreenCoords( &rx, &ry, x, y );
449 r = (double)radius * 1.2 * cam_getZoom();
450
451 glUseProgram( shd->program );
452 glUniform1f( shd->dt, animation_dt );
453 glUniform1f( shd->paramf, radius );
454 gl_renderShader( rx, ry, r, r, angle, shd, c, 1 );
455}
456
460static void gui_renderPilotTarget( void )
461{
462 Pilot *p;
463 const glColour *c;
464
465 /* Player is most likely dead. */
466 if ( gui_target_pilot == NULL )
467 return;
468
469 /* Get the target. */
470 if ( player.p->target != PLAYER_ID )
471 p = pilot_get( player.p->target );
472 else
473 p = NULL;
474
475 /* Make sure pilot exists and is still alive. */
476 if ( ( p == NULL ) || pilot_isFlag( p, PILOT_DEAD ) ) {
477 pilot_setTarget( player.p, player.p->id );
479 return;
480 }
481
482 /* Make sure target is still valid and in range. */
483 if ( !pilot_validTarget( player.p, p ) ) {
484 pilot_setTarget( player.p, player.p->id );
486 return;
487 }
488
489 /* Draw the pilot target. */
490 if ( pilot_isDisabled( p ) )
491 c = &cInert;
492 else if ( pilot_isHostile( p ) )
493 c = &cHostile;
494 else if ( pilot_isFriendly( p ) )
495 c = &cFriend;
496 else
497 c = &cNeutral;
498
499 gui_renderTargetReticles( &shaders.targetship, p->solid.pos.x,
500 p->solid.pos.y, p->ship->size * 0.5, p->solid.dir,
501 c );
502}
503
516static void gui_borderIntersection( double *cx, double *cy, double rx,
517 double ry, double hw, double hh )
518{
519 double a;
520 double w, h;
521
522 /* Get angle. */
523 a = atan2( ry, rx );
524 if ( a < 0. )
525 a += 2. * M_PI;
526
527 /* Helpers. */
528 w = hw - 7.;
529 h = hh - 7.;
530
531 /* Handle by quadrant. */
532 if ( ( a > gui_tr ) && ( a < gui_tl ) ) { /* Top. */
533 *cx = h * ( rx / ry );
534 *cy = h;
535 } else if ( ( a > gui_tl ) && ( a < gui_bl ) ) { /* Left. */
536 *cx = -w;
537 *cy = -w * ( ry / rx );
538 } else if ( ( a > gui_bl ) && ( a < gui_br ) ) { /* Bottom. */
539 *cx = -h * ( rx / ry );
540 *cy = -h;
541 } else { /* Right. */
542 *cx = w;
543 *cy = w * ( ry / rx );
544 }
545
546 /* Translate. */
547 *cx += hw;
548 *cy += hh;
549}
550
556static void gui_renderBorder( double dt )
557{
558 (void)dt;
559 int hw, hh;
560 double rx, ry;
561 double cx, cy;
562 const glColour *col;
563 Pilot *const *pilot_stack;
564
565 NTracingZone( _ctx, 1 );
566
567 /* Get player position. */
568 hw = SCREEN_W / 2;
569 hh = SCREEN_H / 2;
570
571 /* Render borders to enhance contrast. */
572 gl_renderRect( 0., 0., 15., SCREEN_H, &cBlackHilight );
573 gl_renderRect( SCREEN_W - 15., 0., 15., SCREEN_H, &cBlackHilight );
574 gl_renderRect( 15., 0., SCREEN_W - 30., 15., &cBlackHilight );
575 gl_renderRect( 15., SCREEN_H - 15., SCREEN_W - 30., 15., &cBlackHilight );
576
577 /* Draw spobs. */
578 for ( int i = 0; i < array_size( cur_system->spobs ); i++ ) {
579 const Spob *pnt = cur_system->spobs[i];
580
581 /* Skip if unknown. */
582 if ( !spob_isKnown( pnt ) )
583 continue;
584
585 /* Check if out of range. */
586 if ( !gui_onScreenSpob( &rx, &ry, NULL, pnt ) ) {
587
588 /* Get border intersection. */
589 gui_borderIntersection( &cx, &cy, rx, ry, hw, hh );
590
591 col = gui_getSpobColour( i );
592 gl_renderCircle( cx, cy, 5, col, 0 );
593 }
594 }
595
596 /* Draw jump routes. */
597 for ( int i = 0; i < array_size( cur_system->jumps ); i++ ) {
598 const JumpPoint *jp = &cur_system->jumps[i];
599
600 /* Skip if unknown or exit-only. */
601 if ( !jp_isUsable( jp ) )
602 continue;
603
604 /* Check if out of range. */
605 if ( !gui_onScreenSpob( &rx, &ry, jp, NULL ) ) {
606
607 /* Get border intersection. */
608 gui_borderIntersection( &cx, &cy, rx, ry, hw, hh );
609
610 if ( i == player.p->nav_hyperspace )
611 col = &cGreen;
612 else
613 col = &cWhite;
614
615 gl_renderTriangleEmpty( cx, cy, -jp->angle, 10., 1., col );
616 }
617 }
618
619 /* Draw pilots. */
621 for ( int i = 1; i < array_size( pilot_stack ); i++ ) { /* skip the player */
622 const Pilot *plt = pilot_stack[i];
623
624 /* See if in sensor range. */
625 if ( !pilot_inRangePilot( player.p, plt, NULL ) )
626 continue;
627
628 /* Check if out of range. */
629 if ( !gui_onScreenPilot( &rx, &ry, plt ) ) {
630
631 /* Get border intersection. */
632 gui_borderIntersection( &cx, &cy, rx, ry, hw, hh );
633
634 col = gui_getPilotColour( plt );
635 gl_renderRectEmpty( cx - 5, cy - 5, 10, 10, col );
636 }
637 }
638
639 NTracingZoneEnd( _ctx );
640}
641
651int gui_onScreenPilot( double *rx, double *ry, const Pilot *pilot )
652{
653 double z;
654 int cw, ch, w, h;
655
656 z = cam_getZoom();
657
658 /* Get relative positions. */
659 *rx = ( pilot->solid.pos.x - player.p->solid.pos.x ) * z;
660 *ry = ( pilot->solid.pos.y - player.p->solid.pos.y ) * z;
661
662 /* Correct for offset. */
663 *rx -= gui_xoff;
664 *ry -= gui_yoff;
665
666 /* Get size. */
667 w = pilot->ship->size;
668 h = pilot->ship->size;
669
670 /* Compare dimensions. */
671 cw = SCREEN_W / 2 + w / 2;
672 ch = SCREEN_H / 2 + h / 2;
673
674 if ( ( ABS( *rx ) > cw ) || ( ABS( *ry ) > ch ) )
675 return 0;
676
677 return 1;
678}
679
690int gui_onScreenSpob( double *rx, double *ry, const JumpPoint *jp,
691 const Spob *pnt )
692{
693 double z;
694 int cw, ch;
695 glTexture *tex;
696
697 z = cam_getZoom();
698
699 if ( jp == NULL ) {
700 tex = pnt->gfx_space;
701 *rx = ( pnt->pos.x - player.p->solid.pos.x ) * z;
702 *ry = ( pnt->pos.y - player.p->solid.pos.y ) * z;
703 } else {
704 tex = jumppoint_gfx;
705 *rx = ( jp->pos.x - player.p->solid.pos.x ) * z;
706 *ry = ( jp->pos.y - player.p->solid.pos.y ) * z;
707 }
708
709 /* Correct for offset. */
710 *rx -= gui_xoff;
711 *ry -= gui_yoff;
712
713 /* Compare dimensions. */
714 cw = SCREEN_W / 2;
715 ch = SCREEN_H / 2;
716 if ( tex != NULL ) {
717 cw += tex->sw / 2;
718 ch += tex->sh / 2;
719 }
720
721 if ( ( ABS( *rx ) > cw ) || ( ABS( *ry ) > ch ) )
722 return 0;
723
724 return 1;
725}
726
732void gui_renderReticles( double dt )
733{
734 (void)dt;
735
736 /* Player must be alive. */
737 if ( player.p == NULL )
738 return;
739
740 /* Disable in cinematics. */
741 if ( player_isFlag( PLAYER_CINEMATICS ) )
742 return;
743
746}
747
748static int can_jump =
749 0;
755void gui_render( double dt )
756{
757 double fade, direction;
758
759 /* If player is dead just render the cinematic mode. */
760 if ( !menu_isOpen( MENU_MAIN ) &&
761 ( player_isFlag( PLAYER_DESTROYED ) ||
762 player_isFlag( PLAYER_CREATING ) ||
763 ( ( player.p != NULL ) && pilot_isFlag( player.p, PILOT_DEAD ) ) ) ) {
764 NTracingZone( _ctx, 1 );
765
766 gl_viewport( 0., 0., SCREEN_W, SCREEN_H );
769
770 NTracingZoneEnd( _ctx );
771 return;
772 }
773
774 /* Make sure player is valid. */
775 if ( player.p == NULL )
776 return;
777
778 /* Cinematics mode. */
779 if ( player_isFlag( PLAYER_CINEMATICS_GUI ) )
780 return;
781
782 NTracingZone( _ctx, 1 );
783
784 /*
785 * Countdown timers.
786 */
787 animation_dt += dt / dt_mod;
788 blink_pilot -= dt / dt_mod;
789 if ( blink_pilot < 0. )
791 blink_spob -= dt / dt_mod;
792 if ( blink_spob < 0. )
794
795 /* Render the border ships and targets. */
796 gui_renderBorder( dt );
797
798 /* Set viewport. */
799 gl_viewport( 0., 0., gl_screen.rw, gl_screen.rh );
800
801 /* Run Lua. */
802 if ( gui_env != LUA_NOREF ) {
803 if ( gui_prepFunc( gui_lua_render, "render" ) == 0 ) {
804 lua_pushnumber( naevL, dt );
805 lua_pushnumber( naevL, dt_mod );
806 gui_runFunc( "render", 2, 0 );
807 }
808 if ( pilot_isFlag( player.p, PILOT_COOLDOWN ) ) {
809 if ( gui_prepFunc( gui_lua_render_cooldown, "render_cooldown" ) ==
810 0 ) {
811 lua_pushnumber( naevL, player.p->ctimer / player.p->cdelay );
812 lua_pushnumber( naevL, player.p->ctimer );
813 gui_runFunc( "render_cooldown", 2, 0 );
814 }
815 }
816 }
817
818 /* Messages. */
819 gui_renderMessages( dt );
820
821 /* OSD. */
822 osd_render();
823
824 /* Noise when getting near a jump. */
825 if ( player.p->nav_hyperspace >= 0 ) { /* hyperspace target */
826 /* Determine if we have to play the "enter hyperspace range" sound. */
827 int i = space_canHyperspace( player.p );
828 if ( ( i != 0 ) && ( i != can_jump ) )
829 if ( !pilot_isFlag( player.p, PILOT_HYPERSPACE ) )
831 can_jump = i;
832 }
833
834 /* Determine if we need to fade in/out. */
835 fade = direction = 0.;
836 if ( pilot_isFlag( player.p, PILOT_HYPERSPACE ) &&
837 ( player.p->ptimer < HYPERSPACE_FADEOUT ) ) {
838 fade = ( HYPERSPACE_FADEOUT - player.p->ptimer ) / HYPERSPACE_FADEOUT;
839 direction = VANGLE( player.p->solid.vel );
840 } else if ( pilot_isFlag( player.p, PILOT_HYP_END ) &&
841 player.p->ptimer > 0. ) {
842 fade = player.p->ptimer / HYPERSPACE_FADEIN;
843 direction = VANGLE( player.p->solid.vel ) + M_PI;
844 }
845 /* Perform the fade. */
846 if ( fade > 0. ) {
847 mat4 projection = gl_view_matrix;
848
849 /* Set up the program. */
850 glUseProgram( shaders.jump.program );
851 glEnableVertexAttribArray( shaders.jump.vertex );
852 gl_vboActivateAttribOffset( gl_squareVBO, shaders.jump.vertex, 0, 2,
853 GL_FLOAT, 0 );
854
855 /* Set up the projection. */
856 mat4_scale( &projection, gl_screen.nw, gl_screen.nh, 1. );
857
858 /* Pass stuff over. */
859 gl_uniformMat4( shaders.jump.projection, &projection );
860 glUniform1f( shaders.jump.progress, fade );
861 glUniform1f( shaders.jump.direction, direction );
862 glUniform2f( shaders.jump.dimensions, gl_screen.nw, gl_screen.nh );
863 glUniform1f( shaders.jump.brightness, conf.jump_brightness );
864
865 /* Set the subroutine. */
866 if ( gl_has( OPENGL_SUBROUTINES ) ) {
867 if ( cur_system->nebu_density > 0. )
868 glUniformSubroutinesuiv( GL_FRAGMENT_SHADER, 1,
869 &shaders.jump.jump_func.jump_nebula );
870 else
871 glUniformSubroutinesuiv( GL_FRAGMENT_SHADER, 1,
872 &shaders.jump.jump_func.jump_wind );
873 }
874
875 /* Draw. */
876 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
877
878 /* Clear state. */
879 glDisableVertexAttribArray( shaders.jump.vertex );
880 glUseProgram( 0 );
881
882 /* Check errors. */
883 gl_checkErr();
884 }
885
886 /* Reset viewport. */
888
889 /* Render messages. */
890 omsg_render( dt );
891
892 NTracingZoneEnd( _ctx );
893}
894
898void gui_cooldownEnd( void )
899{
900 gui_doFunc( gui_lua_cooldown_end, "cooldown_end" );
901}
902
910int gui_radarInit( int circle, int w, int h )
911{
912 gui_radar.shape = circle ? RADAR_CIRCLE : RADAR_RECT;
913 gui_radar.w = w;
914 gui_radar.h = h;
915 gui_setRadarResolution( player.radar_res );
916 return 0;
917}
918
925void gui_radarRender( double x, double y )
926{
927 int f;
928 Radar *radar;
929 mat4 view_matrix_prev;
930 Pilot *const *pilot_stack;
931
932 if ( !conf.always_radar && ovr_isOpen() )
933 return;
934
935 NTracingZone( _ctx, 1 );
936
937 /* The global radar. */
938 radar = &gui_radar;
939 gui_radar.x = x;
940 gui_radar.y = y;
941
942 /* TODO: modifying gl_view_matrix like this is a bit of a hack */
943 /* TODO: use stencil test for RADAR_CIRCLE */
944 view_matrix_prev = gl_view_matrix;
945 if ( radar->shape == RADAR_RECT ) {
946 gl_clipRect( x, y, radar->w, radar->h );
947 mat4_translate_xy( &gl_view_matrix, x + radar->w / 2.,
948 y + radar->h / 2. );
949 } else if ( radar->shape == RADAR_CIRCLE )
950 mat4_translate_xy( &gl_view_matrix, x, y );
951
952 /*
953 * spobs
954 */
955 for ( int i = 0; i < array_size( cur_system->spobs ); i++ )
956 if ( i != player.p->nav_spob )
957 gui_renderSpob( i, radar->shape, radar->w, radar->h, radar->res, 1.,
958 0 );
959 if ( player.p->nav_spob > -1 )
960 gui_renderSpob( player.p->nav_spob, radar->shape, radar->w, radar->h,
961 radar->res, 1., 0 );
962
963 /*
964 * Jump points.
965 */
966 for ( int i = 0; i < array_size( cur_system->jumps ); i++ ) {
967 const JumpPoint *jp = &cur_system->jumps[i];
968 if ( i != player.p->nav_hyperspace && jp_isUsable( jp ) )
969 gui_renderJumpPoint( i, radar->shape, radar->w, radar->h, radar->res,
970 1., 0 );
971 }
972 if ( player.p->nav_hyperspace > -1 )
973 gui_renderJumpPoint( player.p->nav_hyperspace, radar->shape, radar->w,
974 radar->h, radar->res, 1., 0 );
975
976 /*
977 * weapons
978 */
979 weapon_minimap( radar->res, radar->w, radar->h, radar->shape, 1. );
980
981 /* render the pilot */
983 f = 0;
984 for ( int i = 1; i < array_size( pilot_stack ); i++ ) { /* skip the player */
985 if ( pilot_stack[i]->id == player.p->target )
986 f = i;
987 else
988 gui_renderPilot( pilot_stack[i], radar->shape, radar->w, radar->h,
989 radar->res, 0 );
990 }
991 /* render the targeted pilot */
992 if ( f != 0 )
993 gui_renderPilot( pilot_stack[f], radar->shape, radar->w, radar->h,
994 radar->res, 0 );
995
996 /* Render the asteroids */
997 for ( int i = 0; i < array_size( cur_system->asteroids ); i++ ) {
998 AsteroidAnchor *ast = &cur_system->asteroids[i];
999 double range = EW_ASTEROID_DIST *
1000 player.p->stats.ew_detect; /* TODO don't hardcode. */
1001 int ax, ay, r;
1002 ax = round( player.p->solid.pos.x );
1003 ay = round( player.p->solid.pos.y );
1004 r = ceil( range );
1005 asteroid_collideQueryIL( ast, &gui_qtquery, ax - r, ay - r, ax + r,
1006 ay + r );
1007 for ( int j = 0; j < il_size( &gui_qtquery ); j++ ) {
1008 const Asteroid *a = &ast->asteroids[il_get( &gui_qtquery, j, 0 )];
1009 gui_renderAsteroid( a, radar->w, radar->h, radar->res, 0 );
1010 }
1011 }
1012
1013 /* Render the player. */
1014 gui_renderPlayer( radar->res, 0 );
1015
1016 /* Undo the horrible hack. */
1017 gl_view_matrix = view_matrix_prev;
1018 if ( radar->shape == RADAR_RECT )
1019 gl_unclipRect();
1020
1021 NTracingZoneEnd( _ctx );
1022}
1023
1029void gui_radarGetRes( double *res )
1030{
1031 *res = gui_radar.res;
1032}
1033
1038{
1039 for ( int i = 0; i < mesg_max; i++ ) {
1040 free( mesg_stack[i].str );
1041 free( mesg_stack[i].dstr );
1042 }
1043 memset( mesg_stack, 0, sizeof( Mesg ) * mesg_max );
1044}
1045
1051static void gui_renderMessages( double dt )
1052{
1053 double x, y, h, hs, vx, vy, dy;
1054 int v, o;
1055 glColour c = { .r = 1., .g = 1., .b = 1. };
1056 const glColour msgc = { .r = 0., .g = 0., .b = 0., .a = 0.6 };
1057
1058 NTracingZone( _ctx, 1 );
1059
1060 /* Coordinate translation. */
1061 x = gui_mesg_x;
1062 y = gui_mesg_y;
1063
1064 /* Handle viewpoint hacks. */
1065 v = mesg_viewpoint;
1066 if ( v == -1 )
1067 v = mesg_pointer;
1068
1069 /* Render background. */
1070 h = 0;
1071
1072 /* Set up position. */
1073 vx = x;
1074 vy = y;
1075
1076 /* Must be run here. */
1077 hs = 0.;
1078 o = 0;
1079 if ( mesg_viewpoint != -1 ) {
1080 /* Data. */
1081 hs = h * (double)conf.mesg_visible / (double)mesg_max;
1083 if ( o < 0 )
1084 o += mesg_max;
1085 }
1086
1087 /* Render text. */
1088 for ( int i = 0; i < conf.mesg_visible; i++ ) {
1089 /* Reference translation. */
1090 int m = ( v - i ) % mesg_max;
1091 if ( m < 0 )
1092 m += mesg_max;
1093
1094 /* Timer handling. */
1095 if ( ( mesg_viewpoint != -1 ) || ( mesg_stack[m].t >= 0. ) ) {
1096 /* Decrement timer. */
1097 if ( mesg_viewpoint == -1 )
1098 mesg_stack[m].t -= dt / dt_mod;
1099
1100 /* Only handle non-NULL messages. */
1101 if ( mesg_stack[m].str != NULL ) {
1102 const char *str = ( mesg_stack[m].dstr != NULL )
1103 ? mesg_stack[m].dstr
1104 : mesg_stack[m].str;
1105
1106 glColour fadedWhite = cFontWhite;
1107 fadedWhite.a = ( mesg_viewpoint != -1 ) || ( mesg_stack[m].t > 2. )
1108 ? 1.
1109 : mesg_stack[m].t / 2.;
1110
1111 if ( str[0] == '\t' ) {
1112 gl_printRestore( &mesg_stack[m].restore );
1113 dy = gl_printHeightRaw( &gl_smallFont, gui_mesg_w, &str[1] ) + 6;
1114 gl_renderRect( x - 4., y - 1., gui_mesg_w - 13., dy, &msgc );
1115 gl_printMaxRaw( &gl_smallFont, gui_mesg_w - 45., x + 30, y + 3,
1116 &fadedWhite, -1., &str[1] );
1117 } else {
1118 dy = gl_printHeightRaw( &gl_smallFont, gui_mesg_w, str ) + 6;
1119 gl_renderRect( x - 4., y - 1., gui_mesg_w - 13., dy, &msgc );
1120 gl_printMaxRaw( &gl_smallFont, gui_mesg_w - 15., x, y + 3,
1121 &fadedWhite, -1., str );
1122 }
1123 h += dy;
1124 y += dy;
1125 }
1126 }
1127
1128 /* Increase position. */
1129 }
1130
1131 /* Render position. */
1132 if ( mesg_viewpoint != -1 ) {
1133 /* Border. */
1134 c.a = 0.2;
1135 gl_renderRect( vx + gui_mesg_w - 10., vy, 10, h, &c );
1136
1137 /* Inside. */
1138 c.a = 0.5;
1140 vx + gui_mesg_w - 10.,
1141 vy + hs / 2. +
1142 ( h - hs ) *
1143 ( (double)o / (double)( mesg_max - conf.mesg_visible ) ),
1144 10, hs, &c );
1145 }
1146
1147 NTracingZoneEnd( _ctx );
1148}
1149
1158static const glColour *gui_getPilotColour( const Pilot *p )
1159{
1160 const glColour *col;
1161
1162 if ( p->id == player.p->target )
1163 col = &cRadar_tPilot;
1164 else
1165 col = pilot_getColour( p );
1166
1167 return col;
1168}
1169
1180void gui_renderPilot( const Pilot *p, RadarShape shape, double w, double h,
1181 double res, int overlay )
1182{
1183 double x, y, scale, ssize;
1184 const glColour *col;
1185 int scanning;
1186
1187 /* Make sure is in range. */
1188 if ( !pilot_validTarget( player.p, p ) )
1189 return;
1190
1191 /* Get position. */
1192 if ( overlay ) {
1193 x = ( p->solid.pos.x / res );
1194 y = ( p->solid.pos.y / res );
1195 } else {
1196 x = ( ( p->solid.pos.x - player.p->solid.pos.x ) / res );
1197 y = ( ( p->solid.pos.y - player.p->solid.pos.y ) / res );
1198 }
1199 /* Get size. */
1200 ssize = sqrt( (double)ship_size( p->ship ) );
1201 scale = ( ssize + 1. ) / 2. * ( 1. + RADAR_RES_REF / res );
1202
1203 /* Check if pilot in range. */
1204 if ( ( ( shape == RADAR_RECT ) && ( ( ABS( x ) > ( w + scale ) / 2. ) ||
1205 ( ABS( y ) > ( h + scale ) / 2. ) ) ) ||
1206 ( ( shape == RADAR_CIRCLE ) &&
1207 ( ( pow2( x ) + pow2( y ) ) > pow2( w ) ) ) ) {
1208
1209 /* Draw little targeted symbol. */
1210 if ( p->id == player.p->target && !overlay )
1211 gui_renderRadarOutOfRange( shape, w, h, x, y, &cRadar_tPilot );
1212 return;
1213 }
1214
1215 /* Transform coordinates into the 0,0 -> SCREEN_W, SCREEN_H range. */
1216 if ( overlay ) {
1217 double ox, oy;
1218 ovr_center( &ox, &oy );
1219 x += ox;
1220 y += oy;
1221 }
1222
1223 if ( p->id == player.p->target )
1224 col = &cRadar_hilight;
1225 else
1226 col = gui_getPilotColour( p );
1227
1228 scale = MAX( scale + 2.0, 3.5 + ssize ); /* Compensate for outline. */
1229 scanning =
1230 ( pilot_isFlag( p, PILOT_SCANNING ) && ( p->target == PLAYER_ID ) );
1231
1232 if ( pilot_isFlag( p, PILOT_HILIGHT ) || scanning ) {
1233 glColour highlighted = cRadar_hilight;
1234 highlighted.a = 0.3;
1235 glUseProgram( shaders.hilight.program );
1236 glUniform1f( shaders.hilight.dt, animation_dt );
1237 gl_renderShader( x, y, scale * 2.0, scale * 2.0, 0., &shaders.hilight,
1238 &highlighted, 1 );
1239 }
1240
1241 glUseProgram( shaders.pilotmarker.program );
1242 gl_renderShader( x, y, scale, scale, p->solid.dir, &shaders.pilotmarker, col,
1243 1 );
1244
1245 /* Draw selection if targeted. */
1246 if ( p->id == player.p->target )
1247 gui_blink( x, y, MAX( scale * 2., 10.0 ), &cRadar_hilight,
1249
1250 /* Draw name. */
1251 if ( overlay && pilot_isFlag( p, PILOT_HILIGHT ) ) {
1252 /* TODO try to minimize overlap here. */
1253 gl_printMarkerRaw( &gl_smallFont, x + scale + 5., y - gl_smallFont.h / 2.,
1254 col, p->name );
1255 if ( scanning ) {
1256 glUseProgram( shaders.pilotscanning.program );
1257 gl_renderShader( x + scale + 3., y + scale + gl_smallFont.h / 2. + 3.,
1258 5., 5., 1.5 * animation_dt, &shaders.pilotscanning,
1259 col, 1 );
1260 }
1261 } else {
1262 /* Draw scanning icon. */
1263 if ( scanning ) {
1264 glUseProgram( shaders.pilotscanning.program );
1265 gl_renderShader( x + scale + 3., y + scale + 3., 5., 5.,
1266 1.5 * animation_dt, &shaders.pilotscanning, col, 1 );
1267 }
1268 }
1269}
1270
1280void gui_renderAsteroid( const Asteroid *a, double w, double h, double res,
1281 int overlay )
1282{
1283 int i, j, targeted;
1284 double x, y, r, sx, sy;
1285 double px, py;
1286 const glColour *col;
1287
1288 /* Skip invisible asteroids */
1289 if ( a->state != ASTEROID_FG )
1290 return;
1291
1292 /* Recover the asteroid and field IDs. */
1293 i = a->id;
1294 j = a->parent;
1295
1296 /* Make sure is in range. */
1297 if ( !pilot_inRangeAsteroid( player.p, i, j ) )
1298 return;
1299
1300 /* Get position. */
1301 if ( overlay ) {
1302 x = ( a->sol.pos.x / res );
1303 y = ( a->sol.pos.y / res );
1304 } else {
1305 x = ( ( a->sol.pos.x - player.p->solid.pos.x ) / res );
1306 y = ( ( a->sol.pos.y - player.p->solid.pos.y ) / res );
1307 }
1308
1309 /* Get size. */
1310 sx = 1.;
1311 sy = 1.;
1312
1313 /* Transform coordinates into the 0,0 -> SCREEN_W, SCREEN_H range. */
1314 if ( overlay ) {
1315 double ox, oy;
1316 ovr_center( &ox, &oy );
1317 x += ox;
1318 y += oy;
1319 w *= 2.;
1320 h *= 2.;
1321 }
1322
1323 /* Draw square. */
1324 px = MAX( x - sx, -w );
1325 py = MAX( y - sy, -h );
1326
1327 targeted =
1328 ( ( i == player.p->nav_asteroid ) && ( j == player.p->nav_anchor ) );
1329
1330 /* Colour depends if the asteroid is selected. */
1331 if ( targeted )
1332 col = &cWhite;
1333 else
1334 col = &cGrey70;
1335
1336 // gl_renderRect( px, py, MIN( 2*sx, w-px ), MIN( 2*sy, h-py ), col );
1337 r = ( sx + sy ) / 2.0 + 1.5;
1338 glUseProgram( shaders.asteroidmarker.program );
1339 gl_renderShader( px, py, r, r, 0., &shaders.asteroidmarker, col, 1 );
1340
1341 if ( targeted )
1342 gui_blink( px, py, MAX( 7., 2.0 * r ), col, RADAR_BLINK_PILOT,
1343 blink_pilot );
1344}
1345
1349void gui_renderPlayer( double res, int overlay )
1350{
1351 double x, y, r;
1352
1353 /* Based on gui_renderPilot but with larger fixed size (4x normal ship, but
1354 * the shader is actually quite smaller so it ends up being just a bit
1355 * larger than a capital ship.. */
1356 r = ( sqrt( 24. ) + 1. ) / 2. * ( 1. + RADAR_RES_REF / res );
1357 if ( overlay ) {
1358 double ox, oy;
1359 ovr_center( &ox, &oy );
1360 x = player.p->solid.pos.x / res + ox;
1361 y = player.p->solid.pos.y / res + oy;
1362 r = MAX( 17., r );
1363 } else {
1364 x = y = 0.;
1365 r = MAX( 11., r );
1366 }
1367
1368 glUseProgram( shaders.playermarker.program );
1369 gl_renderShader( x, y, r, r, player.p->solid.dir, &shaders.playermarker,
1370 &cRadar_player, 1 );
1371}
1372
1379static const glColour *gui_getSpobColour( int i )
1380{
1381 const glColour *col;
1382 const Spob *spob = cur_system->spobs[i];
1383
1384 if ( i == player.p->nav_spob )
1385 col = &cRadar_tSpob;
1386 else
1387 col = spob_getColour( spob );
1388
1389 return col;
1390}
1391
1395void gui_forceBlink( void )
1396{
1397 blink_pilot = 0.;
1398 blink_spob = 0.;
1399}
1400
1404static void gui_blink( double cx, double cy, double vr, const glColour *col,
1405 double blinkInterval, double blinkVar )
1406{
1407 if ( blinkVar > blinkInterval / 2. )
1408 return;
1409 glUseProgram( shaders.blinkmarker.program );
1410 gl_renderShader( cx, cy, vr, vr, 0., &shaders.blinkmarker, col, 1 );
1411}
1412
1416static void gui_renderRadarOutOfRange( RadarShape sh, int w, int h, int cx,
1417 int cy, const glColour *col )
1418{
1419 double a, x, y, x2, y2;
1420
1421 /* Draw a line like for pilots. */
1422 a = ANGLE( cx, cy );
1423 if ( sh == RADAR_CIRCLE ) {
1424 x = w * cos( a );
1425 y = w * sin( a );
1426 } else {
1427 int cxa, cya;
1428 cxa = ABS( cx );
1429 cya = ABS( cy );
1430 /* Determine position. */
1431 if ( cy >= cxa ) { /* Bottom */
1432 x = w / 2. * ( cx * 1. / cy );
1433 y = h / 2.;
1434 } else if ( cx >= cya ) { /* Left */
1435 x = w / 2.;
1436 y = h / 2. * ( cy * 1. / cx );
1437 } else if ( cya >= cxa ) { /* Top */
1438 x = -w / 2. * ( cx * 1. / cy );
1439 y = -h / 2.;
1440 } else { /* Right */
1441 x = -w / 2.;
1442 y = -h / 2. * ( cy * 1. / cx );
1443 }
1444 }
1445 x2 = x - .15 * w * cos( a );
1446 y2 = y - .15 * w * sin( a );
1447
1448 gl_renderLine( x, y, x2, y2, col );
1449}
1450
1456void gui_renderSpob( int ind, RadarShape shape, double w, double h, double res,
1457 double alpha, int overlay )
1458{
1459 GLfloat cx, cy, r, vr;
1460 glColour col;
1461 Spob *spob;
1462 const SimpleShader *shd;
1463
1464 /* Make sure is known. */
1465 if ( !spob_isKnown( cur_system->spobs[ind] ) )
1466 return;
1467
1468 /* Default values. */
1469 spob = cur_system->spobs[ind];
1470 r = spob->radius / res;
1471 vr = overlay ? spob->mo.radius : MAX( r, 7.5 );
1472
1473 if ( overlay ) {
1474 cx = spob->pos.x / res;
1475 cy = spob->pos.y / res;
1476 } else {
1477 cx = ( spob->pos.x - player.p->solid.pos.x ) / res;
1478 cy = ( spob->pos.y - player.p->solid.pos.y ) / res;
1479 }
1480
1481 /* Check if in range. */
1482 if ( shape == RADAR_CIRCLE ) {
1483 GLfloat x = ABS( cx ) - r;
1484 GLfloat y = ABS( cy ) - r;
1485 /* Out of range. */
1486 if ( x * x + y * y > pow2( w - 2 * r ) ) {
1487 if ( ( player.p->nav_spob == ind ) && !overlay )
1488 gui_renderRadarOutOfRange( RADAR_CIRCLE, w, w, cx, cy,
1489 &cRadar_tSpob );
1490 return;
1491 }
1492 } else {
1493 if ( shape == RADAR_RECT ) {
1494 /* Out of range. */
1495 if ( ( ABS( cx ) - r > w / 2. ) || ( ABS( cy ) - r > h / 2. ) ) {
1496 if ( ( player.p->nav_spob == ind ) && !overlay )
1497 gui_renderRadarOutOfRange( RADAR_RECT, w, h, cx, cy,
1498 &cRadar_tSpob );
1499 return;
1500 }
1501 }
1502 }
1503
1504 if ( overlay ) {
1505 double ox, oy;
1506 ovr_center( &ox, &oy );
1507 /* Transform coordinates. */
1508 cx += ox;
1509 cy += oy;
1510 }
1511
1512 /* Scale according to marker. */
1513 vr *= spob->marker_scale;
1514
1515 /* Is marked. */
1516 if ( spob_isKnown( spob ) && spob_isFlag( spob, SPOB_MARKED ) ) {
1517 glColour highlighted = cRadar_hilight;
1518 highlighted.a = 0.3;
1519 glUseProgram( shaders.hilight.program );
1520 glUniform1f( shaders.hilight.dt, animation_dt );
1521 gl_renderShader( cx, cy, vr * 3.0, vr * 3.0, 0., &shaders.hilight,
1522 &highlighted, 1 );
1523 }
1524
1525 /* Get the colour. */
1526 col = *gui_getSpobColour( ind );
1527 col.a *= alpha;
1528
1529 /* Do the blink. */
1530 if ( ind == player.p->nav_spob )
1531 gui_blink( cx, cy, vr * 2., &col, RADAR_BLINK_SPOB, blink_spob );
1532
1533 if ( spob->marker != NULL )
1534 shd = spob->marker;
1535 else if ( spob_hasService( spob, SPOB_SERVICE_LAND ) )
1536 shd = &shaders.spobmarker_earth;
1537 else
1538 shd = &shaders.spobmarker_empty;
1539
1540 glUseProgram( shd->program );
1541 gl_renderShader( cx, cy, vr, vr, 0., shd, &col, 1 );
1542
1543 if ( overlay ) {
1544 char buf[STRMAX_SHORT];
1545 snprintf( buf, sizeof( buf ), "%s%s", spob_getSymbol( spob ),
1546 spob_name( spob ) );
1548 cy + spob->mo.text_offy, &col, buf );
1549 }
1550}
1551
1563void gui_renderJumpPoint( int ind, RadarShape shape, double w, double h,
1564 double res, double alpha, int overlay )
1565{
1566 GLfloat cx, cy, x, y, r, vr;
1567 glColour col;
1568 StarSystem *s;
1569 JumpPoint *jp = &cur_system->jumps[ind];
1570
1571 /* Check if known */
1572 if ( !jp_isUsable( jp ) )
1573 return;
1574
1575 /* Default values. */
1576 r = jumppoint_gfx->sw / 2. / res;
1577 vr = overlay ? jp->mo.radius : MAX( r, 5. );
1578 if ( overlay ) {
1579 cx = jp->pos.x / res;
1580 cy = jp->pos.y / res;
1581 } else {
1582 cx = ( jp->pos.x - player.p->solid.pos.x ) / res;
1583 cy = ( jp->pos.y - player.p->solid.pos.y ) / res;
1584 }
1585
1586 /* Check if in range. */
1587 if ( shape == RADAR_RECT ) {
1588 /* Out of range. */
1589 if ( ( ABS( cx ) - r > w / 2. ) || ( ABS( cy ) - r > h / 2. ) ) {
1590 if ( ( player.p->nav_hyperspace == ind ) && !overlay )
1591 gui_renderRadarOutOfRange( RADAR_RECT, w, h, cx, cy,
1592 &cRadar_tSpob );
1593 return;
1594 }
1595 } else if ( shape == RADAR_CIRCLE ) {
1596 x = ABS( cx ) - r;
1597 y = ABS( cy ) - r;
1598 /* Out of range. */
1599 if ( x * x + y * y > pow2( w - 2 * r ) ) {
1600 if ( ( player.p->nav_hyperspace == ind ) && !overlay )
1601 gui_renderRadarOutOfRange( RADAR_CIRCLE, w, w, cx, cy,
1602 &cRadar_tSpob );
1603 return;
1604 }
1605 }
1606
1607 if ( overlay ) {
1608 double ox, oy;
1609 ovr_center( &ox, &oy );
1610 /* Transform coordinates. */
1611 cx += ox;
1612 cy += oy;
1613 }
1614
1615 /* See if far side is marked. */
1616 s = jp->target;
1617 if ( sys_isMarked( s ) ) {
1618 glColour highlighted = cRadar_hilight;
1619 highlighted.a = 0.3;
1620 glUseProgram( shaders.hilight.program );
1621 glUniform1f( shaders.hilight.dt, animation_dt );
1622 gl_renderShader( cx, cy, vr * 3.0, vr * 3.0, 0., &shaders.hilight,
1623 &highlighted, 1 );
1624 }
1625
1626 if ( ind == player.p->nav_hyperspace )
1627 col = cWhite;
1628 else if ( jp_isFlag( jp, JP_HIDDEN ) )
1629 col = cRed;
1630 else
1631 col = cGreen;
1632 col.a *= alpha;
1633
1634 glUseProgram( shaders.jumpmarker.program );
1635 gl_renderShader( cx, cy, vr * 1.5, vr * 1.5, M_PI - jp->angle,
1636 &shaders.jumpmarker, &col, 1 );
1637
1638 /* Blink ontop. */
1639 if ( ind == player.p->nav_hyperspace )
1640 gui_blink( cx, cy, vr * 3., &col, RADAR_BLINK_SPOB, blink_spob );
1641
1642 /* Render name. */
1643 if ( overlay ) {
1644 char buf[STRMAX_SHORT];
1645 snprintf( buf, sizeof( buf ), "%s%s", jump_getSymbol( jp ),
1646 sys_isKnown( jp->target ) ? _( jp->target->name )
1647 : _( "Unknown" ) );
1648 gl_printMarkerRaw( &gl_smallFont, cx + jp->mo.text_offx,
1649 cy + jp->mo.text_offy, &col, buf );
1650 }
1651}
1652
1656void gui_setViewport( double x, double y, double w, double h )
1657{
1658 gui_viewport_x = x;
1659 gui_viewport_y = y;
1660 gui_viewport_w = w;
1661 gui_viewport_h = h;
1662
1663 /* We now set the viewport. */
1667
1668 /* Run border calculations. */
1670}
1671
1676{
1677 gl_setDefViewport( 0., 0., gl_screen.nw, gl_screen.nh );
1679}
1680
1684static void gui_calcBorders( void )
1685{
1686 double w, h;
1687
1688 /* Precalculations. */
1689 w = SCREEN_W / 2.;
1690 h = SCREEN_H / 2.;
1691
1692 /*
1693 * Borders.
1694 */
1695 gui_tl = atan2( +h, -w );
1696 if ( gui_tl < 0. )
1697 gui_tl += 2 * M_PI;
1698 gui_tr = atan2( +h, +w );
1699 if ( gui_tr < 0. )
1700 gui_tr += 2 * M_PI;
1701 gui_bl = atan2( -h, -w );
1702 if ( gui_bl < 0. )
1703 gui_bl += 2 * M_PI;
1704 gui_br = atan2( -h, +w );
1705 if ( gui_br < 0. )
1706 gui_br += 2 * M_PI;
1707}
1708
1714int gui_init( void )
1715{
1716 /* radar */
1717 gui_setRadarResolution( player.radar_res );
1718
1719 /* Messages */
1720 gui_mesg_x = 20;
1721 gui_mesg_y = 30;
1722 gui_mesg_w = SCREEN_W - 400;
1723 if ( mesg_stack == NULL )
1724 mesg_stack = calloc( mesg_max, sizeof( Mesg ) );
1725
1726 /* VBO. */
1727 if ( gui_radar_select_vbo == NULL ) {
1728 GLfloat vertex[16];
1729 vertex[0] = -1.5;
1730 vertex[1] = 1.5;
1731 vertex[2] = -3.3;
1732 vertex[3] = 3.3;
1733 vertex[4] = 1.5;
1734 vertex[5] = 1.5;
1735 vertex[6] = 3.3;
1736 vertex[7] = 3.3;
1737 vertex[8] = 1.5;
1738 vertex[9] = -1.5;
1739 vertex[10] = 3.3;
1740 vertex[11] = -3.3;
1741 vertex[12] = -1.5;
1742 vertex[13] = -1.5;
1743 vertex[14] = -3.3;
1744 vertex[15] = -3.3;
1745 gui_radar_select_vbo =
1746 gl_vboCreateStatic( sizeof( GLfloat ) * 16, vertex );
1747 }
1748
1749 /* OSD */
1750 osd_setup( 30., SCREEN_H - 90., 150., 300. );
1751
1752 /* Set viewport. */
1753 gui_setViewport( 0., 0., gl_screen.w, gl_screen.h );
1754
1755 /* Icons. */
1756 gui_ico_hail = gl_newSprite( GUI_GFX_PATH "hail.webp", 5, 2, 0 );
1757
1758 /* Quadtrees. */
1759 il_create( &gui_qtquery, 1 );
1760
1761 return 0;
1762}
1763
1771static int gui_doFunc( int func_ref, const char *func_name )
1772{
1773 int ret;
1774 if ( gui_env == LUA_NOREF )
1775 return -1;
1776
1777 ret = gui_prepFunc( func_ref, func_name );
1778 if ( ret )
1779 return ret;
1780 return gui_runFunc( func_name, 0, 0 );
1781}
1782
1790static int gui_prepFunc( int func_ref, const char *func_name )
1791{
1792 (void)func_name;
1793#if DEBUGGING
1794 if ( gui_env == LUA_NOREF ) {
1795 WARN( _( "GUI '%s': Trying to run GUI func '%s' but no GUI is loaded!" ),
1796 gui_name, func_name );
1797 return -1;
1798 }
1799#endif /* DEBUGGING */
1800
1801 /* Must have a player. */
1802 if ( player_isFlag( PLAYER_DESTROYED ) || player_isFlag( PLAYER_CREATING ) ||
1803 ( player.p == NULL ) || pilot_isFlag( player.p, PILOT_DEAD ) ) {
1804 return -1;
1805 }
1806
1807 /* Set up function. */
1808 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_ref );
1809#if DEBUGGING
1810 if ( lua_isnil( naevL, -1 ) ) {
1811 WARN( _( "GUI '%s': no function '%s' defined!" ), gui_name, func_name );
1812 lua_pop( naevL, 1 );
1813 return -1;
1814 }
1815#endif /* DEBUGGING */
1816 return 0;
1817}
1818
1826static int gui_runFunc( const char *func, int nargs, int nret )
1827{
1828 /* Run the function. */
1829 int ret = nlua_pcall( gui_env, nargs, nret );
1830 if ( ret != 0 ) { /* error has occurred */
1831 const char *err =
1832 ( lua_isstring( naevL, -1 ) ) ? lua_tostring( naevL, -1 ) : NULL;
1833 WARN( _( "GUI '%s' Lua -> '%s': %s" ), gui_name, func,
1834 ( err ) ? err : _( "unknown error" ) );
1835 lua_pop( naevL, 1 );
1836 return ret;
1837 }
1838
1839 return ret;
1840}
1841
1845void gui_reload( void )
1846{
1847 if ( gui_env == LUA_NOREF )
1848 return;
1849
1850 gui_load( gui_pick() );
1851}
1852
1856void gui_setCargo( void )
1857{
1858 gui_doFunc( gui_lua_update_cargo, "update_cargo" );
1859}
1860
1864void gui_setNav( void )
1865{
1866 gui_doFunc( gui_lua_update_nav, "update_nav" );
1867}
1868
1872void gui_setTarget( void )
1873{
1874 gui_doFunc( gui_lua_update_target, "update_target" );
1875}
1876
1880void gui_setShip( void )
1881{
1882 gui_doFunc( gui_lua_update_ship, "update_ship" );
1883}
1884
1888void gui_setSystem( void )
1889{
1890 gui_doFunc( gui_lua_update_system, "update_system" );
1891}
1892
1897{
1898 if ( player.p != NULL && player.p->nav_spob != -1 )
1899 gui_doFunc( gui_lua_update_faction, "update_faction" );
1900}
1901
1902void gui_updateEffects( void )
1903{
1904 if ( player.p != NULL )
1905 gui_doFunc( gui_lua_update_effects, "update_effects" );
1906}
1907
1913void gui_setGeneric( const Pilot *pilot )
1914{
1915 if ( gui_env == LUA_NOREF )
1916 return;
1917
1918 if ( player_isFlag( PLAYER_DESTROYED ) || player_isFlag( PLAYER_CREATING ) ||
1919 ( player.p == NULL ) || pilot_isFlag( player.p, PILOT_DEAD ) )
1920 return;
1921
1922 if ( ( player.p->target != PLAYER_ID ) && ( pilot->id == player.p->target ) )
1923 gui_setTarget();
1924 else if ( pilot_isPlayer( pilot ) ) {
1925 gui_setCargo();
1926 gui_setShip();
1927 }
1928}
1929
1933const char *gui_pick( void )
1934{
1935 const char *gui;
1936 /* Don't do set a gui if player is dead. This can be triggered through
1937 * naev_resize and can cause an issue if player is dead. */
1938 if ( ( player.p == NULL ) || pilot_isFlag( player.p, PILOT_DEAD ) )
1939 gui = NULL;
1940 else if ( player.gui != NULL )
1941 gui = player.gui;
1942 else
1943 gui = start_gui();
1944 return gui;
1945}
1946
1952int gui_exists( const char *name )
1953{
1954 char path[PATH_MAX];
1955 snprintf( path, sizeof( path ), GUI_PATH "%s.lua", name );
1956 return PHYSFS_exists( path );
1957}
1958
1965int gui_load( const char *name )
1966{
1967 char *buf, path[PATH_MAX];
1968 size_t bufsize;
1969
1970 /* Set defaults. */
1971 gui_cleanup();
1972 if ( name == NULL )
1973 return 0;
1974 gui_name = strdup( name );
1975
1976 /* Open file. */
1977 snprintf( path, sizeof( path ), GUI_PATH "%s.lua", name );
1978 buf = ndata_read( path, &bufsize );
1979 if ( buf == NULL ) {
1980 WARN( _( "Unable to find GUI '%s'." ), path );
1981 return -1;
1982 }
1983
1984 /* Clean up. */
1985 nlua_freeEnv( gui_env );
1986 gui_env = LUA_NOREF;
1987
1988 /* Create Lua state. */
1989 gui_env = nlua_newEnv( name );
1994
1995 /* Run script. */
1996 if ( nlua_dobufenv( gui_env, buf, bufsize, path ) != 0 ) {
1997 WARN( _( "Failed to load GUI Lua: %s\n"
1998 "%s\n"
1999 "Most likely Lua file has improper syntax, please check" ),
2000 path, lua_tostring( naevL, -1 ) );
2001 nlua_freeEnv( gui_env );
2002 gui_env = LUA_NOREF;
2003 free( buf );
2004 return -1;
2005 }
2006 free( buf );
2007
2008 /* Load references. */
2009#define LUA_FUNC( funcname ) \
2010 gui_lua_##funcname = nlua_refenvtype( gui_env, #funcname, LUA_TFUNCTION );
2011 LUA_FUNC( create );
2012 LUA_FUNC( render );
2013 LUA_FUNC( render_cooldown );
2014 LUA_FUNC( cooldown_end );
2015 LUA_FUNC( mouse_move );
2016 LUA_FUNC( mouse_click );
2017 LUA_FUNC( update_cargo );
2018 LUA_FUNC( update_nav );
2019 LUA_FUNC( update_target );
2020 LUA_FUNC( update_ship );
2021 LUA_FUNC( update_system );
2022 LUA_FUNC( update_faction );
2023 LUA_FUNC( update_effects );
2024#undef LUA_FUNC
2025
2026 /* Run create function. */
2027 if ( gui_doFunc( gui_lua_create, "create" ) ) {
2028 nlua_freeEnv( gui_env );
2029 gui_env = LUA_NOREF;
2030 }
2031
2032 /* Recreate land window if landed. */
2033 if ( landed && land_spob ) {
2034 land_genWindows( 0 );
2036 }
2037
2038 /* Add the GUI to the player. */
2039 player_guiAdd( name );
2040
2041 return 0;
2042}
2043
2047void gui_cleanup( void )
2048{
2049 /* Clear messages. */
2051
2052 /* Disable mouse voodoo. */
2055
2056 /* Set the viewport. */
2058
2059 /* Set overlay bounds. */
2060 ovr_boundsSet( 0, 0, 0, 0 );
2061
2062 /* Reset FPS. */
2063 fps_setPos( 15., (double)( gl_screen.h - 15 - gl_defFontMono.h ) );
2064
2065 /* Destroy offset. */
2066 gui_xoff = 0.;
2067 gui_yoff = 0.;
2068
2069 /* Destroy lua. */
2070 nlua_freeEnv( gui_env );
2071 gui_env = LUA_NOREF;
2072
2073 /* OMSG */
2074 omsg_position( SCREEN_W / 2., SCREEN_H * 2. / 3., SCREEN_W * 2. / 3. );
2075
2076 /* Delete the name. */
2077 free( gui_name );
2078 gui_name = NULL;
2079
2080 /* Clear timers. */
2081 animation_dt = 0.;
2082
2083 /* Lua stuff. */
2084#define LUA_CLEANUP( varname ) \
2085 if ( varname != LUA_NOREF ) \
2086 luaL_unref( naevL, LUA_REGISTRYINDEX, varname ); \
2087 varname = LUA_NOREF
2088 LUA_CLEANUP( gui_lua_create );
2089 LUA_CLEANUP( gui_lua_render );
2090 LUA_CLEANUP( gui_lua_render_cooldown );
2091 LUA_CLEANUP( gui_lua_cooldown_end );
2092 LUA_CLEANUP( gui_lua_mouse_move );
2093 LUA_CLEANUP( gui_lua_mouse_click );
2094 LUA_CLEANUP( gui_lua_update_cargo );
2095 LUA_CLEANUP( gui_lua_update_nav );
2096 LUA_CLEANUP( gui_lua_update_target );
2097 LUA_CLEANUP( gui_lua_update_ship );
2098 LUA_CLEANUP( gui_lua_update_system );
2099 LUA_CLEANUP( gui_lua_update_faction );
2100 LUA_CLEANUP( gui_lua_update_effects );
2101#undef LUA_CLEANUP
2102}
2103
2107void gui_free( void )
2108{
2109 gui_cleanup();
2110
2111 free( mesg_stack );
2112 mesg_stack = NULL;
2113
2114 gl_vboDestroy( gui_radar_select_vbo );
2115 gui_radar_select_vbo = NULL;
2116
2117 osd_exit();
2118
2120 gui_ico_hail = NULL;
2122 gui_target_spob = NULL;
2124 gui_target_pilot = NULL;
2125
2126 il_destroy( &gui_qtquery );
2127
2128 omsg_cleanup();
2129}
2130
2136void gui_setRadarResolution( double res )
2137{
2138 gui_radar.res = CLAMP( RADAR_RES_MIN, RADAR_RES_MAX, res );
2139}
2140
2146void gui_setRadarRel( int mod )
2147{
2148 gui_radar.res += mod * RADAR_RES_INTERVAL;
2149 gui_setRadarResolution( gui_radar.res );
2150 player_message( _( "#oRadar set to %.0fx.#0" ), round( gui_radar.res ) );
2151}
2152
2159void gui_getOffset( double *x, double *y )
2160{
2161 *x = gui_xoff;
2162 *y = gui_yoff;
2163}
2164
2169{
2170 return gui_ico_hail;
2171}
2172
2177{
2180}
2181
2186{
2189}
2190
2194static void gui_eventToScreenPos( int *sx, int *sy, int ex, int ey )
2195{
2196 gl_windowToScreenPos( sx, sy, ex, ey );
2197}
2198
2205int gui_radarClickEvent( SDL_Event *event )
2206{
2207 int mxr, myr, in_bounds;
2208 double x, y, cx, cy;
2209
2210 gui_eventToScreenPos( &mxr, &myr, event->button.x, event->button.y );
2211 if ( gui_radar.shape == RADAR_RECT ) {
2212 cx = gui_radar.x + gui_radar.w / 2.;
2213 cy = gui_radar.y + gui_radar.h / 2.;
2214 in_bounds = ( 2 * ABS( mxr - cx ) <= gui_radar.w &&
2215 2 * ABS( myr - cy ) <= gui_radar.h );
2216 } else {
2217 cx = gui_radar.x;
2218 cy = gui_radar.y;
2219 in_bounds =
2220 ( pow2( mxr - cx ) + pow2( myr - cy ) <= pow2( gui_radar.w ) );
2221 }
2222 if ( !in_bounds )
2223 return 0;
2224 x = ( mxr - cx ) * gui_radar.res + player.p->solid.pos.x;
2225 y = ( myr - cy ) * gui_radar.res + player.p->solid.pos.y;
2226 return input_clickPos( event, x, y, 1., 10. * gui_radar.res,
2227 15. * gui_radar.res );
2228}
2229
2236int gui_borderClickEvent( SDL_Event *event )
2237{
2238 unsigned int pid;
2239 double ang, angp, mouseang;
2240 int mx, my;
2241 int pntid, jpid, astid, fieid;
2242 double x, y;
2243 int autonav = ( event->button.button == SDL_BUTTON_RIGHT ) ? 1 : 0;
2244 double px = player.p->solid.pos.x;
2245 double py = player.p->solid.pos.y;
2246 gui_eventToScreenPos( &mx, &my, event->button.x, event->button.y );
2247 mx -= gui_viewport_x;
2248 my -= gui_viewport_y;
2249
2250 /* No intersection with border. */
2251 if ( !( ( mx <= 15 || my <= 15 ) ||
2252 ( my >= gl_screen.h - 15 || mx >= gl_screen.w - 15 ) ) )
2253 return 0;
2254
2255 /* Border targeting is handled as a special case, as it uses angles,
2256 * not coordinates. */
2257 x = ( mx - ( gl_screen.w / 2. ) ) + px;
2258 y = ( my - ( gl_screen.h / 2. ) ) + py;
2259 mouseang = atan2( py - y, px - x );
2260 angp = pilot_getNearestAng( player.p, &pid, mouseang, 1 );
2261 ang = system_getClosestAng( cur_system, &pntid, &jpid, &astid, &fieid, x, y,
2262 mouseang );
2263
2264 if ( ( ABS( angle_diff( mouseang, angp ) ) > M_PI / 64 ) ||
2265 ABS( angle_diff( mouseang, ang ) ) <
2266 ABS( angle_diff( mouseang, angp ) ) )
2267 pid = PLAYER_ID; /* Pilot angle is too great, or spob/jump is closer. */
2268 if ( ABS( angle_diff( mouseang, ang ) ) > M_PI / 64 )
2269 jpid = pntid = astid = fieid =
2270 -1; /* Spob angle difference is too great. */
2271
2272 if ( pid != PLAYER_ID ) {
2273 if ( input_clickedPilot( pid, autonav ) )
2274 return 1;
2275 } else if ( pntid >= 0 ) { /* Spob is closest. */
2276 if ( input_clickedSpob( pntid, autonav, 1 ) )
2277 return 1;
2278 } else if ( jpid >= 0 ) { /* Jump point is closest. */
2279 if ( input_clickedJump( jpid, autonav ) )
2280 return 1;
2281 } else if ( astid >= 0 ) { /* Asteroid is closest. */
2282 if ( input_clickedAsteroid( fieid, astid ) )
2283 return 1;
2284 } else if ( pntid >= 0 ) { /* Spob is closest. */
2285 if ( input_clickedSpob( pntid, autonav, 0 ) )
2286 return 1;
2287 }
2288
2289 return 0;
2290}
2291
2295int gui_handleEvent( SDL_Event *evt )
2296{
2297 int ret;
2298 int x, y;
2299
2300 if ( player.p == NULL )
2301 return 0;
2302 if ( ( evt->type == SDL_MOUSEBUTTONDOWN ) &&
2303 ( pilot_isFlag( player.p, PILOT_HYP_PREP ) ||
2304 pilot_isFlag( player.p, PILOT_HYP_BEGIN ) ||
2305 pilot_isFlag( player.p, PILOT_HYPERSPACE ) ) )
2306 return 0;
2307
2308 ret = 0;
2309 switch ( evt->type ) {
2310 /* Mouse motion. */
2311 case SDL_MOUSEMOTION:
2312 if ( !gui_L_mmove )
2313 break;
2314 if ( gui_prepFunc( gui_lua_mouse_move, "mouse_move" ) == 0 ) {
2315 gui_eventToScreenPos( &x, &y, evt->motion.x, evt->motion.y );
2316 lua_pushnumber( naevL, x );
2317 lua_pushnumber( naevL, y );
2318 gui_runFunc( "mouse_move", 2, 0 );
2319 }
2320 break;
2321
2322 /* Mouse click. */
2323 case SDL_MOUSEBUTTONDOWN:
2324 case SDL_MOUSEBUTTONUP:
2325 if ( !gui_L_mclick )
2326 break;
2327 if ( gui_prepFunc( gui_lua_mouse_click, "mouse_click" ) == 0 ) {
2328 lua_pushnumber( naevL, evt->button.button + 1 );
2329 gui_eventToScreenPos( &x, &y, evt->button.x, evt->button.y );
2330 lua_pushnumber( naevL, x );
2331 lua_pushnumber( naevL, y );
2332 lua_pushboolean( naevL, ( evt->type == SDL_MOUSEBUTTONDOWN ) );
2333 gui_runFunc( "mouse_click", 4, 1 );
2334 ret = lua_toboolean( naevL, -1 );
2335 lua_pop( naevL, 1 );
2336 }
2337 break;
2338
2339 /* Not interested in the rest. */
2340 default:
2341 break;
2342 }
2343 return ret;
2344}
2345
2349void gui_mouseClickEnable( int enable )
2350{
2351 gui_L_mclick = enable;
2352}
2353
2357void gui_mouseMoveEnable( int enable )
2358{
2359 gui_L_mmove = enable;
2360}
Provides macros to work with dynamic arrays.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:179
double cam_getZoom(void)
Gets the camera zoom.
Definition camera.c:101
int gl_printHeightRaw(const glFont *ft_font, const int width, const char *text)
Gets the height of a non-formatted string.
Definition font.c:1050
void gl_printRestoreInit(glFontRestore *restore)
Initializes a restore structure.
Definition font.c:416
int gl_printLineIteratorNext(glPrintLineIterator *iter)
Updates iter with the next line's information.
Definition font.c:550
glFont gl_smallFont
Definition font.c:159
int gl_printWidthRaw(const glFont *ft_font, const char *text)
Gets the width that it would take to print some text.
Definition font.c:984
void gl_printRestore(const glFontRestore *restore)
Restores last colour from a restore structure.
Definition font.c:425
void gl_printLineIteratorInit(glPrintLineIterator *iter, const glFont *ft_font, const char *text, int width)
Initialize an iterator object for breaking text into lines.
Definition font.c:528
int gl_printMaxRaw(const glFont *ft_font, const int max, double x, double y, const glColour *c, double outlineR, const char *text)
Behaves like gl_printRaw but stops displaying text after a certain distance.
Definition font.c:753
glFont gl_defFontMono
Definition font.c:160
void gl_printStoreMax(glFontRestore *restore, const char *text, int max)
Stores the colour information from a piece of text limited to max characters.
Definition font.c:440
void gl_printMarkerRaw(const glFont *ft_font, double x, double y, const glColour *c, const char *text)
Wrapper for gl_printRaw for map overlay markers.
Definition font.c:708
static void gui_borderIntersection(double *cx, double *cy, double rx, double ry, double hw, double hh)
Gets the intersection with the border.
Definition gui.c:516
#define RADAR_BLINK_PILOT
Definition gui.c:52
static const int mesg_max
Definition gui.c:111
static int gui_mesg_w
Definition gui.c:130
static void gui_renderSpobTarget(void)
Sets up rendering of spob and jump point targeting reticles.
Definition gui.c:374
void gui_renderSpob(int ind, RadarShape shape, double w, double h, double res, double alpha, int overlay)
Draws the spobs in the minimap.
Definition gui.c:1456
int gui_radarClickEvent(SDL_Event *event)
Handles a click at a position in the current system.
Definition gui.c:2205
void gui_clearMessages(void)
Clears the GUI messages.
Definition gui.c:1037
int gui_init(void)
Initializes the GUI system.
Definition gui.c:1714
static int gui_L_mmove
Definition gui.c:75
static double gui_yoff
Definition gui.c:108
static glTexture * gui_ico_hail
Definition gui.c:141
int gui_radarInit(int circle, int w, int h)
Initializes the radar.
Definition gui.c:910
void gui_setTarget(void)
Player just changed their pilot target.
Definition gui.c:1872
void gui_renderPlayer(double res, int overlay)
Renders the player cross on the radar or whatever.
Definition gui.c:1349
int gui_handleEvent(SDL_Event *evt)
Handles GUI events.
Definition gui.c:2295
static void gui_renderBorder(double dt)
Renders the ships/spobs in the border.
Definition gui.c:556
void gui_messageScrollDown(int lines)
Scrolls down the message box.
Definition gui.c:254
static int gui_prepFunc(int func_ref, const char *func_name)
Prepares to run a function.
Definition gui.c:1790
static Mesg * mesg_stack
Definition gui.c:128
glTexture * gui_hailIcon(void)
Gets the hail icon texture.
Definition gui.c:2168
void gui_setDefaults(void)
Definition gui.c:198
int gui_borderClickEvent(SDL_Event *event)
Handles clicks on the GUI border icons.
Definition gui.c:2236
unsigned int land_wid
Definition land.c:83
void gui_setSystem(void)
Player just changed their system.
Definition gui.c:1888
static int gui_mesg_x
Definition gui.c:131
static IntList gui_qtquery
Definition gui.c:66
const char * gui_pick(void)
Determines which GUI should be used.
Definition gui.c:1933
void gui_radarRender(double x, double y)
Renders the GUI radar.
Definition gui.c:925
void gui_setRadarRel(int mod)
Modifies the radar resolution.
Definition gui.c:2146
static void gui_eventToScreenPos(int *sx, int *sy, int ex, int ey)
Translates a mouse position from an SDL_Event to GUI coordinates.
Definition gui.c:2194
static void gui_renderRadarOutOfRange(RadarShape sh, int w, int h, int cx, int cy, const glColour *col)
Renders an out of range marker for the spob.
Definition gui.c:1416
void gui_renderAsteroid(const Asteroid *a, double w, double h, double res, int overlay)
Renders an asteroid in the GUI radar.
Definition gui.c:1280
#define RADAR_RES_INTERVAL
Definition gui.c:102
int gui_exists(const char *name)
Checks to see if a GUI exists.
Definition gui.c:1952
static int can_jump
Definition gui.c:748
static double gui_br
Definition gui.c:136
static double gui_tl
Definition gui.c:137
void gui_mouseMoveEnable(int enable)
Enables the mouse movement callback.
Definition gui.c:2357
void gui_messageScrollUp(int lines)
Scrolls up the message box.
Definition gui.c:223
static int mesg_viewpoint
Definition gui.c:114
void gui_mouseClickEnable(int enable)
Enables the mouse click callback.
Definition gui.c:2349
static const double mesg_timeout
Definition gui.c:115
static char * gui_name
Definition gui.c:65
void gui_updateFaction(void)
Player's relationship with a faction was modified.
Definition gui.c:1896
static void gui_renderMessages(double dt)
Renders the player's messages on screen.
Definition gui.c:1051
int gui_load(const char *name)
Attempts to load the actual GUI.
Definition gui.c:1965
void gui_getOffset(double *x, double *y)
Gets the GUI offset.
Definition gui.c:2159
void weapon_minimap(const double res, const double w, const double h, const RadarShape shape, double alpha)
Draws the minimap weapons (used in player.c).
Definition weapon.c:226
static const glColour * gui_getSpobColour(int i)
Gets the colour of a spob.
Definition gui.c:1379
static double gui_xoff
Definition gui.c:107
void gui_setShip(void)
Player just upgraded their ship or modified it.
Definition gui.c:1880
#define RADAR_RES_MAX
Definition gui.c:99
void gui_free(void)
Frees the gui stuff.
Definition gui.c:2107
void gui_messageInit(int width, int x, int y)
Initializes the message system.
Definition gui.c:211
void gui_clearViewport(void)
Resets the viewport.
Definition gui.c:1675
void gui_radarGetRes(double *res)
Outputs the radar's resolution.
Definition gui.c:1029
void gui_reload(void)
Reloads the GUI.
Definition gui.c:1845
static double gui_tr
Definition gui.c:135
void gui_forceBlink(void)
Force sets the spob and pilot radar blink.
Definition gui.c:1395
int gui_onScreenPilot(double *rx, double *ry, const Pilot *pilot)
Takes a pilot and returns whether it's on screen, plus its relative position.
Definition gui.c:651
static double blink_pilot
Definition gui.c:56
void gui_targetPilotGFX(const glTexture *gfx)
Sets the pilot target GFX.
Definition gui.c:2185
static int gui_doFunc(int func_ref, const char *func_name)
Runs a GUI Lua function.
Definition gui.c:1771
static void gui_renderPilotTarget(void)
Renders the players pilot target.
Definition gui.c:460
void gui_cooldownEnd(void)
Notifies GUI scripts that the player broke out of cooldown.
Definition gui.c:898
static int gui_mesg_y
Definition gui.c:132
static const glColour * gui_getPilotColour(const Pilot *p)
Gets a pilot's colour, with a special colour for targets.
Definition gui.c:1158
void gui_renderJumpPoint(int ind, RadarShape shape, double w, double h, double res, double alpha, int overlay)
Renders a jump point on the minimap.
Definition gui.c:1563
int gui_onScreenSpob(double *rx, double *ry, const JumpPoint *jp, const Spob *pnt)
Takes a spob or jump point and returns whether it's on screen, plus its relative position.
Definition gui.c:690
void gui_cleanup(void)
Cleans up the GUI.
Definition gui.c:2047
void gui_renderPilot(const Pilot *p, RadarShape shape, double w, double h, double res, int overlay)
Renders a pilot in the GUI radar.
Definition gui.c:1180
static void gui_calcBorders(void)
Calculates and sets the GUI borders.
Definition gui.c:1684
void gui_targetSpobGFX(const glTexture *gfx)
Sets the spob target GFX.
Definition gui.c:2176
static int mesg_pointer
Definition gui.c:112
static double gui_bl
Definition gui.c:138
static double gui_viewport_y
Definition gui.c:81
static int gui_runFunc(const char *func, int nargs, int nret)
Runs a function.
Definition gui.c:1826
#define RADAR_RES_MIN
Definition gui.c:101
void player_messageRaw(const char *str)
Adds a mesg to the queue to be displayed on screen.
Definition gui.c:293
#define RADAR_BLINK_SPOB
Definition gui.c:53
static int gui_getMessage
Definition gui.c:63
static double blink_spob
Definition gui.c:57
static void gui_blink(double cx, double cy, double vr, const glColour *col, double blinkInterval, double blinkVar)
Renders the spob blink around a position on the minimap.
Definition gui.c:1404
void gui_setNav(void)
Player just changed their nav computer target.
Definition gui.c:1864
void gui_renderReticles(double dt)
Renders the gui targeting reticles.
Definition gui.c:732
void gui_render(double dt)
Renders the player's GUI.
Definition gui.c:755
#define RADAR_RES_REF
Definition gui.c:100
void gui_setGeneric(const Pilot *pilot)
Calls trigger functions depending on who the pilot is.
Definition gui.c:1913
static glTexture * gui_target_spob
Definition gui.c:142
static double gui_viewport_w
Definition gui.c:82
void gui_setViewport(double x, double y, double w, double h)
Sets the viewport.
Definition gui.c:1656
static void gui_renderTargetReticles(const SimpleShader *shd, double x, double y, double radius, double angle, const glColour *c)
Renders spob and jump point targeting reticles.
Definition gui.c:439
static nlua_env gui_env
Definition gui.c:73
void player_message(const char *fmt,...)
Adds a mesg to the queue to be displayed on screen.
Definition gui.c:353
static int gui_L_mclick
Definition gui.c:74
void gui_setRadarResolution(double res)
Sets the radar resolution.
Definition gui.c:2136
static double gui_viewport_x
Definition gui.c:80
static double animation_dt
Definition gui.c:58
void gui_setCargo(void)
Player just changed their cargo.
Definition gui.c:1856
static double gui_viewport_h
Definition gui.c:83
void player_messageToggle(int enable)
Toggles if player should receive messages.
Definition gui.c:283
static glTexture * gui_target_pilot
Definition gui.c:143
int input_clickedPilot(unsigned int pilot, int autonav)
Performs an appropriate action when a pilot is clicked.
Definition input.c:1739
int input_clickPos(SDL_Event *event, double x, double y, double zoom, double minpr, double minr)
Handles a click at a position in the current system.
Definition input.c:1538
int input_clickedAsteroid(int field, int asteroid)
Performs an appropriate action when an asteroid is clicked.
Definition input.c:1724
int input_clickedSpob(int spob, int autonav, int priority)
Performs an appropriate action when a spob is clicked.
Definition input.c:1671
int input_clickedJump(int jump, int autonav)
Performs an appropriate action when a jump point is clicked.
Definition input.c:1629
int landed
Definition land.c:78
void land_genWindows(int load)
Recreates the land windows.
Definition land.c:1232
Spob * land_spob
Definition land.c:87
void mat4_scale(mat4 *m, double x, double y, double z)
Scales a homogeneous transformation matrix.
Definition mat4.c:113
Handles the important game menus.
#define MENU_MAIN
Definition menu.h:9
#define menu_isOpen(f)
Definition menu.h:16
void fps_setPos(double x, double y)
Sets the position to display the FPS.
Definition naev.c:944
Header file with generic functions and naev-specifics.
#define CLAMP(a, b, x)
Definition naev.h:41
#define ABS(x)
Definition naev.h:32
#define pow2(x)
Definition naev.h:53
#define MAX(x, y)
Definition naev.h:37
#define PATH_MAX
Definition naev.h:57
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
Definition ndata.c:207
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
Definition nlua.c:914
lua_State * naevL
Definition nlua.c:54
int nlua_loadGFX(nlua_env env)
Loads the graphics library.
Definition nlua_gfx.c:112
int nlua_loadGUI(nlua_env env)
Loads the GUI library.
Definition nlua_gui.c:58
int nlua_loadTk(nlua_env env)
Loads the Toolkit Lua library.
Definition nlua_tk.c:98
char * strndup(const char *s, size_t n)
Return a pointer to a new string, which is a duplicate of the string s (or, if necessary,...
Definition nstring.c:69
void gl_setDefViewport(int x, int y, int w, int h)
Sets the default viewport.
Definition opengl.c:743
void gl_defViewport(void)
Resets viewport to default.
Definition opengl.c:754
void gl_viewport(int x, int y, int w, int h)
Sets the opengl viewport.
Definition opengl.c:715
void gl_windowToScreenPos(int *sx, int *sy, int wx, int wy)
Translates the window position to screen position.
Definition opengl.c:762
glInfo gl_screen
Definition opengl.c:47
void gl_renderShader(double x, double y, double w, double h, double r, const SimpleShader *shd, const glColour *c, int center)
Renders a simple shader.
void gl_renderRect(double x, double y, double w, double h, const glColour *c)
Renders a rectangle.
void gl_renderLine(double x1, double y1, double x2, double y2, const glColour *c)
Draws a line.
void gl_gameToScreenCoords(double *nx, double *ny, double bx, double by)
Converts in-game coordinates to screen coordinates.
void gl_renderTriangleEmpty(double x, double y, double a, double s, double length, const glColour *c)
Renders a triangle at a given position.
void gl_unclipRect(void)
Clears the 2d clipping planes.
void gl_renderRectEmpty(double x, double y, double w, double h, const glColour *c)
Renders a rectangle.
void gl_clipRect(int x, int y, int w, int h)
Sets up 2d clipping planes around a rectangle.
void gl_renderCircle(double cx, double cy, double r, const glColour *c, int filled)
Draws a circle.
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
Definition opengl_tex.c:891
glTexture * gl_newSprite(const char *path, const int sx, const int sy, const unsigned int flags)
Loads the texture immediately, but also sets it as a sprite.
Definition opengl_tex.c:785
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition opengl_tex.c:835
void gl_vboDestroy(gl_vbo *vbo)
Destroys a VBO.
Definition opengl_vbo.c:244
void gl_vboActivateAttribOffset(gl_vbo *vbo, GLuint index, GLuint offset, GLint size, GLenum type, GLsizei stride)
Activates a VBO's offset.
Definition opengl_vbo.c:224
gl_vbo * gl_vboCreateStatic(GLsizei size, const void *data)
Creates a stream vbo.
Definition opengl_vbo.c:177
double dt_mod
Definition pause.c:20
int pilot_isHostile(const Pilot *p)
Checks to see if pilot is hostile to the player.
Definition pilot.c:699
int pilot_validTarget(const Pilot *p, const Pilot *target)
Checks to see if a pilot is a valid target for another pilot.
Definition pilot.c:235
int pilot_isFriendly(const Pilot *p)
Checks to see if pilot is friendly to the player.
Definition pilot.c:728
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition pilot.c:640
const glColour * pilot_getColour(const Pilot *p)
Gets a pilot's colour.
Definition pilot.c:1328
static Pilot ** pilot_stack
Definition pilot.c:51
Pilot *const * pilot_getAll(void)
Gets the pilot stack.
Definition pilot.c:93
double pilot_getNearestAng(const Pilot *p, unsigned int *tp, double ang, int disabled)
Get the pilot closest to an angle extending from another pilot.
Definition pilot.c:585
void pilot_setTarget(Pilot *p, unsigned int id)
Sets the target of the pilot.
Definition pilot.c:1352
int pilot_inRangePilot(const Pilot *p, const Pilot *target, double *dist2)
Check to see if a pilot is in sensor range of another.
Definition pilot_ew.c:256
int pilot_inRangeSpob(const Pilot *p, int target)
Check to see if a spob is in sensor range of the pilot.
Definition pilot_ew.c:293
int pilot_inRangeAsteroid(const Pilot *p, int ast, int fie)
Check to see if an asteroid is in sensor range of the pilot.
Definition pilot_ew.c:324
int snd_jump
Definition player.c:104
void player_targetSpobSet(int id)
Sets the player's target spob.
Definition player.c:1559
Player_t player
Definition player.c:77
void player_soundPlayGUI(int sound, int once)
Plays a GUI sound (unaffected by time accel).
Definition player.c:947
int player_guiAdd(const char *name)
Adds a gui to the player.
Definition player_gui.c:39
static const double c[]
Definition rng.c:256
int ship_size(const Ship *s)
Gets the size of the ship.
Definition ship.c:526
double system_getClosestAng(const StarSystem *sys, int *pnt, int *jp, int *ast, int *fie, double x, double y, double ang)
Gets the feature nearest to directly ahead of a position in the system.
Definition space.c:808
int space_canHyperspace(const Pilot *p)
Checks to make sure if pilot is far enough away to hyperspace.
Definition space.c:494
const glColour * spob_getColour(const Spob *p)
Gets the spob colour.
Definition space.c:2009
const char * jump_getSymbol(const JumpPoint *jp)
Gets the jump point symbol.
Definition space.c:1317
const char * spob_getSymbol(const Spob *p)
Gets the spob symbol.
Definition space.c:1986
StarSystem * cur_system
Definition space.c:110
const char * spob_name(const Spob *p)
Gets the translated name of a spob.
Definition space.c:1834
glTexture * jumppoint_gfx
Definition space.c:111
void spfx_cinematic(void)
Sets the cinematic mode.
Definition spfx.c:1093
const char * start_gui(void)
Gets the module's starting ship was acquired.
Definition start.c:218
Represents an asteroid field anchor.
Definition asteroid.h:111
Asteroid * asteroids
Definition asteroid.h:116
Represents a single asteroid.
Definition asteroid.h:88
const glTexture * gfx
Definition asteroid.h:94
Solid sol
Definition asteroid.h:98
float text_offx
Definition space.h:71
float radius
Definition space.h:70
float text_offy
Definition space.h:72
On screen player message.
Definition gui.c:121
int dup
Definition gui.c:122
glFontRestore restore
Definition gui.c:126
char * str
Definition gui.c:123
char * dstr
Definition gui.c:124
double t
Definition gui.c:125
The representation of an in-game pilot.
Definition pilot.h:263
unsigned int id
Definition pilot.h:264
const Ship * ship
Definition pilot.h:274
Solid solid
Definition pilot.h:275
Represents the player's radar.
Definition gui.c:90
double y
Definition gui.c:94
double res
Definition gui.c:96
double w
Definition gui.c:91
double h
Definition gui.c:92
RadarShape shape
Definition gui.c:95
double x
Definition gui.c:93
double size
Definition ship.h:149
vec2 pos
Definition physics.h:49
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:102
glTexture * gfx_space
Definition space.h:146
double radius
Definition space.h:110
double marker_scale
Definition space.h:113
const SimpleShader * marker
Definition space.h:112
vec2 pos
Definition space.h:109
MapOverlayPos mo
Definition space.h:157
Evil hack to allow restoring, yes it makes me cry myself to sleep.
Definition font.h:28
The state of a line iteration. This matches the process of rendering text into an on-screen box: An e...
Definition font.h:44
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:43
double sw
Definition opengl_tex.h:53
double sh
Definition opengl_tex.h:54
Definition mat4.h:12
double y
Definition vec2.h:47
double x
Definition vec2.h:46
void window_lower(unsigned int wid)
Lowers a window (causes all other windows to appear above it).
Definition toolkit.c:2577