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.
30 #include <SDL_image.h>
33 #include "leveleditor.h"
35 #include "screen/screen.h"
46 #include "resources.h"
47 #include "background.h"
50 /* definitions to aid development */
52 /* definitions that affect gameplay */
53 #define KEY_CURSOR_SPEED 32
54 #define KEY_CURSOR_FASTSPEED 64
56 /* when pagedown/up pressed speed:*/
57 #define PAGE_CURSOR_SPEED 13*32
59 #define MOUSE_LEFT_MARGIN 80
60 #define MOUSE_RIGHT_MARGIN (560-32)
63 #define KEYBOARD_SPEED 140
64 #define MOUSE_SPEED 40
67 #define SELECT_W 2 // size of the selections lines
68 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
70 enum { TM_IA, TM_BG, TM_FG };
72 LevelEditor::LevelEditor()
74 level_subsets = dsubdirs("/levels", "level1.stl");
75 le_level_subset = new LevelSubset;
79 selected_game_object = NULL;
83 show_selections = true;
86 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
87 le_level_changed = false;
88 le_help_shown = false;
90 le_mouse_pressed[LEFT] = false;
91 le_mouse_pressed[RIGHT] = false;
93 le_mouse_clicked[LEFT] = false;
94 le_mouse_clicked[RIGHT] = false;
96 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
98 select_tilegroup_menu_effect.init(false);
99 select_objects_menu_effect.init(false);
100 display_level_info.init(false);
103 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
104 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
105 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
106 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
107 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
108 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
109 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
110 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
111 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
112 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
113 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
114 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
115 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
116 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
117 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
118 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
119 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
120 le_object_properties_bt->set_active(false);
122 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
123 mouse_select_object->set_mid(16,16);
125 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
126 le_tilemap_panel->set_button_size(32,10);
127 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
128 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0), TM_IA);
129 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
130 le_tilemap_panel->highlight_last(true);
131 le_tilemap_panel->set_last_clicked(TM_IA);
137 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
140 LevelEditor::~LevelEditor()
142 SDL_EnableKeyRepeat(0, 0); // disables key repeating
146 delete leveleditor_menu;
147 delete subset_load_menu;
148 delete subset_new_menu;
149 delete subset_settings_menu;
150 delete level_settings_menu;
151 delete select_tilegroup_menu;
152 delete select_objects_menu;
153 delete le_save_level_bt;
155 delete le_test_level_bt;
156 delete le_next_level_bt;
157 delete le_previous_level_bt;
158 delete le_move_right_bt;
159 delete le_move_left_bt;
160 delete le_move_up_bt;
161 delete le_move_down_bt;
163 delete le_select_mode_one_bt;
164 delete le_select_mode_two_bt;
165 delete le_settings_bt;
166 delete le_tilegroup_bt;
167 delete le_objects_bt;
168 delete le_tilemap_panel;
169 delete le_object_select_bt;
170 delete le_object_properties_bt;
171 delete mouse_select_object;
173 delete le_level_subset;
176 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
177 i != tilegroups_map.end(); ++i)
181 for(ButtonPanelMap::iterator i = objects_map.begin();
182 i != objects_map.end(); ++i)
188 int LevelEditor::run(char* filename)
190 int last_time, now_time, i;
191 DrawingContext context;
196 sound_manager->halt_music();
198 while (SDL_PollEvent(&event))
202 if(load_level_subset(filename))
207 last_time = SDL_GetTicks();
212 if(Menu::current() == select_tilegroup_menu)
214 if(select_tilegroup_menu_effect.check())
216 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
220 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
222 else if(Menu::current() == select_objects_menu)
224 if(select_objects_menu_effect.check())
226 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
229 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
234 /* making events results to be in order */
240 fillrect(0, 0, screen->w, screen->h, 0, 0, 0);
242 /* draw editor interface */
243 drawinterface(context);
245 Menu* menu = Menu::current();
251 if(menu == leveleditor_menu)
253 switch (leveleditor_menu->check())
255 case MNID_RETURNLEVELEDITOR:
257 Menu::set_current(0);
259 Menu::set_current(leveleditor_menu);
261 case MNID_SUBSETSETTINGS:
262 update_subset_settings_menu();
264 case MNID_QUITLEVELEDITOR:
269 else if(menu == level_settings_menu)
271 switch (level_settings_menu->check())
274 apply_level_settings_menu();
275 Menu::set_current(NULL);
282 else if(menu == select_tilegroup_menu)
285 switch (it = select_tilegroup_menu->check())
290 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
291 Menu::set_current(0);
298 else if(menu == select_objects_menu)
301 switch (it = select_objects_menu->check())
306 cur_objects = select_objects_menu->get_item_by_id(it).text;
309 Menu::set_current(0);
314 else if(menu == subset_load_menu)
316 switch (i = subset_load_menu->check())
323 if(load_level_subset(level_subsets.item[i-1]))
329 else if(menu == subset_new_menu)
331 if(subset_new_menu->item[2].input[0] == '\0')
332 subset_new_menu->item[3].kind = MN_DEACTIVE;
335 subset_new_menu->item[3].kind = MN_ACTION;
337 switch (i = subset_new_menu->check())
339 case MNID_CREATESUBSET:
340 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
341 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
342 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
344 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
346 Menu::set_current(subset_settings_menu);
351 else if(menu == subset_settings_menu)
353 if(le_level_subset->title.compare(subset_settings_menu->get_item_by_id(MNID_SUBSETTITLE).input) == 0 && le_level_subset->description.compare(subset_settings_menu->get_item_by_id(MNID_SUBSETDESCRIPTION).input) == 0 )
354 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
356 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
358 switch (i = subset_settings_menu->check())
360 case MNID_SUBSETSAVECHANGES:
361 save_subset_settings_menu();
362 Menu::set_current(leveleditor_menu);
368 MouseCursor::current()->draw(context);
375 ++global_frame_counter;
378 now_time = SDL_GetTicks();
379 if (now_time < last_time + FPS)
380 SDL_Delay(last_time + FPS - now_time); /* delay some time */
382 context.do_drawing();
388 int LevelEditor::load_level_subset(char *filename)
390 le_level_subset->load(filename);
391 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
393 goto_level(le_levelnb);
395 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
397 Menu::set_current(NULL);
402 void LevelEditor::init_menus()
406 leveleditor_menu = new Menu();
407 subset_load_menu = new Menu();
408 subset_new_menu = new Menu();
409 subset_settings_menu = new Menu();
410 level_settings_menu = new Menu();
411 select_tilegroup_menu = new Menu();
412 select_objects_menu = new Menu();
414 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
415 leveleditor_menu->additem(MN_HL,"",0,0);
416 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
417 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
418 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
419 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
420 leveleditor_menu->additem(MN_HL,"",0,0);
421 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
423 Menu::set_current(leveleditor_menu);
425 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
426 subset_load_menu->additem(MN_HL, "", 0, 0);
428 for(i = 0; i < level_subsets.num_items; ++i)
430 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
432 subset_load_menu->additem(MN_HL,"",0,0);
433 subset_load_menu->additem(MN_BACK,"Back",0,0);
435 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
436 subset_new_menu->additem(MN_HL,"",0,0);
437 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
438 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
439 subset_new_menu->additem(MN_HL,"",0,0);
440 subset_new_menu->additem(MN_BACK,"Back",0,0);
442 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
443 subset_settings_menu->additem(MN_HL,"",0,0);
444 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
445 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
446 subset_settings_menu->additem(MN_HL,"",0,0);
447 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
448 subset_settings_menu->additem(MN_HL,"",0,0);
449 subset_settings_menu->additem(MN_BACK,"Back",0,0);
451 level_settings_menu->arrange_left = true;
452 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
453 level_settings_menu->additem(MN_HL,"",0,0);
454 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
455 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
456 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
457 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
458 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
459 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
460 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
461 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
462 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
463 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
464 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
465 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
466 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
467 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
468 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
469 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
470 level_settings_menu->additem(MN_HL,"",0,0);
471 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
473 select_tilegroup_menu->arrange_left = true;
474 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
475 select_tilegroup_menu->additem(MN_HL,"",0,0);
476 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
478 for(std::set<TileGroup>::iterator it = tilegroups->begin();
479 it != tilegroups->end(); ++it )
481 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
483 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
486 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
487 sit != (*it).tiles.end(); ++sit, ++i)
489 Tile& tile = *(TileManager::instance()->get(*sit));
491 if(tile.editor_images.size() > 0)
492 image = tile.editor_images[0];
493 else if(tile.images.size() > 0)
494 image = tile.images[0];
496 // TODO use some notile image...
499 Button* button = new Button(image, it->name, SDLKey(SDLK_a + i),
501 tilegroups_map[it->name]->additem(button, *sit);
504 select_tilegroup_menu->additem(MN_HL,"",0,0);
506 select_objects_menu->arrange_left = true;
507 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
508 select_objects_menu->additem(MN_HL,"",0,0);
510 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
511 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
513 for(int i = 0; i < NUM_BadGuyKinds; ++i)
515 // BadGuy bad_tmp(BadGuyKind(i), 0, 0);
516 // objects_map["BadGuys"]->additem(new Button(0, "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
517 /* FIXME: maybe addbutton should already have a parameter for the surface
518 objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
519 BadGuy(BadGuyKind(i),
520 objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
521 objects_map["BadGuys"]->manipulate_button(i)->get_pos().y
525 select_objects_menu->additem(MN_HL,"",0,0);
529 void LevelEditor::update_level_settings_menu()
534 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_level->name.c_str());
535 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_level->author.c_str());
537 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
538 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
539 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
540 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
541 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
542 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
544 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_level->get_sector("main")->song_title.c_str())) != -1)
545 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
546 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_level->get_sector("main")->background->get_image().c_str())) != -1)
547 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
548 /* if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_level->get_sector("main")->particlesystem.c_str())) != -1)
549 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;*/
551 sprintf(str,"%d",le_level->get_sector("main")->solids->get_width());
552 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
553 sprintf(str,"%d",le_level->get_sector("main")->solids->get_height());
554 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
555 sprintf(str,"%d",le_level->time_left);
556 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
557 sprintf(str,"%2.0f",le_level->get_sector("main")->gravity);
558 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
559 sprintf(str,"%2.2f", le_level->get_sector("main")->background->get_speed());
560 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
561 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_top().red);
562 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
563 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_top().green);
564 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
565 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_top().blue);
566 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
567 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_bottom().red);
568 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
569 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_bottom().green);
570 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
571 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_bottom().blue);
572 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
575 void LevelEditor::update_subset_settings_menu()
577 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
578 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
581 void LevelEditor::apply_level_settings_menu()
585 le_level_changed = true;
587 le_level->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
588 le_level->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
590 if(le_level->get_sector("main")->background->get_image().compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
592 le_level->get_sector("main")->background->set_image(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list), atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input));
596 /* if(le_level->get_sector("main")->particlesystem.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
598 le_level->->get_sector("main")->particlesystem = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
603 le_level->load_gfx();
606 le_level->get_sector("main")->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
608 le_level->get_sector("main")->solids->resize(
609 atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
610 atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
611 le_level->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
612 le_level->get_sector("main")->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
613 le_level->get_sector("main")->background->set_gradient(Color(
614 atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input),
615 atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input),
616 atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input)), Color(
617 atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input),
618 atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input),
619 atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input)));
622 void LevelEditor::save_subset_settings_menu()
624 le_level_subset->title = subset_settings_menu->item[2].input;
625 le_level_subset->description = subset_settings_menu->item[3].input;
626 le_level_subset->save();
627 le_level_changed = false;
630 void LevelEditor::unload_level()
635 // TODO get level number
636 sprintf(str,"Save changes to level %d of %s?", 0/*le_level*/,le_level_subset->name.c_str());
637 Surface* surf = new Surface(le_level->get_sector("main")->background->get_image(), false);
638 if(confirm_dialog(surf, str))
640 le_level->save(le_level_subset->get_level_filename(le_levelnb));
647 le_level_changed = false;
650 void LevelEditor::goto_level(int levelnb)
653 le_level = new Level();
654 le_level->load(le_level_subset->get_level_filename(levelnb));
655 display_level_info.start(2500);
656 le_levelnb = levelnb;
659 void LevelEditor::drawminimap()
662 // if(le_level == NULL)
666 if((unsigned)screen->w - 64 > le_level->get_sector("main")->solids->get_width() * 4)
668 else if((unsigned)screen->w - 64 > le_level->get_sector("main")->solids->get_width() * 2)
672 int left_offset = (screen->w - 64 - le_level->get_sector("main")->solids->get_width()*mini_tile_width) / 2;
674 int mini_tile_height;
675 if((unsigned)screen->h > le_level->get_sector("main")->solids->get_height() * 4)
676 mini_tile_height = 4;
677 else if((unsigned)screen->h > le_level->get_sector("main")->solids->get_height() * 2)
678 mini_tile_height = 2;
680 mini_tile_height = 1;
682 for (unsigned int y = 0; y < le_level->get_sector("main")->solids->get_height(); ++y)
683 for (unsigned int x = 0; x < le_level->get_sector("main")->solids->get_width(); ++x)
686 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
687 mini_tile_width , mini_tile_height, le_level->bg_tiles[y * le_level->get_sector("main")->solids->get_width() + x]);
689 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
690 mini_tile_width , mini_tile_height, le_level->ia_tiles[y * le_level->get_sector("main")->solids->get_width() + x]);
692 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
693 mini_tile_width , mini_tile_height, le_level->fg_tiles[y + le_level->get_sector("main")->solids->get_width() + x]);
697 fillrect(left_offset, 0,
698 le_level->get_sector("main")->solids->get_width()*mini_tile_width, le_level->get_sector("main")->solids->get_height()*mini_tile_height,
701 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height,
702 (VISIBLE_TILES_X-3)*mini_tile_width, 2,
704 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height,
705 2, (VISIBLE_TILES_Y-1)*mini_tile_height,
707 fillrect(left_offset + (pos_x/32)*mini_tile_width + (VISIBLE_TILES_X-3)*mini_tile_width - 2, (pos_y/32)*mini_tile_height,
708 2, (VISIBLE_TILES_Y-1)*mini_tile_height,
710 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height + (VISIBLE_TILES_Y-1)*mini_tile_height - 2,
711 (VISIBLE_TILES_X-3)*mini_tile_width, 2,
716 void LevelEditor::drawinterface(DrawingContext &context)
723 /* draw a grid (if selected) */
726 for(x = 0; x < VISIBLE_TILES_X; x++)
727 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
728 for(y = 0; y < VISIBLE_TILES_Y; y++)
729 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
733 if(show_minimap) // use_gl because the minimap isn't shown correctly in software mode. Any idea? FIXME Possible reasons: SDL_SoftStretch is a hack itsself || an alpha blitting issue SDL can't handle in software mode
736 if(show_selections && MouseCursor::current() != mouse_select_object)
738 if(le_selection_mode == CURSOR)
740 if(le_current.IsTile())
741 context.draw_surface(le_selection, Vector(cursor_x - pos_x, cursor_y - pos_y), LAYER_GUI);
743 else if(le_selection_mode == SQUARE)
746 highlight_selection();
747 /* draw current selection */
748 w = selection.x2 - selection.x1;
749 h = selection.y2 - selection.y1;
750 context.draw_filled_rect(Vector(selection.x1 - pos_x, selection.y1 - pos_y), Vector(w, SELECT_W), Color(SELECT_CLR), LAYER_GUI);
751 context.draw_filled_rect(Vector(selection.x1 - pos_x + w, selection.y1 - pos_y), Vector(SELECT_W, h), Color(SELECT_CLR), LAYER_GUI);
752 context.draw_filled_rect(Vector(selection.x1 - pos_x, selection.y1 - pos_y + h), Vector(w, SELECT_W), Color(SELECT_CLR), LAYER_GUI);
753 context.draw_filled_rect(Vector(selection.x1 - pos_x, selection.y1 - pos_y), Vector(SELECT_W, h), Color(SELECT_CLR), LAYER_GUI);
758 /* draw button bar */
759 context.draw_filled_rect(Vector(screen->w - 64, 0), Vector(64, screen->h), Color(50, 50, 50,255), LAYER_GUI);
761 if(le_current.IsTile())
763 // le_level->get_sector("main")->solids->draw(context);
765 /*screen->w - 32, screen->h - 32, le_current.tile);
766 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
767 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);*/
769 #if 0 // XXX FIXME TODO: Do we have a new solution for draw_on_screen()?
770 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
772 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
773 le_current.obj->draw_on_screen(cursor_x,cursor_y);
777 if(mouse_select_object && selected_game_object != NULL)
779 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,selected_game_object->base.width,3,255,0,0,255);
780 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255);
781 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y+selected_game_object->base.height,selected_game_object->base.width,3,255,0,0,255);
782 fillrect(selected_game_object->base.x-pos_x+selected_game_object->base.width,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255);
787 le_save_level_bt->draw(context);
788 le_exit_bt->draw(context);
789 le_test_level_bt->draw(context);
790 le_next_level_bt->draw(context);
791 le_previous_level_bt->draw(context);
792 le_rubber_bt->draw(context);
793 if(le_selection_mode == SQUARE)
794 le_select_mode_one_bt->draw(context);
795 else if(le_selection_mode == CURSOR)
796 le_select_mode_two_bt->draw(context);
797 le_settings_bt->draw(context);
798 le_move_right_bt->draw(context);
799 le_move_left_bt->draw(context);
800 le_move_up_bt->draw(context);
801 le_move_down_bt->draw(context);
802 le_tilegroup_bt->draw(context);
803 le_objects_bt->draw(context);
804 if(!cur_tilegroup.empty())
805 tilegroups_map[cur_tilegroup]->draw(context);
806 else if(!cur_objects.empty())
808 objects_map[cur_objects]->draw(context);
811 le_tilemap_panel->draw(context);
813 if(!cur_objects.empty())
815 le_object_select_bt->draw(context);
816 le_object_properties_bt->draw(context);
819 sprintf(str, "%d/%d", le_levelnb,le_level_subset->levels);
820 context.draw_text(white_text, str, Vector((le_level_subset->levels < 10) ? -10 : 0, 16), LAYER_GUI);
823 context.draw_text(white_small_text, "F1 for Help", Vector(10, 430), LAYER_GUI);
825 if(display_level_info.check())
826 context.draw_text_center(white_text, le_level->name.c_str(), Vector(0, 0), LAYER_GUI);
831 context.draw_text(white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", Vector(10, 430), LAYER_GUI);
833 context.draw_text(white_small_text, "No Level Subset loaded", Vector(10, 430), LAYER_GUI);
838 void LevelEditor::drawlevel(DrawingContext& context)
843 /* Draw the real background */
844 le_level->get_sector("main")->background->draw(context);
846 if(le_current.IsTile())
848 le_level->get_sector("main")->solids->draw(context);
850 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
851 if(!TileManager::instance()->get(le_current.tile)->images.empty())
852 fillrect(cursor_x-pos_x,cursor_y-pos_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);*/
854 #if 0 // XXX FIXME TODO: Do we have a new solution for move_to()?
855 if(le_current.IsObject())
857 le_current.obj->move_to(cursor_x, cursor_y);
861 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
864 le_level->get_sector("main")->solids->draw(context);
866 // FIXME: make tiles to be drawn semi-transparent when not selected
868 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_level->get_section("main")->height; ++y)
869 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
872 if(active_tm == TM_BG)
877 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
878 le_level->bg_tiles[ (y + (int)(pos_y / 32)) * le_level->get_sector("main")->solids->get_width() +
879 (x + (int)(pos_x / 32))],a);
881 if(active_tm == TM_IA)
886 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
887 le_level->ia_tiles[ (y + (int)(pos_y / 32)) * le_level->get_section("main")->width +
888 (x + (int)(pos_x / 32))],a);
891 if(active_tm == TM_FG)
896 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
897 le_level->fg_tiles[ (y + (int)(pos_y / 32)) * le_level->get_sector("main")->solids->get_width() +
898 (x + (int)(pos_x / 32))],a);
900 /* draw whats inside stuff when cursor is selecting those */
901 /* (draw them all the time - is this the right behaviour?) */
902 Tile* edit_image = TileManager::instance()->get(
904 [ (y + (int)(pos_y / 32)) * le_level->get_section("main")->width + (x + (int)(pos_x / 32))]);
905 if(edit_image && !edit_image->editor_images.empty())
906 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
910 /* Draw the Bad guys: */
911 for (std::vector<GameObject*>::iterator it = le_level->get_sector("main")->gameobjects.begin();
912 it != le_level->get_sector("main")->gameobjects.end(); ++it)
914 BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
918 /* to support frames: img_bsod_left[(frame / 5) % 4] */
919 badguy->draw(context);
922 /* Draw the player: */
923 /* for now, the position is fixed at (100, 240) */
924 largetux.walk_right->draw(context, Vector(100 - pos_x, 240 - pos_y), LAYER_OBJECTS-1);
927 void LevelEditor::change_object_properties(GameObject *pobj)
929 DrawingContext context;
931 Menu* object_properties_menu = new Menu();
934 std::string type = typeid(pobj).name();
935 object_properties_menu->additem(MN_LABEL, type + " Properties",0,0);
936 object_properties_menu->additem(MN_HL,"",0,0);
938 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
941 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
942 for(int i = 0; i < NUM_BadGuyKinds; ++i)
944 string_list_add_item(object_properties_menu->get_item_by_id(1).list,
945 badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
947 object_properties_menu->get_item_by_id(1).list->active_item = i;
949 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
952 object_properties_menu->additem(MN_HL,"",0,0);
953 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
955 Menu::set_current(object_properties_menu);
961 while (SDL_PollEvent(&event))
963 object_properties_menu->event(event);
966 //cap_screen->draw(0,0);
968 object_properties_menu->draw(context);
969 object_properties_menu->action();
971 switch (object_properties_menu->check())
975 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
977 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
978 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
979 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
988 if(Menu::current() == NULL)
991 mouse_cursor->draw(context);
992 // context.draw_filled_rect();
997 Menu::set_current(0);
998 delete object_properties_menu;
1002 void LevelEditor::checkevents()
1009 keymod = SDL_GetModState();
1011 while(SDL_PollEvent(&event))
1013 if (Menu::current())
1015 Menu::current()->event(event);
1016 if(!le_level && !Menu::current())
1017 Menu::set_current(leveleditor_menu);
1021 mouse_cursor->set_state(MC_NORMAL);
1023 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1024 if(event.type == SDL_KEYDOWN
1025 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1026 && (event.motion.x > 0
1027 && event.motion.x < screen->w - 64 &&
1028 event.motion.y > 0 && event.motion.y < screen->h)))
1032 case SDL_KEYDOWN: // key pressed
1033 key = event.key.keysym.sym;
1037 Menu::set_current(leveleditor_menu);
1040 if(le_level != NULL)
1048 cursor_x = (le_level->get_sector("main")->solids->get_width() * 32) - 32;
1052 le_show_grid = !le_show_grid;
1058 case SDL_MOUSEBUTTONDOWN:
1059 if(event.button.button == SDL_BUTTON_LEFT)
1061 le_mouse_pressed[LEFT] = true;
1063 selection.x1 = event.motion.x + pos_x;
1064 selection.y1 = event.motion.y + pos_y;
1065 selection.x2 = event.motion.x + pos_x;
1066 selection.y2 = event.motion.y + pos_y;
1068 else if(event.button.button == SDL_BUTTON_RIGHT)
1070 le_mouse_pressed[RIGHT] = true;
1073 case SDL_MOUSEBUTTONUP:
1074 if(event.button.button == SDL_BUTTON_LEFT)
1076 le_mouse_pressed[LEFT] = false;
1077 le_mouse_clicked[LEFT] = true;
1079 else if(event.button.button == SDL_BUTTON_RIGHT)
1081 le_mouse_pressed[RIGHT] = false;
1082 le_mouse_clicked[RIGHT] = true;
1085 case SDL_MOUSEMOTION:
1087 if(!Menu::current())
1092 if(le_current.IsTile())
1094 cursor_x = ((int)(pos_x + x) / 32) * 32;
1095 cursor_y = ((int)(pos_y + y) / 32) * 32;
1103 if(le_mouse_pressed[LEFT])
1105 selection.x2 = x + pos_x;
1106 selection.y2 = y + pos_y;
1109 if(le_mouse_pressed[RIGHT])
1111 pos_x += -1 * event.motion.xrel;
1112 pos_y += -1 * event.motion.yrel;
1120 else if(event.type == SDL_QUIT) /* window closing */
1126 if(le_level != NULL)
1128 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 &&
1129 event.motion.y > 0 && event.motion.y < screen->h)))
1131 le_mouse_pressed[LEFT] = false;
1132 le_mouse_pressed[RIGHT] = false;
1134 if(!Menu::current())
1136 /* Check for button events */
1137 le_test_level_bt->event(event);
1138 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1140 le_save_level_bt->event(event);
1141 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1142 le_level->save(le_level_subset->name.c_str());
1143 le_exit_bt->event(event);
1144 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1146 Menu::set_current(leveleditor_menu);
1148 le_next_level_bt->event(event);
1149 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1151 if(le_levelnb < le_level_subset->levels)
1153 goto_level(le_levelnb+1);
1159 sprintf(str,"Level %d doesn't exist. Create it?",le_levelnb+1);
1160 Surface* surf = new Surface(le_level->get_sector("main")->background->get_image(), false);
1161 if(confirm_dialog(surf, str))
1163 new_lev.save(le_level_subset->name.c_str());
1164 le_level_subset->levels = le_levelnb;
1165 goto_level(le_levelnb);
1171 le_previous_level_bt->event(event);
1172 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1175 goto_level(le_levelnb -1);
1177 le_rubber_bt->event(event);
1178 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1181 if(!cur_objects.empty())
1183 le_object_select_bt->event(event);
1184 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1186 MouseCursor::set_current(mouse_select_object);
1189 le_object_properties_bt->event(event);
1190 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1192 change_object_properties(selected_game_object);
1197 if(le_selection_mode == SQUARE)
1199 le_select_mode_one_bt->event(event);
1200 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1201 le_selection_mode = CURSOR;
1205 le_select_mode_two_bt->event(event);
1206 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1207 le_selection_mode = SQUARE;
1209 ButtonPanelMap::iterator it;
1210 le_tilegroup_bt->event(event);
1211 switch (le_tilegroup_bt->get_state())
1213 case BUTTON_CLICKED:
1214 Menu::set_current(select_tilegroup_menu);
1215 select_tilegroup_menu_effect.start(200);
1216 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1218 case BUTTON_WHEELUP:
1219 if(cur_tilegroup.empty())
1221 cur_tilegroup = tilegroups_map.begin()->first;
1225 it = tilegroups_map.find(cur_tilegroup);
1226 if((++it) == tilegroups_map.end())
1228 cur_tilegroup = tilegroups_map.begin()->first;
1232 cur_tilegroup = (*it).first;
1238 case BUTTON_WHEELDOWN:
1239 it = tilegroups_map.find(cur_tilegroup);
1240 if(it == tilegroups_map.begin())
1242 cur_tilegroup = tilegroups_map.rbegin()->first;
1246 if(--it != --tilegroups_map.begin())
1247 cur_tilegroup = (*it).first;
1249 cur_tilegroup = tilegroups_map.rbegin()->first;
1257 le_objects_bt->event(event);
1258 switch (le_objects_bt->get_state())
1260 case BUTTON_CLICKED:
1261 Menu::set_current(select_objects_menu);
1262 select_objects_menu_effect.start(200);
1263 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1265 case BUTTON_WHEELUP:
1266 it = objects_map.find(cur_objects);
1267 if(it == objects_map.end())
1269 cur_objects = objects_map.begin()->first;
1273 if(++it != objects_map.end())
1274 cur_objects = (*it).first;
1276 cur_objects = objects_map.begin()->first;
1280 case BUTTON_WHEELDOWN:
1281 it = objects_map.find(cur_objects);
1282 if(it == objects_map.begin())
1284 cur_objects = objects_map.rbegin()->first;
1288 if(--it != --objects_map.begin())
1289 cur_objects = (*it).first;
1291 cur_objects = objects_map.rbegin()->first;
1300 le_settings_bt->event(event);
1301 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1303 update_level_settings_menu();
1304 Menu::set_current(level_settings_menu);
1306 if(!cur_tilegroup.empty())
1308 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1310 if(pbutton->get_state() == BUTTON_CLICKED)
1312 le_current.Tile(pbutton->get_tag());
1316 else if(!cur_objects.empty())
1318 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1320 if(pbutton->get_state() == BUTTON_CLICKED)
1322 #if 0 // TODO FIXME XXX: New solution for this?
1323 le_current.Object(pbutton->get_drawable());
1329 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1331 if(pbutton->get_state() == BUTTON_CLICKED)
1333 active_tm = pbutton->get_tag();
1339 le_settings_bt->event(event);
1340 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1342 Menu::set_current(0);
1344 le_tilegroup_bt->event(event);
1345 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1347 Menu::set_current(0);
1349 le_objects_bt->event(event);
1350 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1352 Menu::set_current(0);
1357 if(!Menu::current() && !show_minimap)
1359 if(le_mouse_pressed[LEFT])
1361 if(MouseCursor::current() != mouse_select_object)
1363 if(le_current.IsTile())
1364 change(cursor_x, cursor_y, active_tm, le_current.tile);
1367 else if(le_mouse_clicked[LEFT])
1369 if(MouseCursor::current() == mouse_select_object)
1371 bool object_got_hit = false;
1372 base_type cursor_base;
1373 if(le_current.IsTile())
1375 cursor_base.x = cursor_x;
1376 cursor_base.y = cursor_y;
1378 else if(le_current.IsObject())
1380 cursor_base.x = cursor_x + pos_x;
1381 cursor_base.y = cursor_y + pos_y;
1383 cursor_base.width = 32;
1384 cursor_base.height = 32;
1386 for(std::vector<GameObject*>::iterator it =
1387 le_level->get_sector("main")->gameobjects.begin();
1388 it != le_level->get_sector("main")->gameobjects.end(); ++it) {
1389 MovingObject* mobj = dynamic_cast<MovingObject*> (*it);
1393 if(rectcollision(cursor_base, mobj->base))
1395 selected_game_object = mobj;
1396 object_got_hit = true;
1403 selected_game_object = NULL;
1404 le_object_properties_bt->set_active(false);
1407 le_object_properties_bt->set_active(true);
1409 MouseCursor::set_current(mouse_cursor);
1416 //FIXME: objects interactions with the level editor should have a major improvement
1417 if(le_current.IsObject())
1419 le_level_changed = true;
1420 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1424 Camera& camera = *le_level->get_sector("main")->camera;
1426 le_level->get_sector("main")->bad_guys.push_back(
1427 new BadGuy(pbadguy->kind,
1428 cursor_x + camera.get_translation().x,
1429 cursor_y + camera.get_translation().y));
1430 le_level->get_sector("main")->gameobjects.push_back(le_level->get_sector("main")->bad_guys.back());
1437 le_mouse_clicked[LEFT] = false;
1443 if(!Menu::current())
1445 show_minimap = false;
1447 if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_TAB)
1448 show_minimap = true;
1450 le_move_left_bt->event(event);
1451 le_move_right_bt->event(event);
1452 le_move_up_bt->event(event);
1453 le_move_down_bt->event(event);
1454 switch(le_move_left_bt->get_state())
1456 case BUTTON_PRESSED:
1457 pos_x -= KEYBOARD_SPEED;
1458 show_minimap = true;
1461 pos_x -= MOUSE_SPEED;
1462 show_minimap = true;
1464 case BUTTON_CLICKED:
1465 show_minimap = true;
1471 switch(le_move_right_bt->get_state())
1473 case BUTTON_PRESSED:
1474 pos_x += KEYBOARD_SPEED;
1475 show_minimap = true;
1478 pos_x += MOUSE_SPEED;
1479 show_minimap = true;
1481 case BUTTON_CLICKED:
1482 show_minimap = true;
1488 switch(le_move_up_bt->get_state())
1490 case BUTTON_PRESSED:
1491 pos_y -= KEYBOARD_SPEED;
1492 show_minimap = true;
1495 pos_y -= MOUSE_SPEED;
1496 show_minimap = true;
1498 case BUTTON_CLICKED:
1499 show_minimap = true;
1505 switch(le_move_down_bt->get_state())
1507 case BUTTON_PRESSED:
1508 pos_y += KEYBOARD_SPEED;
1509 show_minimap = true;
1512 pos_y += MOUSE_SPEED;
1513 show_minimap = true;
1515 case BUTTON_CLICKED:
1516 show_minimap = true;
1522 /* checking if pos_x and pos_y is within the limits... */
1523 if((unsigned)pos_x > (le_level->get_sector("main")->solids->get_width() * 32 + 32*2) - screen->w)
1524 pos_x = (le_level->get_sector("main")->solids->get_width() * 32 + 32*2) - screen->w;
1528 if((unsigned)pos_y > (le_level->get_sector("main")->solids->get_height() * 32) - screen->h)
1529 pos_y = (le_level->get_sector("main")->solids->get_height() * 32) - screen->h;
1533 le_level->get_sector("main")->camera->set_scrolling(pos_x, pos_y);
1537 void LevelEditor::highlight_selection()
1541 if(selection.x1 < selection.x2)
1551 if(selection.y1 < selection.y2)
1567 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1570 void LevelEditor::change(float x, float y, int tm, unsigned int c)
1572 if(le_level != NULL)
1577 le_level_changed = true;
1579 switch(le_selection_mode)
1584 base_type cursor_base;
1587 cursor_base.width = 32;
1588 cursor_base.height = 32;
1590 /* if there is a bad guy over there, remove it */
1592 for(std::vector<GameObject*>::iterator it = le_level->get_sector("main")->gameobjects.begin();
1593 it != le_level->get_sector("main")->gameobjects.end(); ++it) {
1594 BadGuy* badguy = dynamic_cast<BadGuy*>((*it));
1597 if(rectcollision(cursor_base, badguy->base))
1600 le_level->get_sector("main")->gameobjects.erase(std::remove(le_level->get_sector("main")->gameobjects.begin(),
1601 le_level->get_sector("main")->gameobjects.end(), *it),
1602 le_level->get_sector("main")->gameobjects.end());
1610 if(selection.x1 < selection.x2)
1620 if(selection.y1 < selection.y2)
1636 /* if there is a bad guy over there, remove it */
1638 for(std::vector<GameObject*>::iterator it = le_level->get_sector("main")->gameobjects.begin();
1639 it != le_level->get_sector("main")->gameobjects.end(); ++it /* will be at end of loop */)
1641 MovingObject* pmobject = dynamic_cast<MovingObject*> (*it);
1644 if(pmobject->base.x/32 >= x1 && pmobject->base.x/32 <= x2
1645 && pmobject->base.y/32 >= y1 && pmobject->base.y/32 <= y2)
1648 le_level->get_sector("main")->gameobjects.erase(std::remove(le_level->get_sector("main")->gameobjects.begin(), le_level->get_sector("main")->gameobjects.end(), *it), le_level->get_sector("main")->gameobjects.end());
1658 for(xx = x1; xx <= x2; xx++)
1659 for(yy = y1; yy <= y2; yy++)
1661 change(xx*32, yy*32, tm, c);
1671 void LevelEditor::testlevel()
1673 //Make sure a time value is set when testing the level
1674 if(le_level->time_left == 0)
1675 le_level->time_left = 250;
1677 le_level->save("test.stl");
1679 GameSession session("test.stl", ST_GL_TEST);
1681 player_status.reset();
1683 sound_manager->halt_music();
1685 Menu::set_current(NULL);
1688 void LevelEditor::showhelp()
1690 DrawingContext context;
1692 bool tmp_show_grid = le_show_grid;
1693 SelectionMode temp_le_selection_mode = le_selection_mode;
1694 le_selection_mode = NONE;
1695 show_selections = true;
1696 le_show_grid = false;
1697 le_help_shown = true;
1704 " - Supertux level editor tutorial - ",
1706 "To make your map, click the ",
1707 "tilegroup button and choose a ",
1709 "Pick a tile and simply hold down ",
1710 "the left mouse button over the map",
1711 "to \"paint\" your selection over",
1714 "There are three layers for painting",
1715 "tiles upon, Background layer,",
1716 "the Interactive layer, and the",
1717 "Foreground layer, which can be",
1718 "toggled by the BkGrd, IntAct and",
1719 "FrGrd buttons. The Foreground and",
1720 "Background layers do not effect",
1721 "Tux in the gameplay, but lie in",
1722 "front of him or lie behind him in",
1728 " - Supertux level editor tutorial - ",
1730 "The tiles placed on",
1731 "the Interactive layer are those",
1732 "which actually effect Tux in the",
1735 "Click the objects menu to put ",
1736 "bad guys and other objects in the",
1737 "game. Unlike placing tiles, you",
1738 "cannot \"paint\" enemies. Click",
1739 "them onto the screen one at a time.",
1741 "To change the settings of your",
1742 "level, click the button with the",
1743 "screwdriver and wrench. From here",
1744 "you can change the background,",
1745 "music, length of the level,",
1751 " - Supertux level editor tutorial - ",
1753 "You may have more than one level.",
1754 "Pressing the up and down buttons",
1755 "above the button bar lets you",
1756 "choose which one you are working on.",
1758 "If you would like to speed up your",
1759 "level editing, a useful trick is",
1760 "to learn the keyboard shortcuts.",
1761 "They are easy to learn, just right-",
1762 "click on the buttons.",
1764 "Have fun making levels! If you make",
1765 "some good ones, send them to us on",
1766 "the SuperTux mailing list!",
1770 char **text[] = { text1, text2, text3 };
1773 for(int i = 0; i < 3; i++)
1775 context.draw_gradient(Color(0,0,0), Color(255,255,255), LAYER_BACKGROUND0);
1776 drawinterface(context);
1778 context.draw_text_center(blue_text, "- Help -", Vector(0, 30), LAYER_GUI);
1780 for(unsigned int t = 0; t < sizeof(text[i])/sizeof(char *); t++)
1781 context.draw_text(white_text, text[i][t], Vector(5, 80+(t*white_text->get_height())), LAYER_GUI);
1783 sprintf(str,"Press any key to continue - Page %d/%d?", i, sizeof(text));
1784 context.draw_text(gold_text, str, Vector(0, 0), LAYER_GUI);
1786 context.do_drawing();
1792 done_ = wait_for_event(event);
1797 show_selections = true;
1798 le_show_grid = tmp_show_grid;
1799 le_selection_mode = temp_le_selection_mode;
1800 le_help_shown = false;