/* ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 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; }