kettek2/wiki/games/newsboy/Newsboy_0x00/engine/State_Editor.c

1072 lines
35 KiB
C

/*
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
EditorState - Map editor state :)
I don't want to serialize Map data to a format like:
info {
. . .
}
entities {
. . .
}
Rather, I would prefer a more binary-centric format, something like:
INF_START (replace w/ some sort of code)
0x00 - 0x04 (first 4 bytes represent width)
0x04 - 0x08 (next for 4 bytes for height)
etc.
INF_STOP
ENT_START
. . .
ENT_STOP
FLR_START
"cyb_wall" // data
"idle" // set
"face" // facing dir
FLR_BRK
. . .
FLR_STOP
So to accomplish this, we must make the editor first
Transitions:
MenuState
````````````````````````````````
*/
#include "State_Editor.h"
#include "State_Menu.h"
#include "State_Editor_MapSelect.h"
#include "State_Editor_diag_pl.h"
#include "State_Editor_diag_decor.h"
#include "State_Editor_diag_trigger.h"
#include "State_Editor_diag_event.h"
#include "State_Editor_diag_entity.h"
#include "EntityData.h"
#include "State_Animator.h"
#include "State_EntEdit.h"
#include "game_globals.h"
#include "globals.h"
#include "state.h"
#include "render.h"
#include "sprite.h"
#include "string.h"
#include "Resource.h"
int openEditorState() {
report(DEBUG, "EditorState", "opened");
// reset keys
memset(&keys, 0, 7);
mouse = 0;
mouse_x = 0;
mouse_y = 0;
b_flags = 0;
b_mode = 0;
//
show_coords = 0;
opts = OPT_TRIGGERS + OPT_EVENTS;
// selected tile
selected_x = 0;
selected_y = 0;
active_cell = NULL;
// Camera
camera_x = 0;
camera_y = 0;
map_zoom = 1.0f;
// init Map
editor_map = newMapData();
// init Controls
map_box.x = 0;
map_box.y = 0;
map_box.w = g_v_width;
map_box.h = g_v_height - 128;
map_rows = map_box.h / g_tile_h;
map_cols = map_box.w / g_tile_w;
initControls();
// END Initialize Map
// Setup Text
text_cam_x = newText(g_large_font, "x: ");
text_cam_y = newText(g_large_font, "y: ");
// set up resources
editor_sprites = newResources(0, 128);
editor_sprites->loadResource_func = (void*)createSpriteFromFile;
editor_sprites->freeResource_func = (void*)freeSprite;
return 0;
}
int handleEditorState(SDL_Event event) {
switch(event.type) {
case SDL_KEYDOWN:
// input handling
if (input_selected != NULL) {
switch(event.key.keysym.sym) {
case SDLK_LEFT:
if (input_selected->cursor > 0) {
input_selected->cursor--;
}
break;
case SDLK_RIGHT:
if (input_selected->cursor < strlen(input_selected->text)) {
input_selected->cursor++;
}
break;
case SDLK_BACKSPACE:
if (input_selected->cursor != 0) {
deleteTextInput(input_selected, input_selected->cursor-1, 1);
input_selected->cursor--;
}
break;
}
} else {
// end input handling
switch(event.key.keysym.sym) {
case SDLK_LEFT:
case SDLK_a:
keys[KEY_LEFT] = 1;
break;
case SDLK_RIGHT:
case SDLK_d:
keys[KEY_RIGHT] = 1;
break;
case SDLK_UP:
case SDLK_w:
keys[KEY_UP] = 1;
break;
case SDLK_DOWN:
case SDLK_s:
keys[KEY_DOWN] = 1;
break;
case SDLK_DELETE:
case SDLK_BACKSPACE:
keys[KEY_DELETE] = 1;
break;
case SDLK_EQUALS:
if (event.key.keysym.mod & KMOD_SHIFT) {
keys[KEY_ZOOM_IN] = 1;
} else {
// TODO: fix zoom
int x = editor_map->width*g_tile_w;
int y = editor_map->height*g_tile_h;
if (x > y) {
map_zoom = x / map_box.w;
} else {
map_zoom = y / map_box.h;
}
}
break;
case SDLK_MINUS:
keys[KEY_ZOOM_OUT] = 1;
break;
case SDLK_0:
map_zoom = 1.0f;
break;
case SDLK_t:
keys[KEY_T] = 1;
break;
case SDLK_f:
keys[KEY_F] = 1;
break;
case SDLK_1:
keys[KEY_1] = 1;
break;
case SDLK_2:
keys[KEY_2] = 1;
break;
case SDLK_3:
keys[KEY_3] = 1;
break;
}
break;
}
case SDL_KEYUP:
switch(event.key.keysym.sym) {
case SDLK_LEFT:
case SDLK_a:
keys[KEY_LEFT] = 0;
break;
case SDLK_RIGHT:
case SDLK_d:
keys[KEY_RIGHT] = 0;
break;
case SDLK_UP:
case SDLK_w:
keys[KEY_UP] = 0;
break;
case SDLK_DOWN:
case SDLK_s:
keys[KEY_DOWN] = 0;
break;
case SDLK_DELETE:
case SDLK_BACKSPACE:
keys[KEY_DELETE] = 0;
break;
case SDLK_EQUALS:
keys[KEY_ZOOM_IN] = 0;
keys[KEY_ZOOM_FULL] = 0;
break;
case SDLK_MINUS:
keys[KEY_ZOOM_OUT] = 0;
break;
case SDLK_t:
keys[KEY_T] = 0;
break;
case SDLK_f:
keys[KEY_F] = 0;
break;
case SDLK_1:
keys[KEY_1] = 0;
break;
case SDLK_2:
keys[KEY_2] = 0;
break;
case SDLK_3:
keys[KEY_3] = 0;
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
if (input_selected != NULL) {
if (input_selected == input_edit_name) {
editor_map->name = copyString(editor_map->name, input_edit_name->text);
} else if (input_selected == input_edit_session) {
editor_map->session = copyString(editor_map->session, input_edit_session->text);
}
input_selected->flags &= ~UI_ACTIVE;
input_selected = NULL;
SDL_StopTextInput();
}
if (inBox(input_edit_name->box, event.motion.x, event.motion.y)) {
input_selected = input_edit_name;
input_selected->flags |= UI_ACTIVE;
SDL_Rect rect = { input_selected->box.x, input_selected->box.y, input_selected->box.w, input_selected->box.h };
SDL_SetTextInputRect(&rect);
SDL_StartTextInput();
} else if (inBox(input_edit_session->box, event.motion.x, event.motion.y)) {
input_selected = input_edit_session;
input_selected->flags |= UI_ACTIVE;
SDL_Rect rect = { input_selected->box.x, input_selected->box.y, input_selected->box.w, input_selected->box.h };
SDL_SetTextInputRect(&rect);
SDL_StartTextInput();
} else if (inBox(quit_button->box, event.motion.x, event.motion.y)) {
button_selected = quit_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(animator_button->box, event.motion.x, event.motion.y)) {
button_selected = animator_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(entedit_button->box, event.motion.x, event.motion.y)) {
button_selected = entedit_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(save_button->box, event.motion.x, event.motion.y)) {
button_selected = save_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(load_button->box, event.motion.x, event.motion.y)) {
button_selected = load_button;
button_selected->flags |= UI_ACTIVE;
// BEGIN tool buttons
} else if (inBox(none_button->box, event.motion.x, event.motion.y)) {
button_selected = none_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(tile_button->box, event.motion.x, event.motion.y)) {
button_selected = tile_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(decor_button->box, event.motion.x, event.motion.y)) {
button_selected = decor_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(trigger_button->box, event.motion.x, event.motion.y)) {
button_selected = trigger_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(event_button->box, event.motion.x, event.motion.y)) {
button_selected = event_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(player_button->box, event.motion.x, event.motion.y)) {
button_selected = player_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(entity_button->box, event.motion.x, event.motion.y)) {
button_selected = entity_button;
button_selected->flags |= UI_ACTIVE;
// BEGIN option buttons
} else if (inBox(coords_button->box, event.motion.x, event.motion.y)) {
button_selected = coords_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(triggers_button->box, event.motion.x, event.motion.y)) {
button_selected = triggers_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(events_button->box, event.motion.x, event.motion.y)) {
button_selected = events_button;
button_selected->flags |= UI_ACTIVE;
} else if (inBox(hide_button->box, event.motion.x, event.motion.y)) {
button_selected = hide_button;
button_selected->flags |= UI_ACTIVE;
}
switch(event.button.button) {
case SDL_BUTTON_LEFT:
mouse = 1;
break;
case SDL_BUTTON_RIGHT:
mouse = 2;
break;
}
mouse_x = event.motion.x;
mouse_y = event.motion.y;
break;
case SDL_MOUSEBUTTONUP:
if (button_selected != NULL) {
if (inBox(button_selected->box, event.motion.x, event.motion.y)) {
if (button_selected == load_button) {
pushState(g_state_manager, newState(STATE_DEFAULT, openMapSelectState, closeMapSelectState, handleMapSelectState, processMapSelectState, renderMapSelectState));
} else if (button_selected == save_button) {
int ret = saveMapData(editor_map);
if (ret < 0) {
setTextt(info, "%d: error while saving", ret);
} else {
setTextt(info, "%d: map \"%s\" saved to \"%s\"", ret, editor_map->name, editor_map->filename);
}
} else if (button_selected == quit_button) {
if(b_mode == BRUSH_PLAYER || b_mode == BRUSH_DECOR || b_mode == BRUSH_TRIGGER || b_mode == BRUSH_EVENT || b_mode == BRUSH_ENTITY) {
switchMode(0);
}
popState(g_state_manager);
} else if (button_selected == animator_button) {
pushState(g_state_manager, newState(STATE_DEFAULT, openAnimatorState, closeAnimatorState, handleAnimatorState, processAnimatorState, renderAnimatorState));
} else if (button_selected == entedit_button) {
pushState(g_state_manager, newState(STATE_DEFAULT, openEntEditState, closeEntEditState, handleEntEditState, processEntEditState, renderEntEditState));
// BEGIN tool buttons
} else if (button_selected == none_button) {
switchMode(0);
} else if (button_selected == tile_button) {
switchMode(BRUSH_FLAG);
} else if (button_selected == decor_button) {
switchMode(BRUSH_DECOR);
} else if (button_selected == trigger_button) {
switchMode(BRUSH_TRIGGER);
} else if (button_selected == event_button) {
switchMode(BRUSH_EVENT);
} else if (button_selected == player_button) {
switchMode(BRUSH_PLAYER);
} else if (button_selected == entity_button) {
switchMode(BRUSH_ENTITY);
// y'know
} else if (button_selected == coords_button) {
if (opts & OPT_COORDS) {
opts &= ~OPT_COORDS;
} else {
opts |= OPT_COORDS;
}
} else if (button_selected == triggers_button) {
if (opts & OPT_TRIGGERS) {
opts &= ~OPT_TRIGGERS;
} else {
opts |= OPT_TRIGGERS;
}
} else if (button_selected == events_button) {
if (opts & OPT_EVENTS) {
opts &= ~OPT_EVENTS;
} else {
opts |= OPT_EVENTS;
}
} else if (button_selected == hide_button) {
if (opts & OPT_HIDE_CELLS) {
opts &= ~OPT_HIDE_CELLS;
} else {
opts |= OPT_HIDE_CELLS;
}
}
}
button_selected->flags &= ~UI_ACTIVE;
button_selected = NULL;
}
mouse = 0;
mouse_x = event.motion.x;
mouse_y = event.motion.y;
break;
case SDL_MOUSEMOTION:
mouse_x = event.motion.x;
mouse_y = event.motion.y;
break;
case SDL_MOUSEWHEEL:
if (event.wheel.y > 0) {
map_zoom -= 0.1;
} else if (event.wheel.y < 0) {
map_zoom += 0.1;
}
break;
case SDL_TEXTINPUT:
if (input_selected != NULL) {
insertTextInput(input_selected, event.text.text);
}
break;
}
return 0;
}
int processEditorState() {
int i;
for(i=0;i < KEYS;i++) {
if (keys[i] == 1) {
switch(i) {
case KEY_UP:
//camera_y -= 8;
camera_y -= ((float)g_tile_h)*map_zoom;
break;
case KEY_DOWN:
//camera_y += 8;
camera_y += ((float)g_tile_h)*map_zoom;
break;
case KEY_LEFT:
//camera_x -= 8;
camera_x -= ((float)g_tile_w)*map_zoom;
break;
case KEY_RIGHT:
//camera_x += 8;
camera_x += ((float)g_tile_w)*map_zoom;
break;
case KEY_DELETE:
if (b_mode == BRUSH_FLAG) {
setCellFlags(editor_map, selected_x, selected_y, 0);
setTextt(info, "cell %dx%d cleared", selected_x, selected_y);
}
break;
case KEY_ZOOM_IN:
map_zoom -= 0.01;
break;
case KEY_ZOOM_OUT:
map_zoom += 0.01;
break;
case KEY_F:
keys[i] += 1;
if (b_mode != BRUSH_FLAG) {
switchMode(BRUSH_FLAG);
b_flags = 0;
} else {
switchMode(0);
b_mode = 0;
}
break;
case KEY_1:
keys[i] += 1;
if (b_mode == BRUSH_FLAG) {
if (b_flags & CELL_BLOCKS_ENTITY) {
b_flags &= ~CELL_BLOCKS_ENTITY;
} else {
b_flags |= CELL_BLOCKS_ENTITY;
}
}
break;
case KEY_2:
keys[i] += 1;
if (b_mode == BRUSH_FLAG) {
if (b_flags & CELL_BLOCKS_PROJECTILE) {
b_flags &= ~CELL_BLOCKS_PROJECTILE;
} else {
b_flags |= CELL_BLOCKS_PROJECTILE;
}
}
break;
case KEY_3:
keys[i] += 1;
if (b_mode == BRUSH_FLAG) {
if (b_flags & CELL_BLOCKS_VISION) {
b_flags &= ~CELL_BLOCKS_VISION;
} else {
b_flags |= CELL_BLOCKS_VISION;
}
}
break;
case KEY_T:
break;
}
changeText(text_cam_x, "x: %d", camera_x);
changeText(text_cam_y, "y: %d", camera_y);
}
}
// handle controls
if (inBox(controls, mouse_x, mouse_y)) {
mouse = 0;
} else {
int m_mouse_x = mouse_x * map_zoom;
int m_mouse_y = mouse_y * map_zoom;
if (b_mode == BRUSH_NONE) {
if (mouse == 1) {
selected_x = (m_mouse_x + camera_x) / g_tile_w;
selected_y = (m_mouse_y + camera_y) / g_tile_h;
setActiveCell(selected_x, selected_y);
}
} else if (b_mode == BRUSH_DECOR) {
if (mouse == 1 || mouse == 2) {
handleDecorMouse(mouse, m_mouse_x+camera_x, m_mouse_y+camera_y);
}
} else if (b_mode == BRUSH_TRIGGER) {
if (mouse == 1 || mouse == 2) {
handleTriggerMouse(mouse, m_mouse_x+camera_x, m_mouse_y+camera_y);
}
} else if (b_mode == BRUSH_EVENT) {
if (mouse == 1 || mouse == 2) {
handleEventMouse(mouse, m_mouse_x+camera_x, m_mouse_y+camera_y);
}
} else if (b_mode == BRUSH_FLAG) {
if (mouse == 1) {
selected_x = (m_mouse_x + camera_x) / g_tile_w;
selected_y = (m_mouse_y + camera_y) / g_tile_h;
setCellFlags(editor_map, selected_x, selected_y, b_flags);
setActiveCell(selected_x, selected_y);
setTextt(info, "cell %dx%d set to %d", selected_x, selected_y, b_flags);
} else if (mouse == 2) {
selected_x = (m_mouse_x + camera_x) / g_tile_w;
selected_y = (m_mouse_y + camera_y) / g_tile_h;
setCellFlags(editor_map, selected_x, selected_y, 0);
setActiveCell(selected_x, selected_y);
setTextt(info, "cell %dx%d cleared", selected_x, selected_y);
}
} else if (b_mode == BRUSH_PLAYER) {
if (mouse == 1) {
} else if (mouse == 2) {
selected_x = (m_mouse_x + camera_x) / g_tile_w;
selected_y = (m_mouse_y + camera_y) / g_tile_h;
if (setPlayer(editor_map, camera_x+m_mouse_x, camera_y+m_mouse_y, "cyb_pl", "spawn", "s", 0) == 0) {
setTextt(info, "set player to %dx%d", camera_x+m_mouse_x, camera_y+m_mouse_y);
// update Player Dialog
syncPlayerDialog();
}
}
} else if (b_mode == BRUSH_ENTITY) {
if (mouse == 1 || mouse == 2) {
handleEventMouse(mouse, m_mouse_x+camera_x, m_mouse_y+camera_y);
}
}
}
return 0;
}
int renderEditorState() {
int x,y;
int w = g_tile_w;
int h = g_tile_h;
int max_width = (map_box.w / w) * map_zoom;
int max_height = (map_box.h / h) * map_zoom;
int start_x = (camera_x / w) - 1; // -1 for overdraw
int start_y = (camera_y / h) - 1; // ^
int end_x = ((camera_x / w) + max_width +1); // +1 for overdraw
int end_y = ((camera_y / h) + max_height +1); // ^ :)
SDL_Color no_tile = { 8, 8, 8 };
SDL_Color open_tile = { 16, 16, 32 };
SDL_Color active_tile = { 128, 128, 8 };
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, g_v_width*map_zoom, g_v_height*map_zoom, 1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// render decors
glColor3f(1.0f, 1.0f, 1.0f);
for (y = start_y; y < end_y+1; y++) {
for(x = start_x; x < end_x+1; x++) {
if (x >= 0 && x < editor_map->width && y >= 0 && y < editor_map->height) {
int d;
for (d = 0; d < editor_map->cells[x][y].decor_count; d++) {
struct DecorMapData *decor = editor_map->cells[x][y].decor[d];
if(decor->sprite != NULL) {
renderSprite(decor->sprite, (x*w-(camera_x)+decor->x)-(decor->sprite->width/2), (y*h-(camera_y)+decor->y)-(decor->sprite->height/2));
}
}
}
}
}
// render all cells
if (~opts & OPT_HIDE_CELLS) {
for(x = start_x; x < end_x+1; x++) {
for (y = start_y; y < end_y+1; y++) {
// out of bounds
if (x < 0 || x >= editor_map->width || y < 0 || y >= editor_map->height) {
renderLQuad(x*w-(camera_x)+1, y*h-(camera_y)+1, w-1, h-1, no_tile);
// unused
} else {
// TEMP decor signifier
if (editor_map->cells[x][y].decor_count > 0) {
SDL_Color color = { 64, 96, 96 };
renderLQuad(x*w-(camera_x)+2, y*h-(camera_y)+2, w-4, h-4, color);
}
if (editor_map->cells[x][y].flags == 0) {
renderLQuad(x*w-(camera_x)+1, y*h-(camera_y)+1, w-1, h-1, open_tile);
} else {
// blocks entity solid outline
if (editor_map->cells[x][y].flags & CELL_BLOCKS_ENTITY) {
SDL_Color color = { 196, 32, 32 };
renderLQuad(x*w-(camera_x)+1, y*h-(camera_y)+1, w-1, h-1, color);
}
// blocks projectile line stipple
if (editor_map->cells[x][y].flags & CELL_BLOCKS_PROJECTILE) {
glEnable(GL_LINE_STIPPLE);
glLineStipple(3, 0x0f0f);
SDL_Color color = { 32, 64, 196 };
renderLQuad(x*w-(camera_x)+1, y*h-(camera_y)+1, w-1, h-1, color);
glDisable(GL_LINE_STIPPLE);
}
// blocks vision cell stipple
if (editor_map->cells[x][y].flags & CELL_BLOCKS_VISION) {
GLubyte mask[] = {
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
glEnable(GL_POLYGON_STIPPLE);
glPolygonStipple(mask);
SDL_Color color = { 128, 128, 128 };
renderSQuad(x*w-(camera_x)+1, y*h-(camera_y)+1, w-1, h-1, color);
glDisable(GL_POLYGON_STIPPLE);
}
}
}
}
}
}
// end bulk cell rendering
// render selected cell border
if (selected_x >= 0 && selected_x < editor_map->width && selected_y >= 0 && selected_y < editor_map->height) {
renderLQuad(selected_x*w-(camera_x), selected_y*h-(camera_y), w+1, h+1, active_tile);
}
// render cell coordinate strings
if (opts & OPT_COORDS) {
SDL_Color cell_text = { 32, 32, 32 };
for(x = start_x; x < end_x+1; x++) {
for (y = start_y; y < end_y+1; y++) {
renderGlyphStringF(&g_small_glyphs, cell_text, x*w-(camera_x)+8, y*h-(camera_y)+8, "%dx%d", x, y);
}
}
}
if (b_mode == BRUSH_DECOR) {
renderDecorMap(start_x, end_x+1, start_y, end_y+1);
} else if (b_mode == BRUSH_ENTITY) {
renderEntityMap(start_x, end_x+1, start_y, end_y+1);
}
if (opts & OPT_TRIGGERS) {
renderTriggerMap(start_x, end_x+1, start_y, end_y+1);
}
if (opts & OPT_EVENTS) {
renderEventMap(start_x, end_x+1, start_y, end_y+1);
}
//
// these two are faster (from 30~fps to 40~fps), but w/e
/*renderMapQuads();
renderMapCoords();*/
// reset our projection from zoomed
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, g_v_width, g_v_height, 1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw user interface
renderControls();
// draw modal dialog
return 0;
}
void closeEditorState() {
report(DEBUG, "EditorState", "closed");
// free map cells
freeMapData(editor_map);
// free text info
freeTextt(info);
freeTextt(text_selected);
freeTextt(text_tool);
// free map edit text
freeTextt(text_edit_name);
freeTextInput(input_edit_name);
freeTextt(text_edit_session);
freeTextInput(input_edit_session);
// free Texts
freeText(text_cam_x);
freeText(text_cam_y);
//
freeButton(none_button);
freeButton(tile_button);
freeButton(decor_button);
freeButton(trigger_button);
freeButton(event_button);
freeButton(player_button);
freeButton(entity_button);
// free buttons
freeButton(quit_button);
freeButton(save_button);
freeButton(load_button);
//
freeButton(animator_button);
freeButton(entedit_button);
//
freeButton(coords_button);
freeButton(events_button);
freeButton(triggers_button);
freeButton(hide_button);
// free resources
freeResources(editor_sprites);
pushState(g_state_manager, newState(STATE_DEFAULT, openMenuState, closeMenuState, handleMenuState, processMenuState, renderMenuState));
}
// Dialog/Mode ================================
int switchMode(int mode) {
// close out old Mode dialog
if (mode == b_mode) {
return 0;
}
if (b_mode != 0 && b_mode != 1) {
popState(g_state_manager);
}
if (editor_map->cells == NULL) return 1;
// open new Mode dialog
switch(mode) {
case 0:
setTextt(info, "switched to select tool");
break;
case BRUSH_FLAG:
setTextt(info, "switched to tile flag tool");
break;
case BRUSH_PLAYER:
pushState(g_state_manager, newState(STATE_DEFAULT, openPlayerDialog, closePlayerDialog, handlePlayerDialog, NULL, renderPlayerDialog));
setTextt(info, "switched to player tool");
break;
case BRUSH_DECOR:
pushState(g_state_manager, newState(STATE_DEFAULT, openDecorDialog, closeDecorDialog, handleDecorDialog, NULL, renderDecorDialog));
setTextt(info, "switched to decor tool");
break;
case BRUSH_TRIGGER:
pushState(g_state_manager, newState(STATE_DEFAULT, openTriggerDialog, closeTriggerDialog, handleTriggerDialog, NULL, renderTriggerDialog));
setTextt(info, "switched to trigger tool");
break;
case BRUSH_EVENT:
pushState(g_state_manager, newState(STATE_DEFAULT, openEventDialog, closeEventDialog, handleEventDialog, NULL, renderEventDialog));
setTextt(info, "switched to event tool");
break;
case BRUSH_ENTITY:
pushState(g_state_manager, newState(STATE_DEFAULT, openEntityDialog, closeEntityDialog, handleEntityDialog, NULL, renderEntityDialog));
setTextt(info, "switched to entity tool");
break;
default:
setTextt(info, "switched to unknown tool");
break;
}
b_mode = mode;
b_flags = 0;
return 0;
}
// Controls Interface ================================
int initControls() {
// control box
controls.w = g_v_width;
controls.h = 128;
controls.x = 0;
controls.y = g_v_height - controls.h;
int offset_y = controls.y + 8;
int offset_x = controls.x + 2;
// tool information
text_selected = newTextt(&g_small_glyphs, button_colors, "");
text_selected->box.y = offset_y;
text_selected->box.x = controls.x + 2;
offset_y += text_selected->box.h + 8;
text_tool = newTextt(&g_small_glyphs, button_colors, "");
text_tool->box.y = offset_y;
text_tool->box.x = controls.x + 2;
offset_y += text_tool->box.h + 16;
// tile, decor, player, and entity mode buttons
none_button = newButton(&g_small_glyphs, button_colors, "none");
none_button->box.y = offset_y;
none_button->box.x = offset_x;
offset_x += none_button->box.w + 2;
tile_button = newButton(&g_small_glyphs, button_colors, "tile");
tile_button->box.y = offset_y;
tile_button->box.x = offset_x;
offset_x += tile_button->box.w + 2;
decor_button = newButton(&g_small_glyphs, button_colors, "decor");
decor_button->box.y = offset_y;
decor_button->box.x = offset_x;
offset_x += decor_button->box.w + 2;
trigger_button = newButton(&g_small_glyphs, button_colors, "trigger");
trigger_button->box.y = offset_y;
trigger_button->box.x = offset_x;
offset_x += trigger_button->box.w + 2;
event_button = newButton(&g_small_glyphs, button_colors, "event");
event_button->box.y = offset_y;
event_button->box.x = offset_x;
offset_x += event_button->box.w + 2;
player_button = newButton(&g_small_glyphs, button_colors, "player");
player_button->box.y = offset_y;
player_button->box.x = offset_x;
offset_x += player_button->box.w + 2;
entity_button = newButton(&g_small_glyphs, button_colors, "entity");
entity_button->box.y = offset_y;
entity_button->box.x = offset_x;
offset_x += entity_button->box.w + 2;
offset_y += entity_button->box.h + 8;
// options buttons
offset_x = controls.x + 2;
coords_button = newButton(&g_small_glyphs, button_colors, "hide/show coords");
coords_button->box.y = offset_y;
coords_button->box.x = offset_x;
offset_x += coords_button->box.w + 2;
hide_button = newButton(&g_small_glyphs, button_colors, "hide/show cells");
hide_button->box.y = offset_y;
hide_button->box.x = offset_x;
offset_x += hide_button->box.w + 2;
triggers_button = newButton(&g_small_glyphs, button_colors, "hide/show triggers");
triggers_button->box.y = offset_y;
triggers_button->box.x = offset_x;
offset_x += triggers_button->box.w + 2;
events_button = newButton(&g_small_glyphs, button_colors, "hide/show events");
events_button->box.y = offset_y;
events_button->box.x = offset_x;
offset_x += events_button->box.w + 2;
// info box
info = newTextt(&g_medium_glyphs, ui_colors, "");
info->box.x = 0;
info->box.y = controls.y + controls.h - info->box.h;
// edit map information
offset_y = controls.y + 8;
text_edit_name = newTextt(&g_medium_glyphs, button_colors, "");
setTextt(text_edit_name, "name: ");
text_edit_name->box.x = 200;
text_edit_name->box.y = offset_y;
input_edit_name = newTextInput(&g_medium_glyphs, button_colors, 200);
setTextInputText(input_edit_name, "%s", editor_map->name);
input_edit_name->box.x = 200 + text_edit_name->box.w + 4;
input_edit_name->box.y = offset_y;
offset_y += text_edit_name->box.h + 8;
text_edit_session = newTextt(&g_medium_glyphs, button_colors, "");
setTextt(text_edit_session, "session: ");
text_edit_session->box.x = 200;
text_edit_session->box.y = offset_y;
input_edit_session = newTextInput(&g_medium_glyphs, button_colors, 200);
setTextInputText(input_edit_session, "%s", editor_map->session);
input_edit_session->box.x = 200 + text_edit_session->box.w + 4;
input_edit_session->box.y = offset_y;
offset_y += text_edit_session->box.h + 8;
// init buttons
offset_y = controls.y + 8;
save_button = newButton(&g_medium_glyphs, button_colors, "save");
save_button->box.x = controls.w - save_button->box.w - 8;
save_button->box.y = offset_y;
offset_y += save_button->box.h + 8;
load_button = newButton(&g_medium_glyphs, button_colors, "load/new");
load_button->box.x = controls.w - load_button->box.w - 8;
load_button->box.y = offset_y;
offset_y += load_button->box.h + 8;
quit_button = newButton(&g_medium_glyphs, button_colors, "quit to menu");
quit_button->box.x = controls.w - quit_button->box.w - 8;
quit_button->box.y = offset_y;
// other tool buttons
offset_y = controls.y + 8;
offset_x = quit_button->box.x - quit_button->box.w - 8;
animator_button = newButton(&g_medium_glyphs, button_colors, "animator");
animator_button->box.x = offset_x;
animator_button->box.y = offset_y;
offset_y += animator_button->box.h + 8;
entedit_button = newButton(&g_medium_glyphs, button_colors, "entedit");
entedit_button->box.x = quit_button->box.x - quit_button->box.w - 8;
entedit_button->box.x = offset_x;
entedit_button->box.y = offset_y;
return 0;
}
int renderControls() {
SDL_Color ui_color = { 4, 16, 16 };
// draw controls box
renderSQuad(controls.x, controls.y, controls.w, controls.h, ui_color);
// draw selected info
if ((selected_x >= 0 && selected_x < editor_map->width) && (selected_y >= 0 && selected_y < editor_map->height)) {
setTextt(text_selected, "selected: %dx%d, flags: %d", selected_x, selected_y, editor_map->cells[selected_x][selected_y].flags);
}
setTextt(text_tool, "tool: %d, flags: %d", b_mode, b_flags);
//
renderTextt(text_selected);
renderTextt(text_tool);
// tool selection buttons
renderButton(none_button);
renderButton(tile_button);
renderButton(player_button);
renderButton(decor_button);
renderButton(trigger_button);
renderButton(event_button);
renderButton(entity_button);
// draw map edit stuff
renderTextt(text_edit_name);
renderTextInput(input_edit_name);
renderTextt(text_edit_session);
renderTextInput(input_edit_session);
// right-hand buttons
renderButton(quit_button);
renderButton(save_button);
renderButton(load_button);
//
renderButton(animator_button);
renderButton(entedit_button);
//
renderButton(hide_button);
renderButton(coords_button);
renderButton(triggers_button);
renderButton(events_button);
// render action info
renderTextt(info);
// render information
//renderText(text_cam_x, text_cam_x->width/2, g_v_height - text_cam_x->height);
//renderText(text_cam_y, 256, g_v_height - text_cam_y->height);
return 0;
}
int handleControls() {
return 0;
}
// ================================
void setActiveCell(int x, int y) {
if ((x >= 0 && x < editor_map->width) && (y >= 0 && y < editor_map->height)) {
active_cell = &editor_map->cells[x][y];
selected_x = x;
selected_y = y;
} else {
active_cell = NULL;
selected_x = 0;
selected_y = 0;
}
}
int syncControls() {
setTextInputText(input_edit_name, "%s", editor_map->name);
setTextInputText(input_edit_session, "%s", editor_map->session);
return 0;
}
// ================================
int renderMapQuads() {
int x, y;
int w = 128;
int h = 96;
int max_width = g_v_width / w;
int max_height = g_v_height / h;
int start_x = (camera_x / w) + 1; // +1 for overdraw
int start_y = (camera_y / h) + 1; // ^
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, 0);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
int offset_x = camera_x % (w);
int offset_y = camera_y % (h);
glTranslated(-offset_x, -offset_y, 0);
for(x = -1; x < max_width+1; x++) {
for (y = -1; y < max_height+1; y++) {
// out of bounds
if (start_x+x < 0 || start_x+x >= editor_map->width || start_y+y < 0 || start_y+y >= editor_map->height) {
glColor3f(0.1f, 0.1f, 0.1f);
// unused
} else if (start_x+x == selected_x && start_y+y == selected_y) {
glColor3f(0.5f, 0.5f, 0.1f);
} else if (editor_map->cells[start_x+x][start_y+y].flags == 0) {
glColor3f(0.1f, 0.1f, 0.25f);
// used
} else {
glColor3f(0.1f, 0.1f, 0.75f);
}
glBegin(GL_QUADS);
glTexCoord2d(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
glTexCoord2d(1.0f, 0.0f); glVertex2f(w, 0.0f);
glTexCoord2d(1.0f, 1.0f); glVertex2f(w, h);
glTexCoord2d(0.0f, 1.0f); glVertex2f(0.0f, h);
glEnd();
glTranslated(0, h+1, 0);
}
glTranslated(w+1, -((max_height+2)*(h+1)), 0);
}
return 0;
}
int renderMapCoords() {
int x, y;
int w = 128;
int h = 96;
int max_width = g_v_width / w;
int max_height = g_v_height / h;
int start_x = (camera_x / w) + 1; // +1 for overdraw
int start_y = (camera_y / h) + 1; // ^
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, g_large_glyphs.texture);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
int offset_x = camera_x % (w);
int offset_y = camera_y % (h);
glTranslated(-offset_x, -offset_y, 0);
for(x = -1; x < max_width+1; x++) {
for (y = -1; y < max_height+1; y++) {
// out of bounds
if (start_x+x < 0 || start_x+x >= editor_map->width || start_y+y < 0 || start_y+y >= editor_map->height) {
glColor3f(0.1f, 0.1f, 0.1f);
// unused
} else if (start_x+x == selected_x && start_y+y == selected_y) {
glColor3f(0.5f, 0.5f, 0.1f);
} else if (editor_map->cells[start_x+x][start_y+y].flags == 0) {
glColor3f(0.1f, 0.1f, 0.25f);
// used
} else {
glColor3f(0.1f, 0.1f, 0.75f);
}
char *string = "test";
int i = 0;
char ch;
int sw = 0;
while ((ch = string[i++]) != '\0') {
int gw = g_large_glyphs.ch_w[ch-32];
int gh = g_large_glyphs.ch_h[ch-32];
float f_gw = (float)gw / (float)g_large_glyphs.w;
float f_gh = (float)gh / (float)g_large_glyphs.h;
float gx = ((float)g_large_glyphs.offsetx[ch-32] / (float)g_large_glyphs.w);
float gy = 0.0f;
glBegin(GL_QUADS);
glTexCoord2d(gx, gy); glVertex2f(0.0f, 0.0f);
glTexCoord2d(gx+f_gw, gy); glVertex2f(gw, 0.0f);
glTexCoord2d(gx+f_gw, gy+f_gh); glVertex2f(gw, gh);
glTexCoord2d(gx, gy+f_gh); glVertex2f(0.0f, gh);
glEnd();
sw += gw;
glTranslated(gw, 0.0f, 0.0f);
}
glTranslated(-sw, h+1, 0);
}
glTranslated(w+1, -((max_height+2)*(h+1)), 0);
}
return 0;
}