[Change] GUI's are now saved in XML and thrown into data pack file.
-- This allows for multiple gui's. -- Each ship can also have it's own gui if it so chooses.
This commit is contained in:
parent
e0f78e40a3
commit
e1b23f928b
48
dat/gui.xml
Normal file
48
dat/gui.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<GUIs>
|
||||
<gui name="simple" gfx="simple">
|
||||
<radar type="rectangle">
|
||||
<w>128</w>
|
||||
<h>128</h>
|
||||
<x>11</x>
|
||||
<y>10</y>
|
||||
</radar>
|
||||
<health>
|
||||
<shield>
|
||||
<w>129</w>
|
||||
<h>10</h>
|
||||
<x>10</x>
|
||||
<y>201</y>
|
||||
</shield>
|
||||
<armor>
|
||||
<w>129</w>
|
||||
<h>10</h>
|
||||
<x>10</x>
|
||||
<y>218</y>
|
||||
</armor>
|
||||
<energy>
|
||||
<w>129</w>
|
||||
<h>10</h>
|
||||
<x>10</x>
|
||||
<y>236</y>
|
||||
</energy>
|
||||
</health>
|
||||
<target>
|
||||
<gfx>
|
||||
<x>10</x>
|
||||
<y>256</y>
|
||||
</gfx>
|
||||
<name>
|
||||
<x>16</x>
|
||||
<y>261</y>
|
||||
</name>
|
||||
<faction>
|
||||
<x>16</x>
|
||||
<y>274</y>
|
||||
</faction>
|
||||
<health>
|
||||
<x>16</x>
|
||||
<y>334</y>
|
||||
</health>
|
||||
</target>
|
||||
</gui>
|
||||
</GUIs>
|
@ -2,6 +2,7 @@
|
||||
<Ships>
|
||||
<ship name="Merchant Ship">
|
||||
<GFX>ship</GFX>
|
||||
<GUI>simple</GUI>
|
||||
<class>1</class>
|
||||
<movement>
|
||||
<thrust>400</thrust>
|
||||
@ -28,6 +29,7 @@
|
||||
</ship>
|
||||
<ship name="Enemy Test">
|
||||
<GFX>ship1</GFX>
|
||||
<GUI>simple</GUI>
|
||||
<class>1</class>
|
||||
<movement>
|
||||
<thrust>180</thrust>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 181 B |
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 326 B |
@ -33,8 +33,9 @@ static int nfleets = 0;
|
||||
|
||||
// External.
|
||||
extern void ai_destroy(Pilot* p); // Ai.
|
||||
extern void player_think(Pilot* pilot); // Player.c
|
||||
extern void ai_think(Pilot* pilot); // Ai.c
|
||||
extern void player_think(Pilot* pilot); // Player.c
|
||||
extern int gui_load(const char* name); // Player.c
|
||||
// Internal.
|
||||
static void pilot_update(Pilot* pilot, const double dt);
|
||||
void pilot_render(Pilot* pilot);
|
||||
@ -242,6 +243,7 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profi
|
||||
pilot->render = NULL;
|
||||
pilot_setFlag(pilot, PILOT_PLAYER); // It's a player!
|
||||
player = pilot;
|
||||
gui_load(pilot->ship->gui); // Load the GUI.
|
||||
} else {
|
||||
pilot->think = ai_think;
|
||||
pilot->render = pilot_render;
|
||||
|
284
src/player.c
284
src/player.c
@ -12,7 +12,7 @@
|
||||
#define XML_NODE_TEXT 3
|
||||
|
||||
#define XML_GUI_ID "GUIs" // XML section identifier.
|
||||
#define XML_GUI_ID "gui"
|
||||
#define XML_GUI_TAG "gui"
|
||||
|
||||
#define GUI_DATA "../dat/gui.xml"
|
||||
#define GUI_GFX "../gfx/gui/"
|
||||
@ -125,9 +125,10 @@ static Msg* msg_stack;
|
||||
// External.
|
||||
extern void pilot_render(Pilot* pilot); // Extern is in Pilot.*
|
||||
// Internal.
|
||||
//TODO: Gui shit.
|
||||
void gui_renderPilot(Pilot* p);
|
||||
void gui_renderBar(Color* c, Vec2* p, Rect* r, double w);
|
||||
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_renderPilot(const Pilot* p);
|
||||
static void gui_renderBar(const Color* c, const Vec2* p, const Rect* r, const double w);
|
||||
|
||||
void player_message(const char* fmt, ...) {
|
||||
va_list ap;
|
||||
@ -135,11 +136,13 @@ void player_message(const char* fmt, ...) {
|
||||
|
||||
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);
|
||||
@ -266,7 +269,7 @@ void player_render(void) {
|
||||
}
|
||||
|
||||
// Renders a pilot.
|
||||
void gui_renderPilot(Pilot* p) {
|
||||
static void gui_renderPilot(const Pilot* p) {
|
||||
int x, y, sx, sy;
|
||||
|
||||
x = (p->solid->pos.x - player->solid->pos.x) / gui.radar.res;
|
||||
@ -294,7 +297,7 @@ void gui_renderPilot(Pilot* p) {
|
||||
}
|
||||
|
||||
// Render a bar.
|
||||
void gui_renderBar(Color* c, Vec2* p, Rect* r, double w) {
|
||||
static void gui_renderBar(const Color* c, const Vec2* p, const Rect* r, const double w) {
|
||||
int x, y, sx, sy;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
@ -314,63 +317,232 @@ void gui_renderBar(Color* c, Vec2* p, Rect* r, double w) {
|
||||
int gui_init(void) {
|
||||
// Font.
|
||||
gl_fontInit(&gui.smallFont, NULL, 10);
|
||||
// -- Targeting.
|
||||
gui.gfx_targetPilot = gl_newSprite(GFX_GUI_TARG_PILOT, 2, 2);
|
||||
gui.gfx_targetPlanet = gl_newSprite(GFX_GUI_TARG_PLANET, 2, 2);
|
||||
// -- Frame.
|
||||
gui.gfx_frame = gl_newImage(GFX_GUI_FRAME);
|
||||
vect_csetmin(&gui.pos_frame,
|
||||
gl_screen.w - gui.gfx_frame->w, // x.
|
||||
gl_screen.h - gui.gfx_frame->h); // y.
|
||||
gui_xoff = -gui.gfx_frame->w/2.; // Offset is only horizontal and on the right side.
|
||||
|
||||
// -- Radar.
|
||||
gui.radar.res = RADAR_RES_DEFAULT;
|
||||
gui.radar.w = 128.;
|
||||
gui.radar.h = 128.;
|
||||
gui.radar.shape = RADAR_RECT; //RADAR_CIRCLE;
|
||||
vect_csetmin(&gui.pos_radar,
|
||||
VX(gui.pos_frame) + 11, // x
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - 10); // y.
|
||||
|
||||
// -- Bars.
|
||||
gui.shield.w = gui.armor.w = gui.energy.w = 129;
|
||||
gui.shield.h = gui.armor.h = gui.energy.h = 10;
|
||||
vect_csetmin(&gui.pos_shield,
|
||||
VX(gui.pos_frame) + 10, // x
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - 201); // y.
|
||||
|
||||
vect_csetmin(&gui.pos_armor,
|
||||
VX(gui.pos_frame) + 10, // x
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - 218); // y.
|
||||
|
||||
vect_csetmin(&gui.pos_energy,
|
||||
VX(gui.pos_frame) + 10, // x
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - 236); // y.
|
||||
|
||||
// Target.
|
||||
vect_csetmin(&gui.pos_target,
|
||||
VX(gui.pos_frame) + 10,
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - 256 - SHIP_TARGET_H);
|
||||
|
||||
vect_csetmin(&gui.pos_target_name,
|
||||
VX(gui.pos_target) + 10,
|
||||
VY(gui.pos_target) + SHIP_TARGET_H - 10 - gl_defFont.h);
|
||||
|
||||
vect_csetmin(&gui.pos_target_faction,
|
||||
VX(gui.pos_target_name),
|
||||
VY(gui.pos_target_name) - gui.smallFont.h - 4);
|
||||
|
||||
vect_csetmin(&gui.pos_target_health,
|
||||
VX(gui.pos_target) + 10,
|
||||
VY(gui.pos_target) +10);
|
||||
|
||||
// Message system.
|
||||
// -- messages.
|
||||
vect_csetmin(&gui.pos_msg, 20,30);
|
||||
msg_stack = calloc(msg_max, sizeof(Msg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Attempts to load the actual gui.
|
||||
int gui_load(const char* name) {
|
||||
uint32_t bufsize;
|
||||
char* buf = pack_readfile(DATA, GUI_DATA, &bufsize);
|
||||
char* tmp;
|
||||
int found = 0;
|
||||
|
||||
xmlNodePtr node;
|
||||
xmlDocPtr doc = xmlParseMemory(buf, bufsize);
|
||||
|
||||
node = doc->xmlChildrenNode;
|
||||
if(strcmp((char*)node->name, 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(node->type == XML_NODE_START && strcmp((char*)node->name, XML_GUI_TAG)==0) {
|
||||
tmp = (char*)xmlGetProp(node, (xmlChar*)"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);
|
||||
xmlCleanupParser();
|
||||
|
||||
if(!found) {
|
||||
WARN("GUI '%s' not found in '"GUI_DATA"'",name);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rect_parse(const xmlNodePtr parent, double* x, double* y, double* w, double* h) {
|
||||
xmlNodePtr cur;
|
||||
int param;
|
||||
|
||||
param = 0;
|
||||
|
||||
cur = parent->children;
|
||||
|
||||
do {
|
||||
if(strcmp((char*)cur->name, "x")==0) {
|
||||
if(x != NULL) {
|
||||
*x = (double)atoi((char*)cur->children->content);
|
||||
param |= (1<<0);
|
||||
} else
|
||||
WARN("Extra parameter 'x' found for GUI node '%s'", parent->name);
|
||||
}
|
||||
else if(strcmp((char*)cur->name, "y")==0) {
|
||||
if(y != NULL) {
|
||||
*y = (double)atoi((char*)cur->children->content);
|
||||
param |= (1<<1);
|
||||
} else
|
||||
WARN("Extra parameter 'y' found for GUI node '%s'", parent->name);
|
||||
}
|
||||
else if(strcmp((char*)cur->name, "w")==0) {
|
||||
if(w != NULL) {
|
||||
*w = (double)atoi((char*)cur->children->content);
|
||||
param |= (1<<2);
|
||||
} else
|
||||
WARN("Extra parameter 'w' found for GUI node '%s'", parent->name);
|
||||
}
|
||||
else if(strcmp((char*)cur->name, "h")==0) {
|
||||
if(h != NULL) {
|
||||
*h = (double)atoi((char*)cur->children->content);
|
||||
param |= (1<<3);
|
||||
} else
|
||||
WARN("Extra parameter 'h' found for GUI node '%s'", parent->name);
|
||||
}
|
||||
} while((cur = cur->next));
|
||||
|
||||
// Check to see if we got everything we asked for.
|
||||
if(x && !(param & (1<<0)))
|
||||
WARN("Missing parameter 'x' for GUI node '%s'", parent->name);
|
||||
else if(y && !(param & (1<<1)))
|
||||
WARN("Missing parameter 'y' for GUI node '%s'", parent->name);
|
||||
else if(w && !(param & (1<<2)))
|
||||
WARN("Missing parameter 'w' for GUI node '%s'", parent->name);
|
||||
else if(h && !(param & (1<<3)))
|
||||
WARN("Missing parameter 'h' for GUI node '%s'", parent->name);
|
||||
}
|
||||
|
||||
// Parse a gui node.
|
||||
static int gui_parse(const xmlNodePtr parent, const char* name) {
|
||||
xmlNodePtr cur, node;
|
||||
double x, y;
|
||||
char* tmp, *tmp2;
|
||||
|
||||
// Gfx.
|
||||
// Set a property and not a node because it must be loaded first.
|
||||
tmp2 = (char*)xmlGetProp(parent, (xmlChar*)"gfx");
|
||||
if(tmp2 == NULL) {
|
||||
ERR("GUI '%s' has no gfx property", name);
|
||||
return -1;
|
||||
}
|
||||
// Load gfx.
|
||||
tmp = malloc((strlen(tmp2)+strlen(GUI_GFX)+12) * sizeof(char));
|
||||
// Frame.
|
||||
snprintf(tmp, strlen(tmp2)+strlen(GUI_GFX)+5, GUI_GFX"%s.png", tmp2);
|
||||
gui.gfx_frame = gl_newImage(tmp);
|
||||
// Pilot.
|
||||
snprintf(tmp, strlen(tmp2)+strlen(GUI_GFX)+11, GUI_GFX"%s_pilot.png", tmp2);
|
||||
gui.gfx_targetPilot = gl_newSprite(tmp, 2, 2);
|
||||
// Planet.
|
||||
snprintf(tmp, strlen(tmp2)+strlen(GUI_GFX)+12, GUI_GFX"%s_planet.png", tmp2);
|
||||
gui.gfx_targetPlanet = gl_newSprite(tmp, 2, 2);
|
||||
free(tmp);
|
||||
free(tmp2);
|
||||
|
||||
// Frame (based on gfx).
|
||||
vect_csetmin(&gui.pos_frame,
|
||||
gl_screen.w - gui.gfx_frame->w, // x.
|
||||
gl_screen.h - gui.gfx_frame->h); // h.
|
||||
|
||||
// For rendering the player. Displaces it a little so it's centered onscreen.
|
||||
gui_xoff = - gui.gfx_frame->w/2.;
|
||||
|
||||
// Let's parse the data now.
|
||||
node = parent->children;
|
||||
do {
|
||||
if(strcmp((char*)node->name, "radar")==0) {
|
||||
tmp = (char*)xmlGetProp(node, (xmlChar*)"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);
|
||||
|
||||
rect_parse(node, &x, &y, &gui.radar.w, &gui.radar.h);
|
||||
vect_csetmin(&gui.pos_radar,
|
||||
VX(gui.pos_frame) + x,
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - y);
|
||||
}
|
||||
// Health bars.
|
||||
else if(strcmp((char*)node->name, "health")==0) {
|
||||
cur = node->children;
|
||||
do {
|
||||
if(strcmp((char*)cur->name, "shield")==0) {
|
||||
rect_parse(cur, &x, &y, &gui.shield.w, &gui.shield.h);
|
||||
vect_csetmin(&gui.pos_shield,
|
||||
VX(gui.pos_frame) + x,
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - y);
|
||||
}
|
||||
|
||||
if(strcmp((char*)cur->name, "armor")==0) {
|
||||
rect_parse(cur, &x, &y, &gui.armor.w, &gui.armor.h);
|
||||
vect_csetmin(&gui.pos_armor,
|
||||
VX(gui.pos_frame) + x,
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - y);
|
||||
}
|
||||
|
||||
if(strcmp((char*)cur->name, "energy")==0) {
|
||||
rect_parse(cur, &x, &y, &gui.energy.w, &gui.energy.h);
|
||||
vect_csetmin(&gui.pos_energy,
|
||||
VX(gui.pos_frame) + x,
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - y);
|
||||
}
|
||||
} while((cur = cur->next));
|
||||
}
|
||||
// Target.
|
||||
else if(strcmp((char*)node->name, "target")==0) {
|
||||
cur = node->children;
|
||||
do {
|
||||
if(strcmp((char*)cur->name, "gfx")==0) {
|
||||
rect_parse(cur, &x, &y, NULL, NULL);
|
||||
vect_csetmin(&gui.pos_target,
|
||||
VX(gui.pos_frame) + x,
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - y - SHIP_TARGET_H);
|
||||
}
|
||||
|
||||
if(strcmp((char*)cur->name, "name")==0) {
|
||||
rect_parse(cur, &x, &y, NULL, NULL);
|
||||
vect_csetmin(&gui.pos_target_name,
|
||||
VX(gui.pos_frame) + x,
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - y - gl_defFont.h);
|
||||
}
|
||||
|
||||
if(strcmp((char*)cur->name, "faction")==0) {
|
||||
rect_parse(cur, &x, &y, NULL, NULL);
|
||||
vect_csetmin(&gui.pos_target_faction,
|
||||
VX(gui.pos_frame) + x,
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - y - gui.smallFont.h);
|
||||
}
|
||||
|
||||
if(strcmp((char*)cur->name, "health")==0) {
|
||||
rect_parse(cur, &x, &y, NULL, NULL);
|
||||
vect_csetmin(&gui.pos_target_health,
|
||||
VX(gui.pos_frame) + x,
|
||||
VY(gui.pos_frame) + gui.gfx_frame->h - y - gui.smallFont.h);
|
||||
}
|
||||
} while((cur = cur->next));
|
||||
}
|
||||
} while((node = node->next));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Free the GUI.
|
||||
|
@ -59,6 +59,8 @@ static Ship* ship_parse(xmlNodePtr parent) {
|
||||
tmp->gfx_target = gl_newImage(str);
|
||||
|
||||
}
|
||||
else if(strcmp((char*)node->name, "GUI")==0)
|
||||
tmp->gui = strdup((char*)node->children->content);
|
||||
else if(strcmp((char*)node->name, "class")==0)
|
||||
tmp->class = atoi((char*)node->children->content);
|
||||
else if(strcmp((char*)node->name, "movement")==0) {
|
||||
|
@ -34,6 +34,9 @@ typedef struct {
|
||||
// Graphics.
|
||||
gl_texture* gfx_space, *gfx_target;
|
||||
|
||||
// GUI interface.
|
||||
char* gui;
|
||||
|
||||
// Characteristics.
|
||||
int crew;
|
||||
int mass;
|
||||
|
Loading…
Reference in New Issue
Block a user