260 lines
9.1 KiB
C
260 lines
9.1 KiB
C
/******
|
|
SDL opengl renderer
|
|
******/
|
|
#include <SDL/SDL_opengl.h>
|
|
#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) {
|
|
}
|