[Add] Text word wrapping/block text. Allowing for lovely descriptons of planets.

This commit is contained in:
Allanis 2013-02-19 14:18:55 +00:00
parent d66e1a52f9
commit 9a9ace4a42
14 changed files with 153 additions and 53 deletions

View File

@ -2,11 +2,12 @@
<Planets>
<planet name="KonoSphere">
<pos>
<x>10</x>
<y>15</y>
<x>0</x>
<y>0</y>
</pos>
<general>
<class>A</class>
<description>The surface of the planet is predominantly covered with water and the planetary climate is characterised by abundant precipitation and strong winds, yet tolerable enough to make special and expensive weather control measurements unnecessary. Habitable land is characterised by soft meadows, swamps and dense forests. The resource base of KonoSphere consits mainly of agriculture and biomass, with the locally bred and grown kono rice being its main export, and fishing a traditional source of sustenance for its people. Other traditional products include wine, and various livestock, most prominently cattle. Cuisine on KonoSphere is rather refined, with most dishes containing meat.</description>
<faction>Independent</faction>
<services>1</services>
<tech>0</tech>
@ -24,6 +25,7 @@
</pos>
<general>
<class>A</class>
<description>SaraCraft is a desert planet with no natural precipitation.</description>
<faction>Independent</faction>
<services>1</services>
<tech>0</tech>

View File

