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"
44 #include "music_manager.h"
46 /* 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) */
69 int le_load_level_subset(char *filename);
71 void le_drawinterface();
72 void le_checkevents();
73 void le_change(float x, float y, int tm, unsigned int c);
76 void le_set_defaults(void);
77 void le_activate_bad_guys(void);
78 void le_goto_level(int levelnb);
79 void le_highlight_selection();
81 void apply_level_settings_menu();
82 void update_subset_settings_menu();
83 void save_subset_settings_menu();
87 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
89 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
90 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
91 //Returns true for a tile
92 bool IsTile() { return is_tile; };
93 //Returns true for a GameObject
94 bool IsObject() { return !is_tile; };
97 void Init() { tile = 0; obj = NULL; is_tile = true; };
99 bool is_tile; //true for tile (false for object)
104 /* leveleditor internals */
105 static string_list_type level_subsets;
106 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
107 static bool show_minimap;
108 static bool show_selections;
109 static bool le_help_shown;
110 static int pos_x, cursor_x, cursor_y, fire;
112 static World* le_world;
113 static LevelSubset* le_level_subset;
114 static int le_show_grid;
116 static Surface* le_selection;
118 static TileOrObject le_current;
119 static bool le_mouse_pressed[2];
120 static bool le_mouse_clicked[2];
121 static Button* le_save_level_bt;
122 static Button* le_exit_bt;
123 static Button* le_test_level_bt;
124 static Button* le_next_level_bt;
125 static Button* le_previous_level_bt;
126 static Button* le_move_right_bt;
127 static Button* le_move_left_bt;
128 static Button* le_rubber_bt;
129 static Button* le_select_mode_one_bt;
130 static Button* le_select_mode_two_bt;
131 static Button* le_settings_bt;
132 static Button* le_tilegroup_bt;
133 static Button* le_objects_bt;
134 static Button* le_object_select_bt;
135 static Button* le_object_properties_bt;
136 static ButtonPanel* le_tilemap_panel;
137 static Menu* leveleditor_menu;
138 static Menu* subset_load_menu;
139 static Menu* subset_new_menu;
140 static Menu* subset_settings_menu;
141 static Menu* level_settings_menu;
142 static Menu* select_tilegroup_menu;
143 static Menu* select_objects_menu;
144 static Timer select_tilegroup_menu_effect;
145 static Timer select_objects_menu_effect;
146 static Timer display_level_info;
147 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
148 static ButtonPanelMap tilegroups_map;
149 static ButtonPanelMap objects_map;
150 static std::string cur_tilegroup;
151 static std::string cur_objects;
152 static MouseCursor* mouse_select_object;
153 static GameObject* selected_game_object;
155 static square selection;
156 static SelectionMode le_selection_mode;
157 static SDL_Event event;
158 TileMapType active_tm;
160 int leveleditor(char* filename)
162 int last_time, now_time, i;
171 clearscreen(0, 0, 0);
174 music_manager->halt_music();
176 while (SDL_PollEvent(&event))
180 if(le_load_level_subset(filename))
185 last_time = SDL_GetTicks();
190 if(Menu::current() == select_tilegroup_menu)
192 if(select_tilegroup_menu_effect.check())
194 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
198 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
200 else if(Menu::current() == select_objects_menu)
202 if(select_objects_menu_effect.check())
204 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
207 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
212 /* making events results to be in order */
215 if(pos_x > (le_world->get_level()->width * 32) - screen->w)
216 pos_x = (le_world->get_level()->width * 32) - screen->w;
222 clearscreen(0, 0, 0);
224 /* draw editor interface */
227 Menu* menu = Menu::current();
233 if(menu == leveleditor_menu)
235 switch (leveleditor_menu->check())
237 case MNID_RETURNLEVELEDITOR:
239 Menu::set_current(0);
241 Menu::set_current(leveleditor_menu);
243 case MNID_SUBSETSETTINGS:
244 update_subset_settings_menu();
246 case MNID_QUITLEVELEDITOR:
251 else if(menu == level_settings_menu)
253 switch (level_settings_menu->check())
256 apply_level_settings_menu();
257 Menu::set_current(NULL);
264 else if(menu == select_tilegroup_menu)
267 switch (it = select_tilegroup_menu->check())
272 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
273 Menu::set_current(0);
280 else if(menu == select_objects_menu)
283 switch (it = select_objects_menu->check())
288 cur_objects = select_objects_menu->get_item_by_id(it).text;
291 Menu::set_current(0);
296 else if(menu == subset_load_menu)
298 switch (i = subset_load_menu->check())
305 if(le_load_level_subset(level_subsets.item[i-1]))
311 else if(menu == subset_new_menu)
313 if(subset_new_menu->item[2].input[0] == '\0')
314 subset_new_menu->item[3].kind = MN_DEACTIVE;
317 subset_new_menu->item[3].kind = MN_ACTION;
319 switch (i = subset_new_menu->check())
321 case MNID_CREATESUBSET:
322 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
323 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
324 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
326 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
328 Menu::set_current(subset_settings_menu);
333 else if(menu == subset_settings_menu)
335 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 )
336 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
338 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
340 switch (i = subset_settings_menu->check())
342 case MNID_SUBSETSAVECHANGES:
343 save_subset_settings_menu();
344 Menu::set_current(leveleditor_menu);
350 MouseCursor::current()->draw();
358 ++global_frame_counter;
361 now_time = SDL_GetTicks();
362 if (now_time < last_time + FPS)
363 SDL_Delay(last_time + FPS - now_time); /* delay some time */
371 int le_load_level_subset(char *filename)
373 le_level_subset->load(filename);
374 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
378 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
380 Menu::set_current(NULL);
389 leveleditor_menu = new Menu();
390 subset_load_menu = new Menu();
391 subset_new_menu = new Menu();
392 subset_settings_menu = new Menu();
393 level_settings_menu = new Menu();
394 select_tilegroup_menu = new Menu();
395 select_objects_menu = new Menu();
397 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
398 leveleditor_menu->additem(MN_HL,"",0,0);
399 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
400 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
401 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
402 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
403 leveleditor_menu->additem(MN_HL,"",0,0);
404 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
406 Menu::set_current(leveleditor_menu);
408 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
409 subset_load_menu->additem(MN_HL, "", 0, 0);
411 for(i = 0; i < level_subsets.num_items; ++i)
413 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
415 subset_load_menu->additem(MN_HL,"",0,0);
416 subset_load_menu->additem(MN_BACK,"Back",0,0);
418 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
419 subset_new_menu->additem(MN_HL,"",0,0);
420 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
421 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
422 subset_new_menu->additem(MN_HL,"",0,0);
423 subset_new_menu->additem(MN_BACK,"Back",0,0);
425 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
426 subset_settings_menu->additem(MN_HL,"",0,0);
427 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
428 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
429 subset_settings_menu->additem(MN_HL,"",0,0);
430 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
431 subset_settings_menu->additem(MN_HL,"",0,0);
432 subset_settings_menu->additem(MN_BACK,"Back",0,0);
434 level_settings_menu->arrange_left = true;
435 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
436 level_settings_menu->additem(MN_HL,"",0,0);
437 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
438 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
439 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
440 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
441 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
442 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
443 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
444 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
445 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
446 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
447 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
448 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
449 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
450 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
451 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
452 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
453 level_settings_menu->additem(MN_HL,"",0,0);
454 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
456 select_tilegroup_menu->arrange_left = true;
457 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
458 select_tilegroup_menu->additem(MN_HL,"",0,0);
459 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
461 for(std::set<TileGroup>::iterator it = tilegroups->begin();
462 it != tilegroups->end(); ++it )
464 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
466 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
469 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
470 sit != (*it).tiles.end(); ++sit, ++i)
472 std::string imagefile = "/images/tilesets/" ;
473 bool only_editor_image = false;
474 if(!TileManager::instance()->get(*sit)->filenames.empty())
476 imagefile += TileManager::instance()->get(*sit)->filenames[0];
478 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
480 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
481 only_editor_image = true;
485 imagefile += "notile.png";
487 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
489 if(!only_editor_image)
490 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
492 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
493 button->add_icon(imagefile,32,32);
495 tilegroups_map[it->name]->additem(button, *sit);
498 select_tilegroup_menu->additem(MN_HL,"",0,0);
500 select_objects_menu->arrange_left = true;
501 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
502 select_objects_menu->additem(MN_HL,"",0,0);
503 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
504 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
506 for(int i = 0; i < NUM_BadGuyKinds; ++i)
508 BadGuy bad_tmp(0,0,BadGuyKind(i),false);
509 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
510 objects_map["BadGuys"]->manipulate_button(i)->set_game_object(new BadGuy(objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,objects_map["BadGuys"]->manipulate_button(i)->get_pos().y,BadGuyKind(i),false));
513 select_objects_menu->additem(MN_HL,"",0,0);
521 level_subsets = dsubdirs("/levels", "level1.stl");
522 le_level_subset = new LevelSubset;
525 selected_game_object = NULL;
529 show_selections = true;
534 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
535 le_level_changed = false;
536 le_help_shown = false;
538 le_mouse_pressed[LEFT] = false;
539 le_mouse_pressed[RIGHT] = false;
541 le_mouse_clicked[LEFT] = false;
542 le_mouse_clicked[RIGHT] = false;
544 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
546 select_tilegroup_menu_effect.init(false);
547 select_objects_menu_effect.init(false);
548 display_level_info.init(false);
551 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
552 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
553 le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
554 le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
555 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
556 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
557 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
558 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
559 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
560 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
561 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
562 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
563 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
564 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
565 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
566 le_object_properties_bt->set_active(false);
568 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
569 mouse_select_object->set_mid(16,16);
571 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
572 le_tilemap_panel->set_button_size(32,10);
573 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
574 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
575 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
576 le_tilemap_panel->highlight_last(true);
577 le_tilemap_panel->set_last_clicked(TM_IA);
583 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
589 void update_level_settings_menu()
594 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
595 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
597 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
598 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
599 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
600 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
601 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
602 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
604 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
605 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
606 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
607 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
608 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
609 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
611 sprintf(str,"%d",le_world->get_level()->width);
612 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
613 sprintf(str,"%d",le_world->get_level()->height);
614 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
615 sprintf(str,"%d",le_world->get_level()->time_left);
616 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
617 sprintf(str,"%2.0f",le_world->get_level()->gravity);
618 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
619 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
620 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
621 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
622 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
623 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
624 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
625 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
626 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
627 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
628 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
629 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
630 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
631 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
632 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
635 void update_subset_settings_menu()
637 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
638 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
641 void apply_level_settings_menu()
646 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
647 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
649 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
651 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
655 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
657 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
662 le_world->get_level()->load_gfx();
665 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
667 le_world->get_level()->change_width(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
668 le_world->get_level()->change_height(atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
669 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
670 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
671 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
672 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
673 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
674 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
675 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
676 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
677 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
680 void save_subset_settings_menu()
682 le_level_subset->title = subset_settings_menu->item[2].input;
683 le_level_subset->description = subset_settings_menu->item[3].input;
684 le_level_subset->save();
685 le_level_changed = false;
688 void le_unload_level()
695 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
696 if(confirm_dialog(str))
698 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
703 le_level_changed = false;
706 void le_goto_level(int levelnb)
709 le_world = new World(le_level_subset->name, levelnb);
710 display_level_info.start(2500);
716 SDL_EnableKeyRepeat(0, 0); // disables key repeating
720 delete leveleditor_menu;
721 delete subset_load_menu;
722 delete subset_new_menu;
723 delete subset_settings_menu;
724 delete level_settings_menu;
725 delete select_tilegroup_menu;
726 delete select_objects_menu;
727 delete le_save_level_bt;
729 delete le_test_level_bt;
730 delete le_next_level_bt;
731 delete le_previous_level_bt;
732 delete le_move_right_bt;
733 delete le_move_left_bt;
735 delete le_select_mode_one_bt;
736 delete le_select_mode_two_bt;
737 delete le_settings_bt;
738 delete le_tilegroup_bt;
739 delete le_objects_bt;
740 delete le_tilemap_panel;
741 delete le_object_select_bt;
742 delete le_object_properties_bt;
743 delete mouse_select_object;
745 delete le_level_subset;
748 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
749 i != tilegroups_map.end(); ++i)
753 for(ButtonPanelMap::iterator i = objects_map.begin();
754 i != objects_map.end(); ++i)
760 void le_drawminimap()
766 if(screen->w - 64 > le_world->get_level()->width * 4)
768 else if(screen->w - 64 > le_world->get_level()->width * 2)
772 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
774 for (int y = 0; y < 15; ++y)
775 for (int x = 0; x < le_world->get_level()->width; ++x)
778 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
780 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
782 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
786 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, 15*4, 200, 200, 200, 128);
788 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
789 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, 15*4, 200, 200, 200, 200);
790 fillrect(left_offset + (pos_x/32)*mini_tile_width + 19*mini_tile_width - 2, 0, 2, 15*4, 200, 200, 200, 200);
791 fillrect(left_offset + (pos_x/32)*mini_tile_width, 15*4-2, 19*mini_tile_width, 2, 200, 200, 200, 200);
795 void le_drawinterface()
802 /* draw a grid (if selected) */
805 for(x = 0; x < 19; x++)
806 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
807 for(y = 0; y < 15; y++)
808 fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
812 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
815 if(show_selections && MouseCursor::current() != mouse_select_object)
817 if(le_selection_mode == CURSOR)
819 if(le_current.IsTile())
820 le_selection->draw( cursor_x - pos_x, cursor_y);
822 else if(le_selection_mode == SQUARE)
825 le_highlight_selection();
826 /* draw current selection */
827 w = selection.x2 - selection.x1;
828 h = selection.y2 - selection.y1;
829 fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
830 fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
831 fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
832 fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
837 /* draw button bar */
838 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
840 if(le_current.IsTile())
842 Tile::draw(19 * 32, 14 * 32, le_current.tile);
843 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
844 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
846 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
848 le_current.obj->draw_on_screen(19 * 32, 14 * 32);
849 le_current.obj->draw_on_screen(cursor_x,cursor_y);
852 if(mouse_select_object && selected_game_object != NULL)
854 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y,selected_game_object->base.width,3,255,0,0,255);
855 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y,3,selected_game_object->base.height,255,0,0,255);
856 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y+selected_game_object->base.height,selected_game_object->base.width,3,255,0,0,255);
857 fillrect(selected_game_object->base.x-pos_x+selected_game_object->base.width,selected_game_object->base.y,3,selected_game_object->base.height,255,0,0,255);
862 le_save_level_bt->draw();
864 le_test_level_bt->draw();
865 le_next_level_bt->draw();
866 le_previous_level_bt->draw();
867 le_rubber_bt->draw();
868 if(le_selection_mode == SQUARE)
869 le_select_mode_one_bt->draw();
870 else if(le_selection_mode == CURSOR)
871 le_select_mode_two_bt->draw();
872 le_settings_bt->draw();
873 le_move_right_bt->draw();
874 le_move_left_bt->draw();
875 le_tilegroup_bt->draw();
876 le_objects_bt->draw();
877 if(!cur_tilegroup.empty())
878 tilegroups_map[cur_tilegroup]->draw();
879 else if(!cur_objects.empty())
881 objects_map[cur_objects]->draw();
884 le_tilemap_panel->draw();
886 if(!cur_objects.empty())
888 le_object_select_bt->draw();
889 le_object_properties_bt->draw();
892 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
893 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
896 white_small_text->draw("F1 for Help", 10, 430, 1);
898 if(display_level_info.check())
899 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
904 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
906 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
916 /* Draw the real background */
917 if(le_world->get_level()->bkgd_image[0] != '\0')
919 s = (int)((float)pos_x * ((float)le_world->get_level()->bkgd_speed/100.0f)) % screen->w;
920 le_world->get_level()->img_bkgd->draw_part(s,0,0,0,
921 le_world->get_level()->img_bkgd->w - s - 32, le_world->get_level()->img_bkgd->h);
922 le_world->get_level()->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
923 le_world->get_level()->img_bkgd->h);
927 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
930 if(le_current.IsTile())
932 Tile::draw(cursor_x-pos_x, cursor_y,le_current.tile,128);
933 if(!TileManager::instance()->get(le_current.tile)->images.empty())
934 fillrect(cursor_x-pos_x,cursor_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);
936 if(le_current.IsObject())
938 le_current.obj->move_to(cursor_x, cursor_y);
941 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
943 for (y = 0; y < 15; ++y)
944 for (x = 0; x < 20; ++x)
947 if(active_tm == TM_BG)
952 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->bg_tiles[y][x + (int)(pos_x / 32)],a);
954 if(active_tm == TM_IA)
959 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)],a);
961 if(active_tm == TM_FG)
966 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->fg_tiles[y][x + (int)(pos_x / 32)],a);
968 /* draw whats inside stuff when cursor is selecting those */
969 /* (draw them all the time - is this the right behaviour?) */
970 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)]);
971 if(edit_image && !edit_image->editor_images.empty())
972 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
976 /* Draw the Bad guys: */
977 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
979 /* to support frames: img_bsod_left[(frame / 5) % 4] */
986 /* Draw the player: */
987 /* for now, the position is fixed at (100, 240) */
988 largetux.walk_right->draw( 100 - pos_x, 240);
991 void le_change_object_properties(GameObject *pobj)
993 Surface* cap_screen = Surface::CaptureScreen();
994 Menu* object_properties_menu = new Menu();
997 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
998 object_properties_menu->additem(MN_HL,"",0,0);
1000 if(pobj->type() == "BadGuy")
1002 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1003 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1004 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1006 string_list_add_item(object_properties_menu->get_item_by_id(1).list,badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1008 object_properties_menu->get_item_by_id(1).list->active_item = i;
1010 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1013 object_properties_menu->additem(MN_HL,"",0,0);
1014 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1016 Menu::set_current(object_properties_menu);
1022 while (SDL_PollEvent(&event))
1024 object_properties_menu->event(event);
1027 cap_screen->draw(0,0);
1029 object_properties_menu->draw();
1030 object_properties_menu->action();
1032 switch (object_properties_menu->check())
1035 if(pobj->type() == "BadGuy")
1037 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1038 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1039 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1041 std::list<BadGuy*>::iterator it;
1042 for(it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1045 le_world->get_level()->badguy_data[i].kind = pbad->kind;
1046 le_world->get_level()->badguy_data[i].stay_on_platform = pbad->stay_on_platform;
1048 (*it) = new BadGuy(le_world->get_level()->badguy_data[i].x,le_world->get_level()->badguy_data[i].y,le_world->get_level()->badguy_data[i].kind,le_world->get_level()->badguy_data[i].stay_on_platform);
1056 if(Menu::current() == NULL)
1059 mouse_cursor->draw();
1065 Menu::set_current(0);
1066 delete object_properties_menu;
1070 void le_checkevents()
1077 keymod = SDL_GetModState();
1079 while(SDL_PollEvent(&event))
1081 if (Menu::current())
1083 Menu::current()->event(event);
1084 if(!le_world && !Menu::current())
1085 Menu::set_current(leveleditor_menu);
1089 mouse_cursor->set_state(MC_NORMAL);
1091 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1092 if(event.type == SDL_KEYDOWN
1093 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1094 && (event.motion.x > 0
1095 && event.motion.x < screen->w - 64 &&
1096 event.motion.y > 0 && event.motion.y < screen->h)))
1100 case SDL_KEYDOWN: // key pressed
1101 key = event.key.keysym.sym;
1105 Menu::set_current(leveleditor_menu);
1109 cursor_x -= KEY_CURSOR_SPEED;
1111 cursor_x -= KEY_CURSOR_FASTSPEED;
1113 if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
1114 pos_x = cursor_x - MOUSE_LEFT_MARGIN;
1119 cursor_x += KEY_CURSOR_SPEED;
1121 cursor_x += KEY_CURSOR_FASTSPEED;
1123 if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
1124 pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
1129 cursor_y -= KEY_CURSOR_SPEED;
1131 cursor_y -= KEY_CURSOR_FASTSPEED;
1138 cursor_y += KEY_CURSOR_SPEED;
1140 cursor_y += KEY_CURSOR_FASTSPEED;
1142 if(cursor_y > screen->h-32)
1143 cursor_y = screen->h-32;
1149 if(le_world != NULL)
1157 cursor_x = (le_world->get_level()->width * 32) - 32;
1161 le_show_grid = !le_show_grid;
1167 case SDL_KEYUP: /* key released */
1168 switch(event.key.keysym.sym)
1177 case SDL_MOUSEBUTTONDOWN:
1178 if(event.button.button == SDL_BUTTON_LEFT)
1180 le_mouse_pressed[LEFT] = true;
1182 selection.x1 = event.motion.x + pos_x;
1183 selection.y1 = event.motion.y;
1184 selection.x2 = event.motion.x + pos_x;
1185 selection.y2 = event.motion.y;
1187 else if(event.button.button == SDL_BUTTON_RIGHT)
1189 le_mouse_pressed[RIGHT] = true;
1192 case SDL_MOUSEBUTTONUP:
1193 if(event.button.button == SDL_BUTTON_LEFT)
1195 le_mouse_pressed[LEFT] = false;
1196 le_mouse_clicked[LEFT] = true;
1198 else if(event.button.button == SDL_BUTTON_RIGHT)
1200 le_mouse_pressed[RIGHT] = false;
1201 le_mouse_clicked[RIGHT] = true;
1204 case SDL_MOUSEMOTION:
1206 if(!Menu::current())
1211 if(le_current.IsTile())
1213 cursor_x = ((int)(pos_x + x) / 32) * 32;
1214 cursor_y = ((int) y / 32) * 32;
1222 if(le_mouse_pressed[LEFT])
1224 selection.x2 = x + pos_x;
1228 if(le_mouse_pressed[RIGHT])
1230 pos_x += -1 * event.motion.xrel;
1238 else if(event.type == SDL_QUIT) /* window closing */
1244 if(le_world != NULL)
1246 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 &&
1247 event.motion.y > 0 && event.motion.y < screen->h)))
1249 le_mouse_pressed[LEFT] = false;
1250 le_mouse_pressed[RIGHT] = false;
1252 if(!Menu::current())
1254 /* Check for button events */
1255 le_test_level_bt->event(event);
1256 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1258 le_save_level_bt->event(event);
1259 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1260 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1261 le_exit_bt->event(event);
1262 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1264 Menu::set_current(leveleditor_menu);
1266 le_next_level_bt->event(event);
1267 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1269 if(le_level < le_level_subset->levels)
1271 le_goto_level(le_level+1);
1277 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1278 if(confirm_dialog(str))
1280 new_lev.init_defaults();
1281 new_lev.save(le_level_subset->name.c_str(),le_level+1);
1282 le_level_subset->levels = le_level;
1283 le_goto_level(le_level);
1287 le_previous_level_bt->event(event);
1288 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1291 le_goto_level(le_level -1);
1293 le_rubber_bt->event(event);
1294 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1297 if(!cur_objects.empty())
1299 le_object_select_bt->event(event);
1300 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1302 MouseCursor::set_current(mouse_select_object);
1305 le_object_properties_bt->event(event);
1306 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1308 le_change_object_properties(selected_game_object);
1313 if(le_selection_mode == SQUARE)
1315 le_select_mode_one_bt->event(event);
1316 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1317 le_selection_mode = CURSOR;
1321 le_select_mode_two_bt->event(event);
1322 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1323 le_selection_mode = SQUARE;
1325 ButtonPanelMap::iterator it;
1326 le_tilegroup_bt->event(event);
1327 switch (le_tilegroup_bt->get_state())
1329 case BUTTON_CLICKED:
1330 Menu::set_current(select_tilegroup_menu);
1331 select_tilegroup_menu_effect.start(200);
1332 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1334 case BUTTON_WHEELUP:
1335 if(cur_tilegroup.empty())
1337 cur_tilegroup = tilegroups_map.begin()->first;
1341 it = tilegroups_map.find(cur_tilegroup);
1342 if((++it) == tilegroups_map.end())
1344 cur_tilegroup = tilegroups_map.begin()->first;
1348 cur_tilegroup = (*it).first;
1354 case BUTTON_WHEELDOWN:
1355 it = tilegroups_map.find(cur_tilegroup);
1356 if(it == tilegroups_map.begin())
1358 cur_tilegroup = tilegroups_map.rbegin()->first;
1362 if(--it != --tilegroups_map.begin())
1363 cur_tilegroup = (*it).first;
1365 cur_tilegroup = tilegroups_map.rbegin()->first;
1373 le_objects_bt->event(event);
1374 switch (le_objects_bt->get_state())
1376 case BUTTON_CLICKED:
1377 Menu::set_current(select_objects_menu);
1378 select_objects_menu_effect.start(200);
1379 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1381 case BUTTON_WHEELUP:
1382 it = objects_map.find(cur_objects);
1383 if(it == objects_map.end())
1385 cur_objects = objects_map.begin()->first;
1389 if(++it != objects_map.end())
1390 cur_objects = (*it).first;
1392 cur_objects = objects_map.begin()->first;
1396 case BUTTON_WHEELDOWN:
1397 it = objects_map.find(cur_objects);
1398 if(it == objects_map.begin())
1400 cur_objects = objects_map.rbegin()->first;
1404 if(--it != --objects_map.begin())
1405 cur_objects = (*it).first;
1407 cur_objects = objects_map.rbegin()->first;
1416 le_settings_bt->event(event);
1417 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1419 update_level_settings_menu();
1420 Menu::set_current(level_settings_menu);
1422 if(!cur_tilegroup.empty())
1424 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1426 if(pbutton->get_state() == BUTTON_CLICKED)
1428 le_current.Tile(pbutton->get_tag());
1432 else if(!cur_objects.empty())
1434 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1436 if(pbutton->get_state() == BUTTON_CLICKED)
1438 le_current.Object(pbutton->get_game_object());
1443 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1445 if(pbutton->get_state() == BUTTON_CLICKED)
1447 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1453 le_settings_bt->event(event);
1454 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1456 Menu::set_current(0);
1458 le_tilegroup_bt->event(event);
1459 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1461 Menu::set_current(0);
1463 le_objects_bt->event(event);
1464 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1466 Menu::set_current(0);
1471 if(!Menu::current() && !show_minimap)
1473 if(le_mouse_pressed[LEFT])
1475 if(MouseCursor::current() != mouse_select_object)
1477 if(le_current.IsTile())
1478 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1481 else if(le_mouse_clicked[LEFT])
1483 if(MouseCursor::current() == mouse_select_object)
1486 bool object_got_hit = false;
1487 base_type cursor_base;
1488 if(le_current.IsTile())
1490 cursor_base.x = cursor_x;
1491 cursor_base.y = cursor_y;
1493 else if(le_current.IsObject())
1495 cursor_base.x = cursor_x + pos_x;
1496 cursor_base.y = cursor_y + pos_x;
1498 cursor_base.width = 32;
1499 cursor_base.height = 32;
1501 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1502 if(rectcollision(cursor_base,(*it)->base))
1504 selected_game_object = (*it);
1505 object_got_hit = true;
1511 selected_game_object = NULL;
1512 le_object_properties_bt->set_active(false);
1515 le_object_properties_bt->set_active(true);
1517 MouseCursor::set_current(mouse_cursor);
1522 if(le_current.IsObject())
1524 le_level_changed = true;
1525 std::string type = le_current.obj->type();
1526 if(type == "BadGuy")
1528 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1530 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1531 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1536 le_mouse_clicked[LEFT] = false;
1542 if(!Menu::current())
1544 show_minimap = false;
1546 le_move_left_bt->event(event);
1547 le_move_right_bt->event(event);
1548 switch(le_move_left_bt->get_state())
1550 case BUTTON_PRESSED:
1552 show_minimap = true;
1556 show_minimap = true;
1558 case BUTTON_CLICKED:
1559 show_minimap = true;
1565 switch(le_move_right_bt->get_state())
1567 case BUTTON_PRESSED:
1569 show_minimap = true;
1573 show_minimap = true;
1575 case BUTTON_CLICKED:
1576 show_minimap = true;
1586 void le_highlight_selection()
1590 if(selection.x1 < selection.x2)
1600 if(selection.y1 < selection.y2)
1616 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1619 void le_change(float x, float y, int tm, unsigned int c)
1621 if(le_world != NULL)
1627 le_level_changed = true;
1629 switch(le_selection_mode)
1632 le_world->get_level()->change(x,y,tm,c);
1634 base_type cursor_base;
1637 cursor_base.width = 32;
1638 cursor_base.height = 32;
1640 /* if there is a bad guy over there, remove it */
1641 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1642 if(rectcollision(cursor_base,(*it)->base))
1645 le_world->bad_guys.erase(it);
1646 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1652 if(selection.x1 < selection.x2)
1662 if(selection.y1 < selection.y2)
1678 /* if there is a bad guy over there, remove it */
1679 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1680 it != le_world->bad_guys.end(); /* will be at end of loop */)
1682 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1683 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1686 it = le_world->bad_guys.erase(it);
1687 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1697 for(xx = x1; xx <= x2; xx++)
1698 for(yy = y1; yy <= y2; yy++)
1700 le_world->get_level()->change(xx*32, yy*32, tm, c);
1712 //Make sure a time value is set when testing the level
1713 if(le_world->get_level()->time_left == 0)
1714 le_world->get_level()->time_left = 250;
1716 le_world->get_level()->save("test", le_level);
1718 GameSession session("test",le_level, ST_GL_TEST);
1720 player_status.reset();
1722 music_manager->halt_music();
1724 Menu::set_current(NULL);
1725 World::set_current(le_world);
1730 bool tmp_show_grid = le_show_grid;
1731 SelectionMode temp_le_selection_mode = le_selection_mode;
1732 le_selection_mode = NONE;
1733 show_selections = true;
1734 le_show_grid = false;
1735 le_help_shown = true;
1737 drawgradient(Color(0,0,0), Color(255,255,255));
1741 unsigned int i, done_;
1744 " - Supertux level editor tutorial - ",
1746 "To make your map, click the ",
1747 "tilegroup button and choose a ",
1749 "Pick a tile and simply hold down ",
1750 "the left mouse button over the map",
1751 "to \"paint\" your selection over",
1754 "There are three layers for painting",
1755 "tiles upon, Background layer,",
1756 "the Interactive layer, and the",
1757 "Foreground layer, which can be",
1758 "toggled by the BkGrd, IntAct and",
1759 "FrGrd buttons. The Foreground and",
1760 "Background layers do not effect",
1761 "Tux in the gameplay, but lie in",
1762 "front of him or lie behind him in",
1768 " - Supertux level editor tutorial - ",
1770 "The tiles placed on",
1771 "the Interactive layer are those",
1772 "which actually effect Tux in the",
1775 "Click the objects menu to put ",
1776 "bad guys and other objects in the",
1777 "game. Unlike placing tiles, you",
1778 "cannot \"paint\" enemies. Click",
1779 "them onto the screen one at a time.",
1781 "To change the settings of your",
1782 "level, click the button with the",
1783 "screwdriver and wrench. From here",
1784 "you can change the background,",
1785 "music, length of the level,",
1791 " - Supertux level editor tutorial - ",
1793 "You may have more than one level.",
1794 "Pressing the up and down buttons",
1795 "above the button bar lets you",
1796 "choose which one you are working on.",
1798 "If you would like to speed up your",
1799 "level editing, a useful trick is",
1800 "to learn the keyboard shortcuts.",
1801 "They are easy to learn, just right-",
1802 "click on the buttons.",
1804 "Have fun making levels! If you make",
1805 "some good ones, send them to us on",
1806 "the SuperTux mailing list!",
1812 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1814 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1815 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1817 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1825 done_ = wait_for_event(event);
1829 drawgradient(Color(0,0,0), Color(255,255,255));
1833 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1835 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1836 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1838 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1846 done_ = wait_for_event(event);
1850 drawgradient(Color(0,0,0), Color(255,255,255));
1854 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1856 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1857 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1859 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1867 done_ = wait_for_event(event);
1871 show_selections = true;
1872 le_show_grid = tmp_show_grid;
1873 le_selection_mode = temp_le_selection_mode;
1874 le_help_shown = false;