timesynk/tile_editor/sdl.c

425 lines
14 KiB
C

#include <SDL/SDL.h>
#if !defined (__APPLE__)
#include <SDL/SDL_image.h>
#else
#include <SDL_image.h>
#endif
#include "stubs.h"
#include "sdl.h"
#include "assets.h"
#include "elements.h"
#include "font.h"
int interfaceInit() {
// since we use threads, Mac OS 10+ support only. Also threaded os.
SDL_Init(SDL_INIT_VIDEO);
// Enable Unicode, for later text input
SDL_EnableUNICODE(SDL_ENABLE);
// Set up our SDL Window
if ((screen = SDL_SetVideoMode(320, 480, 32, SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE)) == NULL) {
return -1;
}
SDL_WM_SetCaption("Tile Editor", NULL);
menu_area = SDL_CreateRGBSurface(screen->flags, screen->w, 104, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
tile_area_rect.y = 104;
tile_area = SDL_CreateRGBSurface(screen->flags, screen->w, 384, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
loadFont(&font, font_images, font_images_length, 8, 8);
first_element = NULL;
// load up our elements
button_quit = newElement(TYPE_BUTTON);
setElementText(button_quit, "QUIT");
setElementPosition(button_quit, screen->w - getElementWidth(button_quit)-2, 2);
setElementCallback(button_quit, &Quit);
addElement(button_quit, menu_area);
text_console = newElement(TYPE_TEXT);
setElementPosition(text_console, 0, 0);
addElement(text_console, menu_area);
/* graphics input */
text_graphics = newElement(TYPE_TEXT);
setElementText(text_graphics, "graphics:");
setElementPosition(text_graphics, 2, 2 + font.height*3);
addElement(text_graphics, menu_area);
input_graphics = newElement(TYPE_TEXT_INPUT);
setElementPosition(input_graphics, getElementWidth(text_graphics) + font.width + 4, 2 + font.height*3);
setElementSize(input_graphics, 16);
addElement(input_graphics, menu_area);
button_graphics = newElement(TYPE_BUTTON);
setElementText(button_graphics, "load");
setElementPosition(button_graphics, getElementWidth(text_graphics) + getElementWidth(input_graphics) + (font.width*2) + 4, 2 + font.height*3);
setElementCallback(button_graphics, &loadGraphicsCallback);
addElement(button_graphics, menu_area);
/* tileset data input */
text_data = newElement(TYPE_TEXT);
setElementText(text_data, "data: ");
setElementPosition(text_data, 2, 2 + font.height*5);
addElement(text_data, menu_area);
input_data = newElement(TYPE_TEXT_INPUT);
setElementPosition(input_data, getElementWidth(text_data) + font.width + 4, 2 + font.height*5);
setElementSize(input_data, 16);
addElement(input_data, menu_area);
button_data = newElement(TYPE_BUTTON);
setElementText(button_data, "load");
setElementPosition(button_data, getElementWidth(text_data) + getElementWidth(input_data) + (font.width*2) + 4, 2 + font.height*5);
setElementCallback(button_data, &loadDataCallback);
addElement(button_data, menu_area);
button_data_save = newElement(TYPE_BUTTON);
setElementText(button_data_save, "save");
setElementPosition(button_data_save, getElementWidth(text_data) + getElementWidth(input_data) + getElementWidth(button_data) + (font.width*3) + 4, 2 + font.height*5);
setElementCallback(button_data_save, &saveDataCallback);
addElement(button_data_save, menu_area);
/* set input */
text_set = newElement(TYPE_TEXT);
setElementText(text_set, "set:");
setElementPosition(text_set, 2, 2 + font.height*8);
addElement(text_set, menu_area);
input_set = newElement(TYPE_TEXT_INPUT);
setElementPosition(input_set, getElementWidth(text_set) + font.width + 4, 2 + font.height*8);
setElementSize(input_set, 3);
addElement(input_set, menu_area);
button_set = newElement(TYPE_BUTTON);
setElementText(button_set, "ok");
setElementPosition(button_set, getElementWidth(text_set) + getElementWidth(input_set) + (font.width*2) + 4, 2 + font.height*8);
setElementCallback(button_set, &setSetCallback);
addElement(button_set, menu_area);
/* tile id input */
text_id = newElement(TYPE_TEXT);
setElementText(text_id, "id: ");
setElementPosition(text_id, 2, 2 + font.height*10);
addElement(text_id, menu_area);
input_id = newElement(TYPE_TEXT_INPUT);
setElementPosition(input_id, getElementWidth(text_id) + font.width + 4, 2 + font.height*10);
setElementSize(input_id, 3);
addElement(input_id, menu_area);
button_id = newElement(TYPE_BUTTON);
setElementText(button_id, "ok");
setElementPosition(button_id, getElementWidth(text_id) + getElementWidth(input_id) + (font.width*2) + 4, 2 + font.height*10);
setElementCallback(button_id, &setIdCallback);
addElement(button_id, menu_area);
SDL_FillRect(menu_area, NULL, SDL_MapRGB(menu_area->format, 8, 16, 12));
SDL_Rect tile_rect = { getElementWidth(button_id) + getElementWidth(text_id) + getElementWidth(input_id) + (font.width*3) + 4, 2 + font.height*8, 32, 32};
SDL_FillRect(menu_area, &tile_rect, SDL_MapRGB(menu_area->format, 0, 0, 0));
drawElement(button_quit);
drawElement(text_graphics);
drawElement(input_graphics);
drawElement(button_graphics);
drawElement(text_data);
drawElement(input_data);
drawElement(button_data);
drawElement(button_data_save);
drawElement(text_set);
drawElement(input_set);
drawElement(button_set);
drawElement(text_id);
drawElement(input_id);
drawElement(button_id);
clearElement(text_console);
setElementText(text_console, "welcome to the tile editor");
drawElement(text_console);
SDL_BlitSurface(menu_area, NULL, screen, NULL);
/* now load up our tile area stuff */
text_name = newElement(TYPE_TEXT);
setElementText(text_name, "...... name ......");
setElementPosition(text_name, 2, 2);
addElement(text_name, tile_area);
text_value = newElement(TYPE_TEXT);
setElementText(text_value, "...... value ......");
setElementPosition(text_value, 2 + (20 * font.width), 2);
addElement(text_value, tile_area);
drawElement(text_name);
drawElement(text_value);
SDL_BlitSurface(tile_area, NULL, screen, &tile_area_rect);
SDL_Flip(screen);
return 0;
}
int interfaceLoop() {
while (SDL_WaitEvent(&event)) {
switch(event.type) {
case SDL_QUIT:
return 0;
break;
case SDL_MOUSEBUTTONDOWN:
handleMouseDown(&event.button);
break;
case SDL_MOUSEBUTTONUP:
handleMouseUp(&event.button);
break;
case SDL_MOUSEMOTION:
handleMouseMove(&event.motion);
break;
default:
break;
}
//SDL_BlitSurface(menu_area, &update_rect, screen, &update_rect);
SDL_BlitSurface(menu_area, NULL, screen, NULL);
SDL_Flip(screen);
}
return 0;
}
void interfaceClose() {
SDL_FreeSurface(screen);
SDL_Quit();
}
void Quit() {
SDL_Event event;
event.type = SDL_QUIT;
SDL_PushEvent(&event);
}
void addElement(struct Element *element, SDL_Surface *surface) {
if (first_element == NULL) {
first_element = element;
} else {
struct Element *t_element = first_element;
while (t_element->next != NULL) {
t_element = t_element->next;
}
t_element->next = element;
}
element->user = surface;
}
/* drawing functions */
void drawElement(const struct Element *element) {
if (element != NULL) {
SDL_Rect get_rect_son = {element->x, element->y, 0, 0};
switch (element->type) {
case TYPE_BUTTON:
// clear area
get_rect_son.w = (font.width * ((struct ButtonElement*)element->data)->length) + 4;
get_rect_son.h = font.height + 4;
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 8, 16, 12));
if (element->state == STATE_NORMAL) {
get_rect_son.w = (font.width * ((struct ButtonElement*)element->data)->length) + 2;
get_rect_son.h = font.height + 2;
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 32, 32, 48));
get_rect_son.x = element->x+2;
get_rect_son.y = element->y+2;
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 48, 48, 64));
drawString(&font, element->user, element->x+3, element->y+3, ((struct ButtonElement*)element->data)->string);
} else if (element->state == STATE_PRESSED) {
get_rect_son.w = (font.width * ((struct ButtonElement*)element->data)->length) + 2;
get_rect_son.h = font.height + 2;
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 32, 32, 48));
get_rect_son.x = element->x+1;
get_rect_son.y = element->y+1;
get_rect_son.w = (font.width * ((struct ButtonElement*)element->data)->length) + 2;
get_rect_son.h = font.height + 2;
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 48, 48, 64));
drawString(&font, element->user, element->x+2, element->y+2, ((struct ButtonElement*)element->data)->string);
}
break;
case TYPE_TEXT:
get_rect_son.w = (font.width * ((struct TextElement*)element->data)->length) + 2;
get_rect_son.h = font.height + 2;
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 32, 32, 48));
drawString(&font, element->user, element->x+1, element->y+1, ((struct TextElement*)element->data)->string);
break;
case TYPE_TEXT_INPUT:
get_rect_son.x = element->x-1;
get_rect_son.y = element->y-1;
get_rect_son.w = (font.width * ((struct TextInputElement*)element->data)->size) + 4;
get_rect_son.h = font.height + 4;
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 48, 48, 64));
get_rect_son.x = element->x;
get_rect_son.y = element->y;
get_rect_son.w = (font.width * ((struct TextInputElement*)element->data)->size) + 2;
get_rect_son.h = font.height + 2;
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 32, 32, 48));
break;
}
}
}
void drawChar(const struct Font *font, SDL_Surface *surface, int x, int y, const char ch) {
int y_offset = ch / 16;
int x_offset = ch - (y_offset*16);
SDL_Rect character_offset = { x_offset*font->width, y_offset*font->height, font->width, font->height};
SDL_Rect render_position = {x, y, font->width, font->height};
SDL_BlitSurface(font->surface, &character_offset, surface, &render_position);
}
void drawString(const struct Font *font, SDL_Surface *surface, int x, int y, const char *string) {
int i = 0;
while (string[i] != '\0') {
drawChar(font, surface, x + (i*font->width), y, string[i]);
i++;
}
}
void clearElement(const struct Element* element) {
SDL_Rect clear_rect = { element->x, element->y, getElementWidth(element), getElementHeight(element) };
SDL_FillRect(element->user, &clear_rect, SDL_MapRGB(screen->format, 8, 16, 12));
}
/* Element information functions */
int getElementWidth(const struct Element* element) {
switch (element->type) {
case TYPE_TEXT_INPUT:
return (font.width * ((struct TextInputElement*)element->data)->size) + 4;
break;
case TYPE_TEXT:
return (font.width * ((struct TextElement*)element->data)->length) + 2;
break;
case TYPE_BUTTON:
return (font.width * ((struct ButtonElement*)element->data)->length) + 4;
break;
default:
break;
}
return 0;
}
int getElementHeight(const struct Element* element) {
switch (element->type) {
case TYPE_TEXT_INPUT:
return font.height+4;
break;
case TYPE_TEXT:
return font.height*2;
break;
case TYPE_BUTTON:
return font.height + 4;
break;
default:
break;
}
return 0;
}
/* begin handler functions */
void handleMouseDown(const SDL_MouseButtonEvent *event) {
struct Element *element = first_element;
int t_x, t_y, t_w, t_h = 0;
while (element != NULL) {
switch (element->type) {
case TYPE_BUTTON:
t_w = element->x+2 +(font.width * ((struct ButtonElement*)element->data)->length) + 2;
t_h = element->y+2 + font.height + 2;
t_x = element->x+2;
t_y = element->y+2;
break;
}
if ((t_x <= event->x && t_w >= event->x) && (t_y <= event->y && t_h >= event->y)) {
element->state = STATE_PRESSED;
last_element = element;
drawElement(element);
break;
}
element = element->next;
}
update_rect.x = t_x-2;
update_rect.y = t_y-2;
update_rect.w = t_w+2;
update_rect.h = t_h+2;
}
void handleMouseUp(const SDL_MouseButtonEvent *event) {
if (last_element != NULL) {
int t_x, t_y, t_w, t_h = 0;
switch (last_element->type) {
case TYPE_BUTTON:
t_w = last_element->x+2 +(font.width * ((struct ButtonElement*)last_element->data)->length) + 2;
t_h = last_element->y+2 + font.height + 2;
t_x = last_element->x+2;
t_y = last_element->y+2;
break;
}
last_element->state = STATE_NORMAL;
drawElement(last_element);
if ((t_x <= event->x && t_w >= event->x) && (t_y <= event->y && t_h >= event->y)) {
if (last_element->callback != NULL) {
last_element->callback();
}
}
update_rect.x = t_x-2;
update_rect.y = t_y-2;
update_rect.w = t_w+2;
update_rect.h = t_h+2;
}
}
void handleMouseMove(const SDL_MouseMotionEvent *event) {
}
/* button callback */
void loadGraphicsCallback() {
clearElement(text_console);
setElementText(text_console, "loading gfx");
drawElement(text_console);
}
void loadDataCallback() {
clearElement(text_console);
setElementText(text_console, "loading data");
drawElement(text_console);
}
void saveDataCallback() {
clearElement(text_console);
setElementText(text_console, "saving data");
drawElement(text_console);
}
void setSetCallback() {
char temp[16];
sprintf(temp, "OK: using set %s", getElementText(input_set));
clearElement(text_console);
setElementText(text_console, temp);
drawElement(text_console);
}
void setIdCallback() {
char temp[16];
sprintf(temp, "OK: using id %s", getElementText(input_id));
clearElement(text_console);
setElementText(text_console, temp);
drawElement(text_console);
}
/* font stuff */
void loadFont(struct Font *font, unsigned char *memory, unsigned int length, int width, int height) {
font->width = width;
font->height = height;
font->surface = IMG_Load_RW(SDL_RWFromMem(memory, length), 1);
}
void freeFont(struct Font *font) {
SDL_FreeSurface(font->surface);
}