@ -12,6 +12,7 @@
</general>
<planets>
<planet>KonoSphere</planet>
<planet>SaraCraft</planet>
</planets>
<fleets>
<fleet chance="100">Enemy Test</fleet>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -9,8 +9,22 @@
#include "pack.h"
#define FONT_DEF "../gfx/fonts/font.ttf"
// == Font render routines.================================
// Use a display list to store ASCII chars rendered with
// freefont. There are several drawing methods depending
// on whether you want to print it all, to a max width,
// print centered or print a block of text.
//
// There are hardcoded size limits. 256 characters for all
// routines exept gl_printText which has a 1024 limit.
//
// TODO: Check if length is too long.
// ========================================================
// Default font.
glFont gl_defFont;
glFont gl_smallFont;
static void glFontMakeDList(FT_Face face, char ch,
GLuint list_base, GLuint* tex_base, int* width_base);
@ -30,7 +44,7 @@ static int pot(int n) {
void gl_print(const glFont* ft_font, const double x, const double y,
const glColour* c, const char* fmt, ...) {
//float h = ft_font->h / .63; // Slightly increases font size.
char text[256];
char txt[256];
va_list ap;
if(ft_font == NULL) ft_font = &gl_defFont;
@ -39,7 +53,7 @@ void gl_print(const glFont* ft_font, const double x, const double y,
else {
// convert the symbols to text.
va_start(ap, fmt);
vsprintf(text, fmt, ap);
vsprintf(txt, fmt, ap);
va_end(ap);
}
@ -53,7 +67,7 @@ void gl_print(const glFont* ft_font, const double x, const double y,
if(c == NULL) glColor4d(1., 1., 1., 1.);
else COLOUR(*c);
glCallLists(strlen(text), GL_UNSIGNED_BYTE, &text);
glCallLists(strlen(txt), GL_UNSIGNED_BYTE, &txt);
glPopMatrix(); // Translation matrix.
glDisable(GL_TEXTURE_2D);
@ -64,7 +78,7 @@ void gl_print(const glFont* ft_font, const double x, const double y,
int gl_printMax(const glFont* ft_font, const int max, const double x, const double y,
const glColour* c, const char* fmt, ...) {
//float h = ft_font->h / .63; // Slightly increases font size.
char text[256];
char txt[256];
va_list ap;
int i, n, len, ret;
@ -74,17 +88,17 @@ int gl_printMax(const glFont* ft_font, const int max, const double x, const doub
else {
// convert the symbols to text.
va_start(ap, fmt);
vsprintf(text, fmt, ap);
vsprintf(txt, fmt, ap);
va_end(ap);
}
// Limit the size.
len = (int)strlen(text);
len = (int)strlen(txt);
for(n = 0, i = 0; i < len; i++) {
n += ft_font->w[(int)text[i]];
n += ft_font->w[(int)txt[i]];
if(n > max) {
ret = len - i; // Difference.
text[i] = '\0';
txt[i] = '\0';
break;
}
}
@ -100,7 +114,7 @@ int gl_printMax(const glFont* ft_font, const int max, const double x, const doub
if(c == NULL) glColor4d(1., 1., 1., 1.);
else COLOUR(*c);
glCallLists(i, GL_UNSIGNED_BYTE, &text);
glCallLists(i, GL_UNSIGNED_BYTE, &txt);
glPopMatrix(); // Translation matrix.
glDisable(GL_TEXTURE_2D);
@ -112,7 +126,7 @@ int gl_printMax(const glFont* ft_font, const int max, const double x, const doub
int gl_printMid(const glFont* ft_font, const int width, double x, const double y,
const glColour* c, const char* fmt, ...) {
//float h = ft_font->h / .63; // Slightly increases font size.
char text[256];
char txt[256];
va_list ap;
int i, n, len, ret;
@ -124,18 +138,18 @@ int gl_printMid(const glFont* ft_font, const int width, double x, const double y
else {
// convert the symbols to text.
va_start(ap, fmt);
vsprintf(text, fmt, ap);
vsprintf(txt, fmt, ap);
va_end(ap);
}
// Limit the size.
len = (int)strlen(text);
len = (int)strlen(txt);
for(n = 0, i = 0; i < len; i++) {
n += ft_font->w[(int)text[i]];
n += ft_font->w[(int)txt[i]];
if(n > width) {
ret = len - i; // Difference.
n -= ft_font->w[(int)text[i]]; // Actual size.
text[i] = '\0';
n -= ft_font->w[(int)txt[i]]; // Actual size.
txt[i] = '\0';
break;
}
}
@ -153,7 +167,7 @@ int gl_printMid(const glFont* ft_font, const int width, double x, const double y
if(c == NULL) glColor4d(1., 1., 1., 1.);
else COLOUR(*c);
glCallLists(i, GL_UNSIGNED_BYTE, &text);
glCallLists(i, GL_UNSIGNED_BYTE, &txt);
glPopMatrix(); // Translation matrix.
glDisable(GL_TEXTURE_2D);
@ -161,6 +175,77 @@ int gl_printMid(const glFont* ft_font, const int width, double x, const double y
return ret;
}
// Print text with line breaks included to a max width and height precet.
int gl_printText(const glFont* ft_font, const int width, const int height,
double bx, double by, glColour* c, const char* fmt, ...) {
float h = ft_font->h / .63; // Slightly increase font size.
char txt[1024];
char buf[128];
va_list ap;
int p, i, j, n, len, ret, lastspace;
double x, y;
ret = 0; // Default return value.
if(ft_font == NULL) ft_font = &gl_defFont;
if(fmt == NULL) return -1;
else {
// Convert the symbols to text.
va_start(ap, fmt);
vsprintf(txt, fmt, ap);
va_end(ap);
}
bx -= (double)gl_screen.w/2.;
by -= (double)gl_screen.h/2.;
x = bx;
y = by + height - (double)ft_font->h; // y is top left corner.
// Prepare opengl.
glEnable(GL_TEXTURE_2D);
glListBase(ft_font->list_base);
if(c == NULL) glColor4d(1., 1., 1., 1.);
else COLOUR(*c);
len = (int)strlen(txt);
// Limit size per line.
lastspace = 0; // Last ' ' or \n int text.
n = 0; // Current width.
i = 0; // Current position.
p = -1; // Where we last drew up to.
while(i < len+1) {
if(by - y > (double)height) return len-lastspace; // Past height.
n += ft_font->w[(int)txt[i]];
if((txt[i] == ' ') || (txt[i] == '\n') || (txt[i] == '\0')) lastspace = i;
if((n > width) || (txt[i] == '\n') || (txt[i] == '\0')) {
// Time to draw the line.
for(j = 0; j < (lastspace-p-1); j++)
buf[j] = txt[p+j+1];
// No need for null termination.
glMatrixMode(GL_MODELVIEW); // using modelview, projection gets full fast.
glPushMatrix(); // Translation matrix.
glTranslated(x, y, 0);
glCallLists(lastspace-p-1, GL_UNSIGNED_BYTE, &buf); // This is what we are displaying.
glPopMatrix(); // Translation matrix.
p = lastspace;
n = 0;
i = lastspace;
y -= 1.5*(double)ft_font->h; // Move position down.
}
i++;
}
glDisable(GL_TEXTURE_2D);
return ret;
}
// Get the width of the text about to be printed.
int gl_printWidth(const glFont* ft_font, const char* fmt, ...) {
@ -194,14 +279,14 @@ static void glFontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex
int w, h;
int i, j;
if(FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_DEFAULT))
if(FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_FORCE_AUTOHINT))
WARN("FT_Load_Glyph failed");
if(FT_Get_Glyph(face->glyph, &glyph))
WARN("FT_Ge_Glyph failed");
// Convert your glyph to a bitmap.
FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0, 1);
FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
bitmap = bitmap_glyph->bitmap; // To simplify.
@ -264,7 +349,7 @@ static void glFontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex
FT_Done_Glyph(glyph);
}
void glFontInit(glFont* font, const char* fname, const unsigned int h) {
void gl_fontInit(glFont* font, const char* fname, const unsigned int h) {
if(font == NULL) font = &gl_defFont;
uint32_t bufsize;

View File

@ -9,6 +9,7 @@ typedef struct {
GLuint list_base;
} glFont;
extern glFont gl_defFont; // Default font.
extern glFont gl_smallFont; // Small font.
// glFont loading/freeing.
// If font is NULL it uses the internal default font, same with gl_print
@ -27,6 +28,10 @@ int gl_printMax(const glFont* ft_font, const int max, const double x, const doub
int gl_printMid(const glFont* ft_font, const int width, double x, const double y,
const glColour* c, const char* fmt, ...);
// Respects \n -> bx, by is top left position.
int gl_printText(const glFont* ft_font, const int width, const int height,
double bx, double by, 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, ...);

View File

@ -19,8 +19,10 @@ void land(Planet* p) {
land_wid = window_create(-1, -1, LAND_WIDTH, LAND_HEIGHT);
// Pretty display.
window_addText(land_wid, 0., -20., LAND_WIDTH, 1, "txtPlanet", NULL, &cBlack, p->name);
window_addText(land_wid, 0., -20., LAND_WIDTH, 0, 1, "txtPlanet", NULL, &cBlack, p->name);
window_addImage(land_wid, 20., -440, "imgPlanet", p->gfx_exterior);
window_addText(land_wid, 440., 80., 200., 460., 0,
"txtPlanetDesc", &gl_smallFont, &cBlack, p->description);
// Buttons.
window_addButton(land_wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnTakeoff", "Takeoff", (void(*)(char*))takeoff);

View File

@ -32,6 +32,7 @@
#define VERSION_LEN 10
#define MINIMUM_FPS 0.5
#define FONT_SIZE 12
#define FONT_SIZE_SMALL 10
static int quit = 0; // Primary loop.
unsigned int gtime = 0; // Calculate FPS and movement.
@ -123,7 +124,8 @@ int main(int argc, char** argv) {
WARN("Error initializing AI");
// Misc openGL init stuff.
glFontInit(NULL, NULL, FONT_SIZE); // Init default font size.
gl_fontInit(NULL, NULL, FONT_SIZE); // Init default font size.
gl_fontInit(&gl_smallFont, NULL, FONT_SIZE_SMALL); // Small font.
gui_init(); // Init the GUI crap.
toolkit_init(); // Init the toolkit.
@ -181,6 +183,7 @@ int main(int argc, char** argv) {
ships_free();
outfit_free();
factions_free();
gl_freeFont(&gl_smallFont);
gl_freeFont(NULL);

View File

@ -49,7 +49,6 @@ static int pot(int n) {
return i;
}
// Flips the surface vertically. Return 0 on success.
static int SDL_VFlipSurface(SDL_Surface* surface) {
// Flip the image.

View File

@ -76,7 +76,6 @@ typedef struct {
typedef struct {
// Graphics.
glFont smallFont;
glTexture* gfx_frame;
glTexture* gfx_targetPilot, *gfx_targetPlanet;
@ -324,15 +323,15 @@ void player_render(void) {
// Planet landing target.
gl_printMid(NULL, (int)gui.nav.w, gui.nav.x, gui.nav.y - 5, &cConsole, "Land");
gl_printMid(&gui.smallFont, (int)gui.nav.w, gui.nav.x, gui.nav.y - 10 - gui.smallFont.h,
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(planet_target == -1) {
// No planet target.
gl_printMid(NULL, (int)gui.nav.w, gui.nav.x,
gui.nav.y - 5, &cConsole, "Navigation");
gl_printMid(&gui.smallFont, (int)gui.nav.w, gui.nav.x,
gui.nav.y - 10 - gui.smallFont.h, &cGrey, "Off");
gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x,
gui.nav.y - 10 - gl_smallFont.h, &cGrey, "Off");
}
// Health
@ -344,7 +343,7 @@ void player_render(void) {
if(player->secondary == NULL) {
gl_printMid(NULL, (int)gui.weapon.w, gui.weapon.x,
gui.weapon.y - 5, &cConsole, "Secondary");
gl_printMid(&gui.smallFont, (int)gui.weapon.w, gui.weapon.x,
gl_printMid(&gl_smallFont, (int)gui.weapon.w, gui.weapon.x,
gui.weapon.y - 10 - gl_defFont.h, &cGrey, "None");
} else {
f = &gl_defFont;
@ -352,7 +351,7 @@ void player_render(void) {
i = gl_printWidth(f, "%s", player->secondary->outfit->name);
if(i > (int)gui.weapon.w)
// Font is too big.
f = &gui.smallFont;
f = &gl_smallFont;
gl_printMid(f, (int)gui.weapon.w, gui.weapon.x,
gui.weapon.y - (gui.weapon.h - f->h)/2.,
@ -362,14 +361,14 @@ void player_render(void) {
i = gl_printWidth(f, "%s", player->secondary->outfit->name);
if(i > gui.weapon.w)
// Font is too big.
f = &gui.smallFont;
f = &gl_smallFont;
gl_printMid(f, (int)gui.weapon.w, gui.weapon.x,
gui.weapon.y - 5,
&cConsole, "%s", player->ammo->outfit->name);
// Print ammo underneath to the left.
gl_printMid(&gui.smallFont, gui.weapon.w, gui.weapon.x,
gl_printMid(&gl_smallFont, gui.weapon.w, gui.weapon.x,
gui.weapon.y - 10 - gl_defFont.h,
NULL, "%d", player->ammo->quantity);
}
@ -384,21 +383,21 @@ void player_render(void) {
// Target name.
gl_print(NULL, gui.target_name.x, gui.target_name.y,
NULL, "%s", p->name);
gl_print(&gui.smallFont, gui.target_faction.x, gui.target_faction.y,
gl_print(&gl_smallFont, gui.target_faction.x, gui.target_faction.y,
NULL, "%s", p->faction->name);
// Target status.
if(pilot_isDisabled(p))
// Disable the pilot.
gl_print(&gui.smallFont, gui.target_health.x, gui.target_health.y,
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(&gui.smallFont, gui.target_health.x, gui.target_health.y,
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(&gui.smallFont, gui.target_health.x, gui.target_health.y,
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.
@ -416,8 +415,8 @@ void player_render(void) {
snprintf(str, 10, "%.2fK", (double) credits / 1000.);
else
snprintf(str, 10, "%d", credits);
i = gl_printWidth(&gui.smallFont, "%s", str);
gl_print(&gui.smallFont, gui.misc.x + gui.misc.w - 10 - i,
i = gl_printWidth(&gl_smallFont, "%s", str);
gl_print(&gl_smallFont, gui.misc.x + gui.misc.w - 10 - i,
gui.misc.y - 10 - gl_defFont.h, NULL, "%s", str);
// Messages.
@ -498,8 +497,6 @@ int gui_init(void) {
gui.gfx_targetPilot = NULL;
gui.gfx_targetPlanet = NULL;
// Font.
glFontInit(&gui.smallFont, NULL, 10);
// -- Radar.
gui.radar.res = RADAR_RES_DEFAULT;
// -- messages.
@ -722,13 +719,13 @@ static int gui_parse(const xmlNodePtr parent, const char* name) {
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 -= gui.smallFont.h;
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 -= gui.smallFont.h;
gui.target_health.y -= gl_smallFont.h;
}
} while((cur = cur->next));
} else if(xml_isNode(node, "misc")) {
@ -743,8 +740,6 @@ static int gui_parse(const xmlNodePtr parent, const char* name) {
// Free the GUI.
void gui_free(void) {
gl_freeFont(&gui.smallFont);
gl_freeTexture(gui.gfx_frame);
gl_freeTexture(gui.gfx_targetPilot);
gl_freeTexture(gui.gfx_targetPlanet);
@ -875,9 +870,11 @@ void player_land(void) {
int tp;
double td, d;
for(i = 0, tp = -1; i < cur_system->nplanets; i++) {
d = vect_dist(&player->solid->vel, &planet->pos);
if((tp == -1) || (td > d)) {
td = -1; // Temp distance.
tp = -1; // Temp planet.
for(i = 0; i < cur_system->nplanets; i++) {
d = vect_dist(&player->solid->pos, &cur_system->planets[i].pos);
if((tp == -1) || ((td == -1) || (td > d))) {
tp = i;
td = d;
}

View File

@ -289,6 +289,8 @@ static Planet* planet_get(const char* name) {
tmp->class = planetclass_get(cur->children->content[0]);
else if(xml_isNode(cur, "faction"))
tmp->faction = faction_get(xml_get(cur));
else if(xml_isNode(cur, "description"))
tmp->description = strdup(xml_get(cur));
} while((cur = cur->next));
}
} while((node = node->next));
@ -485,14 +487,16 @@ void space_exit(void) {
int i,j;
for(i = 0; i < nsystems; i++) {
free(systems[i].name);
if(systems[i].fleets)
free(systems[i].fleets);
for(j = 0; j < systems[i].nplanets; j++) {
free(systems[i].planets[j].name);
if(systems[i].planets[j].description)
free(systems[i].planets[j].description);
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);
}
free(systems[i].planets);
}

View File

@ -39,6 +39,7 @@ typedef struct {
Vec2 pos; // Position in star system.
PlanetClass class; // Planet type.
char* description; // Planet description.
Faction* faction; // Planet faction.
glTexture* gfx_space; // Graphics in space.
glTexture* gfx_exterior; // Graphics in the exterior.

View File

@ -97,7 +97,7 @@ void window_addButton(const unsigned int wid, const int x, const int y, const in
// 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,
const int w, const int h, const int centered, char* name,
glFont* font, glColour* colour, char* string) {
Window* wdw = window_get(wid);
@ -108,6 +108,7 @@ void window_addText(const unsigned int wid, const int x, const int y,
// Set the properties.
wgt->w = (double) w;
wgt->h = (double) h;
if(font == NULL) wgt->font = &gl_defFont;
else wgt->font = font;
if(x < 0) wgt->x = wdw->w - wgt->w + x;
@ -539,7 +540,7 @@ static void toolkit_renderText(Widget* txt, double bx, double by) {
by + (double)gl_screen.h/2. + txt->y,
txt->colour, txt->text);
else
gl_printMax(txt->font, txt->w,
gl_printText(txt->font, txt->w, txt->h,
bx + (double)gl_screen.w/2. + txt->x,
by + (double)gl_screen.h/2. + txt->y,
txt->colour, txt->text);

View File

@ -13,7 +13,7 @@ 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,
const int w, const int h, const int cenetered, char* name,
glFont* font, glColour* colour, char* string);
void window_addImage(const unsigned int wid, const int x, const int y,