4 // Copyright (C) 2003 Ricardo Cruz <rick2@aeiou.pt>
5 // Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <SDL_image.h>
30 #include "leveleditor.h"
43 #include "resources.h"
45 /* definitions to aid development */
48 /* definitions that affect gameplay */
49 #define KEY_CURSOR_SPEED 32
50 #define KEY_CURSOR_FASTSPEED 64
52 /* when pagedown/up pressed speed:*/
53 #define PAGE_CURSOR_SPEED 13*32
55 #define MOUSE_LEFT_MARGIN 80
56 #define MOUSE_RIGHT_MARGIN (560-32)
57 /* right_margin should noticed that the cursor is 32 pixels,
58 so it should subtract that value */
59 #define MOUSE_POS_SPEED 20
62 #define SELECT_W 2 // size of the selections lines
63 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
65 /* own declerations */
66 /* crutial ones (main loop) */
70 void le_drawinterface();
71 void le_checkevents();
72 void le_change(float x, float y, int tm, unsigned int c);
75 void le_set_defaults(void);
76 void le_activate_bad_guys(void);
78 void le_highlight_selection();
80 void apply_level_settings_menu();
81 void update_subset_settings_menu();
82 void save_subset_settings_menu();
84 static Level* le_current_level;
86 struct LevelEditorWorld
88 std::vector<BadGuy> bad_guys;
89 void arrays_free(void)
94 void add_bad_guy(float x, float y, BadGuyKind kind)
96 bad_guys.push_back(BadGuy());
97 BadGuy& new_bad_guy = bad_guys.back();
99 new_bad_guy.init(x,y,kind);
102 void activate_bad_guys()
104 for (std::vector<BadGuyData>::iterator i = le_current_level->badguy_data.begin();
105 i != le_current_level->badguy_data.end();
108 add_bad_guy(i->x, i->y, i->kind);
113 /* leveleditor internals */
114 static string_list_type level_subsets;
115 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
116 static int pos_x, cursor_x, cursor_y, fire;
118 static LevelEditorWorld le_world;
119 static st_subset le_level_subset;
120 static int le_show_grid;
122 static Surface* le_selection;
124 static unsigned int le_current_tile;
125 static bool le_mouse_pressed[2];
126 static Button* le_save_level_bt;
127 static Button* le_exit_bt;
128 static Button* le_test_level_bt;
129 static Button* le_next_level_bt;
130 static Button* le_previous_level_bt;
131 static Button* le_move_right_bt;
132 static Button* le_move_left_bt;
133 static Button* le_rubber_bt;
134 static Button* le_select_mode_one_bt;
135 static Button* le_select_mode_two_bt;
136 static Button* le_settings_bt;
137 static Button* le_tilegroup_bt;
138 static ButtonPanel* le_tilemap_panel;
139 static Menu* leveleditor_menu;
140 static Menu* subset_load_menu;
141 static Menu* subset_new_menu;
142 static Menu* subset_settings_menu;
143 static Menu* level_settings_menu;
144 static Menu* select_tilegroup_menu;
145 static Timer select_tilegroup_menu_effect;
146 static std::map<std::string, ButtonPanel* > tilegroups_map;
147 static std::string cur_tilegroup;
149 static square selection;
150 static int le_selection_mode;
151 static SDL_Event event;
152 TileMapType active_tm;
154 void le_set_defaults()
156 if(le_current_level != NULL)
160 if(le_current_level->time_left == 0)
161 le_current_level->time_left = 255;
165 int leveleditor(int levelnb)
167 int last_time, now_time, i;
175 clearscreen(0, 0, 0);
178 while (SDL_PollEvent(&event))
183 last_time = SDL_GetTicks();
188 if(Menu::current() == select_tilegroup_menu)
190 if(select_tilegroup_menu_effect.check())
192 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
196 select_tilegroup_menu->set_pos(screen->w - 64,82,-0.5,0.5);
199 if(le_current_level != NULL)
201 /* making events results to be in order */
204 if(pos_x > (le_current_level->width * 32) - screen->w)
205 pos_x = (le_current_level->width * 32) - screen->w;
211 clearscreen(0, 0, 0);
213 /* draw editor interface */
216 Menu* menu = Menu::current();
222 if(menu == leveleditor_menu)
224 switch (leveleditor_menu->check())
227 Menu::set_current(0);
230 update_subset_settings_menu();
237 else if(menu == level_settings_menu)
239 switch (level_settings_menu->check())
242 apply_level_settings_menu();
243 Menu::set_current(leveleditor_menu);
251 else if(menu == select_tilegroup_menu)
254 switch (it = select_tilegroup_menu->check())
259 if(select_tilegroup_menu->item[it].kind == MN_ACTION)
260 cur_tilegroup = select_tilegroup_menu->item[it].text;
262 Menu::set_current(0);
267 else if(menu == subset_load_menu)
269 switch (i = subset_load_menu->check())
276 le_level_subset.load(level_subsets.item[i-2]);
277 leveleditor_menu->item[3].kind = MN_GOTO;
279 le_world.arrays_free();
280 le_current_level = new Level;
281 if(le_current_level->load(le_level_subset.name.c_str(), le_level) != 0)
287 le_current_level->load_gfx();
288 le_world.activate_bad_guys();
291 Menu::set_current(leveleditor_menu);
296 else if(menu == subset_new_menu)
298 if(subset_new_menu->item[2].input[0] == '\0')
299 subset_new_menu->item[3].kind = MN_DEACTIVE;
302 subset_new_menu->item[3].kind = MN_ACTION;
304 switch (i = subset_new_menu->check())
307 st_subset::create(subset_new_menu->item[2].input);
308 le_level_subset.load(subset_new_menu->item[2].input);
309 leveleditor_menu->item[3].kind = MN_GOTO;
311 le_world.arrays_free();
312 le_current_level = new Level;
313 if(le_current_level->load(le_level_subset.name.c_str(), le_level) != 0)
319 le_current_level->load_gfx();
320 le_world.activate_bad_guys();
321 subset_new_menu->item[2].change_input("");
322 // FIXME:? show_menu = true;
323 Menu::set_current(leveleditor_menu);
328 else if(menu == subset_settings_menu)
330 if(le_level_subset.title.compare(subset_settings_menu->item[2].input) == 0 && le_level_subset.description.compare(subset_settings_menu->item[3].input) == 0 )
331 subset_settings_menu->item[5].kind = MN_DEACTIVE;
333 subset_settings_menu->item[5].kind = MN_ACTION;
335 switch (i = subset_settings_menu->check())
338 save_subset_settings_menu();
339 //FIXME:show_menu = true;
340 Menu::set_current(leveleditor_menu);
346 mouse_cursor->draw();
354 ++global_frame_counter;
357 now_time = SDL_GetTicks();
358 if (now_time < last_time + FPS)
359 SDL_Delay(last_time + FPS - now_time); /* delay some time */
370 level_subsets = dsubdirs("/levels", "info");
376 /* level_changed = NO;*/
379 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
380 le_level_changed = false;
381 le_current_level = NULL;
384 le_mouse_pressed[LEFT] = false;
385 le_mouse_pressed[RIGHT] = false;
387 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
389 select_tilegroup_menu_effect.init(false);
392 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
393 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F6,screen->w-32,32);
394 le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
395 le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
396 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
397 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
398 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,64);
399 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
400 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
401 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
402 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
403 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,80);
405 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
406 le_tilemap_panel->set_button_size(32,10);
407 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_F4,0,0),TM_BG);
408 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_F4,0,0),TM_IA);
409 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_F4,0,0),TM_FG);
411 leveleditor_menu = new Menu();
412 subset_load_menu = new Menu();
413 subset_new_menu = new Menu();
414 subset_settings_menu = new Menu();
415 level_settings_menu = new Menu();
416 select_tilegroup_menu = new Menu();
418 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
419 leveleditor_menu->additem(MN_HL,"",0,0);
420 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0);
421 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu);
422 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
423 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
424 leveleditor_menu->additem(MN_HL,"",0,0);
425 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0);
427 Menu::set_current(leveleditor_menu);
429 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
430 subset_load_menu->additem(MN_HL, "", 0, 0);
432 for(i = 0; i < level_subsets.num_items; ++i)
434 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0);
436 subset_load_menu->additem(MN_HL,"",0,0);
437 subset_load_menu->additem(MN_BACK,"Back",0,0);
439 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
440 subset_new_menu->additem(MN_HL,"",0,0);
441 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0);
442 subset_new_menu->additem(MN_ACTION,"Create",0,0);
443 subset_new_menu->additem(MN_HL,"",0,0);
444 subset_new_menu->additem(MN_BACK,"Back",0,0);
446 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
447 subset_settings_menu->additem(MN_HL,"",0,0);
448 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0);
449 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0);
450 subset_settings_menu->additem(MN_HL,"",0,0);
451 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0);
452 subset_settings_menu->additem(MN_HL,"",0,0);
453 subset_settings_menu->additem(MN_BACK,"Back",0,0);
455 level_settings_menu->arrange_left = true;
456 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
457 level_settings_menu->additem(MN_HL,"",0,0);
458 level_settings_menu->additem(MN_TEXTFIELD,"Name ",0,0);
459 level_settings_menu->additem(MN_TEXTFIELD,"Author ",0,0);
460 level_settings_menu->additem(MN_STRINGSELECT,"Theme ",0,0);
461 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0);
462 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0);
463 level_settings_menu->additem(MN_NUMFIELD,"Length ",0,0);
464 level_settings_menu->additem(MN_NUMFIELD,"Time ",0,0);
465 level_settings_menu->additem(MN_NUMFIELD,"Gravity",0,0);
466 level_settings_menu->additem(MN_NUMFIELD,"Top Red ",0,0);
467 level_settings_menu->additem(MN_NUMFIELD,"Top Green ",0,0);
468 level_settings_menu->additem(MN_NUMFIELD,"Top Blue ",0,0);
469 level_settings_menu->additem(MN_NUMFIELD,"Bottom Red ",0,0);
470 level_settings_menu->additem(MN_NUMFIELD,"Bottom Green",0,0);
471 level_settings_menu->additem(MN_NUMFIELD,"Bottom Blue",0,0);
472 level_settings_menu->additem(MN_HL,"",0,0);
473 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0);
475 select_tilegroup_menu->arrange_left = true;
476 select_tilegroup_menu->additem(MN_LABEL,"Select Tilegroup",0,0);
477 select_tilegroup_menu->additem(MN_HL,"",0,0);
478 std::vector<TileGroup>* tilegroups = TileManager::tilegroups();
479 for(std::vector<TileGroup>::iterator it = tilegroups->begin(); it != tilegroups->end(); ++it )
482 select_tilegroup_menu->additem(MN_ACTION,const_cast<char*>((*it).name.c_str()),0,0);
483 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
485 for(std::vector<int>::iterator sit = (*it).tiles.begin(); sit != (*it).tiles.end(); ++sit, ++i)
486 tilegroups_map[(*it).name]->additem(new Button(const_cast<char*>(("images/tilesets/" + TileManager::instance()->get(*sit)->filenames[0]).c_str()), const_cast<char*>((*it).name.c_str()),(SDLKey)(i+'a'),0,0,32,32),(*sit));
488 select_tilegroup_menu->additem(MN_HL,"",0,0);
490 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
495 void update_level_settings_menu()
500 level_settings_menu->item[2].change_input(le_current_level->name.c_str());
501 level_settings_menu->item[3].change_input(le_current_level->author.c_str());
502 sprintf(str,"%d",le_current_level->width);
504 string_list_copy(level_settings_menu->item[4].list, dsubdirs("images/themes", "solid0.png"));
505 string_list_copy(level_settings_menu->item[5].list, dfiles("music/",NULL, "-fast"));
506 string_list_copy(level_settings_menu->item[6].list, dfiles("images/background",NULL, NULL));
507 string_list_add_item(level_settings_menu->item[6].list,"");
508 if((i = string_list_find(level_settings_menu->item[4].list,le_current_level->theme.c_str())) != -1)
509 level_settings_menu->item[3].list->active_item = i;
510 if((i = string_list_find(level_settings_menu->item[5].list,le_current_level->song_title.c_str())) != -1)
511 level_settings_menu->item[4].list->active_item = i;
512 if((i = string_list_find(level_settings_menu->item[6].list,le_current_level->bkgd_image.c_str())) != -1)
513 level_settings_menu->item[5].list->active_item = i;
515 level_settings_menu->item[7].change_input(str);
516 sprintf(str,"%d",le_current_level->time_left);
517 level_settings_menu->item[8].change_input(str);
518 sprintf(str,"%2.0f",le_current_level->gravity);
519 level_settings_menu->item[9].change_input(str);
520 sprintf(str,"%d",le_current_level->bkgd_top.red);
521 level_settings_menu->item[10].change_input(str);
522 sprintf(str,"%d",le_current_level->bkgd_top.green);
523 level_settings_menu->item[11].change_input(str);
524 sprintf(str,"%d",le_current_level->bkgd_top.blue);
525 level_settings_menu->item[12].change_input(str);
526 sprintf(str,"%d",le_current_level->bkgd_bottom.red);
527 level_settings_menu->item[13].change_input(str);
528 sprintf(str,"%d",le_current_level->bkgd_bottom.green);
529 level_settings_menu->item[14].change_input(str);
530 sprintf(str,"%d",le_current_level->bkgd_bottom.blue);
531 level_settings_menu->item[15].change_input(str);
534 void update_subset_settings_menu()
536 subset_settings_menu->item[2].change_input(le_level_subset.title.c_str());
537 subset_settings_menu->item[3].change_input(le_level_subset.description.c_str());
540 void apply_level_settings_menu()
545 le_current_level->name = level_settings_menu->item[2].input;
546 le_current_level->author = level_settings_menu->item[3].input;
548 if(le_current_level->bkgd_image.compare(string_list_active(level_settings_menu->item[6].list)) != 0)
550 le_current_level->bkgd_image = string_list_active(level_settings_menu->item[6].list);
554 if(le_current_level->theme.compare(string_list_active(level_settings_menu->item[4].list)) != 0)
556 le_current_level->theme = string_list_active(level_settings_menu->item[4].list);
562 le_current_level->free_gfx();
563 le_current_level->load_gfx();
566 le_current_level->song_title = string_list_active(level_settings_menu->item[5].list);
568 le_current_level->change_size(atoi(level_settings_menu->item[7].input));
569 le_current_level->time_left = atoi(level_settings_menu->item[8].input);
570 le_current_level->gravity = atof(level_settings_menu->item[9].input);
571 le_current_level->bkgd_top.red = atoi(level_settings_menu->item[10].input);
572 le_current_level->bkgd_top.green = atoi(level_settings_menu->item[11].input);
573 le_current_level->bkgd_top.blue = atoi(level_settings_menu->item[12].input);
574 le_current_level->bkgd_bottom.red = atoi(level_settings_menu->item[13].input);
575 le_current_level->bkgd_bottom.green = atoi(level_settings_menu->item[14].input);
576 le_current_level->bkgd_bottom.blue = atoi(level_settings_menu->item[15].input);
579 void save_subset_settings_menu()
581 le_level_subset.title = subset_settings_menu->item[2].input;
582 le_level_subset.description = subset_settings_menu->item[3].input;
583 le_level_subset.save();
586 void le_goto_level(int levelnb)
588 le_world.arrays_free();
590 le_current_level->cleanup();
591 if(le_current_level->load(le_level_subset.name.c_str(), levelnb) != 0)
593 le_current_level->load(le_level_subset.name.c_str(), le_level);
602 le_current_level->free_gfx();
603 le_current_level->load_gfx();
605 le_world.activate_bad_guys();
610 /*if(level_changed == true)
611 if(askforsaving() == CANCEL)
614 SDL_EnableKeyRepeat(0, 0); // disables key repeating
617 delete leveleditor_menu;
618 delete subset_load_menu;
619 delete subset_new_menu;
620 delete subset_settings_menu;
621 delete level_settings_menu;
622 delete select_tilegroup_menu;
623 delete le_save_level_bt;
625 delete le_test_level_bt;
626 delete le_next_level_bt;
627 delete le_previous_level_bt;
628 delete le_move_right_bt;
629 delete le_move_left_bt;
631 delete le_select_mode_one_bt;
632 delete le_select_mode_two_bt;
633 delete le_settings_bt;
634 delete le_tilegroup_bt;
635 delete le_tilemap_panel;
637 if(le_current_level != NULL)
639 le_current_level->free_gfx();
640 le_current_level->cleanup();
641 le_world.arrays_free();
645 void le_drawinterface()
650 if(le_current_level != NULL)
652 /* draw a grid (if selected) */
655 for(x = 0; x < 19; x++)
656 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
657 for(y = 0; y < 15; y++)
658 fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
662 if(le_selection_mode == CURSOR)
663 le_selection->draw( cursor_x - pos_x, cursor_y);
664 else if(le_selection_mode == SQUARE)
667 le_highlight_selection();
668 /* draw current selection */
669 w = selection.x2 - selection.x1;
670 h = selection.y2 - selection.y1;
671 fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
672 fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
673 fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
674 fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
678 /* draw button bar */
679 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
680 Tile::draw(19 * 32, 14 * 32, le_current_tile);
682 if(TileManager::instance()->get(le_current_tile)->editor_images.size() > 0)
683 TileManager::instance()->get(le_current_tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
685 if(le_current_level != NULL)
687 le_save_level_bt->draw();
689 le_test_level_bt->draw();
690 le_next_level_bt->draw();
691 le_previous_level_bt->draw();
692 le_rubber_bt->draw();
693 le_select_mode_one_bt->draw();
694 le_select_mode_two_bt->draw();
695 le_settings_bt->draw();
696 le_move_right_bt->draw();
697 le_move_left_bt->draw();
698 le_tilegroup_bt->draw();
699 if(!cur_tilegroup.empty())
700 tilegroups_map[cur_tilegroup]->draw();
701 le_tilemap_panel->draw();
703 sprintf(str, "%d/%d", le_level,le_level_subset.levels);
704 white_text->drawf(str, -10, 16, A_RIGHT, A_TOP, 0);
706 white_small_text->draw("F1 for Help", 10, 430, 1);
711 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
713 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
720 unsigned int y,x,i,s;
723 /* Draw the real background */
724 if(le_current_level->bkgd_image[0] != '\0')
727 le_current_level->img_bkgd->draw_part(s,0,0,0,
728 le_current_level->img_bkgd->w - s - 32, le_current_level->img_bkgd->h);
729 le_current_level->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
730 le_current_level->img_bkgd->h);
734 drawgradient(le_current_level->bkgd_top, le_current_level->bkgd_bottom);
737 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
739 for (y = 0; y < 15; ++y)
740 for (x = 0; x < 20; ++x)
743 if(active_tm == TM_BG)
748 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->bg_tiles[y][x + (int)(pos_x / 32)],a);
750 if(active_tm == TM_IA)
755 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->ia_tiles[y][x + (int)(pos_x / 32)],a);
757 if(active_tm == TM_FG)
762 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->fg_tiles[y][x + (int)(pos_x / 32)],a);
764 /* draw whats inside stuff when cursor is selecting those */
765 /* (draw them all the time - is this the right behaviour?) */
766 if(TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images.size() > 0)
767 TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
771 /* Draw the Bad guys: */
772 for (i = 0; i < le_world.bad_guys.size(); ++i)
774 /* to support frames: img_bsod_left[(frame / 5) % 4] */
777 le_world.bad_guys[i].draw();
781 /* Draw the player: */
782 /* for now, the position is fixed at (100, 240) */
783 tux_right[(global_frame_counter / 5) % 3]->draw( 100 - pos_x, 240);
786 void le_checkevents()
793 keymod = SDL_GetModState();
795 while(SDL_PollEvent(&event))
799 Menu::current()->event(event);
803 mouse_cursor->set_state(MC_NORMAL);
805 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
806 if(event.type == SDL_KEYDOWN
807 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
808 && (event.motion.x > 0
809 && event.motion.x < screen->w - 64 &&
810 event.motion.y > 0 && event.motion.y < screen->h)))
814 case SDL_KEYDOWN: // key pressed
815 key = event.key.keysym.sym;
819 Menu::set_current(leveleditor_menu);
822 cursor_x -= KEY_CURSOR_SPEED;
824 cursor_x -= KEY_CURSOR_FASTSPEED;
826 if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
827 pos_x = cursor_x - MOUSE_LEFT_MARGIN;
832 cursor_x += KEY_CURSOR_SPEED;
834 cursor_x += KEY_CURSOR_FASTSPEED;
836 if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
837 pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
842 cursor_y -= KEY_CURSOR_SPEED;
844 cursor_y -= KEY_CURSOR_FASTSPEED;
851 cursor_y += KEY_CURSOR_SPEED;
853 cursor_y += KEY_CURSOR_FASTSPEED;
855 if(cursor_y > screen->h-32)
856 cursor_y = screen->h-32;
869 cursor_x = (le_current_level->width * 32) - 32;
873 le_show_grid = !le_show_grid;
879 case SDL_KEYUP: /* key released */
880 switch(event.key.keysym.sym)
889 case SDL_MOUSEBUTTONDOWN:
890 if(event.button.button == SDL_BUTTON_LEFT)
892 le_mouse_pressed[LEFT] = true;
894 selection.x1 = event.motion.x + pos_x;
895 selection.y1 = event.motion.y;
896 selection.x2 = event.motion.x + pos_x;
897 selection.y2 = event.motion.y;
899 else if(event.button.button == SDL_BUTTON_RIGHT)
901 le_mouse_pressed[RIGHT] = true;
904 case SDL_MOUSEBUTTONUP:
905 if(event.button.button == SDL_BUTTON_LEFT)
906 le_mouse_pressed[LEFT] = false;
907 else if(event.button.button == SDL_BUTTON_RIGHT)
908 le_mouse_pressed[RIGHT] = false;
910 case SDL_MOUSEMOTION:
917 cursor_x = ((int)(pos_x + x) / 32) * 32;
918 cursor_y = ((int) y / 32) * 32;
920 if(le_mouse_pressed[LEFT])
922 selection.x2 = x + pos_x;
926 if(le_mouse_pressed[RIGHT])
928 pos_x += -1 * event.motion.xrel;
932 case SDL_QUIT: // window closed
941 if(le_current_level != NULL)
943 if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > screen->w-64 && event.motion.x < screen->w &&
944 event.motion.y > 0 && event.motion.y < screen->h)))
946 le_mouse_pressed[LEFT] = false;
947 le_mouse_pressed[RIGHT] = false;
951 /* Check for button events */
952 le_test_level_bt->event(event);
953 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
955 le_save_level_bt->event(event);
956 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
957 le_current_level->save(le_level_subset.name.c_str(),le_level);
958 le_exit_bt->event(event);
959 if(le_exit_bt->get_state() == BUTTON_CLICKED)
961 Menu::set_current(leveleditor_menu);
963 le_next_level_bt->event(event);
964 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
966 if(le_level < le_level_subset.levels)
968 le_goto_level(++le_level);
975 sprintf(str,"Level %d doesn't exist.",le_level+1);
976 white_text->drawf(str,0,-18,A_HMIDDLE,A_VMIDDLE,2);
977 white_text->drawf("Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2);
978 red_text->drawf("(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2);
982 while(SDL_PollEvent(&event))
985 case SDL_KEYDOWN: // key pressed
986 switch(event.key.keysym.sym)
989 new_lev.init_defaults();
990 new_lev.save(le_level_subset.name.c_str(),++le_level);
991 le_level_subset.levels = le_level;
992 le_goto_level(le_level);
1009 le_previous_level_bt->event(event);
1010 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1013 le_goto_level(--le_level);
1015 le_rubber_bt->event(event);
1016 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1017 le_current_tile = 0;
1018 le_select_mode_one_bt->event(event);
1019 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1020 le_selection_mode = CURSOR;
1021 le_select_mode_two_bt->event(event);
1022 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1023 le_selection_mode = SQUARE;
1025 le_tilegroup_bt->event(event);
1026 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1028 Menu::set_current(select_tilegroup_menu);
1029 select_tilegroup_menu_effect.start(200);
1030 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1033 le_settings_bt->event(event);
1034 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1036 update_level_settings_menu();
1037 Menu::set_current(level_settings_menu);
1039 if(!cur_tilegroup.empty())
1040 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1042 if(pbutton->get_state() == BUTTON_CLICKED)
1044 le_current_tile = pbutton->get_tag();
1047 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1049 if(pbutton->get_state() == BUTTON_CLICKED)
1051 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1057 le_settings_bt->event(event);
1058 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1060 Menu::set_current(0);
1062 le_tilegroup_bt->event(event);
1063 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1065 Menu::set_current(0);
1070 if(!Menu::current())
1072 le_move_left_bt->event(event);
1073 le_move_right_bt->event(event);
1075 if(le_mouse_pressed[LEFT])
1077 le_change(cursor_x, cursor_y, active_tm, le_current_tile);
1082 if(!Menu::current())
1084 if(le_move_left_bt->get_state() == BUTTON_PRESSED)
1088 else if(le_move_left_bt->get_state() == BUTTON_HOVER)
1093 if(le_move_right_bt->get_state() == BUTTON_PRESSED)
1097 else if(le_move_right_bt->get_state() == BUTTON_HOVER)
1105 void le_highlight_selection()
1109 if(selection.x1 < selection.x2)
1119 if(selection.y1 < selection.y2)
1135 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1138 void le_change(float x, float y, int tm, unsigned int c)
1140 if(le_current_level != NULL)
1146 /* level_changed = true; */
1148 switch(le_selection_mode)
1151 le_current_level->change(x,y,tm,c);
1156 /* if there is a bad guy over there, remove it */
1157 for(i = 0; i < le_world.bad_guys.size(); ++i)
1158 if(xx == le_world.bad_guys[i].base.x/32 && yy == le_world.bad_guys[i].base.y/32)
1159 le_world.bad_guys.erase(le_world.bad_guys.begin() + i);
1161 if(c == '0') /* if it's a bad guy */
1162 le_world.add_bad_guy(xx*32, yy*32, BAD_BSOD);
1164 le_world.add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1166 le_world.add_bad_guy(xx*32, yy*32, BAD_MONEY);
1170 if(selection.x1 < selection.x2)
1180 if(selection.y1 < selection.y2)
1196 /* if there is a bad guy over there, remove it */
1197 for(i = 0; i < le_world.bad_guys.size(); ++i)
1198 if(le_world.bad_guys[i].base.x/32 >= x1 && le_world.bad_guys[i].base.x/32 <= x2
1199 && le_world.bad_guys[i].base.y/32 >= y1 && le_world.bad_guys[i].base.y/32 <= y2)
1200 le_world.bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(&le_world.bad_guys[i]));
1202 for(xx = x1; xx <= x2; xx++)
1203 for(yy = y1; yy <= y2; yy++)
1205 le_current_level->change(xx*32, yy*32, tm, c);
1207 if(c == '0') // if it's a bad guy
1208 le_world.add_bad_guy(xx*32, yy*32, BAD_BSOD);
1210 le_world.add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1212 le_world.add_bad_guy(xx*32, yy*32, BAD_MONEY);
1223 le_current_level->save("test", le_level);
1225 GameSession session("test",le_level, ST_GL_TEST);
1228 Menu::set_current(leveleditor_menu);
1229 le_world.arrays_free();
1230 le_current_level->load_gfx();
1231 le_world.activate_bad_guys();
1237 unsigned int i, done_;
1239 " - This is SuperTux's built-in level editor -",
1240 "It has been designed to be light and easy to use from the start.",
1242 "When you first load the level editor you are given a menu where you",
1243 "can load level subsets, create a new level subset, edit the current",
1244 "subset's settings, or simply quit the editor. You can access this menu",
1245 "from the level editor at any time by pressing the escape key.",
1247 "To your right is your button bar. The center of this contains many",
1248 "tiles you can use to make your level. To select a tile, click on it",
1249 "with your left mouse button; your selection will be shown in the",
1250 "bottom right corner of the button box. Click anywhere on your level",
1251 "with the left mouse button to place that tile down. If you right click",
1252 "a tile in the button bar, you can find out what its keyboard shortcut",
1253 "is. The three buttons FGD, BGD and EMY let you pick from foreground,",
1254 "background, and enemy tiles. The eraser lets you remove tiles.",
1255 "The left and right arrow keys scroll back and forth through your level.",
1256 "The button with the wrench and screwdriver, lets you change the",
1257 "settings of your level, including how long it is or what music it will",
1258 "play. When you are ready to give your level a test, click on the little",
1259 "running Tux. If you like the changes you have made to your level,",
1260 "press the red save key to keep them.",
1261 "To change which level in your subset you are editing, press the white",
1262 "up and down arrow keys at the top of the button box.",
1264 "Have fun making levels! If you make some good ones, send them to us on",
1265 "the SuperTux mailing list!",
1270 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1272 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1273 white_small_text->draw(text[i], 5, 80+(i*white_small_text->h), 1);
1275 gold_text->drawf("Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
1283 done_ = wait_for_event(event);