From 0573336e27564cb4aac55c316fbb5c2d89dd9704 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Sun, 20 Jul 2014 20:48:13 +0100
Subject: [PATCH] [Change] Ripped out all the GUI code and gave it, its own
 file.

---
 src/gui.c      | 1241 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/gui.h      |   27 ++
 src/input.c    |    5 +-
 src/lephisto.c |    8 +-
 src/map.c      |    4 +-
 src/nebulae.c  |    2 +-
 src/opengl.c   |    8 +-
 src/player.c   | 1175 +--------------------------------------------
 src/player.h   |   17 +-
 src/space.c    |    7 +-
 src/weapon.c   |    1 +
 11 files changed, 1313 insertions(+), 1182 deletions(-)
 create mode 100644 src/gui.c
 create mode 100644 src/gui.h

diff --git a/src/gui.c b/src/gui.c
new file mode 100644
index 0000000..ae35f7b
--- /dev/null
+++ b/src/gui.c
@@ -0,0 +1,1241 @@
+/**
+ * @file gui.c
+ *
+ * @brief Contains the GUI stuff for the player.
+ */
+#include <stdlib.h>
+
+#include "player.h"
+#include "lxml.h"
+#include "lephisto.h"
+#include "pilot.h"
+#include "log.h"
+#include "opengl.h"
+#include "font.h"
+#include "ldata.h"
+#include "space.h"
+#include "rng.h"
+#include "land.h"
+#include "sound.h"
+#include "economy.h"
+#include "pause.h"
+#include "menu.h"
+#include "toolkit.h"
+#include "dialogue.h"
+#include "mission.h"
+#include "llua_misn.h"
+#include "ltime.h"
+#include "hook.h"
+#include "map.h"
+#include "lfile.h"
+#include "spfx.h"
+#include "unidiff.h"
+#include "comm.h"
+#include "intro.h"
+#include "perlin.h"
+#include "ai.h"
+#include "ai.h"
+#include "gui.h"
+
+#define XML_GUI_ID  "GUIs"  /**< XML section identifier for GUI document. */
+#define XML_GUI_TAG "gui"   /**< XML section identifier for gui tags. */
+
+#define GUI_DATA    "../dat/gui.xml"  /**< Global GUI configuration file. */
+#define GUI_GFX     "../gfx/gui/"     /**< Location of the GUI graphics. */
+
+#define TARGET_WIDTH  128   /**< Width of the target graphic. */
+#define TARGET_HEIGHT 96    /**< Height of the target graphic. */
+
+#define INTERFERENCE_LAYERS     16  /**< Number of interference layers. */
+#define INTERFERENCE_CHANGE_DT  0.1 /** Speed to change at. */
+
+/* For interference. */
+static int interference_layer = 0;  /**< Layer of the current interference. */
+double interference_alpha = 0.;     /**< Alpha of the current interference layer. */
+static double interference_t = 0.;  /**< Interference timer to control transitions. */
+
+/* Pilot stuff for GUI. */
+extern Pilot** pilot_stack;
+extern int pilot_nstack;
+
+/* Space stuff for GUI. */
+extern StarSystem* systems_stack;
+
+/* Map stuff for autonav. */
+extern int map_npath;
+
+/**
+ * @struct Radar
+ *
+ * @brief Represents the players radar.
+ */
+typedef struct Radar_ {
+  double x;           /**< X position. */
+  double y;           /**< Y position. */
+  double w;           /**< Width. */
+  double h;           /**< Height. */
+  RadarShape shape;   /**< Shape. */
+  double res;         /** Resolution. */
+  glTexture* interference[INTERFERENCE_LAYERS]; /**< Interference texture. */
+} Radar;
+/* Radar resolutions. */
+#define RADAR_RES_MAX       100.  /**< Maximum radar resolution. */
+#define RADAR_RES_MIN       10.   /**< Minimum radar resolution. */
+#define RADAR_RES_INTERVAL  10.   /**< Steps used to increase/decrease resolution. */
+#define RADAR_RES_DEFAULT   40.   /**< Default resolution. */
+
+/**
+ * @struct Rect
+ *
+ * @brief Represents a rectangle.
+ */
+typedef struct Rect_ {
+  double x;   /**< X position. */
+  double y;   /**< Y position. */
+  double w;   /**< Width. */
+  double h;   /**< Height. */
+} Rect;
+
+/**
+ * @struct GUI
+ *
+ * @brief Represents the ingame player graphical user interface.
+ */
+typedef struct GUI_ {
+  /* Graphics. */
+  glTexture* gfx_frame;         /**< Frame of the GUI. */
+  glTexture* gfx_targetPilot;   /**< Graphics used to target pilot. */
+  glTexture* gfx_targetPlanet;  /**< Graphics used to target planets. */
+
+  /*
+   * Rects.
+   */
+  /* Radar. */
+  Radar radar;            /**< The radar. */
+  /* Navigation. */
+  Rect nav;               /**< Navigation computer. */
+  /* Health. */
+  Rect shield;            /**< Shield bar. */
+  glTexture* gfx_shield;  /**< Shield bar texture if applicable. */
+  Rect armour;            /**< Armour bar. */
+  glTexture* gfx_armour;  /**< Armour bar texture if applicable. */
+  Rect energy;            /**< Energy bar. */
+  glTexture* gfx_energy;  /**< Energy bar texture if applicable. */
+  Rect fuel;              /**< Fuel bar. */
+  glTexture* gfx_fuel;    /**< Fuel bar texture if applicable. */
+  /* Weapon. */
+  Rect weapon;            /**< Weapon targetting system. */
+  /* Targetting. */
+  Rect target_health;     /**< Target health. */
+  Rect target_name;       /**< Name of the target. */
+  Rect target_faction;    /**< Faction of the target. */
+  /* Misc. */
+  Rect misc;              /**< Misc stuff: credits, cargo etc.. */
+  /* Messages. */
+  Rect msg;               /**<  Where messages go. */
+
+  /* Positions. */
+  Vec2 frame;            	/**< Global frame position. */
+  Vec2 target;           	/**< Global target position. */
+} GUI;
+
+static GUI gui = {
+  .gfx_frame        = NULL,
+  .gfx_targetPilot  = NULL,
+  .gfx_targetPlanet = NULL
+};
+
+/* Needed to render properly. */
+double gui_xoff = 0.; /**< X offset that GUI introduces. */
+double gui_yoff = 0.; /**< Y offset that GUI introduces. */
+
+/* Messages. */
+#define MSG_SIZE_MAX  120 /**< Maximum message length. */
+double msg_timeout  = 5.; /**< Time it takes for a message to timeout. */
+int msg_max         = 5;  /**< Maximum messages onscreen. */
+
+/**
+ * @struct Msg.
+ *
+ * @brief On screen player messages.
+ */
+typedef struct Msg_ {
+  char str[MSG_SIZE_MAX]; /**< The message. */
+  double t; /**< Timer related to messages. */
+} Msg;
+static Msg* msg_stack;  /**< Stack of messages, will be of msg_max size. */
+
+/* External. */
+extern void weapon_minmap(const double res, const double w, const double h,
+    const RadarShape shape, double alpha); /**< From weapon.c */
+extern void planets_minimap(const double res, const double w, const double h,
+    const RadarShape shape, double alpha); /**< From space.c */
+
+/* Gui. */
+static void gui_createInterference(void);
+static void rect_parseParam(const xmlNodePtr parent,
+    char* name, double* param);
+static void rect_parse(const xmlNodePtr parent,
+    double* x, double* y, double* w, double* h);
+static int gui_parse(const xmlNodePtr parent, const char* name);
+/* Render GUI. */
+static void gui_renderRadar(double dt);
+static void gui_renderMessages(double dt);
+static void gui_renderPilot(const Pilot* p);
+static void gui_renderHealth(const glColour* c,
+    const Rect* r, const glTexture* tex, const double w);
+static void gui_renderInterference(double dt);
+
+/**
+ * @brief Set the GUI to defaults.
+ */
+void gui_setDefaults(void) {
+  gui.radar.res = RADAR_RES_DEFAULT;
+  memset(msg_stack, 0, msg_max * sizeof(Msg));
+}
+
+/**
+ * @brief Add a msg to the queue to be displayed on screen.
+ *    @param fmt String with formatting like printf.
+ */
+void player_message(const char* fmt, ...) {
+  va_list ap;
+  int i;
+
+  if(fmt == NULL) return; /* Message not valid. */
+
+  /* Copy old messages back. */
+  for(i = 1; i < msg_max; i++) {
+    if(msg_stack[msg_max-i-1].str[0] != '\0') {
+      strcpy(msg_stack[msg_max-i].str, msg_stack[msg_max-i-1].str);
+      msg_stack[msg_max-i].t = msg_stack[msg_max-i-1].t;
+    }
+  }
+
+  /* Add the new one. */
+  va_start(ap, fmt);
+  vsnprintf(msg_stack[0].str, MSG_SIZE_MAX, fmt, ap);
+  va_end(ap);
+
+  msg_stack[0].t = msg_timeout;
+}
+
+/**
+ * @brief Render the background GUI stuff, namely planet target gfx.
+ *    @param dt Current delta tick.
+ */
+void gui_renderBG(double dt) {
+  (void) dt;
+  double x, y;
+  glColour* c;
+  Planet* planet;
+
+  /* NJo need to draw if pilot is dead. */
+  if(player_isFlag(PLAYER_DESTROYED) || player_isFlag(PLAYER_CREATING) ||
+      ((player != NULL) && pilot_isFlag(player, PILOT_DEAD)))
+    return;
+
+  if(planet_target >= 0) {
+    planet = cur_system->planets[planet_target];
+
+    c = faction_getColour(planet->faction);
+
+    x = planet->pos.x - planet->gfx_space->sw/2.;
+    y = planet->pos.y + planet->gfx_space->sh/2.;
+    gl_blitSprite(gui.gfx_targetPlanet, x, y, 0, 0, c); /* Top left. */
+
+    x += planet->gfx_space->sw;
+    gl_blitSprite(gui.gfx_targetPlanet, x, y, 1, 0, c); /* Top right. */
+
+    y -= planet->gfx_space->sh;
+    gl_blitSprite(gui.gfx_targetPlanet, x, y, 1, 1, c); /* Bottom right. */
+
+    x -= planet->gfx_space->sw;
+    gl_blitSprite(gui.gfx_targetPlanet, x, y, 0, 1, c); /* Bottom left. */
+  }
+}
+
+/**
+ * @brief Render the players pilot target.
+ *    @param dt Current delta tick.
+ */
+void gui_renderTarget(double dt) {
+  (void)dt;
+  Pilot* p;
+  glColour* c;
+  double x, y;
+
+  /* Get the target. */
+  if(player->target != PLAYER_ID)
+    p = pilot_get(player->target);
+  else p = NULL;
+
+  if((p == NULL) || pilot_isFlag(p, PILOT_DEAD))
+    player->target = PLAYER_ID; /* No more pilot_target. */
+  else { /* Still is a pilot_target. */
+    if(pilot_isDisabled(p))
+      c = &cInert;
+    else if(pilot_isFlag(p, PILOT_BRIBED))
+      c = &cNeutral;
+    else if(pilot_isFlag(p, PILOT_HOSTILE))
+      c = &cHostile;
+    else
+      c = faction_getColour(p->faction);
+
+    x = p->solid->pos.x - p->ship->gfx_space->sw * PILOT_SIZE_APROX/2.;
+    y = p->solid->pos.y + p->ship->gfx_space->sh * PILOT_SIZE_APROX/2.;
+    gl_blitSprite(gui.gfx_targetPilot, x, y, 0, 0, c); /* Top left. */
+
+    x += p->ship->gfx_space->sw * PILOT_SIZE_APROX;
+    gl_blitSprite(gui.gfx_targetPilot, x, y, 1, 0, c); /* Top right. */
+
+    y -= p->ship->gfx_space->sh * PILOT_SIZE_APROX;
+    gl_blitSprite(gui.gfx_targetPilot, x, y, 1, 1, c); /* Bottom right. */
+
+    y -= p->ship->gfx_space->sw * PILOT_SIZE_APROX;
+    gl_blitSprite(gui.gfx_targetPilot, x, y, 0, 1, c); /* Bottom left. */
+  }
+}
+
+static int can_jump = 0; /**< Store whether or not the player is able to jump. */
+/**
+ * @brief Render the players GUI.
+ *    @param dt Current delta tick.
+ */
+void gui_render(double dt) {
+  int i, j;
+  double x;
+  char str[10];
+  Pilot* p;
+  glColour* c;
+  glFont* f;
+  StarSystem* sys;
+  int quantity, delay;
+
+  /* If player is dead, just render the cinematic mode. */
+  if(player_isFlag(PLAYER_DESTROYED) || player_isFlag(PLAYER_CREATING) ||
+      ((player != NULL) && pilot_isFlag(player, PILOT_DEAD))) {
+
+    spfx_cinematic();
+    return;
+  }
+
+  /* Make sure player is valid. */
+  if(player == NULL) return;
+
+  /* Lockon warning. */
+  if(player->lockons > 0)
+    gl_printMid(NULL, SCREEN_W - gui_xoff, 0., SCREEN_H-gl_defFont.h-25.,
+        &cRed, "LOCKON DETECTED");
+
+  /* Volatile environment. */
+  if(cur_system->nebu_volatility > 0.)
+    gl_printMid(NULL, SCREEN_W - gui_xoff, 0., SCREEN_H-gl_defFont.h*2.-35.,
+        &cRed, "VOLATILE ENVIRONMENT DETECTED");
+
+  /*
+   * GUI.
+   */
+  /* Frame. */
+  gl_blitStatic(gui.gfx_frame, gui.frame.x, gui.frame.y, NULL);
+
+  /* Radar. */
+  gui_renderRadar(dt);
+
+  /*
+   * NAV
+   */
+  if(planet_target >= 0) { /* Planet landing target. */
+    gl_printMid(NULL, (int)gui.nav.w,
+        gui.nav.x, gui.nav.y - 5,
+        &cConsole, "Land");
+
+    gl_printMid(&gl_smallFont, (int)gui.nav.w,
+        gui.nav.x, gui.nav.y - 10 - gl_smallFont.h,
+        NULL, "%s", cur_system->planets[planet_target]->name);
+  }
+  else if(hyperspace_target >= 0) { /* Hyperspace target. */
+    sys = &systems_stack[cur_system->jumps[hyperspace_target]];
+
+    /* Determine if we have to play the "enter hyperspace range" sound. */
+    i = space_canHyperspace(player);
+    if((i != 0) && (i != can_jump))
+      if(!pilot_isFlag(player, PILOT_HYPERSPACE))
+        player_playSound(snd_jump, 1);
+    can_jump = i;
+
+    /* Determine the colour of the NAV text. */
+    if(can_jump || pilot_isFlag(player, PILOT_HYPERSPACE) ||
+        pilot_isFlag(player, PILOT_HYP_PREP) ||
+        pilot_isFlag(player, PILOT_HYP_BEGIN))
+      c = &cConsole;
+    else c = NULL;
+
+    gl_printMid(NULL, (int)gui.nav.w,
+        gui.nav.x, gui.nav.y - 5,
+        c, "Hyperspace");
+
+    gl_printMid(&gl_smallFont, (int)gui.nav.w,
+        gui.nav.x, gui.nav.y - 10 - gl_smallFont.h,
+        NULL, "%d - %s", pilot_getJumps(player),
+        (sys_isKnown(sys)) ? sys->name : "Unknown");
+  } else { /* No NAV target. */
+    gl_printMid(NULL, (int)gui.nav.w,
+        gui.nav.x, gui.nav.y - 5,
+        &cConsole, "Navigation");
+
+    gl_printMid(&gl_smallFont, (int)gui.nav.w,
+        gui.nav.x, gui.nav.y - 10 - gl_smallFont.h,
+        &cGrey, "Off");
+  }
+
+  /* Health. */
+  gui_renderHealth(&cShield, &gui.shield, gui.gfx_shield,
+      player->shield / player->shield_max);
+  gui_renderHealth(&cArmour, &gui.armour, gui.gfx_armour,
+      player->armour / player->armour_max);
+  gui_renderHealth(&cEnergy, &gui.energy, gui.gfx_energy,
+      player->energy / player->energy_max);
+  gui_renderHealth(&cFuel, &gui.fuel, gui.gfx_fuel,
+      player->fuel / player->fuel_max);
+
+  /* Weapon. */
+  if(player->secondary == NULL) { /* No secondary weapon. */
+    gl_printMid(NULL, (int)gui.weapon.w,
+        gui.weapon.x, gui.weapon.y - 5,
+        &cConsole, "Secondary");
+
+    gl_printMid(&gl_smallFont, (int)gui.weapon.w,
+        gui.weapon.x, gui.weapon.y - 10 - gl_defFont.h,
+        &cGrey, "None");
+  } else {
+    f = &gl_defFont;
+
+    quantity = pilot_oquantity(player, player->secondary);
+    delay = outfit_delay(player->secondary->outfit);
+
+    /* Check to see if weapon is ready. */
+    if(player->secondary->timer > 0.)
+      c = &cGrey;
+    else
+      c = &cConsole;
+
+    /* Launcher. */
+    if(player->ammo != NULL) {
+      /* Use the ammunitions name. */
+      i = gl_printWidth(f, "%s", outfit_ammo(player->secondary->outfit)->name);
+      if(i > gui.weapon.w) /* Font is too big. */
+        f = &gl_smallFont;
+
+      /* Weapon name. */
+      gl_printMid(f, (int)gui.weapon.w,
+          gui.weapon.x, gui.weapon.y - 5,
+          (player->ammo) ? c : &cGrey, "%s",
+          outfit_ammo(player->secondary->outfit)->name);
+
+      /* Print ammo left underneath. */
+      gl_printMid(&gl_smallFont, (int)gui.weapon.w,
+          gui.weapon.x, gui.weapon.y - 10 - gl_defFont.h,
+          NULL, "%d", (player->ammo) ? player->ammo->quantity : 0);
+    } else { /* Other. */
+      i = gl_printWidth(f, "%s", player->secondary->outfit->name);
+      if(i > (int)gui.weapon.w) /* Font is too big. */
+        f = &gl_smallFont;
+      gl_printMid(f, (int)gui.weapon.w,
+          gui.weapon.x, gui.weapon.y - (gui.weapon.h - f->h)/2.,
+          c, "%s", player->secondary->outfit->name);
+    }
+  }
+
+  /* Target. */
+  if(player->target != PLAYER_ID) {
+    p = pilot_get(player->target);
+
+    /* Blit the pilot target. */
+    gl_blitStatic(p->ship->gfx_target, gui.target.x, gui.target.y, NULL);
+    /* Blit the pilot space image. */
+    /*x = gui.target.x + (TARGET_WIDTH - p->ship->gfx_space->sw)/2.;
+    y = gui.target.y + (TARGET_HEIGHT - p->ship->gfx_space->sh)/2.;
+    gl_blitStaticSprite(p->ship->gfx_space,
+        x, y, p->tsx, p->tsy, NULL); */
+
+    /* Target name. */
+    gl_print(NULL,
+        gui.target_name.x,
+        gui.target_name.y,
+        NULL, "%s", p->name);
+    gl_print(&gl_smallFont,
+        gui.target_faction.x,
+        gui.target_faction.y,
+        NULL, "%s", faction_name(p->faction));
+
+    /* Target status. */
+    if(pilot_isDisabled(p)) /* Pilot is disabled. */
+      gl_print(&gl_smallFont,
+          gui.target_health.x,
+          gui.target_health.y,
+          NULL, "Disabled");
+    else if(p->shield > p->shield_max/100.) /* On shields. */
+      gl_print(&gl_smallFont,
+          gui.target_health.x,
+          gui.target_health.y, NULL,
+          "%s: %.0f%%", "Shield", p->shield/p->armour_max*100.);
+  } else { /* No target. */
+    gl_printMid(NULL, SHIP_TARGET_W,
+        gui.target.x, gui.target.y + (SHIP_TARGET_H - gl_defFont.h)/2.,
+        &cGrey, "No Target");
+  }
+
+  /* Misc. */
+
+  /* Money. */
+  j = gui.misc.y - 8 - gl_smallFont.h;
+  gl_print(&gl_smallFont,
+      gui.misc.x + 8, j,
+      &cConsole, "Creds:");
+  credits2str(str, player->credits, 2);
+  i = gl_printWidth(&gl_smallFont, str);
+  gl_print( &gl_smallFont,
+      gui.misc.x + gui.misc.w - 8 - i, j,
+      NULL, str );
+  /* Cargo and friends. */
+  if(player->ncommodities > 0) {
+    j -= gl_smallFont.h + 5;
+    gl_print(&gl_smallFont,
+        gui.misc.x + 8, j,
+        &cConsole, "Cargo:");
+    for(i = 0; i < MIN(player->ncommodities, 3); i++) {
+      j -= gl_smallFont.h + 3;
+      if(player->commodities[i].quantity) /* Quantity is over. */
+        gl_printMax(&gl_smallFont, gui.misc.w - 15,
+            gui.misc.x + 13, j,
+            NULL, "%d %s%s", player->commodities[i].quantity,
+            player->commodities[i].commodity->name,
+            (player->commodities[i].id) ? "*" : "");
+      else /* Basically for weightless mission stuff. */
+        gl_printMax(&gl_smallFont, gui.misc.w - 15,
+            gui.misc.x + 13, j,
+            NULL, "%s%s", player->commodities[i].commodity->name,
+            (player->commodities[i].id) ? "*" : "");
+    }
+  }
+
+  j -= gl_smallFont.h + 5;
+  gl_print(&gl_smallFont,
+      gui.misc.x + 8, j,
+      &cConsole, "Free:");
+  i = gl_printWidth(&gl_smallFont, "%d", pilot_cargoFree(player));
+  gl_print(&gl_smallFont,
+      gui.misc.x + gui.misc.w - 8 - i, j,
+      NULL, "%d", pilot_cargoFree(player));
+
+  /* Messages. */
+  gui_renderMessages(dt);
+
+  /* Hyperspace. */
+  if(pilot_isFlag(player, PILOT_HYPERSPACE) &&
+      (player->ptimer < HYPERSPACE_FADEOUT)) {
+    if(i < j) {
+      x = (HYPERSPACE_FADEOUT-player->ptimer) / HYPERSPACE_FADEOUT;
+      glColor4d(1.,1.,1., x);
+      glBegin(GL_QUADS);
+        glVertex2d( -SCREEN_W/2., -SCREEN_H/2.);
+        glVertex2d( -SCREEN_W/2.,  SCREEN_H/2.);
+        glVertex2d(  SCREEN_W/2.,  SCREEN_H/2.);
+        glVertex2d(  SCREEN_W/2., -SCREEN_H/2.);
+      glEnd();
+    }
+  }
+}
+
+/**
+ * @brief  Render the GUI Radar.
+ *    @param dt Current deltatick.
+ */
+
+static void gui_renderRadar(double dt) {
+  int i, j;
+
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  if(gui.radar.shape == RADAR_RECT)
+    glTranslated(gui.radar.x - SCREEN_W/2. + gui.radar.w/2.,
+        gui.radar.y - SCREEN_H/2. - gui.radar.h/2., 0);
+  else if(gui.radar.shape == RADAR_CIRCLE)
+    glTranslated(gui.radar.x - SCREEN_W/2.,
+        gui.radar.y - SCREEN_H/2, 0.);
+
+  /* Planets. */
+  planets_minimap(gui.radar.res, gui.radar.w, gui.radar.h,
+      gui.radar.shape, 1.-interference_alpha);
+
+  /* Weapons. */
+  weapon_minimap(gui.radar.res, gui.radar.w, gui.radar.h,
+      gui.radar.shape, 1.-interference_alpha);
+
+  /* Render the pilot_nstack. */
+  j = 0;
+  for(i = 1; j < pilot_nstack; i++) { /* Skip the player. */
+    if(pilot_stack[i]->id == player->target)
+      j = i;
+    else
+      gui_renderPilot(pilot_stack[i]);
+  }
+  /* Render the targetted pilot. */
+  if(j != 0)
+    gui_renderPilot(pilot_stack[j]);
+
+  glPopMatrix(); /* GL_PROJECTION. */
+
+  /* Interference. */
+  gui_renderInterference(dt);
+
+  glPushMatrix();
+  if(gui.radar.shape == RADAR_RECT)
+    glTranslated(gui.radar.x - SCREEN_W/2. + gui.radar.w/2.,
+        gui.radar.y - SCREEN_H/2. - gui.radar.h/2., 0.);
+  else if(gui.radar.shape == RADAR_CIRCLE)
+    glTranslated(gui.radar.x - SCREEN_W/2.,
+        gui.radar.y - SCREEN_H/2., 0.);
+
+  /* The + sign in the center of the radar represents the player. */
+  glBegin(GL_LINES);
+    glVertex2d(  0., -3.);
+    glVertex2d(  0.,  3.);
+    glVertex2d( -3.,  0.);
+    glVertex2d(  3.,  0.);
+  glEnd();
+
+  glPopMatrix(); /* GL_PROJECTION. */
+}
+
+/**
+ * @brief Render the players messages on screen.
+ *    @param dt Current delta tick.
+ */
+
+static void gui_renderMessages(double dt) {
+  double x, y;
+  glColour c;
+  int i;
+
+  x = gui.msg.x;
+  y = gui.msg.y + (double)(gl_defFont.h*msg_max)*1.2;
+  c.r = c.g = c.b = 1.;
+
+  for(i = msg_max-1; i >= 0; i--) {
+    y -= (double)gl_defFont.h*1.2;
+
+    if(msg_stack[i].str[0] != '\0') {
+
+      /* Decrement timer. */
+      msg_stack[i].t -= dt;
+
+      /* Set to NULL if timer is up. */
+      if(msg_stack[i].t < 0.)
+        msg_stack[i].str[0] = '\0';
+      else { /* Draw with variable alpha. */
+        if(msg_stack[i].t - msg_timeout/2 < 0.)
+          c.a = msg_stack[i].t / (msg_timeout/2.);
+        else
+          c.a = 1.;
+        gl_print(NULL, x, y, &c, "%s", msg_stack[i].str);
+      }
+    }
+  }
+}
+
+/**
+ * @brief Render interference if needed.
+ *    @param dt Current deltatick.
+ */
+static void gui_renderInterference(double dt) {
+  glColour c;
+  glTexture* tex;
+  int t;
+
+  /* Must be displaying interference. */
+  if(interference_alpha <= 0.)
+    return;
+
+  /* Calculate frame to draw. */
+  interference_t += dt;
+  if(interference_t > INTERFERENCE_CHANGE_DT) { /* Time to change. */
+    t = RNG(0, INTERFERENCE_LAYERS-1);
+    if(t != interference_layer)
+      interference_layer = t;
+    else
+      interference_layer = (interference_layer == INTERFERENCE_LAYERS-1) ?
+        0 : interference_layer+1;
+    interference_t -= INTERFERENCE_CHANGE_DT;
+  }
+
+  /* Render the interference. */
+  c.r = c.g = c.b = 1.;
+  c.a = interference_alpha;
+  tex = gui.radar.interference[interference_layer];
+  if(gui.radar.shape == RADAR_CIRCLE)
+    gl_blitStatic(tex,
+        gui.radar.x - gui.radar.w,
+        gui.radar.y - gui.radar.w, &c);
+  else if(gui.radar.shape == RADAR_RECT)
+    gl_blitStatic(tex,
+        gui.radar.x - gui.radar.w/2,
+        gui.radar.y - gui.radar.h/2, &c);
+}
+
+/**
+ * @brief Render a pilot in the GUI radar.
+ *    @param p Pilot to render.
+ */
+static void gui_renderPilot(const Pilot* p) {
+  int x, y, sx, sy;
+  double w, h;
+  glColour* col;
+  double a;
+
+  /* Get position. */
+  x = (p->solid->pos.x - player->solid->pos.x) / gui.radar.res;
+  y = (p->solid->pos.y - player->solid->pos.y) / gui.radar.res;
+  /* Get size. */
+  sx = PILOT_SIZE_APROX/2. * p->ship->gfx_space->sw / gui.radar.res;
+  sy = PILOT_SIZE_APROX/2. * p->ship->gfx_space->sh / gui.radar.res;
+  if(sx < 1.)
+    sx = 1.;
+  if(sy < 1.)
+    sy = 1.;
+
+  /* Check if the pilot is in range. */
+  if(((gui.radar.shape == RADAR_RECT) &&
+        ((ABS(x) > gui.radar.w/2.+sx) || (ABS(y) > gui.radar.h/2.+sy))) ||
+      ((gui.radar.shape == RADAR_CIRCLE) &&
+       ((x*x+y*y) > (int)(gui.radar.w*gui.radar.w)))) {
+    /* Draw a little targetted symbol. */
+    if(p->id == player->target) {
+      /* Circle radars have it easy. */
+      if(gui.radar.shape == RADAR_CIRCLE) {
+        /* We'll create a line. */
+        a = ANGLE(x,y);
+        x = gui.radar.w * cos(a);
+        y = gui.radar.w * sin(a);
+        sx = 0.85 * x;
+        sy = 0.85 * y;
+
+        COLOUR(cRadar_tPilot);
+        glBegin(GL_LINES);
+          glVertex2d( x,  y);
+          glVertex2d(sx, sy);
+        glEnd(); /* GL_LINES. */
+      }
+    }
+    return;
+  }
+
+  if(gui.radar.shape == RADAR_RECT) {
+    w = gui.radar.w/2.;
+    h = gui.radar.h/2.;
+  }
+  else if(gui.radar.shape == RADAR_CIRCLE) {
+    w = gui.radar.w;
+    h = gui.radar.w;
+  }
+  glBegin(GL_QUADS);
+    /* Colours. */
+    if(p->id == player->target) col = &cRadar_tPilot;
+    else if(pilot_isDisabled(p))            col = &cInert;
+    else if(pilot_isFlag(p, PILOT_BRIBED))  col = &cNeutral;
+    else if(pilot_isFlag(p, PILOT_HOSTILE)) col = &cHostile;
+    else col = faction_getColour(p->faction);
+    ACOLOUR(*col, 1-interference_alpha); /**< Makes it much harder to see. */
+
+    /* Image. */
+    glVertex2d( MAX(x-sx,-w), MIN(y+sy, h) ); /* Top left. */
+    glVertex2d( MIN(x+sx, w), MIN(y+sy, h) ); /* Top right. */
+    glVertex2d( MIN(x+sx, w), MAX(y-sy,-h) ); /* Bottom right. */
+    glVertex2d( MAX(x-sx,-w), MAX(y-sy,-h) ); /* Bottom left. */
+  glEnd(); /* GL_QUADS. */
+}
+
+/**
+ * @brief Render a health bar.
+ */
+static void gui_renderHealth(const glColour* c,
+    const Rect* r, const glTexture* tex, const double w) {
+
+  double x,y, sx,sy, tx,ty;
+
+  /* Set the colour. */
+  COLOUR(*c);
+
+  if(tex == NULL) {
+   x = r->x - SCREEN_W/2.;
+   y = r->y - SCREEN_H/2.;
+   sx = w * r->w;
+   sy = r->h;
+
+    glBegin(GL_QUADS);
+      glVertex2d(x,     y);
+      glVertex2d(x+sx,  y);
+      glVertex2d(x+sx,  y-sy);
+      glVertex2d(x,     y-sy);
+    glEnd(); /* GL_QUADS. */
+  } else { /* Render the texture. */
+    x = r->x - SCREEN_W/2.;
+    y = r->y - SCREEN_H/2. + tex->sh;
+    sx = w * tex->sw;
+    sy = tex->sh;
+    tx = tex->sw / tex->rw;
+    ty = tex->sh / tex->rh;
+
+    /* Draw the image. */
+    glEnable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, tex->texture);
+    glBegin(GL_QUADS);
+      glTexCoord2d(0., ty);
+      glVertex2d(x, y);
+
+      glTexCoord2d(w*tx, ty);
+      glVertex2d(x+sx, y);
+
+      glTexCoord2d(w*tx, 0.);
+      glVertex2d(x+sx, y-sy);
+
+      glTexCoord2d(0., 0.);
+      glVertex2d(x, y-sy);
+    glEnd(); /* GL_QUADS. */
+    glDisable(GL_TEXTURE_2D);
+  }
+}
+
+/**
+ * brief Initialises the GUI system.
+ *    @return 0 on success.
+ */
+int gui_init(void) {
+  /* Set gfx to NULL. */
+  memset(&gui, 0, sizeof(GUI));
+
+  /* Radar. */
+  gui.radar.res = RADAR_RES_DEFAULT;
+
+  /* Messages. */
+  gui.msg.x = 20;
+  gui.msg.y = 30;
+  msg_stack = calloc(msg_max, sizeof(Msg));
+  if(msg_stack == NULL) {
+    ERR("Out of memory!");
+    return -1;
+  }
+  return 0;
+}
+
+/**
+ * @brief Attempts to load the actual GUI.
+ *    @param name Name of the GUI to load.
+ *    @return 0 on success.
+ */
+int gui_load(const char* name) {
+  uint32_t bufsize;
+  char* buf = ldata_read(GUI_DATA, &bufsize);
+  char* tmp;
+  int found = 0;
+
+  xmlNodePtr node;
+  xmlDocPtr doc = xmlParseMemory(buf, bufsize);
+
+  node = doc->xmlChildrenNode;
+  if(!xml_isNode(node, XML_GUI_ID)) {
+    ERR("Malformed '"GUI_DATA"' file: missing root element '"XML_GUI_ID"'");
+    return -1;
+  }
+
+  node = node->xmlChildrenNode; /* First system node. */
+  if(node == NULL) {
+    ERR("Malformed '"GUI_DATA"' file: does not contain elements");
+    return -1;
+  }
+
+  do {
+    if(xml_isNode(node, XML_GUI_TAG)) {
+      tmp = xml_nodeProp(node, "name"); /* Mallocs. */
+      /* Is this the GUI we are looking for? */
+      if(strcmp(tmp, name) == 0) {
+        found = 1;
+
+        /* Parse the xml node. */
+        if(gui_parse(node, name))
+          WARN("Trouble loading GUI '%s'", name);
+        free(tmp);
+        break;
+      }
+      free(tmp);
+    }
+  } while(xml_nextNode(node));
+
+  xmlFreeDoc(doc);
+  free(buf);
+
+  if(!found) {
+    WARN("GUI '%s' not found in '"GUI_DATA"'", name);
+    return -1;
+  }
+
+  return 0;
+}
+
+/**
+ * @brief Parse a parameter of the rect node.
+ */
+static void rect_parseParam(const xmlNodePtr parent,
+    char* name, double* param) {
+
+  char* buf;
+  
+  /* Get the attribute. */
+  xmlr_attr(parent, name, buf);
+
+  /* Wants attribute. */
+  if(param != NULL) {
+    if(buf == NULL)
+      WARN("Node '%s' mising 'x' parameter.", parent->name);
+    else if(buf != NULL)
+      *param = atoi(buf);
+  }
+  /* Doesn't want it. */
+  else if(buf != NULL)
+    WARN("Node '%s' has superfluous 'x' parameter.", parent->name);
+
+  /* Clean it up. */
+  if(buf != NULL)
+    free(buf);
+}
+
+/**
+ * @brief Used to pull out a rect from an xml node.
+ */
+static void rect_parse(const xmlNodePtr parent,
+    double* x, double* y, double* w, double* h) {
+  rect_parseParam(parent, "w", w);
+  rect_parseParam(parent, "h", h);
+  rect_parseParam(parent, "x", x);
+  rect_parseParam(parent, "y", y);
+}
+
+/**
+ * @brief Create the interference map for the current gui.
+ */
+static void gui_createInterference(void) {
+  uint8_t raw;
+  int i, j, k;
+  float* map;
+  uint32_t* pix;
+  SDL_Surface* sur;
+  int w, h, hw, hh;
+  float c;
+  int r;
+
+  /* Dimension shortcuts. */
+  if(gui.radar.shape == RADAR_CIRCLE) {
+    w = gui.radar.w*2.;
+    h = w;
+  }
+  else if(gui.radar.shape == RADAR_RECT) {
+    w = gui.radar.w;
+    h = gui.radar.h;
+  }
+
+  for(k = 0; k < INTERFERENCE_LAYERS; k++) {
+    /* free the old texture. */
+    if(gui.radar.interference[k] != NULL)
+      gl_freeTexture(gui.radar.interference[k]);
+
+    /* Create the temporary surface. */
+    sur = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RGBAMASK);
+    pix = sur->pixels;
+
+    /* Load the interference map. */
+    map = noise_genRadarInt(w, h, 100.);
+
+    /* Create the texture. */
+    SDL_LockSurface(sur);
+    if(gui.radar.shape == RADAR_CIRCLE) {
+      r = pow2((int)gui.radar.w);
+      hw = w/2;
+      hh = h/2;
+      for(i = 0; i < h; i++) {
+        for(j = 0; j < w; j++) {
+          /* Must be in circle. */
+          if(pow2(i-hh) + pow2(j-hw) > r)
+            continue;
+          c = map[i*w + j];
+          raw = 0xff &(uint8_t)((float)0xff * c);
+          memset(&pix[i*w + j], raw, sizeof(uint32_t));
+          pix[i*w + j] |= AMASK;
+        }
+      }
+    }
+    else if(gui.radar.shape == RADAR_RECT) {
+      for(i = 0; i < h*w; i++) {
+        /* Process pixels. */
+        c = map[i];
+        raw = 0xff &(uint8_t)((float)0xff * c);
+        memset(&pix[i], raw, sizeof(uint32_t));
+        pix[i] |= AMASK;
+      }
+    }
+    SDL_UnlockSurface(sur);
+
+    /* Set the interference. */
+    gui.radar.interference[k] = gl_loadImage(sur);
+
+    /* Clean up. */
+    free(map);
+  }
+}
+
+
+#define RELATIVIZE(a) \
+{(a).x += VX(gui.frame); (a).y = VY(gui.frame)+gui.gfx_frame->h-(a).y;}
+/**< Converts a rect to absolute coords. */
+
+/**
+ * @brief Parses a GUI node.
+ *    @param parent node to parse from.
+ *    @param name Name of the GUI to load.
+ */
+static int gui_parse(const xmlNodePtr parent, const char* name) {
+  xmlNodePtr cur, node;
+  char* tmp, buf[PATH_MAX];
+
+  /* Clean up. */
+  gui_cleanup();
+
+  /* 
+   * -- gfx --
+   * Set as a property and not a node because it must be loaded first.
+   */
+  tmp = xml_nodeProp(parent, "gfx");
+  if(tmp == NULL) {
+    ERR("GUI '%s' has no gfx property", name);
+    return -1;
+  }
+
+  /* Load gfx. */
+  /* Frame. */
+  snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
+  gui.gfx_frame = gl_newImage(buf, 0);
+  /* Pilot. */
+  snprintf(buf, PATH_MAX, GUI_GFX"%s_pilot.png", tmp);
+  gui.gfx_targetPilot = gl_newSprite(buf, 2, 2, 0);
+  /* Planet. */
+  snprintf(buf, PATH_MAX, GUI_GFX"%s_planet.png", tmp);
+  gui.gfx_targetPlanet = gl_newSprite(buf, 2, 2, 0);
+  free(tmp);
+
+  /* Frame (based on gfx). */
+  vect_csetmin(&gui.frame,
+      SCREEN_W - gui.gfx_frame->w,    /* x */
+      SCREEN_H - gui.gfx_frame->h);   /* y */
+
+  /* Now actually parse the data. */
+  node = parent->children;
+
+  do { /* Load all the data. */
+    /* Offset. */
+    if(xml_isNode(node, "offset"))
+      rect_parse(node, &gui_xoff, &gui_yoff, NULL, NULL);
+
+    /* Radar. */
+    else if(xml_isNode(node, "radar")) {
+      tmp = xml_nodeProp(node, "type");
+
+      if(strcmp(tmp, "rectangle")==0)   gui.radar.shape = RADAR_RECT;
+      else if(strcmp(tmp, "circle")==0) gui.radar.shape = RADAR_CIRCLE;
+      else {
+        WARN("Radar for GUI '%s' is missing 'type' tag or has invalid 'type' tag", name);
+        gui.radar.shape = RADAR_RECT;
+      }
+      free(tmp);
+
+      /* Load the appropriate measurements. */
+      if(gui.radar.shape == RADAR_RECT)
+        rect_parse(node, &gui.radar.x, &gui.radar.y, &gui.radar.w, &gui.radar.h);
+      else if(gui.radar.shape == RADAR_CIRCLE)
+        rect_parse(node, &gui.radar.x, &gui.radar.y, &gui.radar.w, NULL);
+      RELATIVIZE(gui.radar);
+    }
+
+    /* Nav computer. */
+    else if(xml_isNode(node, "nav")) {
+     rect_parse(node, &gui.nav.x, &gui.nav.y, &gui.nav.w, &gui.nav.h);
+     RELATIVIZE(gui.nav);
+     gui.nav.y -= gl_defFont.h;
+    }
+
+    /* Health bars. */
+    else if(xml_isNode(node, "health")) {
+      cur = node->children;
+      do {
+        if(xml_isNode(cur, "shield")) {
+          rect_parse(cur, &gui.shield.x, &gui.shield.y,
+              &gui.shield.w, &gui.shield.h);
+          tmp = xml_get(cur);
+          if(tmp != NULL) {
+            snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
+            gui.gfx_shield = gl_newImage(buf, 0);
+          }
+          RELATIVIZE(gui.shield);
+        }
+        if(xml_isNode(cur, "armour")) {
+          rect_parse(cur, &gui.armour.x, &gui.armour.y,
+              &gui.armour.w, &gui.armour.h);
+          tmp = xml_get(cur);
+          if(tmp != NULL) {
+            snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
+            gui.gfx_armour = gl_newImage(buf, 0);
+          }
+          RELATIVIZE(gui.armour);
+        }
+        if(xml_isNode(cur, "energy")) {
+          rect_parse(cur, &gui.energy.x, &gui.energy.y,
+              &gui.energy.w, &gui.energy.h);
+          tmp = xml_get(cur);
+          if(tmp != NULL) {
+            snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
+            gui.gfx_energy = gl_newImage(buf, 0);
+          }
+          RELATIVIZE(gui.energy);
+        }
+        if(xml_isNode(cur, "fuel")) {
+          rect_parse(cur, &gui.fuel.x, &gui.fuel.y,
+              &gui.fuel.w, &gui.fuel.h);
+          tmp = xml_get(cur);
+          if(tmp != NULL) {
+            snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
+            gui.gfx_fuel = gl_newImage(buf, 0);
+          }
+          RELATIVIZE(gui.fuel);
+        }
+      } while(xml_nextNode(cur));
+    }
+
+    /* Secondary weapon. */
+    else if(xml_isNode(node, "weapon")) {
+      rect_parse(node, &gui.weapon.x, &gui.weapon.y,
+          &gui.weapon.w, &gui.weapon.h);
+      RELATIVIZE(gui.weapon);
+      gui.weapon.y -= gl_defFont.h;
+    }
+
+    /* Target. */
+    else if(xml_isNode(node, "target")) {
+      cur = node->children;
+      do {
+        if(xml_isNode(cur, "gfx")) {
+          rect_parse(cur, &gui.target.x, &gui.target.y, NULL, NULL);
+          RELATIVIZE(gui.target);
+          gui.target.y -= SHIP_TARGET_H;
+        }
+        else if(xml_isNode(cur, "name")) {
+          rect_parse(cur, &gui.target_name.x, &gui.target_name.y, NULL, NULL);
+          RELATIVIZE(gui.target_name);
+          gui.target_name.y -= gl_defFont.h;
+        }
+        else if(xml_isNode(cur, "faction")) {
+          rect_parse(cur, &gui.target_faction.x, &gui.target_faction.y, NULL, NULL);
+          RELATIVIZE(gui.target_faction);
+          gui.target_faction.y -= gl_smallFont.h;
+        }
+        else if(xml_isNode(cur, "health")) {
+          rect_parse(cur, &gui.target_health.x, &gui.target_health.y, NULL, NULL);
+          RELATIVIZE(gui.target_health);
+          gui.target_health.y -= gl_defFont.h;
+        }
+      } while(xml_nextNode(cur));
+    }
+
+    /* Misc. */
+    else if(xml_isNode(node, "misc")) {
+      rect_parse(node, &gui.misc.x, &gui.misc.y, &gui.misc.w, &gui.misc.h);
+      RELATIVIZE(gui.misc);
+    }
+  } while(xml_nextNode(node));
+
+  /* Some postprocessing. */
+  gui_createInterference();
+
+  return 0;
+}
+#undef RELATIVIZE
+
+/*
+ * @brief Clean up the GUI.
+ */
+void gui_cleanup(void) {
+  int i;
+  /* free textures. */
+  if( gui.gfx_frame != NULL) {
+    gl_freeTexture(gui.gfx_frame);
+    gui.gfx_frame = NULL;
+  }
+  if(gui.gfx_targetPilot != NULL) {
+    gl_freeTexture(gui.gfx_targetPilot);
+    gui.gfx_targetPilot = NULL;
+  }
+  if(gui.gfx_targetPlanet != NULL) {
+    gl_freeTexture(gui.gfx_targetPlanet);
+    gui.gfx_targetPlanet = NULL;
+  }
+  /* Health textures. */
+  if(gui.gfx_shield != NULL) {
+    gl_freeTexture(gui.gfx_shield);
+    gui.gfx_shield = NULL;
+  }
+  if(gui.gfx_armour != NULL) {
+    gl_freeTexture(gui.gfx_armour);
+    gui.gfx_armour = NULL;
+  }
+  if(gui.gfx_energy != NULL) {
+    gl_freeTexture(gui.gfx_energy);
+    gui.gfx_energy = NULL;
+  }
+  if(gui.gfx_fuel != NULL) {
+    gl_freeTexture(gui.gfx_fuel);
+    gui.gfx_fuel = NULL;
+  }
+  for(i = 0; i < INTERFERENCE_LAYERS; i++) {
+    if(gui.radar.interference[i] != NULL) {
+      gl_freeTexture(gui.radar.interference[i]);
+      gui.radar.interference[i] = NULL;
+    }
+  }
+
+  /* Clean up interference. */
+  interference_alpha  = 0.;
+  interference_layer  = 0;
+  interference_t      = 0;
+}
+
+/**
+ * @brief Free the gui stuff.
+ */
+void gui_free(void) {
+  /* Clean up gui. */
+  gui_cleanup();
+
+  /* Free messages. */
+  free(msg_stack);
+}
+
+/**
+ * @brief Modifies the radar resolution.
+ *    @param mod Number of intervals to jump (up or down).
+ */
+void gui_setRadarRel(int mod) {
+  gui.radar.res += mod * RADAR_RES_INTERVAL;
+  if(gui.radar.res > RADAR_RES_MAX) gui.radar.res = RADAR_RES_MAX;
+  else if(gui.radar.res < RADAR_RES_MIN) gui.radar.res = RADAR_RES_MIN;
+
+  player_message("Radar set to %dx.", (int)gui.radar.res);
+}
+
diff --git a/src/gui.h b/src/gui.h
new file mode 100644
index 0000000..761d8b0
--- /dev/null
+++ b/src/gui.h
@@ -0,0 +1,27 @@
+#pragma once
+
+/* Enums. */
+typedef enum RadarShape_ {
+  RADAR_RECT,   /**< Rectangular radar. */
+  RADAR_CIRCLE  /**< Circular radar. */
+} RadarShape;   /**< Plaers radar shape. */
+
+extern double gui_xoff; /**< GUI X center offset. */
+extern double gui_yoff; /**< GUI Y center offset. */
+
+/* Loading/cleaning up. */
+int gui_init(void);
+void gui_free(void);
+int gui_load(const char* name);
+void gui_cleanup(void);
+
+/* Render. */
+void gui_renderBG(double dt);
+void gui_renderTarget(double dt);
+void gui_render(double dt);
+
+/* Misc. */
+void gui_setDefaults(void);
+void player_message(const char* fmt, ...);
+void gui_setRadarRel(int mod);
+
diff --git a/src/input.c b/src/input.c
index 9439b07..a41c806 100644
--- a/src/input.c
+++ b/src/input.c
@@ -15,6 +15,7 @@
 #include "escort.h"
 #include "land.h"
 #include "lstd.h"
