1072 lines
35 KiB
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;
|
|
}
|