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();
687 void le_unload_level()
694 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
695 if(confirm_dialog(str))
697 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
702 le_level_changed = false;
705 void le_goto_level(int levelnb)
708 le_world = new World(le_level_subset->name, levelnb);
709 display_level_info.start(2500);
715 SDL_EnableKeyRepeat(0, 0); // disables key repeating
719 delete leveleditor_menu;
720 delete subset_load_menu;
721 delete subset_new_menu;
722 delete subset_settings_menu;
723 delete level_settings_menu;
724 delete select_tilegroup_menu;
725 delete select_objects_menu;
726 delete le_save_level_bt;
728 delete le_test_level_bt;
729 delete le_next_level_bt;
730 delete le_previous_level_bt;
731 delete le_move_right_bt;
732 delete le_move_left_bt;
734 delete le_select_mode_one_bt;
735 delete le_select_mode_two_bt;
736 delete le_settings_bt;
737 delete le_tilegroup_bt;
738 delete le_objects_bt;
739 delete le_tilemap_panel;
740 delete le_object_select_bt;
741 delete le_object_properties_bt;
742 delete mouse_select_object;
744 delete le_level_subset;
747 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
748 i != tilegroups_map.end(); ++i)
752 for(ButtonPanelMap::iterator i = objects_map.begin();
753 i != objects_map.end(); ++i)
759 void le_drawminimap()
765 if(screen->w - 64 > le_world->get_level()->width * 4)
767 else if(screen->w - 64 > le_world->get_level()->width * 2)
771 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
773 for (int y = 0; y < 15; ++y)
774 for (int x = 0; x < le_world->get_level()->width; ++x)
777 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
779 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
781 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
785 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, 15*4, 200, 200, 200, 128);
787 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
788 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, 15*4, 200, 200, 200, 200);
789 fillrect(left_offset + (pos_x/32)*mini_tile_width + 19*mini_tile_width - 2, 0, 2, 15*4, 200, 200, 200, 200);
790 fillrect(left_offset + (pos_x/32)*mini_tile_width, 15*4-2, 19*mini_tile_width, 2, 200, 200, 200, 200);
794 void le_drawinterface()
801 /* draw a grid (if selected) */
804 for(x = 0; x < 19; x++)
805 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
806 for(y = 0; y < 15; y++)
807 fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
811 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
814 if(show_selections && MouseCursor::current() != mouse_select_object)
816 if(le_selection_mode == CURSOR)
818 if(le_current.IsTile())
819 le_selection->draw( cursor_x - pos_x, cursor_y);
821 else if(le_selection_mode == SQUARE)
824 le_highlight_selection();
825 /* draw current selection */
826 w = selection.x2 - selection.x1;
827 h = selection.y2 - selection.y1;
828 fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
829 fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
830 fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
831 fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
836 /* draw button bar */
837 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
839 if(le_current.IsTile())
841 Tile::draw(19 * 32, 14 * 32, le_current.tile);
842 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
843 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
845 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
847 le_current.obj->draw_on_screen(19 * 32, 14 * 32);
848 le_current.obj->draw_on_screen(cursor_x,cursor_y);
851 if(mouse_select_object && selected_game_object != NULL)
853 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y,selected_game_object->base.width,3,255,0,0,255);
854 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y,3,selected_game_object->base.height,255,0,0,255);
855 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);
856 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);
861 le_save_level_bt->draw();
863 le_test_level_bt->draw();
864 le_next_level_bt->draw();
865 le_previous_level_bt->draw();
866 le_rubber_bt->draw();
867 if(le_selection_mode == SQUARE)
868 le_select_mode_one_bt->draw();
869 else if(le_selection_mode == CURSOR)
870 le_select_mode_two_bt->draw();
871 le_settings_bt->draw();
872 le_move_right_bt->draw();
873 le_move_left_bt->draw();
874 le_tilegroup_bt->draw();
875 le_objects_bt->draw();
876 if(!cur_tilegroup.empty())
877 tilegroups_map[cur_tilegroup]->draw();
878 else if(!cur_objects.empty())
880 objects_map[cur_objects]->draw();
883 le_tilemap_panel->draw();
885 if(!cur_objects.empty())
887 le_object_select_bt->draw();
888 le_object_properties_bt->draw();
891 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
892 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
895 white_small_text->draw("F1 for Help", 10, 430, 1);
897 if(display_level_info.check())
898 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
903 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
905 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
915 /* Draw the real background */
916 if(le_world->get_level()->bkgd_image[0] != '\0')
918 s = (int)((float)pos_x * ((float)le_world->get_level()->bkgd_speed/100.0f)) % screen->w;
919 le_world->get_level()->img_bkgd->draw_part(s,0,0,0,
920 le_world->get_level()->img_bkgd->w - s - 32, le_world->get_level()->img_bkgd->h);
921 le_world->get_level()->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
922 le_world->get_level()->img_bkgd->h);
926 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
929 if(le_current.IsTile())
931 Tile::draw(cursor_x-pos_x, cursor_y,le_current.tile,128);
932 if(!TileManager::instance()->get(le_current.tile)->images.empty())
933 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);
935 if(le_current.IsObject())
937 le_current.obj->move_to(cursor_x, cursor_y);
940 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
942 for (y = 0; y < 15; ++y)
943 for (x = 0; x < 20; ++x)
946 if(active_tm == TM_BG)
951 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->bg_tiles[y][x + (int)(pos_x / 32)],a);
953 if(active_tm == TM_IA)
958 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)],a);
960 if(active_tm == TM_FG)
965 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->fg_tiles[y][x + (int)(pos_x / 32)],a);
967 /* draw whats inside stuff when cursor is selecting those */
968 /* (draw them all the time - is this the right behaviour?) */
969 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)]);
970 if(edit_image && !edit_image->editor_images.empty())
971 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
975 /* Draw the Bad guys: */
976 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
978 /* to support frames: img_bsod_left[(frame / 5) % 4] */
985 /* Draw the player: */
986 /* for now, the position is fixed at (100, 240) */
987 largetux.walk_right->draw( 100 - pos_x, 240);
990 void le_change_object_properties(GameObject *pobj)
992 Surface* cap_screen = Surface::CaptureScreen();
993 Menu* object_properties_menu = new Menu();
996 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
997 object_properties_menu->additem(MN_HL,"",0,0);
999 if(pobj->type() == "BadGuy")
1001 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1002 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1003 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1005 string_list_add_item(object_properties_menu->get_item_by_id(1).list,badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1007 object_properties_menu->get_item_by_id(1).list->active_item = i;
1009 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1012 object_properties_menu->additem(MN_HL,"",0,0);
1013 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1015 Menu::set_current(object_properties_menu);
1021 while (SDL_PollEvent(&event))
1023 object_properties_menu->event(event);
1026 cap_screen->draw(0,0);
1028 object_properties_menu->draw();
1029 object_properties_menu->action();
1031 switch (object_properties_menu->check())
1034 if(pobj->type() == "BadGuy")
1036 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1037 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1038 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1040 std::list<BadGuy*>::iterator it;
1041 for(it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1044 le_world->get_level()->badguy_data[i].kind = pbad->kind;
1045 le_world->get_level()->badguy_data[i].stay_on_platform = pbad->stay_on_platform;
1047 (*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);
1055 if(Menu::current() == NULL)
1058 mouse_cursor->draw();
1064 Menu::set_current(0);
1065 delete object_properties_menu;
1069 void le_checkevents()
1076 keymod = SDL_GetModState();
1078 while(SDL_PollEvent(&event))
1080 if (Menu::current())
1082 Menu::current()->event(event);
1083 if(!le_world && !Menu::current())
1084 Menu::set_current(leveleditor_menu);
1088 mouse_cursor->set_state(MC_NORMAL);
1090 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1091 if(event.type == SDL_KEYDOWN
1092 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1093 && (event.motion.x > 0
1094 && event.motion.x < screen->w - 64 &&
1095 event.motion.y > 0 && event.motion.y < screen->h)))
1099 case SDL_KEYDOWN: // key pressed
1100 key = event.key.keysym.sym;
1104 Menu::set_current(leveleditor_menu);
1108 cursor_x -= KEY_CURSOR_SPEED;
1110 cursor_x -= KEY_CURSOR_FASTSPEED;
1112 if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
1113 pos_x = cursor_x - MOUSE_LEFT_MARGIN;
1118 cursor_x += KEY_CURSOR_SPEED;
1120 cursor_x += KEY_CURSOR_FASTSPEED;
1122 if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
1123 pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
1128 cursor_y -= KEY_CURSOR_SPEED;
1130 cursor_y -= KEY_CURSOR_FASTSPEED;
1137 cursor_y += KEY_CURSOR_SPEED;
1139 cursor_y += KEY_CURSOR_FASTSPEED;
1141 if(cursor_y > screen->h-32)
1142 cursor_y = screen->h-32;
1148 if(le_world != NULL)
1156 cursor_x = (le_world->get_level()->width * 32) - 32;
1160 le_show_grid = !le_show_grid;
1166 case SDL_KEYUP: /* key released */
1167 switch(event.key.keysym.sym)
1176 case SDL_MOUSEBUTTONDOWN:
1177 if(event.button.button == SDL_BUTTON_LEFT)
1179 le_mouse_pressed[LEFT] = true;
1181 selection.x1 = event.motion.x + pos_x;
1182 selection.y1 = event.motion.y;
1183 selection.x2 = event.motion.x + pos_x;
1184 selection.y2 = event.motion.y;
1186 else if(event.button.button == SDL_BUTTON_RIGHT)
1188 le_mouse_pressed[RIGHT] = true;
1191 case SDL_MOUSEBUTTONUP:
1192 if(event.button.button == SDL_BUTTON_LEFT)
1194 le_mouse_pressed[LEFT] = false;
1195 le_mouse_clicked[LEFT] = true;
1197 else if(event.button.button == SDL_BUTTON_RIGHT)
1199 le_mouse_pressed[RIGHT] = false;
1200 le_mouse_clicked[RIGHT] = true;
1203 case SDL_MOUSEMOTION:
1205 if(!Menu::current())
1210 if(le_current.IsTile())
1212 cursor_x = ((int)(pos_x + x) / 32) * 32;
1213 cursor_y = ((int) y / 32) * 32;
1221 if(le_mouse_pressed[LEFT])
1223 selection.x2 = x + pos_x;
1227 if(le_mouse_pressed[RIGHT])
1229 pos_x += -1 * event.motion.xrel;
1237 else if(event.type == SDL_QUIT) /* window closing */
1243 if(le_world != NULL)
1245 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 &&
1246 event.motion.y > 0 && event.motion.y < screen->h)))
1248 le_mouse_pressed[LEFT] = false;
1249 le_mouse_pressed[RIGHT] = false;
1251 if(!Menu::current())
1253 /* Check for button events */
1254 le_test_level_bt->event(event);
1255 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1257 le_save_level_bt->event(event);
1258 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1259 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1260 le_exit_bt->event(event);
1261 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1263 Menu::set_current(leveleditor_menu);
1265 le_next_level_bt->event(event);
1266 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1268 if(le_level < le_level_subset->levels)
1270 le_goto_level(le_level+1);
1276 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1277 if(confirm_dialog(str))
1279 new_lev.init_defaults();
1280 new_lev.save(le_level_subset->name.c_str(),le_level+1);
1281 le_level_subset->levels = le_level;
1282 le_goto_level(le_level);
1286 le_previous_level_bt->event(event);
1287 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1290 le_goto_level(le_level -1);
1292 le_rubber_bt->event(event);
1293 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1296 if(!cur_objects.empty())
1298 le_object_select_bt->event(event);
1299 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1301 MouseCursor::set_current(mouse_select_object);
1304 le_object_properties_bt->event(event);
1305 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1307 le_change_object_properties(selected_game_object);
1312 if(le_selection_mode == SQUARE)
1314 le_select_mode_one_bt->event(event);
1315 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1316 le_selection_mode = CURSOR;
1320 le_select_mode_two_bt->event(event);
1321 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1322 le_selection_mode = SQUARE;
1324 ButtonPanelMap::iterator it;
1325 le_tilegroup_bt->event(event);
1326 switch (le_tilegroup_bt->get_state())
1328 case BUTTON_CLICKED:
1329 Menu::set_current(select_tilegroup_menu);
1330 select_tilegroup_menu_effect.start(200);
1331 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1333 case BUTTON_WHEELUP:
1334 if(cur_tilegroup.empty())
1336 cur_tilegroup = tilegroups_map.begin()->first;
1340 it = tilegroups_map.find(cur_tilegroup);
1341 if((++it) == tilegroups_map.end())
1343 cur_tilegroup = tilegroups_map.begin()->first;
1347 cur_tilegroup = (*it).first;
1353 case BUTTON_WHEELDOWN:
1354 it = tilegroups_map.find(cur_tilegroup);
1355 if(it == tilegroups_map.begin())
1357 cur_tilegroup = tilegroups_map.rbegin()->first;
1361 if(--it != --tilegroups_map.begin())
1362 cur_tilegroup = (*it).first;
1364 cur_tilegroup = tilegroups_map.rbegin()->first;
1372 le_objects_bt->event(event);
1373 switch (le_objects_bt->get_state())
1375 case BUTTON_CLICKED:
1376 Menu::set_current(select_objects_menu);
1377 select_objects_menu_effect.start(200);
1378 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1380 case BUTTON_WHEELUP:
1381 it = objects_map.find(cur_objects);
1382 if(it == objects_map.end())
1384 cur_objects = objects_map.begin()->first;
1388 if(++it != objects_map.end())
1389 cur_objects = (*it).first;
1391 cur_objects = objects_map.begin()->first;
1395 case BUTTON_WHEELDOWN:
1396 it = objects_map.find(cur_objects);
1397 if(it == objects_map.begin())
1399 cur_objects = objects_map.rbegin()->first;
1403 if(--it != --objects_map.begin())
1404 cur_objects = (*it).first;
1406 cur_objects = objects_map.rbegin()->first;
1415 le_settings_bt->event(event);
1416 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1418 update_level_settings_menu();
1419 Menu::set_current(level_settings_menu);
1421 if(!cur_tilegroup.empty())
1423 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1425 if(pbutton->get_state() == BUTTON_CLICKED)
1427 le_current.Tile(pbutton->get_tag());
1431 else if(!cur_objects.empty())
1433 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1435 if(pbutton->get_state() == BUTTON_CLICKED)
1437 le_current.Object(pbutton->get_game_object());
1442 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1444 if(pbutton->get_state() == BUTTON_CLICKED)
1446 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1452 le_settings_bt->event(event);
1453 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1455 Menu::set_current(0);
1457 le_tilegroup_bt->event(event);
1458 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1460 Menu::set_current(0);
1462 le_objects_bt->event(event);
1463 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1465 Menu::set_current(0);
1470 if(!Menu::current() && !show_minimap)
1472 if(le_mouse_pressed[LEFT])
1474 if(MouseCursor::current() != mouse_select_object)
1476 if(le_current.IsTile())
1477 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1480 else if(le_mouse_clicked[LEFT])
1482 if(MouseCursor::current() == mouse_select_object)
1485 bool object_got_hit = false;
1486 base_type cursor_base;
1487 if(le_current.IsTile())
1489 cursor_base.x = cursor_x;
1490 cursor_base.y = cursor_y;
1492 else if(le_current.IsObject())
1494 cursor_base.x = cursor_x + pos_x;
1495 cursor_base.y = cursor_y + pos_x;
1497 cursor_base.width = 32;
1498 cursor_base.height = 32;
1500 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1501 if(rectcollision(cursor_base,(*it)->base))
1503 selected_game_object = (*it);
1504 object_got_hit = true;
1510 selected_game_object = NULL;
1511 le_object_properties_bt->set_active(false);
1514 le_object_properties_bt->set_active(true);
1516 MouseCursor::set_current(mouse_cursor);
1521 if(le_current.IsObject())
1523 le_level_changed = true;
1524 std::string type = le_current.obj->type();
1525 if(type == "BadGuy")
1527 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1529 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1530 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1535 le_mouse_clicked[LEFT] = false;
1541 if(!Menu::current())
1543 show_minimap = false;
1545 le_move_left_bt->event(event);
1546 le_move_right_bt->event(event);
1547 switch(le_move_left_bt->get_state())
1549 case BUTTON_PRESSED:
1551 show_minimap = true;
1555 show_minimap = true;
1557 case BUTTON_CLICKED:
1558 show_minimap = true;
1564 switch(le_move_right_bt->get_state())
1566 case BUTTON_PRESSED:
1568 show_minimap = true;
1572 show_minimap = true;
1574 case BUTTON_CLICKED:
1575 show_minimap = true;
1585 void le_highlight_selection()
1589 if(selection.x1 < selection.x2)
1599 if(selection.y1 < selection.y2)
1615 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1618 void le_change(float x, float y, int tm, unsigned int c)
1620 if(le_world != NULL)
1626 le_level_changed = true;
1628 switch(le_selection_mode)
1631 le_world->get_level()->change(x,y,tm,c);
1633 base_type cursor_base;
1636 cursor_base.width = 32;
1637 cursor_base.height = 32;
1639 /* if there is a bad guy over there, remove it */
1640 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1641 if(rectcollision(cursor_base,(*it)->base))
1644 le_world->bad_guys.erase(it);
1645 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1651 if(selection.x1 < selection.x2)
1661 if(selection.y1 < selection.y2)
1677 /* if there is a bad guy over there, remove it */
1678 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1679 it != le_world->bad_guys.end(); /* will be at end of loop */)
1681 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1682 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1685 it = le_world->bad_guys.erase(it);
1686 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1696 for(xx = x1; xx <= x2; xx++)
1697 for(yy = y1; yy <= y2; yy++)
1699 le_world->get_level()->change(xx*32, yy*32, tm, c);
1711 //Make sure a time value is set when testing the level
1712 if(le_world->get_level()->time_left == 0)
1713 le_world->get_level()->time_left = 250;
1715 le_world->get_level()->save("test", le_level);
1717 GameSession session("test",le_level, ST_GL_TEST);
1719 player_status.reset();
1721 music_manager->halt_music();
1723 Menu::set_current(NULL);
1724 World::set_current(le_world);
1729 bool tmp_show_grid = le_show_grid;
1730 SelectionMode temp_le_selection_mode = le_selection_mode;
1731 le_selection_mode = NONE;
1732 show_selections = true;
1733 le_show_grid = false;
1734 le_help_shown = true;
1736 drawgradient(Color(0,0,0), Color(255,255,255));
1740 unsigned int i, done_;
1743 " - Supertux level editor tutorial - ",
1745 "To make your map, click the ",
1746 "tilegroup button and choose a ",
1748 "Pick a tile and simply hold down ",
1749 "the left mouse button over the map",
1750 "to \"paint\" your selection over",
1753 "There are three layers for painting",
1754 "tiles upon, Background layer,",
1755 "the Interactive layer, and the",
1756 "Foreground layer, which can be",
1757 "toggled by the BkGrd, IntAct and",
1758 "FrGrd buttons. The Foreground and",
1759 "Background layers do not effect",
1760 "Tux in the gameplay, but lie in",
1761 "front of him or lie behind him in",
1767 " - Supertux level editor tutorial - ",
1769 "The tiles placed on",
1770 "the Interactive layer are those",
1771 "which actually effect Tux in the",
1774 "Click the objects menu to put ",
1775 "bad guys and other objects in the",
1776 "game. Unlike placing tiles, you",
1777 "cannot \"paint\" enemies. Click",
1778 "them onto the screen one at a time.",
1780 "To change the settings of your",
1781 "level, click the button with the",
1782 "screwdriver and wrench. From here",
1783 "you can change the background,",
1784 "music, length of the level,",
1790 " - Supertux level editor tutorial - ",
1792 "You may have more than one level.",
1793 "Pressing the up and down buttons",
1794 "above the button bar lets you",
1795 "choose which one you are working on.",
1797 "If you would like to speed up your",
1798 "level editing, a useful trick is",
1799 "to learn the keyboard shortcuts.",
1800 "They are easy to learn, just right-",
1801 "click on the buttons.",
1803 "Have fun making levels! If you make",
1804 "some good ones, send them to us on",
1805 "the SuperTux mailing list!",
1811 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1813 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1814 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1816 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1824 done_ = wait_for_event(event);
1828 drawgradient(Color(0,0,0), Color(255,255,255));
1832 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1834 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1835 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1837 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1845 done_ = wait_for_event(event);
1849 drawgradient(Color(0,0,0), Color(255,255,255));
1853 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1855 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1856 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1858 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1866 done_ = wait_for_event(event);
1870 show_selections = true;
1871 le_show_grid = tmp_show_grid;
1872 le_selection_mode = temp_le_selection_mode;
1873 le_help_shown = false;