/****** SDL opengl renderer ******/ #include #include "../ui/elements.h" #include "r_gl.h" #include "interface.h" #include "../globals.h" void r_gl_Init() { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if ((screen = SDL_SetVideoMode(g_video_width, g_video_height, 32, SDL_HWSURFACE|SDL_OPENGL|SDL_RESIZABLE|g_video_fullscreen)) == NULL) return; // TODO: handle error glEnable( GL_TEXTURE_2D ); glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); glViewport( 0, 0, g_video_width, g_video_height); glClear( GL_COLOR_BUFFER_BIT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho(0.0f, g_video_width, g_video_height, 1.0f, -1.0f, 1.0f); //glOrtho(0.0f, g_video_width, 0, g_video_height, -1.0f, 1.0f); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); /* enable transparency */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); /* spritesheets */ r_gl_createTexture(&(spritesheet_ui->texture), spritesheet_ui->surface); r_gl_createTexture(&((struct Spritesheet*)menu_bg)->texture, ((struct Spritesheet*)menu_bg)->surface); } void r_gl_Reinit() { } void r_gl_Close() { printf("closing gl\n"); } void r_gl_clearScreen() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void r_gl_renderScreen() { SDL_GL_SwapBuffers(); } void r_gl_renderElements(struct ElementList *list) { if (list == NULL) return; struct Element *current = list->first; while(current != NULL) { struct Element *next = current->next; r_gl_renderElement(current); current = next; } } void r_gl_renderElement(struct Element *element) { if (element == NULL) return; if (element->flags & E_FLAG_HIDE) return; if (element->flags & E_FLAG_UPDATE) { int x_start = element->sx*(g_video_width/3); int y_start = element->sy*(g_video_height/3); int x_offset = 0; int sprite_id = 0; switch (element->type) { case E_TYPE_TEXT: //r_gl_renderText(element->font, ((struct TextElement*)element->data)->string, element->dimen.x, element->dimen.y); r_gl_renderText(element->font, ((struct TextElement*)element->data)->string, element->dimen.x+x_start, element->dimen.y+y_start); break; case E_TYPE_BUTTON: switch (element->state) { case E_STATE_NORMAL: break; case E_STATE_ACTIVE: sprite_id += spritesheet_ui->columns; break; } //r_gl_renderSprite(spritesheet_ui, 0, element->dimen.x, element->dimen.y); r_gl_renderSprite(spritesheet_ui, NULL, sprite_id, element->dimen.x+x_start, element->dimen.y+y_start); x_offset += spritesheet_ui->s_width; int width; for (width = (element->dimen.w/spritesheet_ui->s_width)-2; width > 0; width-=2) { r_gl_renderSprite(spritesheet_ui, NULL, sprite_id+1, element->dimen.x+x_start+x_offset, element->dimen.y+y_start); x_offset += spritesheet_ui->s_width; } r_gl_renderSprite(spritesheet_ui, NULL, sprite_id+2, element->dimen.x+x_start+x_offset, element->dimen.y+y_start); //r_gl_renderText(element->font, ((struct TextElement*)element->data)->string, element->dimen.x, element->dimen.y); //r_gl_renderText(element->font, ((struct TextElement*)element->data)->string, element->dimen.x+x_start+(6*spritesheet_ui->scale_x), element->dimen.y+y_start+(14*spritesheet_ui->scale_y)); r_gl_renderText(element->font, ((struct TextElement*)element->data)->string, element->dimen.x+x_start+( (element->dimen.w/2) - (((struct Font*)element->font)->s_width * ((struct TextElement*)element->data)->length)/2 ), element->dimen.y+y_start+(14*spritesheet_ui->scale_y)); // render the shortkey fancy-like if (element->key != '\0') { // TODO: renderChar //r_gl_renderText(element->font, ((struct TextElement*)element->data)->string[element->key_pos], element->dimen.x+x_start+( (element->dimen.w/2) - (((struct Font*)element->font)->s_width * ((struct TextElement*)element->data)->length)/2 )+4, element->dimen.y+y_start+(14*spritesheet_ui->scale_y)); } break; default: break; } } } void r_gl_renderText(struct Font *font, const char *string, int x, int y) { if (font == NULL) { printf("font is null\n"); return; } if (font->texture == 0) { r_gl_createTexture(&font->texture, font->surface); } int i = 0; int x_offset, y_offset; int x_render = 0; int y_render = 0; /* get the width and height of each sprite in gl texture terms */ double sx = 1.0f/(font->surface->w / font->width); double sy = 1.0f/(font->surface->h / font->height); glBindTexture(GL_TEXTURE_2D, font->texture); while(string[i] != '\0') { switch(string[i]) { case '\n': y_render += font->height*font->scale_y; x_render = 0; break; default: y_offset = string[i] / 16; x_offset = string[i] - (y_offset*16); /* get the texture offsets for the target sprite */ double tx = (x_offset == 0 ? 0.0f : 1.0f/((float)(16.0f/x_offset))); double ty = (y_offset == 0 ? 0.0f : 1.0f/(8.0f/y_offset)); /* reset view */ glLoadIdentity(); /* draw a clipped portion of our font texture to a quad*/ glTranslated(x+x_render, y+y_render, 1.0f); //glTranslated(font->width, y_render, 0.0f); /* draw that quad !*/ glBegin(GL_QUADS); // tl //glTexCoord2d(tx,ty+sy); glVertex2f(0,0); glTexCoord2d(tx,ty); glVertex2f(0,0); // tr //glTexCoord2d(tx+sx,ty+sy); glVertex2f(font->width, 0); glTexCoord2d(tx+sx,ty); glVertex2f(font->width*font->scale_x, 0); // br //glTexCoord2d(tx+sx,ty); glVertex2f(font->width, font->height); glTexCoord2d(tx+sx,ty+sy); glVertex2f(font->width*font->scale_x, font->height*font->scale_y); // bl //glTexCoord2d(tx,ty); glVertex2f(0,font->height); glTexCoord2d(tx,ty+sy); glVertex2f(0,font->height*font->scale_y); glEnd(); x_render += font->width*font->scale_x; break; } i++; } glLoadIdentity(); } void r_gl_renderSprite(struct Spritesheet *sheet, void *surface, int id, int x, int y) { /* get the width and height of each sprite in gl texture terms */ float sx = 1.0f/(sheet->surface->w / sheet->width); float sy = 1.0f/(sheet->surface->h / sheet->height); int y_offset = id / sheet->columns; int x_offset = id - (y_offset*sheet->columns); /* get the texture offsets for the target sprite */ float tx = (x_offset == 0 ? 0.0f : 1.0f/((float)((float)sheet->columns/(float)x_offset))); float ty = (y_offset == 0 ? 0.0f : 1.0f/((float)(((float)sheet->surface->h/(float)sheet->height)/(float)y_offset))); /* reset view */ glLoadIdentity(); /* bind our texture */ glBindTexture(GL_TEXTURE_2D, sheet->texture); /* draw a clipped portion of our sheet texture to a quad*/ glTranslated(x, y, 0.0f); /* draw that quad !*/ glBegin(GL_QUADS); // tl glTexCoord2d(tx,ty); glVertex2f(0,0); // tr glTexCoord2d(tx+sx,ty); glVertex2f(sheet->width*sheet->scale_x, 0); // br glTexCoord2d(tx+sx,ty+sy); glVertex2f(sheet->width*sheet->scale_x, sheet->height*sheet->scale_y); // bl glTexCoord2d(tx,ty+sy); glVertex2f(0,sheet->height*sheet->scale_y); glEnd(); //glLoadIdentity(); } GLuint r_gl_createTexture(GLuint *texture, SDL_Surface *surface) { GLenum format; GLint colors = surface->format->BytesPerPixel; if (colors == 4) { // with alpha if (surface->format->Rmask == 0x000000ff) { format = GL_RGBA; } else { format = GL_BGRA; } } else if (colors == 3) { if (surface->format->Rmask == 0x000000ff) { format = GL_RGB; } else { format = GL_BGR; } } else { // non truecolor, handle error or convert } // generate texture handle glGenTextures(1, texture); // bind the texture object glBindTexture(GL_TEXTURE_2D, *texture); // set stretching properties glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // get the appropriate endianness for data packing int num = 1; int pack_type = ( (*(char*)&num == 1) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_8_8_8_8_REV); // unsigned char vs reversed uint? Doesn't seem right... // copy it over! :) glTexImage2D(GL_TEXTURE_2D, 0, colors, surface->w, surface->h, 0, format, pack_type, surface->pixels); return *texture; } void r_gl_setupElement(struct Element *element) { // set default font setElementFont(element, g_font_medium); // set our element's free/clean event function setElementEvent(element, E_EVENT_FREE, &r_gl_cleanElement); setElementEvent(element, E_EVENT_CHANGE, &genElementDimensions); } int r_gl_loadSpritesheet(struct Spritesheet *spritesheet, char *file_name, int width, int height, int columns) { int ret; if ((ret = loadSpritesheetFromFile(spritesheet, file_name, width, height, columns)) == 0) { r_gl_createTexture(&spritesheet->texture, spritesheet->surface); } return ret; } void r_gl_cleanElement(struct Element *element) { printf("cleaning element in opengl\n"); } void r_gl_changeElement(struct Element *element) { }