From bf9d422150a19a96e562b916ad42913d91882de3 Mon Sep 17 00:00:00 2001 From: Allanis Date: Tue, 19 Feb 2013 00:10:57 +0000 Subject: [PATCH] [Add] Support for images of planets within toolkit. [Change] blit functions use doubles instead of vectors. [Change] Took some time out to clean up space.c bringing it up to xml.h standards. --- dat/planet.xml | 10 +- gfx/planet/{ => exterior}/konosphere.png | Bin gfx/planet/{ => exterior}/saracraft.png | Bin gfx/planet/space/konosphere.png | Bin 0 -> 17592 bytes gfx/planet/space/saracraft.png | Bin 0 -> 17592 bytes src/colour.c | 1 + src/colour.h | 1 + src/land.c | 9 +- src/opengl.c | 19 +- src/opengl.h | 13 +- src/pilot.c | 2 +- src/player.c | 48 ++-- src/space.c | 138 ++++++----- src/space.h | 1 + src/toolkit.c | 278 +++++++++++++++-------- src/toolkit.h | 8 +- src/weapon.c | 2 +- 17 files changed, 334 insertions(+), 196 deletions(-) rename gfx/planet/{ => exterior}/konosphere.png (100%) rename gfx/planet/{ => exterior}/saracraft.png (100%) create mode 100644 gfx/planet/space/konosphere.png create mode 100644 gfx/planet/space/saracraft.png diff --git a/dat/planet.xml b/dat/planet.xml index a8c8f85..569185a 100644 --- a/dat/planet.xml +++ b/dat/planet.xml @@ -12,7 +12,10 @@ 0 1 - konosphere.png + + konosphere.png + konosphere.png + @@ -26,6 +29,9 @@ 0 1 - saracraft.png + + saracraft.png + saracraft.png + diff --git a/gfx/planet/konosphere.png b/gfx/planet/exterior/konosphere.png similarity index 100% rename from gfx/planet/konosphere.png rename to gfx/planet/exterior/konosphere.png diff --git a/gfx/planet/saracraft.png b/gfx/planet/exterior/saracraft.png similarity index 100% rename from gfx/planet/saracraft.png rename to gfx/planet/exterior/saracraft.png diff --git a/gfx/planet/space/konosphere.png b/gfx/planet/space/konosphere.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccb16dccd686601cbaa767614059033c42d4ff GIT binary patch literal 17592 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, NULL, &cBlack); + window_addText(land_wid, 0., -20., LAND_WIDTH, 1, "txtPlanet", NULL, &cBlack, p->name); + //window_addImage(land_wid, 20., -440, "imgPlanet", p->gfx_exterior); // Buttons. window_addButton(land_wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, - "takeoff", "Takeoff", (void(*)(char*))takeoff); + "btnTakeoff", "Takeoff", (void(*)(char*))takeoff); landed = 1; } diff --git a/src/opengl.c b/src/opengl.c index 45803db..7f8df98 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -345,23 +345,25 @@ void gl_getSpriteFromDir(int* x, int* y, const glTexture* t, const double dir) { // ================ // Blit the sprite at given position. -void gl_blitSprite(const glTexture* sprite, const Vec2* pos, const int sx, const int sy, const glColour* c) { +void gl_blitSprite(const glTexture* sprite, const double bx, const double by, + const int sx, const int sy, const glColour* c) { // Don't bother drawing if offscreen -- waste of cycles. - if(fabs(VX(*pos) -VX(*gl_camera)+gui_xoff) > gl_screen.w / 2 + sprite->sw / 2 || - fabs(VY(*pos) -VY(*gl_camera)+gui_yoff) > gl_screen.h / 2 + sprite->sh / 2) + if(fabs(bx-VX(*gl_camera)+gui_xoff) > gl_screen.w / 2 + sprite->sw / 2 || + fabs(by-VY(*gl_camera)+gui_yoff) > gl_screen.h / 2 + sprite->sh / 2) return; double x, y, tx, ty; glEnable(GL_TEXTURE_2D); - x = VX(*pos) - VX(*gl_camera) - sprite->sw/2. + gui_xoff; - y = VY(*pos) - VY(*gl_camera) - sprite->sh/2. + gui_yoff; + x = bx - VX(*gl_camera) - sprite->sw/2. + gui_xoff; + y = by - VY(*gl_camera) - sprite->sh/2. + gui_yoff; tx = sprite->sw * (double)(sx)/sprite->rw; ty = sprite->sh * (sprite->sy-(double)sy-1)/sprite->rh; // Actual blitting.... + glShadeModel(GL_FLAT); glBindTexture(GL_TEXTURE_2D, sprite->texture); glBegin(GL_QUADS); if(c == NULL) glColor4d(1., 1., 1., 1.); @@ -385,12 +387,12 @@ void gl_blitSprite(const glTexture* sprite, const Vec2* pos, const int sx, const } // Just straight out blit the thing at position. -void gl_blitStatic(const glTexture* texture, const Vec2* pos, const glColour* c) { +void gl_blitStatic(const glTexture* texture, const double bx, const double by, const glColour* c) { double x, y; glEnable(GL_TEXTURE_2D); - x = VX(*pos) - (double)gl_screen.w/2.; - y = VY(*pos) - (double)gl_screen.h/2.; + x = bx - (double)gl_screen.w/2.; + y = by - (double)gl_screen.h/2.; // Actual blitting.. glBindTexture(GL_TEXTURE_2D, texture->texture); @@ -798,6 +800,7 @@ int gl_init(void) { //glEnable(GL_TEXTURE_2D); // Don't enable globally, it will break non-texture blits. glDisable(GL_LIGHTING); // No lighting, it is done when rendered. glEnable(GL_BLEND); + glShadeModel(GL_FLAT); // Default shade model. Functions should keep this when done.. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_PROJECTION); glLoadIdentity(); diff --git a/src/opengl.h b/src/opengl.h index 56b0807..01c1c5f 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -66,21 +66,30 @@ glTexture* gl_newSprite(const char* path, const int sx, const int sy); void gl_freeTexture(glTexture* texture); // Rendering. -void gl_blitSprite(const glTexture* sprite, const Vec2* pos, +// Blits a sprite. +void gl_blitSprite(const glTexture* sprite, const double bx, const double by, const int sx, const int sy, const glColour* c); -void gl_blitStatic(const glTexture* texture, const Vec2* pos, const glColour* c); +// Blit the entire image. +void gl_blitStatic(const glTexture* texture, const double bx, const double by, + const glColour* c); + +// Bind the camera to a vector. void gl_bindCamera(const Vec2* pos); +// Print text. void gl_print(const glFont* ft_font, const double x, const double y, const glColour* c, const char* fmt, ...); +// Print text to a max length. int gl_printMax(const glFont* ft_font, const int max, const double x, const double y, const glColour* c, const char* fmt, ...); +// Print text centered in width at x. int gl_printMid(const glFont* ft_font, const int width, double x, const double y, const glColour* c, const char* fmt, ...); +// Get the width of the text that you wish to print. int gl_printWidth(const glFont* ft_font, const char* fmt, ...); // Initialize/cleanup. diff --git a/src/pilot.c b/src/pilot.c index e1e91d8..2a93a43 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -200,7 +200,7 @@ void pilot_render(Pilot* p) { // Get the sprite corresponding to the direction facing. gl_getSpriteFromDir(&sx, &sy, p->ship->gfx_space, p->solid->dir); - gl_blitSprite(p->ship->gfx_space, &p->solid->pos, sx, sy, NULL); + gl_blitSprite(p->ship->gfx_space, p->solid->pos.x, p->solid->pos.y, sx, sy, NULL); } // Update the pilot. diff --git a/src/player.c b/src/player.c index 82905f3..c848add 100644 --- a/src/player.c +++ b/src/player.c @@ -218,7 +218,6 @@ void player_render(void) { Planet* planet; glColour* c; glFont* f; - Vec2 v; // Render the player target graphics. if(player_target != PLAYER_ID) { @@ -227,16 +226,19 @@ void player_render(void) { if(pilot_isDisabled(p)) c = &cInert; else if(pilot_isFlag(p, PILOT_HOSTILE)) c = &cHostile; else c = &cNeutral; + + 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. - vect_csetmin(&v, VX(p->solid->pos) - p->ship->gfx_space->sw * PILOT_SIZE_APROX/2., - VY(p->solid->pos) + p->ship->gfx_space->sh * PILOT_SIZE_APROX/2.); - gl_blitSprite(gui.gfx_targetPilot, &v, 0, 0, c); // Top left. - VX(v) += p->ship->gfx_space->sw * PILOT_SIZE_APROX; - gl_blitSprite(gui.gfx_targetPilot, &v, 1, 0, c); // Top right. - VY(v) -= p->ship->gfx_space->sh * PILOT_SIZE_APROX; - gl_blitSprite(gui.gfx_targetPilot, &v, 1, 1, c); // Bottom right. - VX(v) -= p->ship->gfx_space->sw * PILOT_SIZE_APROX; - gl_blitSprite(gui.gfx_targetPilot, &v, 0, 1, c); // Bottom 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. } // Render the planet target graphics. if(planet_target >= 0) { @@ -244,23 +246,27 @@ void player_render(void) { if(areEnemies(player->faction, planet->faction)) c = &cHostile; else c = &cNeutral; + + 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_targetPlanet, x, y, 0, 0, c); // Top left. + + x += p->ship->gfx_space->sw * PILOT_SIZE_APROX; + gl_blitSprite(gui.gfx_targetPlanet, x, y, 1, 0, c); // Top right. + + y -= p->ship->gfx_space->sh * PILOT_SIZE_APROX; + gl_blitSprite(gui.gfx_targetPlanet, x, y, 1, 1, c); // Bottom right. + + x -= p->ship->gfx_space->sw * PILOT_SIZE_APROX; + gl_blitSprite(gui.gfx_targetPlanet, x, y, 0, 1, c); // Bottom left. - vect_csetmin(&v, VX(planet->pos) - planet->gfx_space->sw/2., - VY(planet->pos) + planet->gfx_space->sh/2.); - gl_blitSprite(gui.gfx_targetPlanet, &v, 0, 0, c); // Top left. - VX(v) += planet->gfx_space->sw; - gl_blitSprite(gui.gfx_targetPlanet, &v, 1, 0, c); // Top right. - VY(v) -= planet->gfx_space->sh; - gl_blitSprite(gui.gfx_targetPlanet, &v, 1, 1, c); // Bottom right. - VX(v) -= planet->gfx_space->sw; - gl_blitSprite(gui.gfx_targetPlanet, &v, 0, 1, c); // Bottom left. } // Render the player. pilot_render(player); // GUI! // -- Frame. - gl_blitStatic(gui.gfx_frame, &gui.frame, NULL); + gl_blitStatic(gui.gfx_frame, gui.frame.x, gui.frame.y, NULL); // -- Radar. glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -368,7 +374,7 @@ void player_render(void) { if(player_target != PLAYER_ID) { p = pilot_get(player_target); - gl_blitStatic(p->ship->gfx_target, &gui.target, NULL); + gl_blitStatic(p->ship->gfx_target, gui.target.x, gui.target.y, NULL); // Target name. gl_print(NULL, gui.target_name.x, gui.target_name.y, diff --git a/src/space.c b/src/space.c index 54ec5df..7fccac7 100644 --- a/src/space.c +++ b/src/space.c @@ -11,22 +11,26 @@ #include "pause.h" #include "player.h" -#define XML_PLANET_ID "Planets" -#define XML_PLANET_TAG "planet" +#define XML_PLANET_ID "Planets" +#define XML_PLANET_TAG "planet" -#define XML_SYSTEM_ID "Systems" -#define XML_SYSTEM_TAG "ssys" +#define XML_SYSTEM_ID "Systems" +#define XML_SYSTEM_TAG "ssys" -#define PLANET_DATA "../dat/planet.xml" -#define SYSTEM_DATA "../dat/ssys.xml" +#define PLANET_DATA "../dat/planet.xml" +#define SYSTEM_DATA "../dat/ssys.xml" -#define PLANET_GFX "../gfx/planet/" +#define PLANET_GFX_SPACE "../gfx/planet/space/" +#define PLANET_GFX_EXTERIOR "../gfx/planer/exterior/" + +#define PLANET_GFX_EXTERIOR_W 400 +#define PLANET_GFX_EXTERIOR_H 400 // Overcome warning due to zero value. #define FLAG_XSET (1<<0) #define FLAG_YSET (1<<1) -#define FLAG_ASTEROIDSSET (1<<2) +#define FLAG_ASTEROIDSSET (1<<2) #define FLAG_INTEFERENCESET (1<<3) static StarSystem* systems = NULL; @@ -239,8 +243,8 @@ static Planet* planet_get(const char* name) { } do { - if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_PLANET_TAG)==0) { - tstr = (char*)xmlGetProp(node, (xmlChar*)"name"); + if(xml_isNode(node, XML_PLANET_TAG)) { + tstr = xml_nodeProp(node, "name"); if(strcmp(tstr, name)==0) { // Found. tmp = CALLOC_L(Planet); tmp->name = tstr; @@ -248,34 +252,43 @@ static Planet* planet_get(const char* name) { node = node->xmlChildrenNode; do { - if(strcmp((char*)node->name, "GFX")==0) { - cur = node->children; - if(strcmp((char*)cur->name, "text")==0) { - snprintf(str, strlen((char*)cur->content)+sizeof(PLANET_GFX), - PLANET_GFX"%s", (char*)cur->content); - tmp->gfx_space = gl_newImage(str); - } - } - else if(strcmp((char*)node->name, "pos")==0) { + if(xml_isNode(node, "GFX")) { cur = node->children; do { - if(strcmp((char*)cur->name, "x")==0) { - flags |= FLAG_XSET; - tmp->pos.x = atof((char*)cur->children->content); + if(xml_isNode(cur, "space")) { + // Load space gfx. + snprintf(str, strlen(xml_get(cur))+sizeof(PLANET_GFX_SPACE), + PLANET_GFX_SPACE"%s", xml_get(cur)); + tmp->gfx_space = gl_newImage(str); } - else if(strcmp((char*)cur->name, "y")==0) { - flags |= FLAG_YSET; - tmp->pos.y = atof((char*)cur->children->content); + else if(xml_isNode(cur, "exterior")) { + // Load land gfx. + snprintf(str, strlen(xml_get(cur))+sizeof(PLANET_GFX_EXTERIOR), + PLANET_GFX_EXTERIOR"%s", xml_get(cur)); + tmp->gfx_exterior = gl_newImage(str); } } while((cur = cur->next)); } - else if(strcmp((char*)node->name, "general")==0) { + else if(xml_isNode(node, "pos")) { cur = node->children; do { - if(strcmp((char*)cur->name, "class")==0) + if(xml_isNode(cur, "x")) { + flags |= FLAG_XSET; + tmp->pos.x = xml_getFloat(cur); + } + else if(xml_isNode(cur, "y")) { + flags |= FLAG_YSET; + tmp->pos.y = xml_getFloat(cur); + } + } while((cur = cur->next)); + } + else if(xml_isNode(node, "general")) { + cur = node->children; + do { + if(xml_isNode(cur, "class")) tmp->class = planetclass_get(cur->children->content[0]); - else if(strcmp((char*)cur->name, "faction")==0) - tmp->faction = faction_get((char*)cur->children->content); + else if(xml_isNode(cur, "faction")) + tmp->faction = faction_get(xml_get(cur)); } while((cur = cur->next)); } } while((node = node->next)); @@ -292,10 +305,12 @@ static Planet* planet_get(const char* name) { // Check elements. if(tmp) { #define MELEMENT(o,s) if((o) == 0) WARN("Planet '%s' missing '"s"' element", tmp->name) - MELEMENT(flags&FLAG_XSET, "x"); - MELEMENT(flags&FLAG_YSET, "y"); - MELEMENT(tmp->class, "class"); - MELEMENT(tmp->faction, "faction"); + MELEMENT(tmp->gfx_space, "GFX_space"); + MELEMENT(tmp->gfx_exterior, "GFX_exterior"); + MELEMENT(flags&FLAG_XSET, "x"); + MELEMENT(flags&FLAG_YSET, "y"); + MELEMENT(tmp->class, "class"); + MELEMENT(tmp->faction, "faction"); #undef MELEMENT } else WARN("No planet found matching name '%s'", name); @@ -314,45 +329,46 @@ static StarSystem* system_parse(const xmlNodePtr parent) { uint32_t flags; - tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name"); // Already mallocs. + tmp->name = xml_nodeProp(parent, "name"); // Already mallocs. node = parent->xmlChildrenNode; do { // Load all the things! - if(strcmp((char*)node->name, "pos")==0) { + if(xml_isNode(node, "pos")) { cur = node->children; do { - if(strcmp((char*)cur->name, "x")==0) { + if(xml_isNode(cur, "x")) { flags |= FLAG_XSET; - tmp->pos.x = atof((char*)cur->children->content); + tmp->pos.x = xml_getFloat(cur); } - if(strcmp((char*)cur->name, "y")==0) { + if(xml_isNode(cur, "y")) { flags |= FLAG_YSET; - tmp->pos.y = atof((char*)cur->children->content); + tmp->pos.y = xml_getFloat(cur); } } while((cur = cur->next)); } - else if(strcmp((char*)node->name, "general")==0) { + else if(xml_isNode(node, "general")) { cur = node->children; do { - if(strcmp((char*)cur->name, "stars")==0) // Non-zero. - tmp->stars = atoi((char*)cur->children->content); - else if(strcmp((char*)cur->name, "asteroids")==0) { + if(xml_isNode(cur, "stars")) // Non-zero. + tmp->stars = xml_getInt(cur); + else if(xml_isNode(cur, "asteroids")) { flags |= FLAG_ASTEROIDSSET; - tmp->asteroids = atoi((char*)cur->children->content); + tmp->asteroids = xml_getInt(cur); } - else if(strcmp((char*)cur->name, "interference")==0) { + else if(xml_isNode(cur, "interference")) { flags |= FLAG_INTEFERENCESET; - tmp->interference = atof((char*)cur->children->content); + tmp->interference = xml_getFloat(cur)/100; } }while((cur = cur->next)); } // Load all the planets. - else if(strcmp((char*)node->name, "planets")==0) { + else if(xml_isNode(node, "planets")) { cur = node->children; do { - if(strcmp((char*)cur->name, "planet")==0) { + if(xml_isNode(cur, "planet")) { + planet = planet_get(xml_get(cur)); planet = planet_get((const char*)cur->children->content); tmp->planets = realloc(tmp->planets, sizeof(Planet)*(++tmp->nplanets)); memcpy(tmp->planets+(tmp->nplanets-1), planet, sizeof(Planet)); @@ -361,16 +377,16 @@ static StarSystem* system_parse(const xmlNodePtr parent) { } while((cur = cur->next)); } // Load all the fleets. - else if(strcmp((char*)node->name, "fleets")==0) { + else if(xml_isNode(node, "fleets")) { cur = node->children; do { - if(strcmp((char*)cur->name, "fleet")==0) { + if(xml_isNode(cur, "fleet")) { fleet = CALLOC_L(SystemFleet); - fleet->fleet = fleet_get((const char*)cur->children->content); + fleet->fleet = fleet_get(xml_get(cur)); if(fleet->fleet == NULL) - WARN("Fleet %s for Star System %s not found", (char*)cur->children->content, tmp->name); + WARN("Fleet %s for Star System %s not found", xml_get(cur), tmp->name); - ptrc = (char*)xmlGetProp(cur, (xmlChar*)"chance"); // Malloc ptrc. + ptrc = xml_nodeProp(cur, "chance"); // Malloc ptrc. fleet->chance = atoi(ptrc); if(fleet->chance == 0) WARN("Fleet %s for Star System %s has 0%% chance to appear", @@ -408,7 +424,7 @@ int space_load(void) { xmlDocPtr doc = xmlParseMemory(buf, bufsize); node = doc->xmlChildrenNode; - if(strcmp((char*)node->name, XML_SYSTEM_ID)) { + if(!xml_isNode(node, XML_SYSTEM_ID)) { ERR("Malformed "SYSTEM_DATA" file: missing root element '"XML_SYSTEM_ID"'"); return -1; } @@ -418,7 +434,7 @@ int space_load(void) { return -1; } do { - if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_SYSTEM_TAG)==0) { + if(xml_isNode(node, XML_SYSTEM_TAG)) { tmp = system_parse(node); systems = realloc(systems, sizeof(StarSystem)*(++nsystems)); memcpy(systems+nsystems-1, tmp, sizeof(StarSystem)); @@ -436,9 +452,6 @@ int space_load(void) { // Render the system. -- Just playing god now. void space_render(double dt) { int i; - glMatrixMode(GL_PROJECTION); - glPushMatrix(); // Projection translation matrix. - glTranslated(-(double)gl_screen.w/2., -(double)gl_screen.h/2., 0.); glBegin(GL_POINTS); for(i = 0; i < nstars; i++) { if(!paused) { @@ -453,17 +466,18 @@ void space_render(double dt) { } // Render. glColor4d(1., 1., 1., stars[i].brightness); - glVertex2d(stars[i].x, stars[i].y); + glVertex2d(stars[i].x - (double)gl_screen.w/2., + stars[i].y - (double)gl_screen.h/2.); } glEnd(); - glPopMatrix(); // Projection translation matrix. } // Render the planets. void planets_render(void) { int i; for(i = 0; i < cur_system->nplanets; i++) - gl_blitSprite(cur_system->planets[i].gfx_space, &cur_system->planets[i].pos, 0, 0, NULL); + gl_blitSprite(cur_system->planets[i].gfx_space, + cur_system->planets[i].pos.x, cur_system->planets[i].pos.y, 0, 0, NULL); } // Clean up the system. @@ -475,6 +489,8 @@ void space_exit(void) { free(systems[i].planets[j].name); if(systems[i].planets[j].gfx_space) gl_freeTexture(systems[i].planets[j].gfx_space); + if(systems[i].planets[j].gfx_exterior) + gl_freeTexture(systems[i].planets[j].gfx_exterior); if(systems[i].fleets) free(systems[i].fleets); } diff --git a/src/space.h b/src/space.h index ae8a164..a1640a4 100644 --- a/src/space.h +++ b/src/space.h @@ -41,6 +41,7 @@ typedef struct { PlanetClass class; // Planet type. Faction* faction; // Planet faction. glTexture* gfx_space; // Graphics in space. + glTexture* gfx_exterior; // Graphics in the exterior. } Planet; // Star systems. diff --git a/src/toolkit.c b/src/toolkit.c index 82bca35..f5b0574 100644 --- a/src/toolkit.c +++ b/src/toolkit.c @@ -29,17 +29,18 @@ typedef struct { // Widget button. struct { void(*fptr) (char*); // Callback. - char* string; // Stored text. + char* display; // Stored text. }; // Widget text. struct { + char* text; glFont* font; glColour* colour; int centered; }; struct { // Widget image. - glTexture* texture; + glTexture* image; }; }; } Widget; @@ -70,6 +71,7 @@ static Window* window_get(const unsigned int wid); static void window_render(Window* w); static void toolkit_renderButton(Widget* btn, double bx, double by); static void toolkit_renderText(Widget* txt, double bx, double by); +static void toolkit_renderImage(Widget* img, double bx, double by); // Add a button that when pressed will trigger call, passing it's name as the // only parameter. @@ -81,7 +83,7 @@ void window_addButton(const unsigned int wid, const int x, const int y, const in wgt->type = WIDGET_BUTTON; wgt->name = strdup(name); - wgt->string = strdup(display); + wgt->display = strdup(display); // Set the properties. wgt->w = (double) w; @@ -93,8 +95,10 @@ void window_addButton(const unsigned int wid, const int x, const int y, const in wgt->fptr = call; } -void window_addText(const unsigned int wid, const int x, const int y, const int w, - const int centered, char* name, glFont* font, glColour* colour) { +// Add text to the window. +void window_addText(const unsigned int wid, const int x, const int y, + const int w, const int centered, char* name, + glFont* font, glColour* colour, char* string) { Window* wdw = window_get(wid); Widget* wgt = window_newWidget(wdw); @@ -108,11 +112,29 @@ void window_addText(const unsigned int wid, const int x, const int y, const int else wgt->font = font; if(x < 0) wgt->x = wdw->w - wgt->w + x; else wgt->x = (double)x; - if(y < 0) wgt->y = wdw->h - wgt->font->h + y; + if(y < 0) wgt->y = wdw->h + y; else wgt->y = (double) y; wgt->colour = colour; wgt->centered = centered; + wgt->text = strdup(string); +} +// Add a graphic to the window. +void window_addImage(const unsigned int wid, const int x, const int y, + char* name, glTexture* image) { + + Window* wdw = window_get(wid); + Widget* wgt = window_newWidget(wdw); + + wgt->type = WIDGET_IMAGE; + wgt->name = strdup(name); + + // Set the propertied. + wgt->image = image; + if(x < 0) wgt->x = wdw->w - wgt->image->sw + x; + else wgt->x = (double)x; + if(y < 0) wgt->y = wdw->h + y; + else wgt->y = (double)y; } // Return pointer to newly allocated widget. @@ -178,9 +200,17 @@ unsigned int window_create(const int x, const int y, const int w, const int h) { // Destroy a widget. static void widget_cleanup(Widget* widget) { if(widget->name) free(widget->name); - - if((widget->type == WIDGET_BUTTON) && widget->string) - free(widget->string); + + switch(widget->type) { + case WIDGET_BUTTON: + if(widget->display) free(widget->display); + break; + case WIDGET_TEXT: + if(widget->text) free(widget->text); + break; + default: + break; + } } // Destroy a window. @@ -208,6 +238,27 @@ void window_destroy(unsigned int wid) { } } +void window_destroyWidget(unsigned int wid, const char* wgtname) { + Window* w = window_get(wid); + int i; + + for(i = 0; i < w->nwidgets; i++) + if(strcmp(wgtname, w->widgets[i].name)==0) + break; + + if(i >= w->nwidgets) { + DEBUG("Widget '%s' not found in window '%d'", wgtname, wid); + return; + } + + widget_cleanup(&w->widgets[i]); + if(i < w->nwidgets-1) + // This isn't the last widget. + w->widgets[i] = w->widgets[i-1]; + + w->nwidgets--; // Not that we don't actually realloc the space.. +} + // Render a window. static void window_render(Window* w) { int i; @@ -297,78 +348,79 @@ static void window_render(Window* w) { glBegin(GL_LINE_LOOP); // Left side. COLOUR(*c); - glVertex2d(x+21., y); - glVertex2d(x+15., y+1.); - glVertex2d(x+10., y+3.); - glVertex2d(x+6., y+6.); - glVertex2d(x+3., y+10.); - glVertex2d(x+1., y+15.); - glVertex2d(x, y+21.); + glVertex2d(x+21.+1., y); + glVertex2d(x+15.+1., y+1.+1.); + glVertex2d(x+10.+1., y+3.+1.); + glVertex2d(x+6.+1., y+6.+1.); + glVertex2d(x+3.+1., y+10.+1.); + glVertex2d(x+1.+1., y+15.+1.); + glVertex2d(x+1., y+21.+1.); COLOUR(*lc); - glVertex2d(x, y+0.6*w->h); // Front of center. - glVertex2d(x, y+w->h-21.); - glVertex2d(x+1., y+w->h-15.); - glVertex2d(x+3., y+w->h-10.); - glVertex2d(x+6., y+w->h-6.); - glVertex2d(x+10., y+w->h-2.); - glVertex2d(x+15., y+w->h-1.); - glVertex2d(x+21., y+w->h); + glVertex2d(x+1., y+0.6*w->h); // Front of center. + glVertex2d(x+1., y+w->h-21.-1.); + glVertex2d(x+1.+1., y+w->h-15.-1.); + glVertex2d(x+3.+1., y+w->h-10.-1.); + glVertex2d(x+6.+1., y+w->h-6.-1.); + glVertex2d(x+10.+1., y+w->h-2.-1.); + glVertex2d(x+15.+1., y+w->h-1.-1.); + glVertex2d(x+21.+1., y+w->h-1.); // Switch to right via top. - glVertex2d(x+w->w-21., y+w->h); - glVertex2d(x+w->w-15., y+w->h-1.); - glVertex2d(x+w->w-10., y+w->h-3.); - glVertex2d(x+w->w-6., y+w->h-6.); - glVertex2d(x+w->w-2., y+w->h-10.); - glVertex2d(x+w->w-1., y+w->h-15.); - glVertex2d(x+w->w, y+w->h-21.); - glVertex2d(x+w->w, y+0.6*w->h); // Front of center. + glVertex2d(x+w->w-21.-1., y+w->h); + glVertex2d(x+w->w-15.-1., y+w->h-1.-1.); + glVertex2d(x+w->w-10.-1., y+w->h-3.-1.); + glVertex2d(x+w->w-6.-1., y+w->h-6.-1.); + glVertex2d(x+w->w-2.-1., y+w->h-10.-1.); + glVertex2d(x+w->w-1.-1., y+w->h-15.-1.); + glVertex2d(x+w->w-.1, y+w->h-21.-1.); + glVertex2d(x+w->w-1., y+0.6*w->h); // Front of center. COLOUR(*c); - glVertex2d(x+w->w, y+21.); - glVertex2d(x+w->w-1., y+15.); - glVertex2d(x+w->w-3., y+10.); - glVertex2d(x+w->w-6., y+6.); - glVertex2d(x+w->w-10., y+3.); - glVertex2d(x+w->w-15., y+1.); - glVertex2d(x+w->w-21., y); - glVertex2d(x+21., y); + glVertex2d(x+w->w-1., y+21.+1.); + glVertex2d(x+w->w-1.-1., y+15.+1.); + glVertex2d(x+w->w-3.-1., y+10.+1.); + glVertex2d(x+w->w-6.-1., y+6.+1.); + glVertex2d(x+w->w-10.-1., y+3.+1.); + glVertex2d(x+w->w-15.-1., y+1.+1.); + glVertex2d(x+w->w-21.-1., y+1.); + glVertex2d(x+21.+1., y+1.); glEnd(); // Outter outline. - glShadeModel(GL_SMOOTH); + glShadeModel(GL_FLAT); glBegin(GL_LINE_LOOP); // Left side. COLOUR(*oc); - glVertex2d(x+21.-1., y-1.); - glVertex2d(x+15.-1., y+1.-1.); - glVertex2d(x+10.-1., y+3.-1.); - glVertex2d(x+6.-1., y+6.-1.); - glVertex2d(x+3.-1., y+10.-1.); - glVertex2d(x+1.-1., y+15.-1.); - glVertex2d(x-1., y+21.-1.); - glVertex2d(x-1., y+0.6*w->h); // Front of center. - glVertex2d(x-1., y+w->h-21.+1.); - glVertex2d(x+1.-1., y+w->h-15.+1.); - glVertex2d(x+3.-1., y+w->h-10.+1.); - glVertex2d(x+6.-1., y+w->h-6.+1.); - glVertex2d(x+10.-1., y+w->h-3.+1.); - glVertex2d(x+15.-1., y+w->h-1.+1.); - glVertex2d(x+21.-1., y+w->h+1.); + glVertex2d(x+21., y); + glVertex2d(x+15., y+1.); + glVertex2d(x+10., y+3.); + glVertex2d(x+6., y+6.); + glVertex2d(x+3., y+10.); + glVertex2d(x+1., y+15.); + glVertex2d(x, y+21.); + glVertex2d(x, y+0.6*w->h); // Front of center. + glVertex2d(x, y+w->h-21.); + glVertex2d(x+1., y+w->h-15.); + glVertex2d(x+3., y+w->h-10.); + glVertex2d(x+6., y+w->h-6.); + glVertex2d(x+10., y+w->h-3.); + glVertex2d(x+15., y+w->h-1.); + glVertex2d(x+21., y+w->h); // Switch to right via top. - glVertex2d(x+w->w-21.+1., y+w->h+1.); - glVertex2d(x+w->w-15.+1., y+w->h-1.+1.); - glVertex2d(x+w->w-10.+1., y+w->h-3.+1.); - glVertex2d(x+w->w-6.+1., y+w->h-6.+1.); - glVertex2d(x+w->w-3.+1., y+w->h-10.+1.); - glVertex2d(x+w->w-1.+1., y+w->h-15.+1.); - glVertex2d(x+w->w+1., y+w->h-21.+1.); - glVertex2d(x+w->w+1., y+0.6*w->h); // Front of center. - glVertex2d(x+w->w-1.+1., y+21.-1.); - glVertex2d(x+w->w-3.+1., y+15.-1.); - glVertex2d(x+w->w-6.+1., y+6.-1.); - glVertex2d(x+w->w-10.+1., y+3.-1.); - glVertex2d(x+w->w-15.+1., y+1.-1.); - glVertex2d(x+w->w-21.+1., y-1.); - glVertex2d(x+21.-1., y-1.); // Back to beginning. + glVertex2d(x+w->w-21., y+w->h); + glVertex2d(x+w->w-15., y+w->h-1.); + glVertex2d(x+w->w-10., y+w->h-3.); + glVertex2d(x+w->w-6., y+w->h-6.); + glVertex2d(x+w->w-3., y+w->h-10.); + glVertex2d(x+w->w-1., y+w->h-15.); + glVertex2d(x+w->w, y+w->h-21.); + glVertex2d(x+w->w, y+0.6*w->h); // Front of center. + glVertex2d(x+w->w, y+21.); + glVertex2d(x+w->w-1., y+15.); + glVertex2d(x+w->w-3., y+10.); + glVertex2d(x+w->w-6., y+6.); + glVertex2d(x+w->w-10., y+3.); + glVertex2d(x+w->w-15., y+1.); + glVertex2d(x+w->w-21., y); + glVertex2d(x+21., y); // Back to beginning. glEnd(); // Widgets. @@ -383,6 +435,7 @@ static void window_render(Window* w) { toolkit_renderText(&w->widgets[i], x, y); break; case WIDGET_IMAGE: + toolkit_renderImage(&w->widgets[i], x, y); break; } } @@ -439,36 +492,23 @@ static void toolkit_renderButton(Widget* btn, double bx, double by) { // Inner outline. glShadeModel(GL_SMOOTH); - // Left. - glBegin(GL_LINES); + glBegin(GL_LINE_LOOP); + // Left. COLOUR(*c); glVertex2d(x, y); COLOUR(*lc); glVertex2d(x, y+btn->h); - glEnd(); - // Right. - glBegin(GL_LINES); - COLOUR(*c); - glVertex2d(x+btn->w, y); - COLOUR(*lc); + // Top. glVertex2d(x+btn->w, y+btn->h); - glEnd(); - - glShadeModel(GL_FLAT); - // Bottom. - glBegin(GL_LINES); + // Right. COLOUR(*c); - glVertex2d(x, y); glVertex2d(x+btn->w, y); - glEnd(); - // Top. - glBegin(GL_LINES); - COLOUR(*lc); - glVertex2d(x, y+btn->h); - glVertex2d(x+btn->w, y+btn->h); + // Bottom. + glVertex2d(x, y); glEnd(); // Outter outline. + glShadeModel(GL_FLAT); glBegin(GL_LINE_LOOP); COLOUR(cBlack); // Left. @@ -483,12 +523,13 @@ static void toolkit_renderButton(Widget* btn, double bx, double by) { // Bottom. glVertex2d(x+btn->w, y-1.); glVertex2d(x, y-1.); + glVertex2d(x-1, y); glEnd(); gl_printMid(NULL, (int)btn->w, bx + (double)gl_screen.w/2. + btn->x, by + (double)gl_screen.h/2. + btn->y + (btn->h - gl_defFont.h)/2., - &cRed, btn->string); + &cDarkRed, btn->display); } static void toolkit_renderText(Widget* txt, double bx, double by) { @@ -496,12 +537,61 @@ static void toolkit_renderText(Widget* txt, double bx, double by) { gl_printMid(txt->font, txt->w, bx + (double)gl_screen.w/2. + txt->x, by + (double)gl_screen.h/2. + txt->y, - txt->colour, txt->name); + txt->colour, txt->text); else gl_printMax(txt->font, txt->w, bx + (double)gl_screen.w/2. + txt->x, by + (double)gl_screen.h/2. + txt->y, - txt->colour, txt->name); + txt->colour, txt->text); +} + +// Render the image. +static void toolkit_renderImage(Widget* img, double bx, double by) { + glColour* lc, *c, *oc; + double x, y; + x = bx + img->x; + y = by + img->y; + + lc = &cGrey90; + c = &cGrey70; + oc = &cGrey30; + + // Image. + gl_blitStatic(img->image, + x + (double)gl_screen.w/2., + y + (double)gl_screen.h/2., NULL); + + // Inner outline (outwards). + glShadeModel(GL_SMOOTH); + glBegin(GL_LINE_LOOP); + COLOUR(*lc); + // Top. + glVertex2d(x-1, y+img->image->sh+1.); + glVertex2d(x+img->image->sw, y+img->image->sh+1.); + // Right. + COLOUR(*c); + glVertex2d(x+img->image->sw, y); + // Bottom. + glVertex2d(x-1., y); + // Left. + COLOUR(*lc); + glVertex2d(x-1., y+img->image->sh+1.); + glEnd(); + + // Outter outline. + glShadeModel(GL_SMOOTH); + glBegin(GL_LINE_LOOP); + COLOUR(*oc); + // Top. + glVertex2d(x-2., y+img->image->sh+2.); + glVertex2d(x+img->image->sw+1., y+img->image->sh+2.); + // Right. + glVertex2d(x+img->image->sw+1., y-1.); + // Bottom. + glVertex2d(x-2., y-1.); + // Left. + glVertex2d(x-2., y+img->image->sh+2.); + glEnd(); } // Render the window. diff --git a/src/toolkit.h b/src/toolkit.h index aa097a3..9e1f2e9 100644 --- a/src/toolkit.h +++ b/src/toolkit.h @@ -12,11 +12,15 @@ void window_addButton(const unsigned int wid, const int x, const int y, void(*call)(char*)); void window_addText(const unsigned int wid, const int x, const int y, - const int w, const int cenetered, - char* name, glFont* font, glColour* colour); + const int w, const int cenetered, char* name, + glFont* font, glColour* colour, char* string); + +void window_addImage(const unsigned int wid, const int x, const int y, + char* name, glTexture* image); // Destroy window. void window_destroy(const unsigned int wid); +void window_destroyWidget(unsigned wid, const char* wgtname); // Render. void toolkit_render(void); diff --git a/src/weapon.c b/src/weapon.c index d975393..b059eff 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -193,7 +193,7 @@ static void weapon_render(const Weapon* w) { // Get the sprite corresponding to the direction facing. gl_getSpriteFromDir(&sx, &sy, w->outfit->gfx_space, w->solid->dir); - gl_blitSprite(w->outfit->gfx_space, &w->solid->pos, sx, sy, NULL); + gl_blitSprite(w->outfit->gfx_space, w->solid->pos.x, w->solid->pos.y, sx, sy, NULL); } // Update the weapon.