+#include "gui.h"
 #include "input.h"
 
 #define KEY_PRESS   ( 1.) /**< Key is pressed. */
@@ -552,11 +553,11 @@ static void input_key(int keynum, double value, double kabs) {
   }
   /* Zoom in. */
   else if(KEY("mapzoomin") && INGAME()) {
-    if(value == KEY_PRESS) player_setRadarRel(1);
+    if(value == KEY_PRESS) gui_setRadarRel(1);
   }
   /* Zoom out. */
   else if(KEY("mapzoomout") && INGAME()) {
-    if(value == KEY_PRESS) player_setRadarRel(-1);
+    if(value == KEY_PRESS) gui_setRadarRel(-1);
   }
   /* Take a screenshot. */
   else if(KEY("screenshot") && INGAME()) {
diff --git a/src/lephisto.c b/src/lephisto.c
index 4b58f0b..6d53c2c 100644
--- a/src/lephisto.c
+++ b/src/lephisto.c
@@ -52,6 +52,7 @@
 #include "llua_misn.h"
 #include "lfile.h"
 #include "unidiff.h"
+#include "gui.h"
 #include "nebulae.h"
 
 
@@ -512,22 +513,23 @@ static void render_all(void) {
   double dt;
 
   dt = (paused) ? 0. : cur_dt;
+
   /* Setup. */
   spfx_start(dt);
   /* BG. */
   space_render(dt);
   planets_render();
-  player_renderBG();
+  gui_renderBG(dt);
   weapons_render(WEAPON_LAYER_BG, dt);
   /* N. */
   pilots_render();
   weapons_render(WEAPON_LAYER_FG, dt);
   spfx_render(SPFX_LAYER_BACK);
   /* FG. */
-  player_render();
+  player_render(dt);
   spfx_render(SPFX_LAYER_FRONT);
   space_renderOverlay(dt);
-  player_renderGUI(dt);
+  gui_render(dt);
   display_fps(dt); /* Exception. */
 }
 
diff --git a/src/map.c b/src/map.c
index a1d0bc5..8ff5bfe 100644
--- a/src/map.c
+++ b/src/map.c
@@ -9,6 +9,7 @@
 #include "opengl.h"
 #include "mission.h"
 #include "colour.h"
+#include "player.h"
 #include "map.h"
 
 #define MAP_WDWNAME     "Star Map"  /**< Map window name. */
@@ -37,9 +38,6 @@ static int map_drag = 0;              /**< Is the user dragging the map? */
 /* space.c */
 extern StarSystem* systems_stack;
 extern int systems_nstack;
-/* player.c */
-extern int planet_target;
-extern int hyperspace_target;
 
 static void map_update(unsigned int wid);
 static int  map_inPath(StarSystem* sys);
diff --git a/src/nebulae.c b/src/nebulae.c
index 1df4f9a..737f8c9 100644
--- a/src/nebulae.c
+++ b/src/nebulae.c
@@ -17,6 +17,7 @@
 #include "menu.h"
 #include "player.h"
 #include "pause.h"
+#include "gui.h"
 #include "perlin.h"
 
 #define NEBULAE_Z             16    /**< Z plane. */
@@ -26,7 +27,6 @@
 #define NEBULAE_PUFF_BUFFER   300 /**< Nebulae buffer. */
 
 /* Extern. */
-extern double gui_xoff, gui_yoff; /**< From player.c */
 extern Vec2 shake_pos;            /**< From spfx.c. */
 extern void loadscreen_render(double done, const char* msg); /**< From lephisto.c. */
 
diff --git a/src/opengl.c b/src/opengl.c
index 3f498bd..dea3609 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -40,6 +40,7 @@
 #include "lephisto.h"
 #include "log.h"
 #include "ldata.h"
+#include "gui.h"
 #include "opengl.h"
 
 /* Requirements. */
@@ -48,13 +49,6 @@
 glInfo gl_screen; /**< Give data of current opengl settings. */
 Vec2* gl_camera;  /**< Camera we are using. */
 
-/*
- * Used to adjust the pilots place onscreen to be in the middle
- * even with the GUI.
- */
-extern double gui_xoff; /**< GUI X offset. */
-extern double gui_yoff; /**< GUI Y offset. */
-
 /* Graphic list. */
 /**
  * @brief Represents a node in the texture list.
diff --git a/src/player.c b/src/player.c
index e18774d..23f09e9 100644
--- a/src/player.c
+++ b/src/player.c
@@ -35,28 +35,17 @@
 #include "perlin.h"
 #include "ai.h"
 #include "music.h"
+#include "gui.h"
 #include "player.h"
 
-#define XML_GUI_ID    "GUIs"    /**< XML section identifier for GUI document. */
-#define XML_GUI_TAG   "gui"     /**< XML section identifier for GUI tags. */
-
 #define XML_START_ID  "Start"   /**< Module start xml document identifier. */
 
-#define GUI_DATA      "../dat/gui.xml"    /**< Global GUI configuration file. */
-#define GUI_GFX       "../gfx/gui/"       /**< Location of the GUI graphics. */
-
 #define START_DATA    "../dat/start.xml"  /**< Module start information file. */
 
-#define TARGET_WIDTH  128             /**< Width of target graphics. */
-#define TARGET_HEIGHT 96              /**< Height of target graphics. */
-
 #define PLAYER_RESERVED_CHANNELS 6    /**< Number of channels to reserve for player sounds. */
 #define PLAYER_ENGINE_CHANNEL    9    /**< Player channel for engine noises. */
 #define PLAYER_GUI_CHANNEL       9    /**< Player channel. */
 
-#define INTERFERENCE_LAYERS      16   /**< Number of interference layers. */
-#define INTERFERENCE_CHANGE_DT   0.1  /**< Speed to change at. */
-
 /* Player stuff. */
 Pilot* player                 = NULL; /**< The player. */
 static Ship* player_ship      = NULL; /**< Temp ship to hold when naming it. */
@@ -77,9 +66,9 @@ static int player_nlicenses     = 0;    /**< Number of licenses player has. */
 /*
  * Player sounds.
  */
-static int snd_target = -1;
-static int snd_jump   = -1;
-static int snd_nav    = -1;
+int snd_target = -1;    /**< Sound when targetting. */
+int snd_jump   = -1;    /**< Sound when can jump. */
+int snd_nav    = -1;    /**< Sound when changing nav computer. */
 
 /* Player pilot stack - Ships she owns. */
 static Pilot** player_stack = NULL;     /**< Stack of ships player has. */
@@ -103,131 +92,23 @@ int hyperspace_target = -1;             /**< Target hyperspace route. -1 is none
 /* For death etc. */
 static double player_timer = 0;         /**< For death and such. */
 static Vec2 player_cam;                 /**< Again, for death etc. */
-/* For interference. */
-static int interference_layer = 0;   /**< Layer of the current interference. */
-double interference_alpha     = 0.;  /**< Alpha of the current interference layer. */
-static double interference_t  = 0.;  /**< Interference timer to control transitions. */
 
 static int* missions_done   = NULL;  /**< Saves position of completed missions. */
 static int  missions_mdone  = 0;     /**< Memory size of completed missions. */
 static int  missions_ndone  = 0;     /**< Number of completed missions. */
 
-/* Pilot stuff for GUI. */
+/* Extern stuff for player ships. */
 extern Pilot** pilot_stack;
 extern int pilot_nstack;
 
-/* Space stuff for GUI. */
+/* Stuff for autonav etc. */
 extern StarSystem* systems_stack;
 
 /* Map stuff for autonav. */
 extern int map_npath;
 
-/**
- * @struct Radar
- *
- * @brief Represents the player's radar.
- */
-typedef struct Radar_ {
-  double x;           /**< X position. */
-  double y;           /**< Y position. */
-  double w;           /**< Width. */
-  double h;           /**< Height. */
-  RadarShape shape;   /**< Shape. */
-  double res;         /**< Resolution. */
-  glTexture* interference[INTERFERENCE_LAYERS]; /**< Interference texture. */
-} Radar;
-
-/* Radar res. */
-#define RADAR_RES_MAX       100.  /**< Max radar resolution. */
-#define RADAR_RES_MIN       10.   /**< Min radar resolution. */
-#define RADAR_RES_INTERVAL  10.   /**< Steps used to increase/decrease resolution. */
-#define RADAR_RES_DEFAULT   40.   /**< Default resolution. */
-
-/**
- * @struct Rect
- *
- * @brief Represents a rectangle.
- */
-typedef struct Rect_ {
-  double x;   /**< X position. */
-  double y;   /**< Y position. */
-  double w;   /**< Width. */
-  double h;   /**< Height. */
-} Rect;
-
-/**
- * @struct GUI
- *
- * @brief Represents the ingame player graphical user interface.
- */
-typedef struct GUI_ {
-  /* Graphics. */
-  glTexture* gfx_frame;                           /**< Frame of the GUI. */
-  glTexture* gfx_targetPilot, *gfx_targetPlanet;  /**< Graphics used to target planets. */
-
-  /* Rects. */
-
-  /* Radar. */
-  Radar radar;                    /**< The radar. */
-  /* Navigation. */
-  Rect nav;                       /**< Navigation computer. */
-  /* Health. */
-  Rect shield;                    /**< Shield bar. */
-  glTexture* gfx_shield;          /**< Shield bar texture if applicable. */
-  Rect armour;                    /**< Armour bar. */
-  glTexture* gfx_armour;          /**M Armour bar texture if applicable. */
-  Rect energy;                    /**< Energy bar. */
-  glTexture* gfx_energy;          /**< Energy bar texture if applicable. */
-  Rect fuel;                      /**< Fuel bar. */
-  glTexture* gfx_fuel;            /**< Fuel bar texture if applicable. */
-  /* Weapon. */
-  Rect weapon;                    /**< Weapon targeting system. */
-  /* Targetting. */
-  Rect target_health;             /**< Target health. */
-  Rect target_name;               /**< Name of the target. */
-  Rect target_faction;            /**< Faction of the target. */
-  /* Misc. */
-  Rect misc;                      /**< Misc stuff: credits, cargo.. */
-  /* Messages. */
-  Rect msg;                       /**< Where messages go. */
-
-  /* Positions. */
-  Vec2 frame;   /**< Global frame position. */
-  Vec2 target;  /**< Global target position. */
-} GUI;
-
-static GUI gui = {
-  .gfx_frame        = NULL,
-  .gfx_targetPilot  = NULL,
-  .gfx_targetPlanet = NULL
-}; /**< The GUI. */
-
-/* Needed to render properly. */
-double gui_xoff = 0.;   /**< X offset that GUI introduces. */
-double gui_yoff = 0.;   /**< Y offset that GUI introduces. */
-
-/* Messages. */
-#define MSG_SIZE_MAX 120  /**< Max message length. */
-double msg_timeout = 5.;  /**< How long it takes for a message to timeout. */
-int msg_max = 5;          /**< Max messages on screen. */
-
-/**
- * @struct Mesg
- *
- * @brief On screen player message.
- */
-typedef struct Msg_ {
-  char str[MSG_SIZE_MAX]; /**< The message. */
-  double t;               /**< Time related to creation. */
-} Msg;
-static Msg* msg_stack; /**< Stack of messages,  will be of msg_max size. */
-
 /* External. */
 extern void pilot_render(const Pilot* pilot); /* Extern is in Pilot.* */
-extern void weapon_minimap(const double res, const double w, const double h,
-    const RadarShape shape, double alpha); /* weapon.c */
-extern void planets_minimap(const double res, const double w, const double h,
-    const RadarShape shape, double alpha); /* space.c */
 /* Internal. */
 
 /* Creation. */
@@ -235,19 +116,6 @@ static int player_newMake(void);
 static void player_newShipMake(char* name);
 /* Sound. */
 static void player_initSound(void);
-/* Gui. */
-static void gui_createInterference(void);
-static void rect_parseParam(const xmlNodePtr parent, char* name, double* param);
-static void rect_parse(const xmlNodePtr parent,
-                       double* x, double* y, double* w, double* h);
-static int gui_parse(const xmlNodePtr parent, const char* name);
-static void gui_cleanup(void);
-/* Render GUI. */
-static void gui_renderMessages(double dt);
-static void gui_renderPilot(const Pilot* p);
-static void gui_renderHealth(const glColour* c, const Rect* r,
-    const glTexture* tex, const double w);
-static void gui_renderInterference(double dt);
 /* Save/Load. */
 static int player_saveShip(xmlTextWriterPtr writer, Pilot* ship, char* loc);
 static int player_parse(xmlNodePtr parent);
@@ -280,8 +148,8 @@ void player_new(void) {
   vectnull(&player_cam);
   gl_bindCamera(&player_cam);
 
-  gui.radar.res = RADAR_RES_DEFAULT;
-  memset(msg_stack, 0, msg_max * sizeof(Msg));
+  /* Set up GUI. */
+  gui_setDefaults();
 
   /* Setup sound. */
   player_initSound();
@@ -623,9 +491,8 @@ void player_cleanup(void) {
   /* Clean up name. */
   if(player_name != NULL) free(player_name);
 
-  /* Clean up messages. */
-  for(i = 0; i < msg_max; i++)
-    memset(msg_stack[i].str, '\0', MSG_SIZE_MAX);
+  /* Clean up GUI. */
+  gui_cleanup();
 
   /* Clean up the stack. */
   if(player_nstack > 0) {
@@ -663,11 +530,6 @@ void player_cleanup(void) {
     pilot_free(player);
     player = NULL;
   }
-
-  /* Clean up interference. */
-  interference_alpha = 0.;
-  interference_layer = 0;
-  interference_t     = 0.;
 }
 
 static int player_soundReserved = 0; /**< Has the player already reserved sound? */
@@ -706,31 +568,6 @@ void player_stopSound(void) {
   sound_stopGroup(PLAYER_ENGINE_CHANNEL);
 }
 
-/**
- * @brief Add a msg to the queue to be displayed on screen.
- *    @param fmt String with formatting like prinf.
- */
-void player_message(const char* fmt, ...) {
-  va_list ap;
-  int i;
-
-  if(fmt == NULL) return; /* Message not valid. */
-
-  /* Copy old messages back. */
-  for(i = 1; i < msg_max; i++) {
-    if(msg_stack[msg_max-i-1].str[0] != '\0') {
-      strcpy(msg_stack[msg_max-i].str, msg_stack[msg_max-i-1].str);
-      msg_stack[msg_max-i].t = msg_stack[msg_max-i-1].t;
-    }
-  }
-  /* Add the new one. */
-  va_start(ap, fmt);
-  vsprintf(msg_stack[0].str, fmt, ap);
-  va_end(ap);
-
-  msg_stack[0].t = msg_timeout;
-}
-
 /**
  * @brief Warp the player to the new position.
  *    @param x X value of the position to warp to.
@@ -806,983 +643,29 @@ int player_cargoOwned(const char* commodityname) {
   return 0;
 }
 
-/**
- * @brief Render the background player stuff, namely planet target gfx.
- */
-void player_renderBG(void) {
-  double x, y;
-  glColour* c;
-  Planet* planet;
-
-  if(player_isFlag(PLAYER_DESTROYED) || player_isFlag(PLAYER_CREATING) ||
-      pilot_isFlag(player, PLAYER_DESTROYED)) return;
-
-  if(planet_target >= 0) {
-    planet = cur_system->planets[planet_target];
-
-    c = faction_getColour(planet->faction);
-
-    x = planet->pos.x - planet->gfx_space->sw/2.;
-    y = planet->pos.y + planet->gfx_space->sh/2.;
-    gl_blitSprite(gui.gfx_targetPlanet, x, y, 0, 0, c); /* Top left. */
-
-    x += planet->gfx_space->sw;
-    gl_blitSprite(gui.gfx_targetPlanet, x, y, 1, 0, c); /* Top right. */
-
-    y -= planet->gfx_space->sh;
-    gl_blitSprite(gui.gfx_targetPlanet, x, y, 1, 1, c); /* Bottom right. */
-
-    x -= planet->gfx_space->sw;
-    gl_blitSprite(gui.gfx_targetPlanet, x, y, 0, 1, c); /* Bottom left. */
-  }
-}
-
 /**
  * @brief Render the player.
  */
-void player_render(void) {
-  Pilot* p;
-  glColour* c;
-  double x, y;
-
-  if((player != NULL) && !player_isFlag(PLAYER_CREATING)) {
-    /* Render the player target graphics. */
-    if(player->target != PLAYER_ID) p = pilot_get(player->target);
-    else p = NULL;
-    if((p == NULL) || pilot_isFlag(p, PILOT_DEAD))
-      player->target = PLAYER_ID; /* No more pilot target. */
-    else {
-      /* There is still a pilot target. */
-      if(pilot_isDisabled(p)) c = &cInert;
-      else if(pilot_isFlag(p, PILOT_BRIBED)) c = &cNeutral;
-      else if(pilot_isFlag(p, PILOT_HOSTILE)) c = &cHostile;
-      else c = faction_getColour(p->faction);
-
-      x = p->solid->pos.x - p->ship->gfx_space->sw * PILOT_SIZE_APROX/2.;
-      y = p->solid->pos.y + p->ship->gfx_space->sh * PILOT_SIZE_APROX/2.;
-      gl_blitSprite(gui.gfx_targetPilot, x, y, 0, 0, c); /* Top left. */
-
-      x += p->ship->gfx_space->sw * PILOT_SIZE_APROX;
-      gl_blitSprite(gui.gfx_targetPilot, x, y, 1, 0, c); /* Top right. */
-
-      y -= p->ship->gfx_space->sh * PILOT_SIZE_APROX;
-      gl_blitSprite(gui.gfx_targetPilot, x, y, 1, 1, c); /* Bottom right. */
-
-      x -= p->ship->gfx_space->sw * PILOT_SIZE_APROX;
-      gl_blitSprite(gui.gfx_targetPilot, x, y, 0, 1, c); /* Bottom left. */
+void player_render(double dt) {
+  /* Check to see if the death menu should pop up. */
+  if(player_isFlag(PLAYER_DESTROYED)) {
+    player_timer -= dt;
+    if(!toolkit && !player_isFlag(PLAYER_CREATING) &&
+        (player_timer < 0.)) {
+      menu_death();
     }
+  }
+
+  /* Render the player. */
+  if((player != NULL) && !player_isFlag(PLAYER_CREATING)) {
+    /* Render players target first. */
+    gui_renderTarget(dt);
 
     /* Player is ontop of targeting graphic. */
     pilot_render(player);
   }
 }
 
-static int can_jump = 0; /**< Store whether or not the player is able to jump. */
-/**
- * @brief Render the players GUI.
- */
-void player_renderGUI(double dt) {
-  int i, j;
-  double x;
-  char str[10];
-  Pilot* p;
-  glColour* c;
-  glFont* f;
-  StarSystem* sys;
-  int quantity, delay;
-
-  /* If player is dead, just render the cinematic mode. */
-  if(player_isFlag(PLAYER_DESTROYED) || player_isFlag(PLAYER_CREATING) ||
-      ((player != NULL) && pilot_isFlag(player, PILOT_DEAD))) {
-
-    if(player_isFlag(PLAYER_DESTROYED)) {
-      player_timer -= dt;
-      if(!toolkit && !player_isFlag(PLAYER_CREATING) &&
-          (player_timer < 0.)) {
-        menu_death();
-      }
-    }
-    /* Fancy cinematic scene borders. */
-    spfx_cinematic();
-
-    return;
-  }
-
-  if(player == NULL) return;
-
-  /* Lockon warning. */
-  if(player->lockons > 0)
-    gl_printMid(NULL, SCREEN_W - gui_xoff, 0., SCREEN_H-gl_defFont.h-25.,
-        &cRed, "LOCKON DETECTED");
-
-  /* Volatile Environment. */
-  if(cur_system->nebu_volatility > 0.)
-    gl_printMid(NULL, SCREEN_W - gui_xoff, 0., SCREEN_H-gl_defFont.h*2.-35.,
-        &cRed, "VOLATILE ENVIRONMENT DETECTED");
-
-  /* GUI! */
-  /* -- Frame. */
-  gl_blitStatic(gui.gfx_frame, gui.frame.x, gui.frame.y, NULL);
-  /* -- Radar. */
-  glMatrixMode(GL_PROJECTION);
-  glPushMatrix();
-  if(gui.radar.shape == RADAR_RECT)
-    glTranslated(gui.radar.x - SCREEN_W/2. + gui.radar.w/2.,
-                 gui.radar.y - SCREEN_H/2. - gui.radar.h/2., 0.);
-  else if(gui.radar.shape == RADAR_CIRCLE)
-    glTranslated(gui.radar.x - SCREEN_W/2.,
-                 gui.radar.y - SCREEN_H/2., 0.);
-
-  /* Planets. */
-  planets_minimap(gui.radar.res, gui.radar.w, gui.radar.h,
-      gui.radar.shape, 1.-interference_alpha);
-
-  /* Weapons. */
-  weapon_minimap(gui.radar.res, gui.radar.w, gui.radar.h,
-      gui.radar.shape, 1.-interference_alpha);
-
-  /* Render the pilot_nstack. */
-  j = 0;
-  for(i = 1; i < pilot_nstack; i++) { /* Skip the player. */
-    if(pilot_stack[i]->id == player->target)
-      j = i;
-    else
-      gui_renderPilot(pilot_stack[i]);
-  }
-  /* Render the targetted pilot. */
-  if(j != 0) gui_renderPilot(pilot_stack[j]);
-
-  glPopMatrix();
-
-  /* Interference. */
-  gui_renderInterference(dt);
-
-  glPushMatrix();
-  if(gui.radar.shape == RADAR_RECT)
-    glTranslated(gui.radar.x - SCREEN_W/2. + gui.radar.w/2.,
-        gui.radar.y - SCREEN_H/2. - gui.radar.h/2., 0.);
-  else if(gui.radar.shape == RADAR_CIRCLE)
-    glTranslated(gui.radar.x - SCREEN_W/2.,
-        gui.radar.y - SCREEN_H/2., 0.);
-
-  /* The + sign in the middle of the radar represents the player. */
-  glBegin(GL_LINES);
-    COLOUR(cRadar_player);
-    glVertex2d( 0., -3.);
-    glVertex2d( 0.,  3.);
-    glVertex2d(-3.,  0.);
-    glVertex2d( 3.,  0.);
-  glEnd();
-
-  glPopMatrix(); /* GL_PROJECTION. */
-
-  /* Nav. */
-  if(planet_target >= 0) {
-    /* Planet landing target. */
-    gl_printMid(NULL, (int)gui.nav.w,
-                gui.nav.x, gui.nav.y - 5, &cConsole, "Land");
-
-    gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x,
-                gui.nav.y - 10 - gl_smallFont.h,  NULL, "%s",
-                cur_system->planets[planet_target]->name);
-  }
-  else if(hyperspace_target >= 0) {
-    /* Hyperspace target. */
-    sys = &systems_stack[cur_system->jumps[hyperspace_target]];
-
-    /* Determine if we have to play the "enter hyperspace range" sound. */
-    i = space_canHyperspace(player);
-    if((i != 0) && (i != can_jump))
-      if(!pilot_isFlag(player, PILOT_HYPERSPACE))
-        player_playSound(snd_jump, 1);
-    can_jump = i;
-
-    /* Determine the colour of the NAV text. */
-    if(can_jump || pilot_isFlag(player, PILOT_HYPERSPACE) ||
-        pilot_isFlag(player, PILOT_HYP_PREP) ||
-        pilot_isFlag(player, PILOT_HYP_BEGIN))
-      c = &cConsole;
-    else c = NULL;
-    gl_printMid(NULL, (int)gui.nav.w, gui.nav.x, gui.nav.y - 5,
-                c, "Hyperspace");
-
-    gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x,
-                gui.nav.y - 10 - gl_smallFont.h,
-                NULL, "%d - %s", pilot_getJumps(player),
-                (sys_isKnown(sys)) ? sys->name : "Unknown");
-  }
-  else {
-    /* No NAV target. */
-    gl_printMid(NULL, (int)gui.nav.w, gui.nav.x,
-                gui.nav.y - 5, &cConsole, "Navigation");
-    gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x,
-                gui.nav.y - 10 - gl_smallFont.h, &cGrey, "Off");
-  }
-
-  /* Health */
-  gui_renderHealth(&cShield, &gui.shield, gui.gfx_shield, player->shield / player->shield_max);
-  gui_renderHealth(&cArmour, &gui.armour, gui.gfx_armour, player->armour / player->armour_max);
-  gui_renderHealth(&cEnergy, &gui.energy, gui.gfx_energy, player->energy / player->energy_max);
-  gui_renderHealth(&cFuel,   &gui.fuel,   gui.gfx_fuel,   player->fuel   / player->fuel_max);
-
-  /* Weapon. */
-  if(player->secondary == NULL) {
-    gl_printMid(NULL, (int)gui.weapon.w, gui.weapon.x,
-                gui.weapon.y - 5, &cConsole, "Secondary");
-    gl_printMid(&gl_smallFont, (int)gui.weapon.w,  gui.weapon.x,
-                gui.weapon.y - 10 - gl_defFont.h, &cGrey, "None");
-  } else {
-    f = &gl_defFont;
-    
-    quantity = pilot_oquantity(player, player->secondary);
-    delay = outfit_delay(player->secondary->outfit);
-
-    /* Check to see if weapon is ready. */
-    if(player->secondary->timer > 0.)
-      c = &cGrey;
-    else
-      c = &cConsole;
-
-    /* Launcher. */
-    if(player->ammo != NULL) {
-      /* Use the ammunitions name. */
-      i = gl_printWidth(f, "%s", outfit_ammo(player->secondary->outfit)->name);
-      if(i > gui.weapon.w)
-        /* Font is too big. */
-        f = &gl_smallFont;
-
-      /* Weapon name. */
-      gl_printMid(f, (int)gui.weapon.w, gui.weapon.x,
-                  gui.weapon.y - 5,
-                  (player->ammo) ? c : &cGrey, "%s",
-                  outfit_ammo(player->secondary->outfit)->name);
-
-      /* Print ammo underneath to the left. */
-      gl_printMid(&gl_smallFont, (int)gui.weapon.w, gui.weapon.x,
-                  gui.weapon.y - 10 - gl_defFont.h,
-                  NULL, "%d", (player->ammo) ? player->ammo->quantity : 0);
-      /* Other. */
-    } else {
-      /* Just print the item name. */
-      i = gl_printWidth(f, "%s", player->secondary->outfit->name);
-      if(i > (int)gui.weapon.w)
-        /* Font is too big. */
-        f = &gl_smallFont;
-      gl_printMid(f, (int)gui.weapon.w,
-                  gui.weapon.x, gui.weapon.y - (gui.weapon.h - f->h)/2.,
-                  c, "%s", player->secondary->outfit->name);
-    }
-  }
-
-  /* Target. */
-  if(player->target != PLAYER_ID) {
-    p = pilot_get(player->target);
-
-    /* Blit the pilot target. */
-    gl_blitStatic(p->ship->gfx_target, gui.target.x, gui.target.y, NULL);
-    /* Blit the pilot space image. */
-    /*x = gui.target.x + (TARGET_WIDTH - p->ship->gfx_space->sw)/2.;
-    y = gui.target.y + (TARGET_HEIGHT - p->ship->gfx_space->sh)/2.;
-    gl_blitStaticSprite(p->ship->gfx_space,
-        x, y, p->tsx, p->tsy, NULL);*/
-
-    /* Target name. */
-    gl_print(NULL, gui.target_name.x, gui.target_name.y,
-             NULL, "%s", p->name);
-    gl_print(&gl_smallFont, gui.target_faction.x, gui.target_faction.y,
-             NULL, "%s", faction_name(p->faction));
-
-    /* Target status. */
-    if(pilot_isDisabled(p))
-      /* Disable the pilot. */
-      gl_print(&gl_smallFont, gui.target_health.x, gui.target_health.y,
-               NULL, "Disabled");
-    else if(p->shield > p->shield_max / 100.)
-      /* On shields. */
-      gl_print(&gl_smallFont, gui.target_health.x, gui.target_health.y,
-               NULL, "%s: %.0f%%", "Shield", p->shield/p->shield_max*100.);
-    else
-      /* On armour. */
-      gl_print(&gl_smallFont, gui.target_health.x, gui.target_health.y,
-               NULL, "%s: %.0f%%", "Armor", p->armour/p->armour_max*100.);
-  } else {
-    /* No target. */
-    gl_printMid(NULL, SHIP_TARGET_W, gui.target.x,
-                gui.target.y + (SHIP_TARGET_H - gl_defFont.h)/2.,
-                &cGrey80, "No Target");
-  }
-
-  /* Misc. */
-  j = gui.misc.y - 8 - gl_smallFont.h;
-  gl_print(NULL, gui.misc.x + 8, j,
-           &cConsole, "SCreds:");
-
-  credits2str(str, player->credits, 2);
-
-  i = gl_printWidth(&gl_smallFont, str);
-  gl_print(&gl_smallFont, gui.misc.x + gui.misc.w - 8 - i, j,
-           NULL, str);
-
-  /* Cargo and co. */
-  if(player->ncommodities > 0) {
-    j -= gl_smallFont.h + 5;
-    gl_print(&gl_smallFont,
-             gui.misc.x + 8, j, &cConsole, "Cargo");
-
-    for(i = 0; i < MIN(player->ncommodities,3); i++) {
-      j -= gl_smallFont.h + 3;
-      if(player->commodities[i].quantity) /* Quantity is over. */
-        gl_printMax(&gl_smallFont, gui.misc.w - 15,
-                gui.misc.x + 13, j,
-                NULL, "%d %s%s", player->commodities[i].quantity,
-                player->commodities[i].commodity->name,
-                (player->commodities[i].id) ? "*" : "");
-      else /* Basically for weightless mission stuff. */
-        gl_printMax(&gl_smallFont, gui.misc.w - 15,
-            gui.misc.x + 13, j,
-            NULL, "%s%s", player->commodities[i].commodity->name,
-            (player->commodities[i].id) ? "*" : "");
-    }
-  }
-
-  j -= gl_smallFont.h + 5;
-  gl_print(&gl_smallFont,
-           gui.misc.x + 8, j, &cConsole, "Free:");
-
-  i = gl_printWidth(&gl_smallFont, "%d", pilot_cargoFree(player));
-  gl_print(&gl_smallFont,
-           gui.misc.x + gui.misc.w - 8 - i, j,
-           NULL, "%d", pilot_cargoFree(player));
-
-  /* Messages. */
-  gui_renderMessages(dt);
-
-  /* Hyperspace FLASH BANG!!! */
-  if(pilot_isFlag(player, PILOT_HYPERSPACE) &&
-      (player->ptimer < HYPERSPACE_FADEOUT)) {
-    if(i < j) {
-      x = (HYPERSPACE_FADEOUT-player->ptimer) / HYPERSPACE_FADEOUT;
-      glColor4d(1.,1.,1., x); /* We'll | I'll, make this more effiecent later. */
-      glBegin(GL_QUADS);
-      glVertex2d(-SCREEN_W/2., -SCREEN_H/2.);
-      glVertex2d(-SCREEN_W/2.,  SCREEN_H/2.);
-      glVertex2d( SCREEN_W/2.,  SCREEN_H/2.);
-      glVertex2d( SCREEN_W/2., -SCREEN_H/2.);
-      glEnd();
-    }
-  }
-}
-
-/**
- * @brief Renders the players messages on screen.
- *    @param dt Current delta tick.
- */
-static void gui_renderMessages(double dt) {
-  double x, y;
-  glColour c;
-  int i;
-
-  x = gui.msg.x;
-  y = gui.msg.y + (double)(gl_defFont.h*msg_max)*1.2;
-  c.r = c.g = c.b = 1.;
-
-  for(i = msg_max-1; i >= 0; i--) {
-    y -= (double)gl_defFont.h*1.2;
-
-    /* Only handle non-NULL messages. */
-    if(msg_stack[i].str[0] != '\0') {
-      /* Decrement timer. */
-      msg_stack[i].t -= dt;
-
-      /* Set to NULL if timer is up. */
-      if(msg_stack[i].t < 0.)
-        msg_stack[i]..str[0] = '\0';
-
-      /* Draw with variable alpha. */
-      else {
-        if(msg_stack[i].t - msg_timeout/2 < 0.)
-          c.a = msg_stack[i].t / (msg_timeout/2.);
-        else
-          c.a = 1.;
-        gl_print(NULL, x, y, &c, "%s", msg_stack[i].str);
-      }
-    }
-  }
-}
-
-/**
- * @brief Render interference if needed.
- *    @param dt Current deltatick.
- */
-static void gui_renderInterference(double dt) {
-  glColour c;
-  glTexture* tex;
-  int t;
-
-  /* Must be displaying inteference. */
-  if(interference_alpha <= 0.)
-    return;
-
-  /* Calculate frame to draw. */
-  interference_t += dt;
-  if(interference_t > INTERFERENCE_CHANGE_DT) { /* Time to change. */
-    t = RNG(0, INTERFERENCE_LAYERS-1);
-    if(t != interference_layer)
-      interference_layer = t;
-    else
-      interference_layer = (interference_layer == INTERFERENCE_LAYERS-1) ?
-        0 : interference_layer+1;
-    interference_t -= INTERFERENCE_CHANGE_DT;
-  }
-
-  /* Render the interference. */
-  c.r = c.g = c.b = 1.;
-  c.a = interference_alpha;
-  tex = gui.radar.interference[interference_layer];
-  if(gui.radar.shape == RADAR_CIRCLE)
-    gl_blitStatic(tex,
-        gui.radar.x - gui.radar.w,
-        gui.radar.y - gui.radar.w, &c);
-  else if(gui.radar.shape == RADAR_RECT)
-    gl_blitStatic(tex,
-        gui.radar.x - gui.radar.w / 2,
-        gui.radar.y - gui.radar.h/2, &c);
-}
-
-/* Renders a pilot. */
-static void gui_renderPilot(const Pilot* p) {
-  int x, y, sx, sy;
-  double w, h;
-  glColour* col;
-  double a;
-
-  /* Get position. */
-  x = (p->solid->pos.x - player->solid->pos.x) / gui.radar.res;
-  y = (p->solid->pos.y - player->solid->pos.y) / gui.radar.res;
-  /* Get size. */
-  sx = PILOT_SIZE_APROX/2. * p->ship->gfx_space->sw / gui.radar.res;
-  sy = PILOT_SIZE_APROX/2. * p->ship->gfx_space->sh / gui.radar.res;
-  if(sx < 1.) sx = 1.;
-  if(sy < 1.) sy = 1.;
-
-  /* Check if pilot in range. */
-  if(((gui.radar.shape == RADAR_RECT) && ((ABS(x) > gui.radar.w/2.+sx)
-          || (ABS(y) > gui.radar.h/2.+sy))) ||
-          ((gui.radar.shape == RADAR_CIRCLE) &&
-          ((x*x + y*y) > (int)(gui.radar.w*gui.radar.w)))) {
-
-    /* Draw a little targetted symbol. */
-    if(p->id == player->target) {
-      /* Circle radars have it easy. */
-      if(gui.radar.shape == RADAR_CIRCLE) {
-        /* We'll create a line. */
-        a = ANGLE(x, y);
-        x = gui.radar.w*cos(a);
-        y = gui.radar.w*sin(a);
-        sx = 0.85 * x;
-        sy = 0.85 * y;
-
-        COLOUR(cRadar_tPilot);
-        glBegin(GL_LINES);
-          glVertex2d(x, y);
-          glVertex2d(sx, sy);
-        glEnd();
-      }
-    }
-    return;
-  }
-
-  if(gui.radar.shape == RADAR_RECT) {
-    w = gui.radar.w/2.;
-    h = gui.radar.h/2.;
-  }
-  else if(gui.radar.shape == RADAR_CIRCLE) {
-    w = gui.radar.w;
-    h = gui.radar.w;
-  }
-
-  glBegin(GL_QUADS);
-    /* Colours. */
-    if(p->id == player->target) col = &cRadar_tPilot;
-    else if(pilot_isDisabled(p)) col = &cInert;
-    else if(pilot_isFlag(p, PILOT_BRIBED)) col = &cNeutral;
-    else if(pilot_isFlag(p, PILOT_HOSTILE)) col = &cHostile;
-    else col = faction_getColour(p->faction);
-    ACOLOUR(*col, 1-interference_alpha); /**< Makes it much harder to see. */
-
-    /* Image. */
-    glVertex2d(MAX(x-sx, -w), MIN(y+sy,  h)); /* Top left. */
-    glVertex2d(MIN(x+sx,  w), MIN(y+sy,  h)); /* Top right. */
-    glVertex2d(MIN(x+sx,  w), MAX(y-sy, -h)); /* Bottom right. */
-    glVertex2d(MAX(x-sx, -w), MAX(y-sy, -h)); /* Bottom left. */
-  glEnd();
-}
-
-/**
- * @brief Render a health bar.
- */
-static void gui_renderHealth(const glColour* c, const Rect* r, const glTexture* tex,
-    const double w) {
-  
-  double x, y, sx, sy, tx, ty;
-
-  /* Set colour. */
-  COLOUR(*c);
-
-  /* Just create a bar. */
-  if(tex == NULL) {
-    /* Set the position values. */
-    x = r->x - SCREEN_W/2.;
-    y = r->y - SCREEN_H/2.;
-    sx = w * r->w;
-    sy = r->h;
-
-    glBegin(GL_QUADS);
-      glVertex2d(x, y);
-      glVertex2d(x+sx, y);
-      glVertex2d(x+sx, y-sy);
-      glVertex2d(x, y-sy);
-    glEnd();
-  } else { /* Render the texture. */
-    /* Set the position values. */
-    x = r->x - SCREEN_W/2.;
-    y = r->y - SCREEN_H/2. + tex->sh;
-    sx = w * tex->sw;
-    sy = tex->sh;
-    tx = tex->sw / tex->rw;
-    ty = tex->sh / tex->rh;
-
-    /* Draw the image. */
-    glEnable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, tex->texture);
-    glBegin(GL_QUADS);
-      COLOUR(*c);
-      glTexCoord2d(0., ty);
-      glVertex2d(x, y);
-
-      glTexCoord2d(w*tx, ty);
-      glVertex2d(x + sx, y);
-
-      glTexCoord2d(w*tx, 0.);
-      glVertex2d(x+sx, y - sy);
-
-      glTexCoord2d(0., 0.);
-      glVertex2d(x, y - sy);
-    glEnd();
-    glDisable(GL_TEXTURE_2D);
-  }
-}
-
-/**
- * @brief Initialize the GUI system.
- *    @return 0 on success.
- */
-int gui_init(void) {
-  /* Set graphics to NULL. */
-  memset(&gui, 0, sizeof(GUI));
-
-  /* -- Radar. */
-  gui.radar.res = RADAR_RES_DEFAULT;
-  /* -- messages. */
-  gui.msg.x = 20;
-  gui.msg.y = 30;
-  msg_stack = calloc(msg_max, sizeof(Msg));
-
-  if(msg_stack == NULL) {
-    ERR("Out of memory!");
-    return -1;
-  }
-
-  return 0;
-}
-
-/**
- * @brief Attempt to load the actual GUI.
- *    @brief name Name of the GUI to load.
- *    @brief 0 on success.
- */
-int gui_load(const char* name) {
-  uint32_t bufsize;
-  char* buf = ldata_read(GUI_DATA, &bufsize);
-  char* tmp;
-  int found = 0;
-
-  xmlNodePtr node;
-  xmlDocPtr doc = xmlParseMemory(buf, bufsize);
-
-  node = doc->xmlChildrenNode;
-  if(!xml_isNode(node, XML_GUI_ID)) {
-    ERR("Malformed '"GUI_DATA"' file: missing root element '"XML_GUI_ID"'");
-    return -1;
-  }
-
-  node = node->xmlChildrenNode; /* First system node. */
-  if(node == NULL) {
-    ERR("Malformed '"GUI_DATA"' file: does not contain elements");
-    return -1;
-  }
-
-  do {
-    if(xml_isNode(node, XML_GUI_TAG)) {
-      tmp = xml_nodeProp(node, "name"); /* Mallocs. */
-
-      /* Is this the gui we are looking for? */
-      if(strcmp(tmp, name)==0) {
-        found = 1;
-
-        /* Parse the xml node. */
-        if(gui_parse(node, name)) WARN("Trouble loading GUI '%s'", name);
-        free(tmp);
-        break;
-      }
-      free(tmp);
-    }
-  } while((node = node->next));
-
-  xmlFreeDoc(doc);
-  free(buf);
-
-  if(!found) {
-    WARN("GUI '%s' not found in '"GUI_DATA"'",name);
-    return -1;
-  }
-  return 0;
-}
-
-/**
- * @brief Parse a parameter of the rect node.
- */
-static void rect_parseParam(const xmlNodePtr parent, char* name, double* param) {
-  char* buf;
-
-  /* Get the attribute. */
-  xmlr_attr(parent, name, buf);
-
-  /* Wants attribute. */
-  if(param != NULL) {
-    if(buf == NULL)
-      WARN("Node '%s' missing 'x' parameter.", parent->name);
-    else if(buf != NULL)
-      *param = atoi(buf);
-  }
-  /* Doesn't want it. */
-  else if(buf != NULL)
-    WARN("Node '%s' has superfluous 'x' parameter.", parent->name);
-
-  /* Clean up. */
-  if(buf != NULL)
-    free(buf);
-}
-
-/**
- * @brief Used to pull out a rect from an xml node.
- */
-static void rect_parse(const xmlNodePtr parent,
-    double* x, double* y, double* w, double* h) {
-  rect_parseParam(parent, "w", w);
-  rect_parseParam(parent, "h", h);
-  rect_parseParam(parent, "x", x);
-  rect_parseParam(parent, "y", y);
-}
-
-/**
- * @brief Create the interference map for the current gui.
- */
-static void gui_createInterference(void) {
-  uint8_t raw;
-  int i, j, k;
-  float* map;
-  uint32_t* pix;
-  SDL_Surface* sur;
-  int w, h, hw, hh;
-  float c;
-  int r;
-
-  /* Dimension shortcuts. */
-  if(gui.radar.shape == RADAR_CIRCLE) {
-    w = gui.radar.w*2.;
-    h = w;
-  }
-  else if(gui.radar.shape == RADAR_RECT) {
-    w = gui.radar.w;
-    h = gui.radar.h;
-  }
-
-  for(k = 0; k < INTERFERENCE_LAYERS; k++) {
-    /* Free the old texture. */
-    if(gui.radar.interference[k] != NULL)
-      gl_freeTexture(gui.radar.interference[k]);
-
-    /* Create the temp surface. */
-    sur = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RGBAMASK);
-    pix = sur->pixels;
-
-    /* Load the interference map. */
-    map = noise_genRadarInt(w, h, 100.);
-
-    /* Create the texture. */
-    SDL_LockSurface(sur);
-    if(gui.radar.shape == RADAR_CIRCLE) {
-      r = pow2((int)gui.radar.w);
-      hw = w/2;
-      hh = h/2;
-      for(i = 0; i < h; i++) {
-        for(j = 0; j < w; j++) {
-          /* Must be in circle. */
-          if(pow2(i-hh) + pow2(j-hw) > r)
-            continue;
-          c = map[i*w + j];
-          raw = 0xff & (uint8_t)((float)0xff * c);
-          memset(&pix[i*w + j], raw, sizeof(uint32_t));
-          pix[i*w + j] |= AMASK;
-        }
-      }
-    }
-    else if(gui.radar.shape == RADAR_RECT) {
-      for(i = 0; i < h*w; i++) {
-        /* Process pixels. */
-        c = map[i];
-        raw = 0xff & (uint8_t)((float)0xff * c);
-        memset(&pix[i], raw, sizeof(uint32_t));
-        pix[i] |= AMASK;
-      }    
-    }
-    SDL_UnlockSurface(sur);
-
-    /* Set the interference. */
-    gui.radar.interference[k] = gl_loadImage(sur);
-
-    /* Clean up. */
-    free(map);
-  }
-}
-
-#define RELATIVIZE(a) \
-{ (a).x += VX(gui.frame); (a).y = VY(gui.frame) + gui.gfx_frame->h-(a).y; }
-/**< Converts a rect to absolute coords. */
-
-/**
- * @brief Parses a gui node.
- *    @param parent Node to parse from.
- *    @param name Name of the GUI to load.
- */
-static int gui_parse(const xmlNodePtr parent, const char* name) {
-  xmlNodePtr cur, node;
-  char* tmp, buf[PATH_MAX];
-
-  /* Clean up. */
-  gui_cleanup();
-
-  /* Gfx. */
-  /* Set a property and not a node because it must be loaded first. */
-  tmp = xml_nodeProp(parent, "gfx");
-  if(tmp == NULL) {
-    ERR("GUI '%s' has no gfx property", name);
-    return -1;
-  }
-  
-  /* Load gfx. */
-  /* Frame. */
-  snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
-  gui.gfx_frame = gl_newImage(buf, 0);
-  /* Pilot. */
-  snprintf(buf, PATH_MAX, GUI_GFX"%s_pilot.png", tmp);
-  gui.gfx_targetPilot = gl_newSprite(buf, 2, 2, 0);
-  /* Planet. */
-  snprintf(buf, PATH_MAX, GUI_GFX"%s_planet.png", tmp);
-  gui.gfx_targetPlanet = gl_newSprite(buf, 2, 2, 0);
-  free(tmp);
-
-  /* Frame (based on gfx). */
-  vect_csetmin(&gui.frame,
-               SCREEN_W - gui.gfx_frame->w,  /* x. */
-               SCREEN_H - gui.gfx_frame->h); /* h. */
-
-  /* Let's parse the data now. */
-  node = parent->children;
-  do {
-    /* Offset. */
-    if(xml_isNode(node, "offset"))
-      rect_parse(node, &gui_xoff, &gui_yoff, NULL, NULL);
-    /* Radar. */
-    else if(xml_isNode(node, "radar")) {
-      tmp = xml_nodeProp(node,"type");
-      /* Make sure type is valid. */
-      if(strcmp(tmp, "rectangle")==0) gui.radar.shape = RADAR_RECT;
-      else if(strcmp(tmp, "circle")==0) gui.radar.shape = RADAR_CIRCLE;
-      else {
-        WARN("Radar for GUI '%s' is missing 'type' tag or has invalid 'type' tag", name);
-        gui.radar.shape = RADAR_RECT;
-      }
-      free(tmp);
-
-      /* Load the appropriate measurements. */
-      if(gui.radar.shape == RADAR_RECT)
-        rect_parse(node, &gui.radar.x, &gui.radar.y, &gui.radar.w, &gui.radar.h);
-      else if(gui.radar.shape == RADAR_CIRCLE)
-        rect_parse(node, &gui.radar.x, &gui.radar.y, &gui.radar.w, NULL);
-      RELATIVIZE(gui.radar);
-    }
-    /* Nav computer. */
-    else if(xml_isNode(node, "nav")) {
-      rect_parse(node, &gui.nav.x, &gui.nav.y, &gui.nav.w, &gui.nav.h);
-      RELATIVIZE(gui.nav);
-      gui.nav.y -= gl_defFont.h;
-    }
-    /* Health bars. */
-    else if(xml_isNode(node, "health")) {
-      cur = node->children;
-      do {
-        if(xml_isNode(cur, "shield")) {
-          rect_parse(cur, &gui.shield.x, &gui.shield.y,
-                     &gui.shield.w, &gui.shield.h);
-          tmp = xml_get(cur);
-          if(tmp != NULL) {
-            snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
-            gui.gfx_shield = gl_newImage(buf, 0);
-          }
-          RELATIVIZE(gui.shield);
-        }
-
-        if(xml_isNode(cur, "armour")) {
-          rect_parse(cur, &gui.armour.x, &gui.armour.y,
-                     &gui.armour.w, &gui.armour.h);
-          tmp = xml_get(cur);
-          if(tmp != NULL) {
-            snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
-            gui.gfx_armour = gl_newImage(buf, 0);
-          }
-          RELATIVIZE(gui.armour);
-        }
-
-        if(xml_isNode(cur, "energy")) {
-          rect_parse(cur, &gui.energy.x, &gui.energy.y,
-                     &gui.energy.w, &gui.energy.h);
-          tmp = xml_get(cur);
-          if(tmp != NULL) {
-            snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
-            gui.gfx_energy = gl_newImage(buf, 0);
-          }
-          RELATIVIZE(gui.energy);
-        }
-        if(xml_isNode(cur, "fuel")) {
-          rect_parse(cur, &gui.fuel.x, &gui.fuel.y,
-              &gui.fuel.w, &gui.fuel.h);
-          tmp = xml_get(cur);
-          if(tmp != NULL) {
-            snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp);
-            gui.gfx_fuel = gl_newImage(buf, 0);
-          }
-          RELATIVIZE(gui.fuel);
-        }
-      } while((cur = cur->next));
-    }
-    /* Secondary weapon. */
-    else if(xml_isNode(node, "weapon")) {
-      rect_parse(node, &gui.weapon.x, &gui.weapon.y,
-                 &gui.weapon.w, &gui.weapon.h);
-      RELATIVIZE(gui.weapon);
-      gui.weapon.y -= gl_defFont.h;
-    }
-    /* Target. */
-    else if(xml_isNode(node, "target")) {
-      cur = node->children;
-      do {
-        if(xml_isNode(cur, "gfx")) {
-          rect_parse(cur, &gui.target.x, &gui.target.y, NULL, NULL);
-          RELATIVIZE(gui.target);
-          gui.target.y -= SHIP_TARGET_H;
-        }
-
-        if(xml_isNode(cur, "name")) {
-          rect_parse(cur, &gui.target_name.x, &gui.target_name.y, NULL, NULL);
-          RELATIVIZE(gui.target_name);
-          gui.target_name.y -= gl_defFont.h;
-        }
-
-        if(xml_isNode(cur, "faction")) {
-          rect_parse(cur, &gui.target_faction.x, &gui.target_faction.y,
-                     NULL, NULL);
-          RELATIVIZE(gui.target_faction);
-          gui.target_faction.y -= gl_smallFont.h;
-        }
-
-        if(xml_isNode(cur, "health")) {
-          rect_parse(cur, &gui.target_health.x, &gui.target_health.y,
-                     NULL, NULL);
-          RELATIVIZE(gui.target_health);
-          gui.target_health.y -= gl_smallFont.h;
-        }
-      } while((cur = cur->next));
-    } else if(xml_isNode(node, "misc")) {
-      rect_parse(node, &gui.misc.x, &gui.misc.y, &gui.misc.w, &gui.misc.h);
-      RELATIVIZE(gui.misc);
-    }
-  } while(xml_nextNode(node));
-
-  /* Some postprocessing. */
-  gui_createInterference();
-
-  return 0;
-}
-#undef RELATIVIZE
-
-/**
- * @brief Clean up the GUI.
- */
-static void gui_cleanup(void) {
-  int i;
-
-  /* Free textures. */
-  if(gui.gfx_frame != NULL) {
-    gl_freeTexture(gui.gfx_frame);
-    gui.gfx_frame = NULL;
-  }
-  if(gui.gfx_targetPilot != NULL) {
-    gl_freeTexture(gui.gfx_targetPilot);
-    gui.gfx_targetPilot = NULL;
-  }
-  if(gui.gfx_targetPlanet != NULL) {
-    gl_freeTexture(gui.gfx_targetPlanet);
-    gui.gfx_targetPlanet = NULL;
-  }
-  /* Health textures. */
-  if(gui.gfx_shield != NULL) {
-    gl_freeTexture(gui.gfx_shield);
-    gui.gfx_shield = NULL;
-  }
-  if(gui.gfx_armour != NULL) {
-    gl_freeTexture(gui.gfx_armour);
-    gui.gfx_armour = NULL;
-  }
-  if(gui.gfx_energy != NULL) {
-    gl_freeTexture(gui.gfx_energy);
-    gui.gfx_energy = NULL;
-  }
-  if(gui.gfx_fuel != NULL) {
-    gl_freeTexture(gui.gfx_fuel);
-    gui.gfx_fuel = NULL;
-  }
-
-  for(i = 0; i < INTERFERENCE_LAYERS; i++) {
-    if(gui.radar.interference[i] != NULL) {
-      gl_freeTexture(gui.radar.interference[i]);
-      gui.radar.interference[i] = NULL;
-    }
-  }
-}
-
-/**
- * @brief Free the GUI.
- */
-void gui_free(void) {
-  /* Clean up gui. */
-  gui_cleanup();
-
-  /* Free messages. */
-  free(msg_stack);
-}
-
 /**
  * @brief Start autonav.
  */
