122 lines
3.4 KiB
C
122 lines
3.4 KiB
C
#include <SDL2/SDL_image.h>
|
|
#include <stdlib.h>
|
|
#include "opengl.h"
|
|
#include "FrameSheet.h"
|
|
#include "fifo.h"
|
|
#include "report.h"
|
|
#include "string.h"
|
|
|
|
struct FrameSheet *newFrameSheet() {
|
|
struct FrameSheet *sheet = malloc(sizeof(struct FrameSheet));
|
|
sheet->textures = NULL;
|
|
sheet->surfaces = NULL;
|
|
sheet->count = 0;
|
|
sheet->state = 0;
|
|
return sheet;
|
|
}
|
|
|
|
struct FrameSheet *loadFrameSheet(const char *name, const char *framedir) {
|
|
if (framedir == NULL) return NULL;
|
|
struct Dir *dir = openDir(framedir, 0);
|
|
if (dir == NULL) {
|
|
report(ERROR, "loadFrameSheet", "dir %s does not exist", framedir);
|
|
return NULL;
|
|
}
|
|
struct FrameSheet *sheet = newFrameSheet();
|
|
struct DirEntry *entry;
|
|
while ((entry = readDir(dir)) != NULL) {
|
|
if (entry->d_type != F_REG) continue;
|
|
char *filename = NULL;
|
|
filename = setStringF(filename, "%s/%s", framedir, entry->d_name);
|
|
SDL_Surface *surface = NULL;
|
|
if ((surface = IMG_Load(filename)) == NULL) {
|
|
report(ERROR, "loadFrameSheet", "error loading surface: %s", SDL_GetError());
|
|
free(filename);
|
|
continue;
|
|
}
|
|
free(filename);
|
|
// seems valid, let's add it as a frame
|
|
sheet->count++;
|
|
sheet->surfaces = realloc(sheet->surfaces, sheet->count*sizeof(SDL_Surface*));
|
|
if (sheet->surfaces == NULL) {
|
|
report(ERROR, "loadFrameSheet", "could not realloc surfaces");
|
|
freeFrameSheet(sheet);
|
|
return NULL;
|
|
}
|
|
sheet->surfaces[sheet->count-1] = surface;
|
|
}
|
|
sheet->textures = realloc(sheet->textures, sheet->count*sizeof(GLuint));
|
|
closeDir(dir);
|
|
return sheet;
|
|
}
|
|
int freeFrameSheet(struct FrameSheet *sheet) {
|
|
if (sheet == NULL) return 1;
|
|
int i;
|
|
if (sheet->surfaces != NULL) {
|
|
for (i = 0; i < sheet->count; i++) {
|
|
SDL_FreeSurface(sheet->surfaces[i]);
|
|
}
|
|
free(sheet->surfaces);
|
|
}
|
|
// clean up textures if open
|
|
if (sheet->textures != NULL) {
|
|
closeFrameSheet(sheet);
|
|
free(sheet->textures);
|
|
}
|
|
free(sheet);
|
|
return 0;
|
|
}
|
|
int openFrameSheet(struct FrameSheet *sheet) {
|
|
if (sheet == NULL) return 1;
|
|
if (sheet->state == 0) {
|
|
int i;
|
|
for (i = 0; i < sheet->count; i++) {
|
|
sheet->textures[i] = createTexture(sheet->surfaces[i]);
|
|
}
|
|
}
|
|
sheet->state = 1;
|
|
return 0;
|
|
}
|
|
int closeFrameSheet(struct FrameSheet *sheet) {
|
|
if (sheet == NULL) return 1;
|
|
if (sheet->state == 1) {
|
|
int i;
|
|
for (i = 0; i < sheet->count; i++) {
|
|
glDeleteTextures(1, &sheet->textures[i]);
|
|
}
|
|
}
|
|
sheet->state = 0;
|
|
return 0;
|
|
}
|
|
int renderFrame(struct FrameSheet *sheet, int frame, int x, int y) {
|
|
if (sheet == NULL) return 1;
|
|
if (frame < 0 || frame >= sheet->count) return 2;
|
|
if (sheet->state == 0) {
|
|
openFrameSheet(sheet);
|
|
}
|
|
x -= sheet->surfaces[frame]->w/2;
|
|
y -= sheet->surfaces[frame]->h/2;
|
|
float sx = sheet->surfaces[frame]->w;
|
|
float sy = sheet->surfaces[frame]->h;
|
|
// bind our texture
|
|
glBindTexture(GL_TEXTURE_2D, sheet->textures[frame]);
|
|
// make sure we're rendering textures
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
// reset view
|
|
glLoadIdentity();
|
|
// translate to a quad
|
|
glTranslated(x, y, 1.0f);
|
|
// draw !
|
|
glBegin(GL_QUADS);
|
|
// top left
|
|
glTexCoord2d(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
|
|
// top right
|
|
glTexCoord2d(1.0, 0.0f); glVertex2f(sx, 0.0f);
|
|
// bottom right
|
|
glTexCoord2d(1.0f, 1.0f); glVertex2f(sx, sy);
|
|
// bottom left
|
|
glTexCoord2d(0.0f, 1.0f); glVertex2f(0.0f, sy);
|
|
glEnd();
|
|
return 0;
|
|
}
|