From 074e60afa5b1756af07e7bfad0e910155388812b Mon Sep 17 00:00:00 2001 From: Allanis <allanis@saracraft.net> Date: Mon, 18 Feb 2013 17:12:35 +0000 Subject: [PATCH] [Add] Finished the basic toolkit by rounding off corners, adding gl_printMax and gl_printMid. [Add] Use flag system with gl_screen. -- Optional AA for primitives. --- src/conf.c | 17 ++- src/land.c | 2 - src/opengl.c | 140 +++++++++++++++++++--- src/opengl.h | 35 +++++- src/player.c | 46 +++---- src/toolkit.c | 325 +++++++++++++++++++++++++++++++++++++++++++++----- src/toolkit.h | 3 + 7 files changed, 482 insertions(+), 86 deletions(-) diff --git a/src/conf.c b/src/conf.c index e12691c..95b64c3 100644 --- a/src/conf.c +++ b/src/conf.c @@ -65,7 +65,7 @@ void conf_setDefaults(void) { // GL. gl_screen.w = 800; gl_screen.h = 640; - gl_screen.fullscreen = 0; + gl_screen.flags = 0; // Joystick. indjoystick = -1; namjoystick = NULL; @@ -75,7 +75,7 @@ void conf_setDefaults(void) { // Ok.. Parse a config file plox. int conf_loadConfig(const char* file) { - int i; + int i = 0; lua_State* L = luaL_newstate(); if(luaL_dofile(L, file) == 0) { @@ -86,7 +86,16 @@ int conf_loadConfig(const char* file) { // OpenGL properties.. conf_loadInt("width", gl_screen.w); conf_loadInt("height", gl_screen.h); - conf_loadBool("fullscreen", gl_screen.fullscreen); + conf_loadBool("fullscreen", i); + if(i)gl_screen.flags |= OPENGL_FULLSCREEN; + conf_loadBool("aa", i); + if(i)gl_screen.flags |= OPENGL_AA_POINT | OPENGL_AA_LINE || OPENGL_AA_POLYGON; + conf_loadBool("aa_point", i); + if(i)gl_screen.flags |= OPENGL_AA_POINT; + conf_loadBool("aa_line", i) + if(i)gl_screen.flags |= OPENGL_AA_LINE; + conf_loadBool("aa_polygon", i); + if(i)gl_screen.flags |= OPENGL_AA_POLYGON; conf_loadBool("showfps", show_fps); conf_loadInt("maxfps", max_fps); @@ -178,7 +187,7 @@ void conf_parseCLI(int argc, char** argv) { while((c = getopt_long(argc, argv, "fF:d:J:j:hv", long_options, &option_index)) != -1) { switch(c) { case 'f': - gl_screen.fullscreen = 1; + gl_screen.flags |= OPENGL_FULLSCREEN; break; case 'F': max_fps = atoi(optarg); diff --git a/src/land.c b/src/land.c index 7f56c2b..1c9e6b3 100644 --- a/src/land.c +++ b/src/land.c @@ -12,7 +12,6 @@ void land(Planet* p) { if(landed) return; planet = p; - pause(); land_wid = window_create(-1, -1, 400, 300); window_addButton(land_wid, 400-80-20, 20, 80, 40, "takeoff", "Takeoff", (void(*)(char*))takeoff); landed = 1; @@ -23,7 +22,6 @@ void takeoff(void) { if(!landed) return; planet = NULL; - unpause(); window_destroy(land_wid); landed = 0; } diff --git a/src/opengl.c b/src/opengl.c index 69558d9..0beeab7 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -19,11 +19,21 @@ #define FONT_DEF "../gfx/fonts/font.ttf" // Default colors. -glColour cLightGrey = { .r = 0.80, .g = 0.80, .b = 0.80, .a = 1 }; -glColour cGrey = { .r = 0.65, .g = 0.65, .b = 0.65, .a = 1 }; -glColour cDarkGrey = { .r = 0.50, .g = 0.50, .b = 0.50, .a = 1 }; -glColour cGreen = { .r = 0.20, .g = 0.80, .b = 0.20, .a = 1 }; -glColour cRed = { .r = 0.80, .g = 0.20, .b = 0.20, .a = 1 }; +glColour cWhite = { .r = 1.00, .g = 1.00, .b = 1.00, .a = 1 }; +glColour cGrey90 = { .r = 0.90, .g = 0.90, .b = 0.90, .a = 1 }; +glColour cGrey80 = { .r = 0.80, .g = 0.80, .b = 0.80, .a = 1 }; +glColour cGrey70 = { .r = 0.70, .g = 0.70, .b = 0.70, .a = 1 }; +glColour cGrey60 = { .r = 0.60, .g = 0.60, .b = 0.60, .a = 1 }; +glColour cGrey50 = { .r = 0.50, .g = 0.50, .b = 0.50, .a = 1 }; +glColour cGrey40 = { .r = 0.40, .g = 0.40, .b = 0.40, .a = 1 }; +glColour cGrey30 = { .r = 0.30, .g = 0.30, .b = 0.30, .a = 1 }; +glColour cGrey20 = { .r = 0.20, .g = 0.20, .b = 0.20, .a = 1 }; +glColour cGrey10 = { .r = 0.10, .g = 0.10, .b = 0.10, .a = 1 }; +glColour cBlack = { .r = 0.00, .g = 0.00, .b = 0.00, .a = 1 }; + +glColour cGreen = { .r = 0.20, .g = 0.80, .b = 0.20, .a = 1 }; +glColour cRed = { .r = 0.80, .g = 0.20, .b = 0.20, .a = 1 }; + // offsets to Adjust the pilot's place onscreen to be in the middle, even with the GUI. extern double gui_xoff; @@ -461,6 +471,109 @@ void gl_print(const glFont* ft_font, const double x, const double y, glDisable(GL_TEXTURE_2D); } +// Acts just like gl_print, but prints to a max length of max. +// Return the amount of characters we had to suppress. +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]; + va_list ap; + int i, n, len, ret; + + if(ft_font == NULL) ft_font = &gl_defFont; + + if(fmt == NULL) return -1; + else { + // convert the symbols to text. + va_start(ap, fmt); + vsprintf(text, fmt, ap); + va_end(ap); + } + + // Limit the size. + len = (int)strlen(text); + for(n = 0, i = 0; i < len; i++) { + n += ft_font->w[(int)text[i]]; + if(n > max) { + ret = len - i; // Difference. + text[i] = '\0'; + break; + } + } + + // Display the text. + glEnable(GL_TEXTURE_2D); + + glListBase(ft_font->list_base); + + glMatrixMode(GL_MODELVIEW); // Projection gets full fast using modelview. + glPushMatrix(); // Translation matrix. + glTranslated(x - (double)gl_screen.w/2., y - (double)gl_screen.h/2., 0); + + if(c == NULL) glColor4d(1., 1., 1., 1.); + else COLOUR(*c); + glCallLists(i, GL_UNSIGNED_BYTE, &text); + + glPopMatrix(); // Translation matrix. + glDisable(GL_TEXTURE_2D); + + return ret; +} + +// Acts just like gl_printMax, but centers the text in the width. +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]; + va_list ap; + int i, n, len, ret; + + 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(text, fmt, ap); + va_end(ap); + } + + // Limit the size. + len = (int)strlen(text); + for(n = 0, i = 0; i < len; i++) { + n += ft_font->w[(int)text[i]]; + if(n > width) { + ret = len - i; // Difference. + n -= ft_font->w[(int)text[i]]; // Actual size. + text[i] = '\0'; + break; + } + } + + x += (double)(width-n)/2.; + + // Display the text. + glEnable(GL_TEXTURE_2D); + + glListBase(ft_font->list_base); + + glMatrixMode(GL_MODELVIEW); // Projection gets full fast using modelview. + glPushMatrix(); // Translation matrix. + glTranslated(x - (double)gl_screen.w/2., y - (double)gl_screen.h/2., 0); + + if(c == NULL) glColor4d(1., 1., 1., 1.); + else COLOUR(*c); + glCallLists(i, GL_UNSIGNED_BYTE, &text); + + glPopMatrix(); // Translation matrix. + 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, ...) { int i, n; @@ -621,10 +734,10 @@ void gl_freeFont(glFont* font) { // Initialize SDL/OpenGL etc. int gl_init(void) { - int depth, i, supported = 0; + int doublebuf, depth, i, supported = 0; SDL_Rect** modes; int flags = SDL_OPENGL; - flags |= SDL_FULLSCREEN * gl_screen.fullscreen; + flags |= SDL_FULLSCREEN * (gl_has(OPENGL_FULLSCREEN) ? 1: 0); // Initializes video. if(SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { @@ -632,12 +745,8 @@ int gl_init(void) { return -1; } - // FFUUUU Ugly cursor thing. - // -- Ok, Maybe for now. - //SDL_ShowCursor(SDL_DISABLE); - // Get available fullscreen modes. - if(gl_screen.fullscreen) { + if(gl_has(OPENGL_FULLSCREEN)) { modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN); if(modes == NULL) { // Could happen, but rare. WARN("No fullscreen modes available"); @@ -689,14 +798,15 @@ int gl_init(void) { SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &gl_screen.g); SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &gl_screen.b); SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &gl_screen.a); - SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &gl_screen.doublebuf); + SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuf); + if(doublebuf) gl_screen.flags |= OPENGL_DOUBLEBUF; gl_screen.depth = gl_screen.r + gl_screen.g + gl_screen.b + gl_screen.a; // Debug heaven. DEBUG("OpenGL Window Created: %dx%d@%dbpp %s", gl_screen.w, gl_screen.h, gl_screen.depth, - gl_screen.fullscreen ? "fullscreen" : "window"); + (gl_has(OPENGL_FULLSCREEN)) ? "fullscreen" : "window"); DEBUG("r: %d, g: %d, b: %d, a: %d, doublebuffer: %s", gl_screen.r, gl_screen.g, gl_screen.b, gl_screen.a, - gl_screen.doublebuf ? "yes" : "no"); + (gl_has(OPENGL_DOUBLEBUF)) ? "yes" : "no"); DEBUG("Renderer: %s", glGetString(GL_RENDERER)); // Some openGL options. diff --git a/src/opengl.h b/src/opengl.h index c7481a7..4216b56 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -18,12 +18,17 @@ #define RGBMASK RMASK,GMASK,BMASK,AMASK // Info about opengl screen. +#define OPENGL_FULLSCREEN (1<<0) +#define OPENGL_DOUBLEBUF (1<<1) +#define OPENGL_AA_POINT (1<<2) +#define OPENGL_AA_LINE (1<<3) +#define OPENGL_AA_POLYGON (1<<4) +#define gl_has(f) (gl_screen.flags & (f)) // Check for the flag. typedef struct { int w, h; // Window dimensions. int depth; // Depth in bpp. - int fullscreen; // 1 = fullscreen, 0 = windowed. int r, g, b, a; // Framebuffer values in bits. - int doublebuf; // Double buffer. + int flags; // Store different properties. } glInfo; extern glInfo gl_screen; // Local structure set with gl_init etc. @@ -34,9 +39,21 @@ typedef struct { #define COLOUR(x) glColor4d((x).r, (x).g, (x).b, (x).a) // Default colors. -extern glColour cLightGrey; -extern glColour cGrey; -extern glColour cDarkGrey; +// -- Greyscale. +extern glColour cWhite; +#define cGrey cGrey70 +extern glColour cBlack; + +extern glColour cGrey90; +extern glColour cGrey80; +extern glColour cGrey70; +extern glColour cGrey60; +extern glColour cGrey50; +extern glColour cGrey40; +extern glColour cGrey30; +extern glColour cGrey20; +extern glColour cGrey10; + extern glColour cGreen; extern glColour cRed; @@ -76,8 +93,16 @@ void gl_blitSprite(const glTexture* sprite, const Vec2* pos, void gl_blitStatic(const glTexture* texture, const Vec2* pos, const glColour* c); void gl_bindCamera(const Vec2* pos); + void gl_print(const glFont* ft_font, const double x, const double y, const glColour* c, const char* fmt, ...); + +int gl_printMax(const glFont* ft_font, const int max, const double x, const double y, + const glColour* c, const char* fmt, ...); + +int gl_printMid(const glFont* ft_font, const int width, double x, const double y, + const glColour* c, const char* fmt, ...); + int gl_printWidth(const glFont* ft_font, const char* fmt, ...); // Initialize/cleanup. diff --git a/src/player.c b/src/player.c index 63a6db1..174ea8a 100644 --- a/src/player.c +++ b/src/player.c @@ -311,21 +311,16 @@ void player_render(void) { // Nav. if(planet_target >= 0) { // Planet landing target. - i = gl_printWidth(NULL, "Land"); - gl_print(NULL, gui.nav.x + (gui.nav.w - i)/2., - gui.nav.y - 5, &cConsole, "Land"); - i = gl_printWidth(&gui.smallFont, "%s", cur_system->planets[planet_target].name); - gl_print(&gui.smallFont, gui.nav.x + (gui.nav.w - i)/2., - gui.nav.y - 10 - gui.smallFont.h, NULL, - "%s", cur_system->planets[planet_target].name); + 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, + NULL, "%s", cur_system->planets[planet_target].name); } else if(planet_target == -1) { // No planet target. - i = gl_printWidth(NULL, "Navigation"); - gl_print(NULL, gui.nav.x + (gui.nav.w - i)/2., + gl_printMid(NULL, (int)gui.nav.w, gui.nav.x, gui.nav.y - 5, &cConsole, "Navigation"); - i = gl_printWidth(&gui.smallFont, "Off"); - gl_print(&gui.smallFont, gui.nav.x + (gui.nav.w - i)/2., + gl_printMid(&gui.smallFont, (int)gui.nav.w, gui.nav.x, gui.nav.y - 10 - gui.smallFont.h, &cGrey, "Off"); } @@ -336,39 +331,34 @@ void player_render(void) { // Weapon. if(player->secondary == NULL) { - i = gl_printWidth(NULL, "Secondary"); - gl_print(NULL, gui.weapon.x + (gui.weapon.w - i)/2., + gl_printMid(NULL, (int)gui.weapon.w, gui.weapon.x, gui.weapon.y - 5, &cConsole, "Secondary"); - i = gl_printWidth(&gui.smallFont, "None"); - gl_print(&gui.smallFont, gui.weapon.x + (gui.weapon.w - i)/2., + gl_printMid(&gui.smallFont, (int)gui.weapon.w, gui.weapon.x, gui.weapon.y - 10 - gl_defFont.h, &cGrey, "None"); } else { f = &gl_defFont; if(player->ammo == NULL) { i = gl_printWidth(f, "%s", player->secondary->outfit->name); - if(i > gui.weapon.w) { + if(i > (int)gui.weapon.w) // Font is too big. f = &gui.smallFont; - i = gl_printWidth(f, "%s", player->secondary->outfit->name); - } - gl_print(f, gui.weapon.x + (gui.weapon.w - i)/2., + + gl_printMid(f, (int)gui.weapon.w, gui.weapon.x, gui.weapon.y - (gui.weapon.h - f->h)/2., &cConsole, "%s", player->secondary->outfit->name); } else { // Use the ammunitions name. i = gl_printWidth(f, "%s", player->secondary->outfit->name); - if(i > gui.weapon.w) { + if(i > gui.weapon.w) // Font is too big. f = &gui.smallFont; - i = gl_printWidth(f, "%s", player->ammo->outfit->name); - } - gl_print(f, gui.weapon.x + (gui.weapon.w - i)/2., + + 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. - i = gl_printWidth(&gui.smallFont, "%d", player->ammo->quantity); - gl_print(&gui.smallFont, gui.weapon.x + (gui.weapon.w - i)/2., + gl_printMid(&gui.smallFont, gui.weapon.w, gui.weapon.x, gui.weapon.y - 10 - gl_defFont.h, NULL, "%d", player->ammo->quantity); } @@ -401,10 +391,9 @@ void player_render(void) { NULL, "%s: %.0f%%", "Armor", p->armour/p->armour_max*100.); } else { // No target. - i = gl_printWidth(NULL, "No Target"); - gl_print(NULL, gui.target.x + (SHIP_TARGET_W - i)/2., + gl_printMid(NULL, SHIP_TARGET_W, gui.target.x, gui.target.y + (SHIP_TARGET_H - gl_defFont.h)/2., - &cGrey, "No Target"); + &cGrey80, "No Target"); } // Misc. @@ -891,6 +880,7 @@ void player_screenshot(void) { char filename[20]; // TODO not overwirte old screenshots. strncpy(filename, "screenshot.png", 20); + DEBUG("SCREENSHOT!"); gl_screenshot(filename); } diff --git a/src/toolkit.c b/src/toolkit.c index 473ded7..9407665 100644 --- a/src/toolkit.c +++ b/src/toolkit.c @@ -23,9 +23,19 @@ typedef struct { double w,h; // Dimensions. WidgetStatus status; - - void(*fptr) (char*); // Callback. - char* string; // Stored text. + + union { + // Widget button. + struct { + void(*fptr) (char*); // Callback. + char* string; // Stored text. + }; + // Widget text. + struct { + glFont* font; + glColour* colour; + }; + }; } Widget; typedef struct { @@ -52,24 +62,42 @@ static void widget_cleanup(Widget* widget); // Render. 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); // Add a button that when pressed will trigger call, passing it's name as the // only parameter. void window_addButton(const unsigned int wid, const int x, const int y, const int w, const int h, char* name, char* display, void (*call)(char*)) { - Widget* widget = window_newWidget(wid); + Widget* wgt = window_newWidget(wid); - widget->type = WIDGET_BUTTON; - widget->name = strdup(name); - widget->string = strdup(display); + wgt->type = WIDGET_BUTTON; + wgt->name = strdup(name); + wgt->string = strdup(display); // Set the properties. - widget->x = (double) x; - widget->y = (double) y; - widget->w = (double) w; - widget->h = (double) h; - widget->fptr = call; + wgt->x = (double) x; + wgt->y = (double) y; + wgt->w = (double) w; + wgt->h = (double) h; + wgt->fptr = call; +} + +void window_addText(const unsigned int wid, const int x, const int y, const int w, + const int h, char* name, glFont* font, glColour* colour) { + Widget* wgt = window_newWidget(wid); + + wgt->type = WIDGET_TEXT; + wgt->name = strdup(name); // Display the widgets name. + + // Set the properties. + wgt->x = (double) x; + wgt->y = (double) y; + wgt->w = (double) w; + wgt->h = (double) h; + wgt->font = font; + wgt->colour = colour; + } // Return pointer to newly allocated widget. @@ -109,8 +137,8 @@ unsigned int window_create(const int x, const int y, const int w, const int h) { windows[nwindows].h = (double) h; if((x == -1) && (y == -1)) { // Center. - windows[nwindows].x = windows[nwindows].w/2.; - windows[nwindows].y = windows[nwindows].h/2.; + windows[nwindows].x = gl_screen.w/2. - windows[nwindows].w/2.; + windows[nwindows].y = gl_screen.h/2. - windows[nwindows].h/2.; } else { windows[nwindows].x = (double) x; windows[nwindows].y = (double) y; @@ -159,6 +187,7 @@ void window_destroy(unsigned int wid) { // No windows left. SDL_ShowCursor(SDL_DISABLE); toolkit = 0; // Disable the toolkit. + if(paused) unpause(); } } @@ -166,18 +195,163 @@ void window_destroy(unsigned int wid) { static void window_render(Window* w) { int i; double x, y; + glColour *lc, *c, *dc, *oc; + // Position. x = w->x - (double)gl_screen.w/2.; y = w->y - (double)gl_screen.h/2.; - // Window background. - glBegin(GL_QUADS); - COLOUR(cLightGrey); + // Colours. + lc = &cGrey90; + c = &cGrey70; + dc = &cGrey50; + oc = &cGrey30; - glVertex2d(x, y); - glVertex2d(x + w->w, y); - glVertex2d(x + w->w, y + w->h); - glVertex2d(x, y + w->h); + // Window shaded background. + // Main body. + glShadeModel(GL_SMOOTH); + glBegin(GL_QUADS); + COLOUR(*dc); + glVertex2d(x+21., y); + glVertex2d(x+w->w-21., y); + + COLOUR(*c); + glVertex2d(x+w->w-21, y+0.6*w->h); + glVertex2d(x+21, y+0.6*w->h); + glEnd(); + + glShadeModel(GL_FLAT); + glBegin(GL_QUADS); + COLOUR(*c); + glVertex2d(x+21., y+0.6*w->h); + glVertex2d(x+w->w-21., y+0.6*w->h); + glVertex2d(x+w->w-21., y+w->h); + glVertex2d(x+21., y+w->h); + glEnd(); + + glShadeModel(GL_SMOOTH); + // Left side. + glBegin(GL_POLYGON); + COLOUR(*c); + glVertex2d(x+21., y+0.6*w->h); // Center. + COLOUR(*dc); + 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.); + glVertex2s(x, y+21.); + COLOUR(*c); + 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); + glEnd(); + // Right side. + glBegin(GL_POLYGON); + COLOUR(*c); + glVertex2d(x+w->w-21., y+0.6*w->h); // Center. + COLOUR(*dc); + glVertex2d(x+w->w-21., y); + glVertex2d(x+w->w-15., y+1.); + glVertex2d(x+w->w-10., y+3.); + glVertex2d(x+w->w-6., y+6.); + glVertex2d(x+w->w-3., y+10.); + glVertex2d(x+w->w-1., y+15.); + glVertex2d(x+w->w, y+21.); + COLOUR(*c); + glVertex2d(x+w->w, y+0.6*w->h); // Front of center. + glVertex2d(x+w->w, y+w->h-21.); + glVertex2d(x+w->w-1., y+w->h-15.); + glVertex2d(x+w->w-3., y+w->h-10.); + glVertex2d(x+w->w-6., y+w->h-6.); + glVertex2d(x+w->w-10., y+w->h-3.); + glVertex2d(x+w->w-15., y+w->h-1.); + glVertex2d(x+w->w-21., y+w->h); + glEnd(); + + // Inner outline. + glShadeModel(GL_SMOOTH); + 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.); + 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); + // 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. + 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); + glEnd(); + + // Outter outline. + glShadeModel(GL_SMOOTH); + 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.); + // 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. glEnd(); // Widgets. @@ -189,13 +363,14 @@ static void window_render(Window* w) { toolkit_renderButton(&w->widgets[i], x, y); break; case WIDGET_TEXT: + toolkit_renderText(&w->widgets[i], x, y); break; } } } static void toolkit_renderButton(Widget* btn, double bx, double by) { - glColour* c; + glColour* c, *dc, *oc, *lc; double x, y; int j; @@ -204,32 +379,118 @@ static void toolkit_renderButton(Widget* btn, double bx, double by) { switch(btn->status) { // Set the color. - case WIDGET_STATUS_NORMAL: c = &cDarkGrey; break; - case WIDGET_STATUS_MOUSEOVER: c = &cGrey; break; - case WIDGET_STATUS_MOUSEDOWN: c = &cGreen; break; + case WIDGET_STATUS_NORMAL: + lc = &cGrey80; + c = &cGrey60; + dc = &cGrey40; + oc = &cGrey20; + break; + case WIDGET_STATUS_MOUSEOVER: + lc = &cWhite; + c = &cGrey80; + dc = &cGrey60; + oc = &cGrey40; + break; + case WIDGET_STATUS_MOUSEDOWN: + lc = &cGreen; + c = &cGreen; + dc = &cGrey40; + oc = &cGrey20; + break; } + // Shaded base. glShadeModel(GL_SMOOTH); glBegin(GL_QUADS); + COLOUR(*dc); + glVertex2d(x, y+2/3*btn->h); + glVertex2d(x+btn->w, y+2/3*btn->h); COLOUR(*c); - glVertex2d(x, y + 2/3*btn->h); - glVertex2d(x + btn->w, y + 2/3*btn->h); - glVertex2d(x + btn->w, y + btn->h); - glVertex2d(x, y + btn->h); + glVertex2d(x+btn->w, y+0.6*btn->h); + glVertex2d(x, y+0.6*btn->h); glEnd(); - j = gl_printWidth(NULL, btn->string); - gl_print(NULL, - bx + (double)gl_screen.w/2. + btn->x + (btn->w - (double)j)/2, + glShadeModel(GL_FLAT); + glBegin(GL_QUADS); + COLOUR(*c); + glVertex2d(x, y+0.6*btn->h); + glVertex2d(x+btn->w, y+0.6*btn->h); + glVertex2d(x+btn->w, y+btn->h); + glVertex2d(x, y+btn->h); + glEnd(); + + // Inner outline. + glShadeModel(GL_SMOOTH); + // Left. + glBegin(GL_LINES); + 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); + glVertex2d(x+btn->w, y+btn->h); + glEnd(); + + glShadeModel(GL_FLAT); + // Bottom. + glBegin(GL_LINES); + 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); + glEnd(); + + // Outter outline. + glBegin(GL_LINE_LOOP); + COLOUR(cBlack); + // Left. + glVertex2d(x-1., y); + glVertex2d(x-1., y+btn->h); + // Top. + glVertex2d(x, y+btn->h+1.); + glVertex2d(x+btn->w, y+btn->h+1.); + // Right. + glVertex2d(x+btn->w+1., y+btn->h); + glVertex2d(x+btn->w+1., y); + // Bottom. + glVertex2d(x+btn->w, y-1.); + glVertex2d(x, y-1.); + 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); } +static void toolkit_renderText(Widget* txt, double bx, double by) { + 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); +} + // Render the window. void toolkit_render(void) { int i; + + if(gl_has(OPENGL_AA_LINE)) glEnable(GL_LINE_SMOOTH); + if(gl_has(OPENGL_AA_POLYGON)) glEnable(GL_POLYGON_SMOOTH); + for(i = 0; i < nwindows; i++) window_render(&windows[i]); + + if(gl_has(OPENGL_AA_LINE)) glDisable(GL_LINE_SMOOTH); + if(gl_has(OPENGL_AA_POLYGON)) glDisable(GL_POLYGON_SMOOTH); + } // Input. diff --git a/src/toolkit.h b/src/toolkit.h index 8b98af0..b601057 100644 --- a/src/toolkit.h +++ b/src/toolkit.h @@ -11,6 +11,9 @@ void window_addButton(const unsigned int wid, const int x, const int y, const int w, const int h, char* name, char* display, void(*call)(char*)); +void window_addText(const unsigned int wid, const int x, const int y, + const int w, const int h, char* name, glFont* font, glColour* colour); + // Destroy window. void window_destroy(const unsigned int wid);