@@ -1950,18 +833,6 @@ void player_think(Pilot* pplayer) {
 /*
  * For use in keybindings.
  */
-/**
- * @brief Modify the radar resolution.
- *    @param mod Number of intervals to jump (up or down).
- */
-
-void player_setRadarRel(int mod) {
-  gui.radar.res += mod * RADAR_RES_INTERVAL;
-  if(gui.radar.res > RADAR_RES_MAX) gui.radar.res = RADAR_RES_MAX;
-  else if(gui.radar.res < RADAR_RES_MIN) gui.radar.res = RADAR_RES_MIN;
-
-  player_message("Radar set to %dx.", (int)gui.radar.res);
-}
 
 /**
  * @brief Get the next secondary weapon.
diff --git a/src/player.h b/src/player.h
index 7cb1fe2..257955a 100644
--- a/src/player.h
+++ b/src/player.h
@@ -28,10 +28,14 @@ extern unsigned int player_flags;   /**< Player's flags. */
 extern double player_crating;       /**< Player's combat rating. */
 extern int player_enemies;          /**< Amount of enemies player has. */
 
-/* Enums. */
+/* Targetting. */
+extern int planet_target;           /**< Targetted planet. -1 is none. */
+extern int hyperspace_target;       /**< Targetted hyperspace route. -1 is none. */
 
-/* For render functions. */
-typedef enum RadarShape_ { RADAR_RECT, RADAR_CIRCLE } RadarShape; /**< Player's radar shape. */
+/* Common player sounds. */
+extern int snd_target;              /**< Sound when targetting. */
+extern int snd_jump;                /**< Sound when can jump. */
+extern int snd_nav;                 /**< Sound when changing nav computer. */
 
 /* Creation/Cleanup. */
 void player_new(void);
@@ -41,11 +45,7 @@ void player_cleanup(void);
 int gui_load(const char* name);
 
 /* Render. */
-int gui_init(void);
-void gui_free(void);
-void player_render(void);
-void player_renderBG(void);   /* Render BG layer. */
-void player_renderGUI(double dt);  /* Render the GUI stuff. */
+void player_render(double dt);
 
 /* Misc. */
 void player_message(const char* fmt, ...);
@@ -85,7 +85,6 @@ void player_targetHostile(void);
 void player_targetNext(void);
 void player_targetPrev(void);
 void player_targetNearest(void);
-void player_setRadarRel(int mod);
 void player_secondaryNext(void);
 void player_secondaryPrev(void);
 void player_targetPlanet(void);
diff --git a/src/space.c b/src/space.c
index 0f12bb1..5f809c4 100644
--- a/src/space.c
+++ b/src/space.c
@@ -16,6 +16,7 @@
 #include "ltime.h"
 #include "nebulae.h"
 #include "music.h"
+#include "gui.h"
 #include "space.h"
 
 #define XML_PLANET_ID       "Planets"
@@ -80,12 +81,10 @@ static int nstars = 0;      /* Total stars. */
 static int mstars = 0;      /* Memory stars are taking. */
 
 /* Interference. */
-extern double interference_alpha;       /* player.c */
+extern double interference_alpha;       /* gui.c */
 static double interference_target;      /**< Target alpha level .*/
 static double interference_timer = 0.;  /**< Interference timer. */
 
-extern int planet_target;   /* player.c */
-
 /* Intern. */
 /* Planet load. */
 static int planet_parse(Planet* planet, const xmlNodePtr parent);
@@ -98,8 +97,6 @@ static void system_setFaction(StarSystem* sys);
 static void space_renderStars(const double dt);
 static void space_addFleet(Fleet* fleet, int init);
 static PlanetClass planetclass_get(const char a);
-/* Extern. */
-extern void player_message(const char* fmt, ...);
 
 void planets_minimap(const double res, const double w,
     const double h, const RadarShape shape, double alpha);
diff --git a/src/weapon.c b/src/weapon.c
index 96d7143..fac3872 100644
--- a/src/weapon.c
+++ b/src/weapon.c
@@ -22,6 +22,7 @@
 #include "spfx.h"
 #include "opengl.h"
 #include "explosion.h"
+#include "gui.h"
 #include "weapon.h"
 
 #define weapon_isSmart(w) (w->think != NULL) /**< Checks if the weapon w is smart. */