1770 lines
65 KiB
C
1770 lines
65 KiB
C
#include <SDL/SDL.h>
|
|
#if !defined (__APPLE__)
|
|
#include <SDL/SDL_image.h>
|
|
#else
|
|
#include <SDL_image.h>
|
|
#include "CoreFoundation/CoreFoundation.h" // yee apple path rubbish
|
|
#endif
|
|
|
|
#include <SDL/SDL_syswm.h> // for wm hints
|
|
|
|
#include <unistd.h> // for getcwd
|
|
|
|
#include "stubs.h"
|
|
#include "sdl.h"
|
|
#include "assets.h"
|
|
#include "elements.h"
|
|
#include "font.h"
|
|
|
|
#include "../common/data.h"
|
|
#include "../common/fio.h"
|
|
|
|
int interfaceInit() {
|
|
#ifdef __APPLE__
|
|
char path[PATH_MAX];
|
|
CFURLRef res = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
|
|
CFURLGetFileSystemRepresentation(res, TRUE, (UInt8 *)path, PATH_MAX);
|
|
CFRelease(res);
|
|
// there's likely a better way to do this!
|
|
size_t path_len = strlen(path);
|
|
int p_i = path_len;
|
|
int p_c = 0;
|
|
while (p_i > 0) {
|
|
if (path[p_i] == '/') {
|
|
p_c++;
|
|
}
|
|
if (p_c == 3) break;
|
|
p_i--;
|
|
}
|
|
char bundle_path[p_i+1];
|
|
memcpy(bundle_path, path, p_i);
|
|
bundle_path[p_i] = '\0';
|
|
chdir(bundle_path);
|
|
#endif
|
|
// TODO: move to newData function
|
|
tiles_data = malloc(sizeof(struct Data));
|
|
tiles_data->size = SET_SIZE;
|
|
tiles_data->id = malloc(sizeof(int)*SET_SIZE);
|
|
tiles_data->set = malloc(sizeof(struct TileSetData*)*SET_SIZE);
|
|
memset(tiles_data->set, 0, sizeof(struct TileSetData*)*SET_SIZE);
|
|
tiles_data->set_count = 0;
|
|
// TODO: move to newTileSetData function or similar
|
|
int i=0;
|
|
while (i < 7) {
|
|
tiles_data->set[i] = malloc(sizeof(struct TileSetData));
|
|
tiles_data->set[i]->tid = i;
|
|
tiles_data->set[i]->tile_count = 0;
|
|
tiles_data->set[i]->size = SET_SIZE;
|
|
tiles_data->set[i]->keys = newTable(SET_SIZE);
|
|
tiles_data->set[i]->tile = malloc(sizeof(struct TileData*)*SET_SIZE);
|
|
int j = 0;
|
|
while (j < SET_SIZE) {
|
|
tiles_data->set[i]->tile[j++] = NULL;
|
|
}
|
|
i++;
|
|
}
|
|
g_data = 1;
|
|
|
|
g_width = 400;
|
|
g_height = 480;
|
|
// 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(g_width, g_height, 32, SDL_SWSURFACE|SDL_DOUBLEBUF)) == NULL) {
|
|
return -1;
|
|
}
|
|
SDL_WM_SetCaption("TS:Tile Editor", NULL);
|
|
menu_area = SDL_CreateRGBSurface(screen->flags, g_width, 112, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
|
tile_area_rect.y = 112;
|
|
tile_area = SDL_CreateRGBSurface(screen->flags, g_width, 392, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
|
|
|
sprite_area_rect.x = g_width;
|
|
sprite_area = SDL_CreateRGBSurface(screen->flags, g_width, screen->h, 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;
|
|
last_element = NULL;
|
|
focus_element = NULL;
|
|
|
|
menu_elements = newElementList();
|
|
hookElementList(menu_elements, HOOK_ADD, &addElementHook);
|
|
setElementListUser(menu_elements, menu_area);
|
|
|
|
editor_elements = newElementList();
|
|
hookElementList(editor_elements, HOOK_ADD, &addElementHook);
|
|
setElementListUser(editor_elements, tile_area);
|
|
|
|
// load up our elements
|
|
button_quit = newElement(TYPE_BUTTON);
|
|
setElementText(button_quit, "QUIT");
|
|
setElementPosition(button_quit, menu_area->w - getElementWidth(button_quit)-13, 2+font.height*2);
|
|
setElementCallback(button_quit, &Quit);
|
|
addElementToList(menu_elements, button_quit);
|
|
|
|
text_console = newElement(TYPE_TEXT);
|
|
//setElementPosition(text_console, 0, 2+font.height*2);
|
|
setElementPosition(text_console, 0, 2);
|
|
addElementToList(menu_elements, text_console);
|
|
|
|
/* graphics input */
|
|
text_graphics = newElement(TYPE_TEXT);
|
|
setElementText(text_graphics, "graphics:");
|
|
setElementPosition(text_graphics, 2, 2 + font.height*4);
|
|
addElementToList(menu_elements, text_graphics);
|
|
|
|
input_graphics = newElement(TYPE_TEXT_INPUT);
|
|
setElementPosition(input_graphics, getElementWidth(text_graphics) + font.width + 4, 2 + font.height*4);
|
|
setElementCallback(input_graphics, &loadGraphicsCallback);
|
|
setElementSize(input_graphics, 27);
|
|
addElementToList(menu_elements, input_graphics);
|
|
|
|
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*4);
|
|
setElementCallback(button_graphics, &loadGraphicsCallback);
|
|
addElementToList(menu_elements, button_graphics);
|
|
|
|
/* tileset data input */
|
|
text_data = newElement(TYPE_TEXT);
|
|
setElementText(text_data, "data: ");
|
|
setElementPosition(text_data, 2, 2 + font.height*6);
|
|
addElementToList(menu_elements, text_data);
|
|
|
|
input_data = newElement(TYPE_TEXT_INPUT);
|
|
setElementPosition(input_data, getElementWidth(text_data) + font.width + 4, 2 + font.height*6);
|
|
setElementCallback(input_data, &loadDataCallback);
|
|
setElementSize(input_data, 27);
|
|
addElementToList(menu_elements, input_data);
|
|
|
|
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*6);
|
|
setElementCallback(button_data, &loadDataCallback);
|
|
addElementToList(menu_elements, button_data);
|
|
|
|
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*6);
|
|
setElementCallback(button_data_save, &saveDataCallback);
|
|
addElementToList(menu_elements, button_data_save);
|
|
|
|
/* set input */
|
|
text_set = newElement(TYPE_TEXT);
|
|
setElementText(text_set, "set:");
|
|
setElementPosition(text_set, 2, 2 + font.height*9);
|
|
addElementToList(menu_elements, text_set);
|
|
|
|
g_set = 0;
|
|
input_set = newElement(TYPE_SPINNER);
|
|
setElementPosition(input_set, getElementWidth(text_set) + font.width + 4, 2 + font.height*9);
|
|
setElementCallback(input_set, &setSetCallback);
|
|
setElementSize(input_set, 3);
|
|
setElementValue(input_set, 0);
|
|
addElementToList(menu_elements, input_set);
|
|
|
|
/*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*9);
|
|
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*11);
|
|
addElementToList(menu_elements, text_id);
|
|
|
|
g_id = 0;
|
|
input_id = newElement(TYPE_SPINNER);
|
|
setElementPosition(input_id, getElementWidth(text_id) + font.width + 4, 2 + font.height*11);
|
|
setElementCallback(input_id, &setIdCallback);
|
|
setElementSize(input_id, 3);
|
|
setElementValue(input_id, 0);
|
|
addElementToList(menu_elements, input_id);
|
|
|
|
SDL_FillRect(menu_area, NULL, SDL_MapRGB(menu_area->format, 8, 16, 12));
|
|
|
|
image_tile = newElement(TYPE_IMAGE);
|
|
//setElementPosition(image_tile, getElementWidth(button_id) + getElementWidth(text_id) + getElementWidth(input_id) + (font.width*3) + 4, 2 + font.height*9);
|
|
setElementPosition(image_tile, getElementWidth(text_set) + getElementWidth(input_set) + (font.width*3) + 4, 2 + font.height*9);
|
|
setElementCallback(image_tile, &showSpritesheet);
|
|
SDL_Surface *tile_surface = SDL_CreateRGBSurface(menu_area->flags, 32, 32, menu_area->format->BitsPerPixel, menu_area->format->Rmask, menu_area->format->Gmask, menu_area->format->Bmask, menu_area->format->Amask);
|
|
setElementImage(image_tile, tile_surface, 32, 32);
|
|
addElementToList(menu_elements, image_tile);
|
|
|
|
char cwd[128];
|
|
getcwd(cwd, sizeof(cwd));
|
|
printConsole(cwd);
|
|
|
|
/* now load up our tile area stuff */
|
|
/*text_name = newElement(TYPE_TEXT);
|
|
setElementText(text_name, "...... name ......");
|
|
setElementPosition(text_name, 2, 2);
|
|
addElementToList(editor_elements, text_name);
|
|
|
|
text_value = newElement(TYPE_TEXT);
|
|
setElementText(text_value, "...... value ......");
|
|
setElementPosition(text_value, 2 + (20 * font.width), 2);
|
|
addElementToList(editor_elements, text_value);*/
|
|
|
|
SDL_FillRect(tile_area, NULL, SDL_MapRGB(tile_area->format, 8, 16, 24));
|
|
|
|
drawElements();
|
|
|
|
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;
|
|
case SDL_KEYDOWN:
|
|
if (event.key.state == SDL_PRESSED) {
|
|
handleKeyDown(&event.key);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
//SDL_BlitSurface(menu_area, &update_rect, screen, &update_rect);
|
|
|
|
//SDL_Surface *scaled_area = SDL_ScaleSurface(menu_area, 2.0f, 2.0f);
|
|
SDL_BlitSurface(menu_area, NULL, screen, NULL);
|
|
SDL_BlitSurface(tile_area, NULL, screen, &tile_area_rect);
|
|
//SDL_BlitSurface(scaled_area, NULL, screen, NULL);
|
|
SDL_Flip(screen);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void interfaceClose() {
|
|
SDL_FreeSurface(screen);
|
|
struct Element *t_element = first_element;
|
|
while (t_element) {
|
|
struct Element *next_element = t_element->next;
|
|
if (t_element->type == TYPE_IMAGE) {
|
|
if (((struct ImageElement*)t_element->data)->image)
|
|
SDL_FreeSurface(((struct ImageElement*)t_element->data)->image);
|
|
}
|
|
freeElement(t_element);
|
|
t_element = next_element;
|
|
}
|
|
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;
|
|
}
|
|
|
|
void addElementHook(struct ElementList *list, struct Element *element) {
|
|
element->user = list->user;
|
|
}
|
|
|
|
void drawElements() {
|
|
struct Element *element = menu_elements->first;
|
|
while (element != NULL) {
|
|
drawElement(element);
|
|
element = element->next;
|
|
}
|
|
element = editor_elements->first;
|
|
while (element != NULL) {
|
|
drawElement(element);
|
|
element = element->next;
|
|
}
|
|
}
|
|
|
|
/* 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_SPINNER:
|
|
get_rect_son.x = element->x-1;
|
|
get_rect_son.y = element->y-1;
|
|
get_rect_son.w = font.width * ((((struct SpinnerElement*)element->data)->size)+1) + 4;
|
|
get_rect_son.h = font.height + 4;
|
|
if (element->state == STATE_FOCUS) {
|
|
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 128, 128, 200));
|
|
} else {
|
|
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 SpinnerElement*)element->data)->size)+1) + 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));
|
|
// draw string
|
|
drawString(&font, element->user, element->x+1, element->y+1, ((struct SpinnerElement*)element->data)->string);
|
|
if (element->state == STATE_FOCUS) {
|
|
get_rect_son.x = element->x + (font.width * ((struct SpinnerElement*)element->data)->cursor);
|
|
get_rect_son.y = element->y+1;
|
|
get_rect_son.w = 2;
|
|
get_rect_son.h = font.height;
|
|
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 128, 128, 200));
|
|
}
|
|
// draw button bg
|
|
get_rect_son.x = element->x + (font.width * ((((struct SpinnerElement*)element->data)->size)+1)) + 3;
|
|
get_rect_son.y = element->y-1;
|
|
get_rect_son.w = font.width + 2;
|
|
get_rect_son.h = font.height + 4;
|
|
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 32, 32, 48));
|
|
// draw top button
|
|
get_rect_son.x = element->x + (font.width * ((((struct SpinnerElement*)element->data)->size)+1)) + 4;
|
|
get_rect_son.y = element->y-1;
|
|
get_rect_son.w = font.width;
|
|
get_rect_son.h = font.height/2;
|
|
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 48, 48, 64));
|
|
get_rect_son.x = element->x + (font.width * ((((struct SpinnerElement*)element->data)->size)+1)) + 5;
|
|
get_rect_son.y = element->y;
|
|
get_rect_son.w = font.width-2;
|
|
get_rect_son.h = font.height/4;
|
|
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 128, 128, 200));
|
|
// draw bottom button
|
|
get_rect_son.x = element->x + (font.width * ((((struct SpinnerElement*)element->data)->size)+1)) + 4;
|
|
get_rect_son.y = element->y + 3 + font.height/2;
|
|
get_rect_son.w = font.width;
|
|
get_rect_son.h = font.height/2;
|
|
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 48, 48, 64));
|
|
get_rect_son.x = element->x + (font.width * ((((struct SpinnerElement*)element->data)->size)+1)) + 1 + font.width/2;
|
|
get_rect_son.y = element->y + font.height/2 + font.height/2;
|
|
get_rect_son.w = font.width-2;
|
|
get_rect_son.h = font.height/4;
|
|
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 128, 128, 200));
|
|
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;
|
|
if (element->state == STATE_FOCUS) {
|
|
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 128, 128, 200));
|
|
} else {
|
|
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));
|
|
// draw string
|
|
drawString(&font, element->user, element->x+1, element->y+1, ((struct TextInputElement*)element->data)->string);
|
|
if (element->state == STATE_FOCUS) {
|
|
get_rect_son.x = element->x + (font.width * ((struct TextInputElement*)element->data)->cursor);
|
|
get_rect_son.y = element->y+1;
|
|
get_rect_son.w = 2;
|
|
get_rect_son.h = font.height;
|
|
SDL_FillRect(element->user, &get_rect_son, SDL_MapRGB(((SDL_Surface*)element->user)->format, 128, 128, 200));
|
|
}
|
|
break;
|
|
case TYPE_IMAGE:
|
|
get_rect_son.w = ((struct ImageElement*)element->data)->width;
|
|
get_rect_son.h = ((struct ImageElement*)element->data)->height;
|
|
SDL_BlitSurface(((struct ImageElement*)element->data)->image, NULL, element->user, &get_rect_son);
|
|
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_SPINNER:
|
|
return font.width * (((struct SpinnerElement*)element->data)->size+2) + 4;
|
|
break;
|
|
case TYPE_BUTTON:
|
|
return (font.width * ((struct ButtonElement*)element->data)->length) + 4;
|
|
break;
|
|
case TYPE_IMAGE:
|
|
return ((struct ImageElement*)element->data)->width;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int getElementHeight(const struct Element* element) {
|
|
switch (element->type) {
|
|
case TYPE_TEXT_INPUT:
|
|
case TYPE_SPINNER:
|
|
return font.height+4;
|
|
break;
|
|
case TYPE_TEXT:
|
|
return font.height*2;
|
|
break;
|
|
case TYPE_BUTTON:
|
|
return font.height + 4;
|
|
break;
|
|
case TYPE_IMAGE:
|
|
return ((struct ImageElement*)element->data)->height;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* begin handler functions */
|
|
|
|
void handleKeyDown(const SDL_KeyboardEvent *event) {
|
|
printf("sdl keysym unicode: %d, scancode: %d, keycode: %d, mod: %d\n", event->keysym.unicode, event->keysym.scancode, event->keysym.sym, event->keysym.mod);
|
|
// F11 = fullscreen/windowed toggle
|
|
if (event->keysym.sym == 292) {
|
|
if (g_fullscreen == 1) {
|
|
screen = SDL_SetVideoMode(g_width, g_height, 32, SDL_SWSURFACE|SDL_DOUBLEBUF);
|
|
g_fullscreen = 0;
|
|
} else {
|
|
screen = SDL_SetVideoMode(g_width, g_height, 32, SDL_FULLSCREEN|SDL_SWSURFACE|SDL_DOUBLEBUF);
|
|
g_fullscreen = 1;
|
|
}
|
|
return;
|
|
} else if (event->keysym.sym == 9) { // tab
|
|
if (focus_element != NULL) {
|
|
if (focus_element->next != NULL) {
|
|
focus_element->state = STATE_NORMAL;
|
|
drawElement(focus_element);
|
|
focus_element = focus_element->next;
|
|
while (focus_element->next != NULL) {
|
|
if (focus_element->type == TYPE_SPINNER || focus_element->type == TYPE_TEXT_INPUT) {
|
|
break;
|
|
} else {
|
|
focus_element = focus_element->next;
|
|
}
|
|
}
|
|
focus_element->state = STATE_FOCUS;
|
|
drawElement(focus_element);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
int mod = SDL_GetModState();
|
|
if (focus_element != NULL) {
|
|
if (mod != 0) {
|
|
if (mod & KMOD_SHIFT) {
|
|
handleInputElement(focus_element, event->keysym.unicode);
|
|
} else {
|
|
handleInputElement(focus_element, event->keysym.sym);
|
|
}
|
|
} else {
|
|
handleInputElement(focus_element, event->keysym.sym);
|
|
}
|
|
drawElement(focus_element);
|
|
}
|
|
}
|
|
|
|
void handleMouseDown(const SDL_MouseButtonEvent *event) {
|
|
if (event->x >= menu_area->w) {
|
|
return;
|
|
}
|
|
int x_offset = 0;
|
|
int y_offset = 0;
|
|
struct Element *element = NULL;
|
|
if (event->x <= menu_area->w && event->y <= menu_area->h) {
|
|
element = menu_elements->first;
|
|
} else if (event->x <= tile_area->w && event->y <= tile_area->h) {
|
|
element = editor_elements->first;
|
|
x_offset = tile_area_rect.x;
|
|
y_offset = tile_area_rect.y;
|
|
}
|
|
int t_x, t_y, t_w, t_h = 0;
|
|
while (element != NULL) {
|
|
switch (element->type) {
|
|
case TYPE_BUTTON:
|
|
t_w = x_offset + element->x+2 +(font.width * ((struct ButtonElement*)element->data)->length) + 2;
|
|
t_h = y_offset + element->y+2 + font.height + 2;
|
|
t_x = x_offset + element->x+2;
|
|
t_y = y_offset + element->y+2;
|
|
break;
|
|
case TYPE_TEXT_INPUT:
|
|
t_w = x_offset + element->x-1 +(font.width * ((struct TextInputElement*)element->data)->size) + 4;
|
|
t_h = y_offset + element->y-1 + font.height + 4;
|
|
t_x = x_offset + element->x-1;
|
|
t_y = y_offset + element->y-1;
|
|
break;
|
|
case TYPE_SPINNER:
|
|
t_w = x_offset + element->x-1 + (font.width * (((struct SpinnerElement*)element->data)->size+2)) + 4;
|
|
t_h = y_offset + element->y-1 + font.height + 4;
|
|
t_x = x_offset + element->x-1;
|
|
t_y = y_offset + element->y-1;
|
|
break;
|
|
case TYPE_IMAGE:
|
|
t_w = x_offset + element->x + ((struct ImageElement*)element->data)->width;
|
|
t_h = y_offset + element->y + ((struct ImageElement*)element->data)->height;
|
|
t_x = x_offset + element->x;
|
|
t_y = y_offset + element->y;
|
|
break;
|
|
}
|
|
if ((t_x <= event->x && t_w >= event->x) && (t_y <= event->y && t_h >= event->y)) {
|
|
element->state = STATE_PRESSED;
|
|
if (last_element != NULL) {
|
|
if (last_element != element) {
|
|
last_element->state = STATE_NORMAL;
|
|
drawElement(last_element);
|
|
}
|
|
}
|
|
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 (event->x >= menu_area->w) {
|
|
handleSpritesheetClick(event->x-menu_area->w, event->y);
|
|
return;
|
|
}
|
|
int x_offset = 0;
|
|
int y_offset = 0;
|
|
if (event->x <= menu_area->w && event->y <= menu_area->h) {
|
|
} else if (event->x <= tile_area->w && event->y <= tile_area->h) {
|
|
x_offset = tile_area_rect.x;
|
|
y_offset = tile_area_rect.y;
|
|
}
|
|
if (last_element != NULL) {
|
|
int t_x, t_y, t_w, t_h = 0;
|
|
switch (last_element->type) {
|
|
case TYPE_BUTTON:
|
|
t_w = x_offset + last_element->x+2 +(font.width * ((struct ButtonElement*)last_element->data)->length) + 2;
|
|
t_h = y_offset + last_element->y+2 + font.height + 2;
|
|
t_x = x_offset + last_element->x+2;
|
|
t_y = y_offset + last_element->y+2;
|
|
break;
|
|
case TYPE_TEXT_INPUT:
|
|
t_w = x_offset + last_element->x-1 +(font.width * ((struct TextInputElement*)last_element->data)->size) + 4;
|
|
t_h = y_offset + last_element->y-1 + font.height + 4;
|
|
t_x = x_offset + last_element->x-1;
|
|
t_y = y_offset + last_element->y-1;
|
|
break;
|
|
case TYPE_SPINNER:
|
|
t_w = x_offset + last_element->x-1 + font.width * (((struct SpinnerElement*)last_element->data)->size+2) + 4;
|
|
t_h = y_offset + last_element->y-1 + font.height + 4;
|
|
t_x = x_offset + last_element->x-1;
|
|
t_y = y_offset + last_element->y-1;
|
|
break;
|
|
case TYPE_IMAGE:
|
|
t_w = x_offset + last_element->x + ((struct ImageElement*)last_element->data)->width;
|
|
t_h = y_offset + last_element->y + ((struct ImageElement*)last_element->data)->height;
|
|
t_x = x_offset + last_element->x;
|
|
t_y = y_offset + last_element->y;
|
|
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)) {
|
|
// check against spinner up + down buttons
|
|
if (last_element->type == TYPE_SPINNER) {
|
|
t_x = last_element->x + (font.width * ((((struct SpinnerElement*)last_element->data)->size)+1)) + 4;
|
|
t_w = font.width + t_x;
|
|
t_h = t_y + font.height/2;
|
|
if ((t_x <= event->x && t_w >= event->x) && (t_y <= event->y && t_h >= event->y)) {
|
|
if (event->button < 4)
|
|
handleMouseButton(last_element, 4);
|
|
else
|
|
handleMouseButton(last_element, event->button);
|
|
} else {
|
|
// bottom
|
|
t_y = last_element->y + 3 + font.height/2;
|
|
t_h = t_y + font.height/2;
|
|
if ((t_x <= event->x && t_w >= event->x) && (t_y <= event->y && t_h >= event->y)) {
|
|
if (event->button < 4)
|
|
handleMouseButton(last_element, 5);
|
|
else
|
|
handleMouseButton(last_element, event->button);
|
|
} else {
|
|
int cursor = (event->x - last_element->x) / font.width;
|
|
if (((struct SpinnerElement*)last_element->data)->length >= cursor) {
|
|
((struct SpinnerElement*)last_element->data)->cursor = cursor;
|
|
}
|
|
handleMouseButton(last_element, event->button);
|
|
}
|
|
}
|
|
} else if (last_element->type == TYPE_TEXT_INPUT) {
|
|
int cursor = (event->x - last_element->x) / font.width;
|
|
if (((struct TextInputElement*)last_element->data)->length >= cursor) {
|
|
((struct TextInputElement*)last_element->data)->cursor = cursor;
|
|
}
|
|
handleMouseButton(last_element, event->button);
|
|
} else {
|
|
handleMouseButton(last_element, event->button);
|
|
}
|
|
// chance of last_element being free'd or otherwise at this point, so check if NULL
|
|
if (last_element != NULL) {
|
|
if (last_element->type == TYPE_TEXT_INPUT || last_element->type == TYPE_SPINNER) {
|
|
focus_element = last_element;
|
|
focus_element->state = STATE_FOCUS;
|
|
}
|
|
}
|
|
} else {
|
|
focus_element = NULL;
|
|
}
|
|
if (last_element != NULL) {
|
|
drawElement(last_element);
|
|
}
|
|
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) {
|
|
|
|
}
|
|
|
|
void handleSpritesheetClick(int x, int y) {
|
|
struct Spritesheet *spritesheet;
|
|
switch (g_set) {
|
|
case PLAYER:
|
|
spritesheet = &player_sprites;
|
|
break;
|
|
case FLOOR:
|
|
spritesheet = &floor_sprites;
|
|
break;
|
|
case WALL:
|
|
spritesheet = &wall_sprites;
|
|
break;
|
|
case DOOR:
|
|
spritesheet = &door_sprites;
|
|
break;
|
|
case ITEM:
|
|
spritesheet = &item_sprites;
|
|
break;
|
|
case EQUIP:
|
|
spritesheet = &equip_sprites;
|
|
break;
|
|
case NPC:
|
|
spritesheet = &npc_sprites;
|
|
break;
|
|
default:
|
|
return;
|
|
break;
|
|
}
|
|
/* now load small preview of tile */
|
|
int id = (x / spritesheet->width) + ((y / spritesheet->height)*spritesheet->columns);
|
|
setElementValue(input_id, id);
|
|
setIdCallback();
|
|
drawElement(input_id);
|
|
//int y_offset = g_id / spritesheet->columns;
|
|
//int x_offset = g_id - (y_offset * spritesheet->columns);
|
|
}
|
|
|
|
void positionElements() {
|
|
struct Element *element = editor_elements->first;
|
|
struct Element *delete_element = NULL;
|
|
int x_offset = 2;
|
|
//int y_offset = 2;
|
|
int y_offset = getElementHeight(button_add_pair)+6;
|
|
while (element != NULL) {
|
|
switch (element->id) {
|
|
case ID_DELETE:
|
|
x_offset = 2;
|
|
delete_element = element;
|
|
setElementPosition(element, x_offset, y_offset-1);
|
|
x_offset += getElementWidth(element)+6;
|
|
break;
|
|
case ID_KEY:
|
|
setElementPosition(element, x_offset, y_offset);
|
|
x_offset += getElementWidth(element)+2;
|
|
break;
|
|
case ID_VALUE:
|
|
setElementPosition(element, x_offset, y_offset);
|
|
y_offset += getElementHeight(element)+2;
|
|
x_offset = 2;
|
|
break;
|
|
case ID_INV_ADD:
|
|
setElementPosition(element, x_offset, y_offset);
|
|
y_offset += getElementHeight(element)+2;
|
|
x_offset = getElementWidth(delete_element)+2;
|
|
break;
|
|
case ID_ITEM_DEL:
|
|
x_offset = getElementWidth(delete_element) + 2;
|
|
setElementPosition(element, x_offset, y_offset);
|
|
x_offset += getElementWidth(element)+4;
|
|
break;
|
|
case ID_ITEM_NAME:
|
|
setElementPosition(element, x_offset, y_offset);
|
|
x_offset += getElementWidth(element)+2;
|
|
break;
|
|
case ID_ITEM_NAME_VAL:
|
|
setElementPosition(element, x_offset, y_offset);
|
|
x_offset = (getElementWidth(delete_element)*2)+6;
|
|
y_offset += getElementHeight(element)+2;
|
|
break;
|
|
case ID_ITEM_MIN:
|
|
case ID_ITEM_MAX:
|
|
case ID_ITEM_CHANCE:
|
|
setElementPosition(element, x_offset, y_offset);
|
|
x_offset += getElementWidth(element)+2;
|
|
break;
|
|
case ID_ITEM_MIN_VAL:
|
|
case ID_ITEM_MAX_VAL:
|
|
setElementPosition(element, x_offset, y_offset);
|
|
x_offset += getElementWidth(element)+4;
|
|
break;
|
|
case ID_ITEM_CHANCE_VAL:
|
|
setElementPosition(element, x_offset, y_offset);
|
|
x_offset = 2;
|
|
y_offset += getElementHeight(element)+2;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
element = element->next;
|
|
}
|
|
}
|
|
|
|
/* button callback */
|
|
|
|
void loadGraphicsCallback() {
|
|
printConsole("loading gfx");
|
|
|
|
int ret = 0;
|
|
char temp[64];
|
|
char temp_2[96];
|
|
sprintf(temp, "%s/%s", getElementText(input_graphics), "players.png");
|
|
sprintf(temp_2, "loading %s", temp);
|
|
printConsole(temp_2);
|
|
ret = loadSpritesheetFromFile(&player_sprites, temp, 16, 32, 6);
|
|
if (ret != 0) {
|
|
sprintf(temp_2, "error(%d) loading %s", ret, temp);
|
|
printConsole(temp_2);
|
|
return;
|
|
}
|
|
sprintf(temp, "%s/%s", getElementText(input_graphics), "items.png");
|
|
sprintf(temp_2, "loading %s", temp);
|
|
printConsole(temp_2);
|
|
ret = loadSpritesheetFromFile(&item_sprites, temp, 16, 32, 16);
|
|
if (ret != 0) {
|
|
sprintf(temp_2, "error(%d) loading %s", ret, temp);
|
|
printConsole(temp_2);
|
|
return;
|
|
}
|
|
sprintf(temp, "%s/%s", getElementText(input_graphics), "equips.png");
|
|
sprintf(temp_2, "loading %s", temp);
|
|
printConsole(temp_2);
|
|
ret = loadSpritesheetFromFile(&equip_sprites, temp, 16, 32, 16);
|
|
if (ret != 0) {
|
|
sprintf(temp_2, "error(%d) loading %s", ret, temp);
|
|
printConsole(temp_2);
|
|
return;
|
|
}
|
|
sprintf(temp, "%s/%s", getElementText(input_graphics), "doors.png");
|
|
sprintf(temp_2, "loading %s", temp);
|
|
printConsole(temp_2);
|
|
ret = loadSpritesheetFromFile(&door_sprites, temp, 16, 32, 16);
|
|
if (ret != 0) {
|
|
sprintf(temp_2, "error(%d) loading %s", ret, temp);
|
|
printConsole(temp_2);
|
|
return;
|
|
}
|
|
sprintf(temp, "%s/%s", getElementText(input_graphics), "npcs.png");
|
|
sprintf(temp_2, "loading %s", temp);
|
|
printConsole(temp_2);
|
|
ret = loadSpritesheetFromFile(&npc_sprites, temp, 16, 32, 16);
|
|
if (ret != 0) {
|
|
sprintf(temp_2, "error(%d) loading %s", ret, temp);
|
|
printConsole(temp_2);
|
|
return;
|
|
}
|
|
sprintf(temp, "%s/%s", getElementText(input_graphics), "floors.png");
|
|
sprintf(temp_2, "loading %s", temp);
|
|
printConsole(temp_2);
|
|
ret = loadSpritesheetFromFile(&floor_sprites, temp, 16, 32, 16);
|
|
if (ret != 0) {
|
|
sprintf(temp_2, "error(%d) loading %s", ret, temp);
|
|
printConsole(temp_2);
|
|
return;
|
|
}
|
|
sprintf(temp, "%s/%s", getElementText(input_graphics), "walls.png");
|
|
sprintf(temp_2, "loading %s", temp);
|
|
printConsole(temp_2);
|
|
ret = loadSpritesheetFromFile(&wall_sprites, temp, 16, 32, 16);
|
|
if (ret != 0) {
|
|
sprintf(temp_2, "error(%d) loading %s", ret, temp);
|
|
printConsole(temp_2);
|
|
return;
|
|
}
|
|
sprintf(temp_2, "OK, graphics loaded successfully");
|
|
g_gfx = 1;
|
|
|
|
printConsole(temp_2);
|
|
reloadImagePreview();
|
|
showSpritesheet();
|
|
}
|
|
|
|
void loadDataCallback() {
|
|
printConsole("loading data");
|
|
char *buffer = NULL;
|
|
char temp[128];
|
|
int size = fileToMemory(&buffer, getElementText(input_data));
|
|
if (size > 0) {
|
|
if (tiles_data != NULL) {
|
|
freeData(tiles_data);
|
|
tiles_data = loadDataFromMemory(buffer, size);
|
|
} else {
|
|
tiles_data = loadDataFromMemory(buffer, size);
|
|
}
|
|
sprintf(temp, "loaded %d tile sets!\n", tiles_data->set_count);
|
|
//g_data = 1;
|
|
} else {
|
|
sprintf(temp, "ERR, could not load %s", getElementText(input_data));
|
|
}
|
|
printConsole(temp);
|
|
|
|
if (buffer != NULL) {
|
|
loadTile(g_set, g_id);
|
|
free(buffer);
|
|
}
|
|
}
|
|
|
|
void saveDataCallback() {
|
|
char temp[256];
|
|
sprintf(temp, "saving data to %s", getElementText(input_data));
|
|
printConsole(temp);
|
|
int return_value;
|
|
if ((return_value = saveDataToFile(tiles_data, getElementText(input_data))) > 0) {
|
|
sprintf(temp, "OK(%d), data saved to %s!", return_value, getElementText(input_data));
|
|
} else {
|
|
sprintf(temp, "ERR(%d), could not save to %s", return_value, getElementText(input_data));
|
|
}
|
|
printConsole(temp);
|
|
}
|
|
|
|
void loadTile(int set, int id) {
|
|
char temp[128];
|
|
|
|
if (g_data != 1) {
|
|
return;
|
|
}
|
|
/* delete old elements */
|
|
SDL_FillRect(tile_area, NULL, SDL_MapRGB(tile_area->format, 8, 16, 24));
|
|
deleteElementsFromList(editor_elements);
|
|
|
|
if (set < 0) {
|
|
sprintf(temp, "ERR, set(%d) must be non-negative!", set);
|
|
printConsole(temp);
|
|
return;
|
|
}
|
|
if (id < 0) {
|
|
sprintf(temp, "ERR, id(%d) must be non-negative!", id);
|
|
printConsole(temp);
|
|
return;
|
|
}
|
|
|
|
button_add_pair = newElement(TYPE_BUTTON);
|
|
setElementText(button_add_pair, "add pair");
|
|
setElementPosition(button_add_pair, 2, 2);
|
|
setElementCallback(button_add_pair, &addPairCallback);
|
|
addElementToList(editor_elements, button_add_pair);
|
|
|
|
button_add_inventory = newElement(TYPE_BUTTON);
|
|
setElementText(button_add_inventory, "add inventory");
|
|
setElementCallback(button_add_inventory, &addInventoryCallback);
|
|
setElementPosition(button_add_inventory, 4+getElementWidth(button_add_pair), 2);
|
|
addElementToList(editor_elements, button_add_inventory);
|
|
|
|
button_commit = newElement(TYPE_BUTTON);
|
|
setElementText(button_commit, "commit changes");
|
|
setElementCallback(button_commit, &commitChangesCallback);
|
|
setElementPosition(button_commit, tile_area->w - getElementWidth(button_commit) - 2, 2);
|
|
addElementToList(editor_elements, button_commit);
|
|
|
|
drawElement(button_add_inventory);
|
|
drawElement(button_add_pair);
|
|
drawElement(button_commit);
|
|
|
|
struct TileData *tile = getTileDataById(tiles_data, set, id);
|
|
if (tile == NULL) {
|
|
sprintf(temp, "tile %d:%d does not exist(yet!)\n", set, id);
|
|
printConsole(temp);
|
|
return;
|
|
}
|
|
sprintf(temp, "loaded %d:%d(%s)\n", set, id, (char*)getTablePairValue(tile->table, "name"));
|
|
|
|
int i;
|
|
int j = 0;
|
|
for(i = 0;i < tile->table->size;i++) {
|
|
struct TablePair *table_pair = tile->table->pair[i];
|
|
while(table_pair != NULL) {
|
|
struct InventoryData *inv;
|
|
struct Element *extra_element;
|
|
struct Element *delete_element;
|
|
delete_element = newElement(TYPE_BUTTON);
|
|
setElementText(delete_element, "x");
|
|
setElementCallback(delete_element, &deleteElementCallback);
|
|
setElementId(delete_element, ID_DELETE);
|
|
addElementToList(editor_elements, delete_element);
|
|
struct Element *value_element;
|
|
struct Element *key_element = newElement(TYPE_TEXT_INPUT); // @@ memory leak here
|
|
setElementSize(key_element, 16);
|
|
setElementText(key_element, table_pair->key);
|
|
setElementId(key_element, ID_KEY);
|
|
addElementToList(editor_elements, key_element);
|
|
|
|
setElementParent(delete_element, key_element);
|
|
addElementChild(key_element, delete_element);
|
|
switch(table_pair->type) {
|
|
case T_STRING:
|
|
value_element = newElement(TYPE_TEXT_INPUT); // and here
|
|
addElementChild(key_element, value_element);
|
|
setElementParent(value_element, key_element);
|
|
setElementSize(value_element, 30);
|
|
setElementText(value_element, table_pair->value);
|
|
setElementCallback(value_element, &changeValueCallback);
|
|
setElementId(value_element, ID_VALUE);
|
|
addElementToList(editor_elements, value_element);
|
|
break;
|
|
case T_INT:
|
|
value_element = newElement(TYPE_TEXT_INPUT); // and here
|
|
addElementChild(key_element, value_element);
|
|
setElementParent(value_element, key_element);
|
|
setElementSize(value_element, 30);
|
|
setElementValue(value_element, (*(int*)table_pair->value));
|
|
setElementCallback(value_element, &changeValueCallback);
|
|
setElementId(value_element, ID_VALUE);
|
|
addElementToList(editor_elements, value_element);
|
|
break;
|
|
case T_PROTO_INVENTORY:
|
|
setElementGid(key_element, GID_INVENTORY);
|
|
setElementGid(delete_element, GID_INVENTORY);
|
|
extra_element = newElement(TYPE_BUTTON);
|
|
setElementText(extra_element, "add");
|
|
addElementToList(editor_elements, extra_element);
|
|
setElementId(extra_element, ID_INV_ADD);
|
|
setElementGid(extra_element, GID_INVENTORY);
|
|
setElementCallback(extra_element, &addInventoryElementCallback);
|
|
addElementChild(key_element, extra_element);
|
|
setElementParent(extra_element, key_element);
|
|
inv = table_pair->value;
|
|
while (inv != NULL) {
|
|
j++;
|
|
// delete element button
|
|
delete_element = newElement(TYPE_BUTTON);
|
|
setElementText(delete_element, "x");
|
|
addElementToList(editor_elements, delete_element);
|
|
addElementChild(key_element, delete_element);
|
|
setElementParent(delete_element, key_element);
|
|
setElementCallback(delete_element, &deleteInventoryElementCallback);
|
|
setElementId(delete_element, ID_ITEM_DEL);
|
|
setElementGid(delete_element, GID_INVENTORY);
|
|
// name key
|
|
extra_element = newElement(TYPE_TEXT);
|
|
setElementSize(extra_element, 10);
|
|
setElementText(extra_element, "name");
|
|
addElementChild(key_element, extra_element);
|
|
addElementToList(editor_elements, extra_element);
|
|
setElementId(extra_element, ID_ITEM_NAME);
|
|
setElementGid(extra_element, GID_INVENTORY);
|
|
// name value
|
|
value_element = newElement(TYPE_TEXT_INPUT);
|
|
addElementChild(key_element, value_element);
|
|
setElementParent(value_element, key_element);
|
|
addElementChild(key_element, value_element);
|
|
setElementSize(value_element, 30);
|
|
setElementText(value_element, inv->name);
|
|
setElementCallback(value_element, &changeValueCallback);
|
|
addElementToList(editor_elements, value_element);
|
|
setElementId(value_element, ID_ITEM_NAME_VAL);
|
|
setElementGid(value_element, GID_INVENTORY);
|
|
j++;
|
|
// count min key
|
|
struct Element *count_min_key_element = newElement(TYPE_TEXT);
|
|
setElementSize(count_min_key_element, 4);
|
|
setElementText(count_min_key_element, "min");
|
|
addElementChild(key_element, count_min_key_element);
|
|
addElementToList(editor_elements, count_min_key_element);
|
|
setElementId(count_min_key_element, ID_ITEM_MIN);
|
|
setElementGid(count_min_key_element, GID_INVENTORY);
|
|
// count min count_min_value
|
|
struct Element *count_min_value_element = newElement(TYPE_SPINNER);
|
|
addElementChild(key_element, count_min_value_element);
|
|
setElementParent(count_min_value_element, key_element);
|
|
setElementSize(count_min_value_element, 4);
|
|
setElementValue(count_min_value_element, inv->count.min);
|
|
addElementToList(editor_elements, count_min_value_element);
|
|
setElementId(count_min_value_element, ID_ITEM_MIN_VAL);
|
|
setElementGid(count_min_value_element, GID_INVENTORY);
|
|
// count max key
|
|
struct Element *count_max_key_element = newElement(TYPE_TEXT);
|
|
setElementSize(count_max_key_element, 4);
|
|
setElementText(count_max_key_element, "max");
|
|
addElementChild(key_element, count_max_key_element);
|
|
addElementToList(editor_elements, count_max_key_element);
|
|
setElementId(count_max_key_element, ID_ITEM_MAX);
|
|
setElementGid(count_max_key_element, GID_INVENTORY);
|
|
// count max count_max_value
|
|
struct Element *count_max_value_element = newElement(TYPE_SPINNER);
|
|
addElementChild(key_element, count_max_value_element);
|
|
setElementParent(count_max_value_element, key_element);
|
|
setElementSize(count_max_value_element, 4);
|
|
setElementValue(count_max_value_element, inv->count.max);
|
|
addElementToList(editor_elements, count_max_value_element);
|
|
setElementId(count_max_value_element, ID_ITEM_MAX_VAL);
|
|
setElementGid(count_max_value_element, GID_INVENTORY);
|
|
// count max key
|
|
struct Element *chance_key_element = newElement(TYPE_TEXT);
|
|
setElementSize(chance_key_element, 7);
|
|
setElementText(chance_key_element, "chance");
|
|
addElementChild(key_element, chance_key_element);
|
|
addElementToList(editor_elements, chance_key_element);
|
|
setElementId(chance_key_element, ID_ITEM_CHANCE);
|
|
setElementGid(chance_key_element, GID_INVENTORY);
|
|
// count max chance_value
|
|
struct Element *chance_value_element = newElement(TYPE_SPINNER);
|
|
addElementChild(key_element, chance_value_element);
|
|
setElementParent(chance_value_element, key_element);
|
|
setElementSize(chance_value_element, 4);
|
|
setElementValue(chance_value_element, inv->chance);
|
|
addElementToList(editor_elements, chance_value_element);
|
|
setElementId(chance_value_element, ID_ITEM_CHANCE_VAL);
|
|
setElementGid(chance_value_element, GID_INVENTORY);
|
|
|
|
inv = inv->next;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
setElementCallback(key_element, &changeKeyCallback);
|
|
table_pair = table_pair->next;
|
|
j++;
|
|
}
|
|
}
|
|
positionElements();
|
|
drawElements();
|
|
printConsole(temp);
|
|
}
|
|
|
|
void addPairCallback(struct Element *element) {
|
|
struct Element *delete_element = newElement(TYPE_BUTTON);
|
|
setElementText(delete_element, "x");
|
|
setElementCallback(delete_element, &deleteElementCallback);
|
|
setElementId(delete_element, ID_DELETE);
|
|
addElementToList(editor_elements, delete_element);
|
|
|
|
struct Element *key_element = newElement(TYPE_TEXT_INPUT);
|
|
setElementSize(key_element, 16);
|
|
setElementText(key_element, "");
|
|
setElementId(key_element, ID_KEY);
|
|
setElementParent(delete_element, key_element);
|
|
addElementChild(key_element, delete_element);
|
|
addElementToList(editor_elements, key_element);
|
|
|
|
struct Element *value_element = newElement(TYPE_TEXT_INPUT);
|
|
setElementSize(value_element, 30);
|
|
setElementText(value_element, "");
|
|
setElementCallback(value_element, &changeValueCallback);
|
|
setElementId(value_element, ID_VALUE);
|
|
setElementParent(value_element, key_element);
|
|
addElementChild(key_element, value_element);
|
|
addElementToList(editor_elements, value_element);
|
|
|
|
SDL_FillRect(tile_area, NULL, SDL_MapRGB(tile_area->format, 8, 16, 24));
|
|
positionElements();
|
|
drawElements();
|
|
}
|
|
|
|
void addInventoryCallback(struct Element *element) {
|
|
struct Element *delete_element = newElement(TYPE_BUTTON);
|
|
setElementText(delete_element, "x");
|
|
setElementCallback(delete_element, &deleteElementCallback);
|
|
setElementId(delete_element, ID_DELETE);
|
|
addElementToList(editor_elements, delete_element);
|
|
|
|
struct Element *key_element = newElement(TYPE_TEXT_INPUT);
|
|
setElementSize(key_element, 16);
|
|
setElementText(key_element, "");
|
|
setElementId(key_element, ID_KEY);
|
|
setElementParent(delete_element, key_element);
|
|
addElementChild(key_element, delete_element);
|
|
addElementToList(editor_elements, key_element);
|
|
|
|
struct Element *extra_element = newElement(TYPE_BUTTON);
|
|
setElementText(extra_element, "add");
|
|
addElementToList(editor_elements, extra_element);
|
|
setElementId(extra_element, ID_INV_ADD);
|
|
setElementParent(extra_element, key_element);
|
|
setElementCallback(extra_element, &addInventoryElementCallback);
|
|
setElementGid(extra_element, GID_INVENTORY);
|
|
addElementChild(key_element, extra_element);
|
|
// delete element button
|
|
delete_element = newElement(TYPE_BUTTON);
|
|
setElementText(delete_element, "x");
|
|
addElementToList(editor_elements, delete_element);
|
|
addElementChild(key_element, delete_element);
|
|
setElementParent(delete_element, key_element);
|
|
setElementCallback(delete_element, &deleteInventoryElementCallback);
|
|
setElementId(delete_element, ID_ITEM_DEL);
|
|
setElementGid(delete_element, GID_INVENTORY);
|
|
// name key
|
|
extra_element = newElement(TYPE_TEXT);
|
|
setElementSize(extra_element, 10);
|
|
setElementText(extra_element, "name");
|
|
addElementChild(key_element, extra_element);
|
|
addElementToList(editor_elements, extra_element);
|
|
setElementId(extra_element, ID_ITEM_NAME);
|
|
setElementGid(extra_element, GID_INVENTORY);
|
|
// name value
|
|
struct Element *value_element = newElement(TYPE_TEXT_INPUT);
|
|
addElementChild(key_element, value_element);
|
|
setElementParent(value_element, key_element);
|
|
addElementChild(key_element, value_element);
|
|
setElementSize(value_element, 30);
|
|
setElementText(value_element, "");
|
|
setElementCallback(value_element, &changeValueCallback);
|
|
addElementToList(editor_elements, value_element);
|
|
setElementId(value_element, ID_ITEM_NAME_VAL);
|
|
setElementGid(value_element, GID_INVENTORY);
|
|
// count min key
|
|
struct Element *count_min_key_element = newElement(TYPE_TEXT);
|
|
setElementSize(count_min_key_element, 4);
|
|
setElementText(count_min_key_element, "min");
|
|
addElementChild(key_element, count_min_key_element);
|
|
addElementToList(editor_elements, count_min_key_element);
|
|
setElementId(count_min_key_element, ID_ITEM_MIN);
|
|
setElementGid(count_min_key_element, GID_INVENTORY);
|
|
// count min count_min_value
|
|
struct Element *count_min_value_element = newElement(TYPE_SPINNER);
|
|
addElementChild(key_element, count_min_value_element);
|
|
setElementParent(count_min_value_element, key_element);
|
|
setElementSize(count_min_value_element, 4);
|
|
setElementValue(count_min_value_element, 1);
|
|
addElementToList(editor_elements, count_min_value_element);
|
|
setElementId(count_min_value_element, ID_ITEM_MIN_VAL);
|
|
setElementGid(count_min_value_element, GID_INVENTORY);
|
|
// count max key
|
|
struct Element *count_max_key_element = newElement(TYPE_TEXT);
|
|
setElementSize(count_max_key_element, 4);
|
|
setElementText(count_max_key_element, "max");
|
|
addElementChild(key_element, count_max_key_element);
|
|
addElementToList(editor_elements, count_max_key_element);
|
|
setElementId(count_max_key_element, ID_ITEM_MAX);
|
|
setElementGid(count_max_key_element, GID_INVENTORY);
|
|
// count max count_max_value
|
|
struct Element *count_max_value_element = newElement(TYPE_SPINNER);
|
|
addElementChild(key_element, count_max_value_element);
|
|
setElementParent(count_max_value_element, key_element);
|
|
setElementSize(count_max_value_element, 4);
|
|
setElementValue(count_max_value_element, 1);
|
|
addElementToList(editor_elements, count_max_value_element);
|
|
setElementId(count_max_value_element, ID_ITEM_MAX_VAL);
|
|
setElementGid(count_max_value_element, GID_INVENTORY);
|
|
// count max key
|
|
struct Element *chance_key_element = newElement(TYPE_TEXT);
|
|
setElementSize(chance_key_element, 7);
|
|
setElementText(chance_key_element, "chance");
|
|
addElementChild(key_element, chance_key_element);
|
|
addElementToList(editor_elements, chance_key_element);
|
|
setElementId(chance_key_element, ID_ITEM_CHANCE);
|
|
setElementGid(chance_key_element, GID_INVENTORY);
|
|
// count max chance_value
|
|
struct Element *chance_value_element = newElement(TYPE_SPINNER);
|
|
addElementChild(key_element, chance_value_element);
|
|
setElementParent(chance_value_element, key_element);
|
|
setElementSize(chance_value_element, 4);
|
|
setElementValue(chance_value_element, 100);
|
|
addElementToList(editor_elements, chance_value_element);
|
|
setElementId(chance_value_element, ID_ITEM_CHANCE_VAL);
|
|
setElementGid(chance_value_element, GID_INVENTORY);
|
|
|
|
positionElements();
|
|
drawElements();
|
|
}
|
|
|
|
void addInventoryElementCallback(struct Element *element) {
|
|
struct Element *current = element;
|
|
struct Element *previous = NULL;
|
|
struct Element *next = current->next;
|
|
while (current != NULL) {
|
|
next = current->next;
|
|
if (current->id == ID_DELETE) {
|
|
break;
|
|
}
|
|
previous = current;
|
|
current = next;
|
|
}
|
|
|
|
struct Element *key_element = element->parent; // parent of add item is always the root key (inventory name)
|
|
|
|
// delete element button
|
|
struct Element *delete_element = newElement(TYPE_BUTTON);
|
|
setElementText(delete_element, "x");
|
|
addElementChild(key_element, delete_element);
|
|
setElementParent(delete_element, key_element);
|
|
setElementCallback(delete_element, &deleteInventoryElementCallback);
|
|
setElementId(delete_element, ID_ITEM_DEL);
|
|
setElementGid(delete_element, GID_INVENTORY);
|
|
addElementHook(editor_elements, delete_element); // call hook manually
|
|
previous->next = delete_element;
|
|
// name key
|
|
struct Element *extra_element = newElement(TYPE_TEXT);
|
|
setElementSize(extra_element, 10);
|
|
setElementText(extra_element, "name");
|
|
addElementChild(key_element, extra_element);
|
|
setElementId(extra_element, ID_ITEM_NAME);
|
|
setElementGid(extra_element, GID_INVENTORY);
|
|
addElementHook(editor_elements, extra_element); // call hook manually
|
|
delete_element->next = extra_element;
|
|
// name value
|
|
struct Element *value_element = newElement(TYPE_TEXT_INPUT);
|
|
addElementChild(key_element, value_element);
|
|
setElementParent(value_element, key_element);
|
|
addElementChild(key_element, value_element);
|
|
setElementSize(value_element, 30);
|
|
setElementText(value_element, "");
|
|
setElementCallback(value_element, &changeValueCallback);
|
|
setElementId(value_element, ID_ITEM_NAME_VAL);
|
|
setElementGid(value_element, GID_INVENTORY);
|
|
addElementHook(editor_elements, value_element); // call hook manually
|
|
extra_element->next = value_element;
|
|
// count min key
|
|
struct Element *count_min_key_element = newElement(TYPE_TEXT);
|
|
setElementSize(count_min_key_element, 4);
|
|
setElementText(count_min_key_element, "min");
|
|
addElementChild(key_element, count_min_key_element);
|
|
setElementId(count_min_key_element, ID_ITEM_MIN);
|
|
setElementGid(count_min_key_element, GID_INVENTORY);
|
|
addElementHook(editor_elements, count_min_key_element); // call hook manually
|
|
value_element->next = count_min_key_element;
|
|
// count min count_min_value
|
|
struct Element *count_min_value_element = newElement(TYPE_SPINNER);
|
|
addElementChild(key_element, count_min_value_element);
|
|
setElementParent(count_min_value_element, key_element);
|
|
setElementSize(count_min_value_element, 4);
|
|
setElementValue(count_min_value_element, 1);
|
|
setElementId(count_min_value_element, ID_ITEM_MIN_VAL);
|
|
setElementGid(count_min_value_element, GID_INVENTORY);
|
|
addElementHook(editor_elements, count_min_value_element); // call hook manually
|
|
count_min_key_element->next = count_min_value_element;
|
|
// count max key
|
|
struct Element *count_max_key_element = newElement(TYPE_TEXT);
|
|
setElementSize(count_max_key_element, 4);
|
|
setElementText(count_max_key_element, "max");
|
|
addElementChild(key_element, count_max_key_element);
|
|
setElementId(count_max_key_element, ID_ITEM_MAX);
|
|
setElementGid(count_max_key_element, GID_INVENTORY);
|
|
addElementHook(editor_elements, count_max_key_element); // call hook manually
|
|
count_min_value_element->next = count_max_key_element;
|
|
// count max count_max_value
|
|
struct Element *count_max_value_element = newElement(TYPE_SPINNER);
|
|
addElementChild(key_element, count_max_value_element);
|
|
setElementParent(count_max_value_element, key_element);
|
|
setElementSize(count_max_value_element, 4);
|
|
setElementValue(count_max_value_element, 1);
|
|
setElementId(count_max_value_element, ID_ITEM_MAX_VAL);
|
|
setElementGid(count_max_value_element, GID_INVENTORY);
|
|
addElementHook(editor_elements, count_max_value_element); // call hook manually
|
|
count_max_key_element->next = count_max_value_element;
|
|
// count max key
|
|
struct Element *chance_key_element = newElement(TYPE_TEXT);
|
|
setElementSize(chance_key_element, 7);
|
|
setElementText(chance_key_element, "chance");
|
|
addElementChild(key_element, chance_key_element);
|
|
setElementId(chance_key_element, ID_ITEM_CHANCE);
|
|
setElementGid(chance_key_element, GID_INVENTORY);
|
|
addElementHook(editor_elements, chance_key_element); // call hook manually
|
|
count_max_value_element->next = chance_key_element;
|
|
// count max chance_value
|
|
struct Element *chance_value_element = newElement(TYPE_SPINNER);
|
|
addElementChild(key_element, chance_value_element);
|
|
setElementParent(chance_value_element, key_element);
|
|
setElementSize(chance_value_element, 4);
|
|
setElementValue(chance_value_element, 100);
|
|
setElementId(chance_value_element, ID_ITEM_CHANCE_VAL);
|
|
setElementGid(chance_value_element, GID_INVENTORY);
|
|
addElementHook(editor_elements, chance_value_element); // call hook manually
|
|
chance_key_element->next = chance_value_element;
|
|
|
|
chance_value_element->next = current;
|
|
if (current == NULL) {
|
|
editor_elements->last = chance_value_element;
|
|
}
|
|
|
|
positionElements();
|
|
SDL_FillRect(tile_area, NULL, SDL_MapRGB(tile_area->format, 8, 16, 24));
|
|
drawElements();
|
|
}
|
|
|
|
void deleteInventoryElementCallback(struct Element *element) {
|
|
struct Element *current = element;
|
|
while (current != NULL) {
|
|
struct Element *next = current->next;
|
|
if (current->id == ID_ITEM_DEL) { // reached ourself or next inventory item
|
|
if (current != element) { // if next, bail out
|
|
break;
|
|
} else { // otherwise, delete self
|
|
removeElementFromList(editor_elements, current);
|
|
freeElement(current);
|
|
}
|
|
} else if (current->id == ID_DELETE) { // reached next key=>value pair
|
|
break;
|
|
} else { // reached element that is part of this inventory item
|
|
removeElementFromList(editor_elements, current);
|
|
freeElement(current);
|
|
}
|
|
current = next;
|
|
}
|
|
|
|
last_element = NULL;
|
|
focus_element = NULL;
|
|
positionElements();
|
|
SDL_FillRect(tile_area, NULL, SDL_MapRGB(tile_area->format, 8, 16, 24));
|
|
drawElements();
|
|
}
|
|
|
|
void deleteElementCallback(struct Element *element) {
|
|
struct Element *current = element;
|
|
while (current != NULL) {
|
|
struct Element *next = current->next;
|
|
if (current->id == ID_DELETE) {
|
|
if (current != element) { // if it is not this element, it is next pair
|
|
break;
|
|
} else { // otherwise, delete self
|
|
removeElementFromList(editor_elements, current);
|
|
freeElement(current);
|
|
}
|
|
} else {
|
|
removeElementFromList(editor_elements, current);
|
|
freeElement(current);
|
|
}
|
|
current = next;
|
|
}
|
|
|
|
last_element = NULL;
|
|
focus_element = NULL;
|
|
positionElements();
|
|
SDL_FillRect(tile_area, NULL, SDL_MapRGB(tile_area->format, 8, 16, 24));
|
|
drawElements();
|
|
}
|
|
|
|
void commitChangesCallback(struct Element *element) {
|
|
struct Element *current = element->next;
|
|
const char *current_key;
|
|
const char *current_value;
|
|
int min_count = 0;
|
|
int max_count = 0;
|
|
int chance = 0;
|
|
/* completely delete old TileData */
|
|
struct TileData *tile = getTileDataById(tiles_data, g_set, g_id);
|
|
if (tile != NULL) {
|
|
freeTileData(tile);
|
|
tiles_data->set[g_set]->tile[g_id] = NULL;
|
|
}
|
|
/* create new TileData for commit rewrite */
|
|
|
|
tile = newTileData(8);
|
|
tile->id = g_id;
|
|
tiles_data->set[g_set]->tile[g_id] = tile;
|
|
|
|
while (current != NULL) {
|
|
switch(current->id) {
|
|
case ID_DELETE:
|
|
break;
|
|
case ID_KEY:
|
|
current_key = getElementText(current);
|
|
break;
|
|
case ID_VALUE:
|
|
current_value = getElementText(current);
|
|
addTablePair(tile->table, current_key, (void*)current_value, strlen(current_value)+1, T_STRING);
|
|
break;
|
|
case ID_ITEM_NAME_VAL:
|
|
current_value = getElementText(current);
|
|
break;
|
|
case ID_ITEM_MIN_VAL:
|
|
min_count = getElementValue(current);
|
|
break;
|
|
case ID_ITEM_MAX_VAL:
|
|
max_count = getElementValue(current);
|
|
break;
|
|
case ID_ITEM_CHANCE_VAL:
|
|
chance = getElementValue(current);
|
|
struct TablePair *pair = getTablePair(tile->table, current_key);
|
|
if (pair != NULL) {
|
|
// inventory exists, walk down the chain and append new InventoryData
|
|
if (pair->type == T_PROTO_INVENTORY) {
|
|
struct InventoryData *inv = pair->value;
|
|
while (inv->next != NULL) {
|
|
inv = inv->next;
|
|
}
|
|
struct InventoryData *inventory = newInventoryData();
|
|
inventory->count.min = min_count;
|
|
inventory->count.max = max_count;
|
|
inventory->chance = chance;
|
|
setInventoryDataName(inventory, current_value);
|
|
inv->next = inventory;
|
|
}
|
|
} else {
|
|
// inventory does not exist, create it
|
|
struct InventoryData *inventory = newInventoryData();
|
|
inventory->count.min = min_count;
|
|
inventory->count.max = max_count;
|
|
inventory->chance = chance;
|
|
setInventoryDataName(inventory, current_value);
|
|
addTablePairPointer(tile->table, current_key, inventory, T_PROTO_INVENTORY);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
current = current->next;
|
|
}
|
|
// table has no key=>value pairs, thus meaning there are no elements - free & remove it!
|
|
if (tile->table->count <= 0) {
|
|
freeTileData(tile);
|
|
tiles_data->set[g_set]->tile[g_id] = NULL;
|
|
}
|
|
char temp[128];
|
|
sprintf(temp, "Changes committed for %d:%d", g_set, g_id);
|
|
printConsole(temp);
|
|
}
|
|
|
|
void changeKeyCallback() {
|
|
printf("changing key\n");
|
|
}
|
|
|
|
void changeValueCallback() {
|
|
printf("changing value\n");
|
|
}
|
|
|
|
void setSetCallback() {
|
|
g_set = atoi(getElementText(input_set));
|
|
if (g_gfx == 1) {
|
|
reloadImagePreview();
|
|
showSpritesheet();
|
|
}
|
|
if (g_data == 1) {
|
|
loadTile(g_set, g_id);
|
|
}
|
|
}
|
|
|
|
void setIdCallback() {
|
|
g_id = atoi(getElementText(input_id));
|
|
if (g_gfx == 1) {
|
|
reloadImagePreview();
|
|
showSpritesheet(); // TODO: just reload the area on the sheet surface that has changed
|
|
}
|
|
if (g_data == 1) {
|
|
loadTile(g_set, g_id);
|
|
}
|
|
}
|
|
|
|
void showSpritesheet() {
|
|
if (g_gfx != 1)
|
|
return;
|
|
struct Spritesheet *spritesheet;
|
|
switch (g_set) {
|
|
case PLAYER:
|
|
spritesheet = &player_sprites;
|
|
break;
|
|
case FLOOR:
|
|
spritesheet = &floor_sprites;
|
|
break;
|
|
case WALL:
|
|
spritesheet = &wall_sprites;
|
|
break;
|
|
case DOOR:
|
|
spritesheet = &door_sprites;
|
|
break;
|
|
case ITEM:
|
|
spritesheet = &item_sprites;
|
|
break;
|
|
case EQUIP:
|
|
spritesheet = &equip_sprites;
|
|
break;
|
|
case NPC:
|
|
spritesheet = &npc_sprites;
|
|
break;
|
|
default:
|
|
return;
|
|
break;
|
|
}
|
|
screen = SDL_SetVideoMode(g_width+spritesheet->spritesheet->w, g_height, 32, SDL_SWSURFACE|SDL_DOUBLEBUF);
|
|
|
|
int rows = spritesheet->spritesheet->h / spritesheet->height;
|
|
|
|
int i, j = 0;
|
|
Uint32 color_a = SDL_MapRGB(screen->format, 95, 95, 128);
|
|
Uint32 color_b = SDL_MapRGB(screen->format, 128, 128, 95);
|
|
for (i = 0;i < spritesheet->columns;i++) {
|
|
for (j = 0;j < rows;j++) {
|
|
SDL_Rect sprite_rect = { i*spritesheet->width, j*spritesheet->height, spritesheet->width, spritesheet->height};
|
|
SDL_FillRect(sprite_area, &sprite_rect, (((j+i) & 1) == 1 ? color_a : color_b));
|
|
}
|
|
}
|
|
// draw different bg for current id
|
|
int y_offset = g_id / spritesheet->columns;
|
|
int x_offset = g_id - (y_offset * spritesheet->columns);
|
|
SDL_Rect sprite_rect = { x_offset*spritesheet->width, y_offset*spritesheet->height, spritesheet->width, spritesheet->height};
|
|
SDL_FillRect(sprite_area, &sprite_rect, SDL_MapRGB(screen->format, 196, 196, 95));
|
|
|
|
//SDL_FillRect(sprite_area, &spritesheet_rect, SDL_MapRGB(screen->format, 95, 95, 128));
|
|
SDL_BlitSurface(spritesheet->spritesheet, NULL, sprite_area, NULL);
|
|
SDL_BlitSurface(sprite_area, NULL, screen, &sprite_area_rect);
|
|
}
|
|
|
|
void reloadImagePreview() {
|
|
struct Spritesheet *spritesheet;
|
|
switch (g_set) {
|
|
case PLAYER:
|
|
spritesheet = &player_sprites;
|
|
break;
|
|
case FLOOR:
|
|
spritesheet = &floor_sprites;
|
|
break;
|
|
case WALL:
|
|
spritesheet = &wall_sprites;
|
|
break;
|
|
case DOOR:
|
|
spritesheet = &door_sprites;
|
|
break;
|
|
case ITEM:
|
|
spritesheet = &item_sprites;
|
|
break;
|
|
case EQUIP:
|
|
spritesheet = &equip_sprites;
|
|
break;
|
|
case NPC:
|
|
spritesheet = &npc_sprites;
|
|
break;
|
|
default:
|
|
return;
|
|
break;
|
|
}
|
|
/* now load small preview of tile */
|
|
int y_offset = g_id / spritesheet->columns;
|
|
int x_offset = g_id - (y_offset * spritesheet->columns);
|
|
|
|
SDL_Rect sprite_offset = { x_offset*spritesheet->width, y_offset*spritesheet->height, spritesheet->width, spritesheet->height};
|
|
SDL_Rect render_position = {0, 0, spritesheet->width, spritesheet->height};
|
|
|
|
SDL_FillRect(((struct ImageElement *)image_tile->data)->image, NULL, SDL_MapRGB(menu_area->format, 96, 96, 128));
|
|
|
|
SDL_BlitSurface(spritesheet->spritesheet, &sprite_offset, ((struct ImageElement*)image_tile->data)->image, &render_position);
|
|
|
|
drawElement(image_tile);
|
|
}
|
|
|
|
void printConsole(const char *string) {
|
|
clearElement(text_console);
|
|
setElementText(text_console, string);
|
|
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);
|
|
}
|
|
|
|
/* spritesheet stuff */
|
|
int loadSpritesheetFromFile(struct Spritesheet *spritesheet, char *file_name, int width, int height, int columns) {
|
|
spritesheet->width = width;
|
|
spritesheet->height = height;
|
|
spritesheet->columns = columns;
|
|
spritesheet->spritesheet = IMG_Load(file_name);
|
|
if (spritesheet->spritesheet == NULL)
|
|
return -1;
|
|
spritesheet->scale_x = 1.0f;
|
|
spritesheet->scale_y = 1.0f;
|
|
spritesheet->s_spritesheet = SDL_ScaleSurface(spritesheet->spritesheet, 1.0f, 1.0f);
|
|
spritesheet->s_width = width;
|
|
spritesheet->s_height = height;
|
|
return 0;
|
|
}
|
|
|
|
void freeSpritesheet(struct Spritesheet *spritesheet) {
|
|
SDL_FreeSurface(spritesheet->s_spritesheet);
|
|
SDL_FreeSurface(spritesheet->spritesheet);
|
|
}
|
|
|
|
/* sdl helper stuff */
|
|
SDL_Surface *SDL_ScaleSurface(SDL_Surface *surface, float scale_x, float scale_y) {
|
|
long x;
|
|
long y;
|
|
long output_x;
|
|
long output_y;
|
|
long new_width = (long)((float)surface->w * scale_x+0.5f);
|
|
long new_height = (long)((float)surface->h * scale_y+0.5f);
|
|
SDL_Surface *new_surface = SDL_CreateRGBSurface(surface->flags, new_width, new_height, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask);
|
|
|
|
for (y = 0;y < surface->h;y++) {
|
|
for (x = 0;x < surface->w;x++) {
|
|
for (output_y = 0;output_y < scale_y; ++output_y) {
|
|
for (output_x = 0;output_x < scale_x; ++output_x) {
|
|
putpixel(new_surface, (Sint32)(scale_x*x) + output_x, (Sint32)(scale_y*y)+output_y, getpixel(surface, x, y));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return new_surface;
|
|
}
|
|
|
|
Uint32 getpixel(SDL_Surface *surface, int x, int y) {
|
|
if (y >= 0 && x >= 0 && x <= surface->w && y <= surface->h) {
|
|
int bpp = surface->format->BytesPerPixel;
|
|
/* Here p is the address to the pixel we want to retrieve */
|
|
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
|
|
|
switch(bpp) {
|
|
case 1:
|
|
return *p;
|
|
break;
|
|
|
|
case 2:
|
|
return *(Uint16 *)p;
|
|
break;
|
|
|
|
case 3:
|
|
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
|
return p[0] << 16 | p[1] << 8 | p[2];
|
|
else
|
|
return p[0] | p[1] << 8 | p[2] << 16;
|
|
break;
|
|
|
|
case 4:
|
|
return *(Uint32 *)p;
|
|
break;
|
|
|
|
default:
|
|
return 0; /* shouldn't happen, but avoids warnings */
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) {
|
|
if (y >= 0 && x >= 0 && x <= surface->w && y <= surface->h) {
|
|
int bpp = surface->format->BytesPerPixel;
|
|
/* Here p is the address to the pixel we want to set */
|
|
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
|
|
|
switch(bpp) {
|
|
case 1:
|
|
*p = pixel;
|
|
break;
|
|
|
|
case 2:
|
|
*(Uint16 *)p = pixel;
|
|
break;
|
|
|
|
case 3:
|
|
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
|
|
p[0] = (pixel >> 16) & 0xff;
|
|
p[1] = (pixel >> 8) & 0xff;
|
|
p[2] = pixel & 0xff;
|
|
} else {
|
|
p[0] = pixel & 0xff;
|
|
p[1] = (pixel >> 8) & 0xff;
|
|
p[2] = (pixel >> 16) & 0xff;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
*(Uint32 *)p = pixel;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|