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, pos_y, cursor_x, cursor_y;
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_move_up_bt;
129 static Button* le_move_down_bt;
130 static Button* le_rubber_bt;
131 static Button* le_select_mode_one_bt;
132 static Button* le_select_mode_two_bt;
133 static Button* le_settings_bt;
134 static Button* le_tilegroup_bt;
135 static Button* le_objects_bt;
136 static Button* le_object_select_bt;
137 static Button* le_object_properties_bt;
138 static ButtonPanel* le_tilemap_panel;
139 static Menu* leveleditor_menu;
140 static Menu* subset_load_menu;
141 static Menu* subset_new_menu;
142 static Menu* subset_settings_menu;
143 static Menu* level_settings_menu;
144 static Menu* select_tilegroup_menu;
145 static Menu* select_objects_menu;
146 static Timer select_tilegroup_menu_effect;
147 static Timer select_objects_menu_effect;
148 static Timer display_level_info;
149 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
150 static ButtonPanelMap tilegroups_map;
151 static ButtonPanelMap objects_map;
152 static std::string cur_tilegroup;
153 static std::string cur_objects;
154 static MouseCursor* mouse_select_object;
155 static GameObject* selected_game_object;
157 static square selection;
158 static SelectionMode le_selection_mode;
159 static SDL_Event event;
160 TileMapType active_tm;
162 int leveleditor(char* filename)
164 int last_time, now_time, i;
173 clearscreen(0, 0, 0);
176 music_manager->halt_music();
178 while (SDL_PollEvent(&event))
182 if(le_load_level_subset(filename))
187 last_time = SDL_GetTicks();
192 if(Menu::current() == select_tilegroup_menu)
194 if(select_tilegroup_menu_effect.check())
196 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
200 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
202 else if(Menu::current() == select_objects_menu)
204 if(select_objects_menu_effect.check())
206 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
209 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
214 /* making events results to be in order */
220 clearscreen(0, 0, 0);
222 /* draw editor interface */
225 Menu* menu = Menu::current();
231 if(menu == leveleditor_menu)
233 switch (leveleditor_menu->check())
235 case MNID_RETURNLEVELEDITOR:
237 Menu::set_current(0);
239 Menu::set_current(leveleditor_menu);
241 case MNID_SUBSETSETTINGS:
242 update_subset_settings_menu();
244 case MNID_QUITLEVELEDITOR:
249 else if(menu == level_settings_menu)
251 switch (level_settings_menu->check())
254 apply_level_settings_menu();
255 Menu::set_current(NULL);
262 else if(menu == select_tilegroup_menu)
265 switch (it = select_tilegroup_menu->check())
270 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
271 Menu::set_current(0);
278 else if(menu == select_objects_menu)
281 switch (it = select_objects_menu->check())
286 cur_objects = select_objects_menu->get_item_by_id(it).text;
289 Menu::set_current(0);
294 else if(menu == subset_load_menu)
296 switch (i = subset_load_menu->check())
303 if(le_load_level_subset(level_subsets.item[i-1]))
309 else if(menu == subset_new_menu)
311 if(subset_new_menu->item[2].input[0] == '\0')
312 subset_new_menu->item[3].kind = MN_DEACTIVE;
315 subset_new_menu->item[3].kind = MN_ACTION;
317 switch (i = subset_new_menu->check())
319 case MNID_CREATESUBSET:
320 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
321 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
322 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
324 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
326 Menu::set_current(subset_settings_menu);
331 else if(menu == subset_settings_menu)
333 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 )
334 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
336 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
338 switch (i = subset_settings_menu->check())
340 case MNID_SUBSETSAVECHANGES:
341 save_subset_settings_menu();
342 Menu::set_current(leveleditor_menu);
348 MouseCursor::current()->draw();
356 ++global_frame_counter;
359 now_time = SDL_GetTicks();
360 if (now_time < last_time + FPS)
361 SDL_Delay(last_time + FPS - now_time); /* delay some time */
369 int le_load_level_subset(char *filename)
371 le_level_subset->load(filename);
372 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
376 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
378 Menu::set_current(NULL);
387 leveleditor_menu = new Menu();
388 subset_load_menu = new Menu();
389 subset_new_menu = new Menu();
390 subset_settings_menu = new Menu();
391 level_settings_menu = new Menu();
392 select_tilegroup_menu = new Menu();
393 select_objects_menu = new Menu();
395 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
396 leveleditor_menu->additem(MN_HL,"",0,0);
397 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
398 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
399 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
400 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
401 leveleditor_menu->additem(MN_HL,"",0,0);
402 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
404 Menu::set_current(leveleditor_menu);
406 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
407 subset_load_menu->additem(MN_HL, "", 0, 0);
409 for(i = 0; i < level_subsets.num_items; ++i)
411 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
413 subset_load_menu->additem(MN_HL,"",0,0);
414 subset_load_menu->additem(MN_BACK,"Back",0,0);
416 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
417 subset_new_menu->additem(MN_HL,"",0,0);
418 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
419 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
420 subset_new_menu->additem(MN_HL,"",0,0);
421 subset_new_menu->additem(MN_BACK,"Back",0,0);
423 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
424 subset_settings_menu->additem(MN_HL,"",0,0);
425 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
426 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
427 subset_settings_menu->additem(MN_HL,"",0,0);
428 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
429 subset_settings_menu->additem(MN_HL,"",0,0);
430 subset_settings_menu->additem(MN_BACK,"Back",0,0);
432 level_settings_menu->arrange_left = true;
433 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
434 level_settings_menu->additem(MN_HL,"",0,0);
435 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
436 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
437 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
438 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
439 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
440 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
441 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
442 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
443 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
444 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
445 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
446 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
447 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
448 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
449 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
450 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
451 level_settings_menu->additem(MN_HL,"",0,0);
452 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
454 select_tilegroup_menu->arrange_left = true;
455 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
456 select_tilegroup_menu->additem(MN_HL,"",0,0);
457 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
459 for(std::set<TileGroup>::iterator it = tilegroups->begin();
460 it != tilegroups->end(); ++it )
462 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
464 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
467 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
468 sit != (*it).tiles.end(); ++sit, ++i)
470 std::string imagefile = "/images/tilesets/" ;
471 bool only_editor_image = false;
472 if(!TileManager::instance()->get(*sit)->filenames.empty())
474 imagefile += TileManager::instance()->get(*sit)->filenames[0];
476 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
478 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
479 only_editor_image = true;
483 imagefile += "notile.png";
485 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
487 if(!only_editor_image)
488 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
490 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
491 button->add_icon(imagefile,32,32);
493 tilegroups_map[it->name]->additem(button, *sit);
496 select_tilegroup_menu->additem(MN_HL,"",0,0);
498 select_objects_menu->arrange_left = true;
499 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
500 select_objects_menu->additem(MN_HL,"",0,0);
501 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
502 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
504 for(int i = 0; i < NUM_BadGuyKinds; ++i)
506 BadGuy bad_tmp(0,0,BadGuyKind(i),false);
507 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
508 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));
511 select_objects_menu->additem(MN_HL,"",0,0);
519 level_subsets = dsubdirs("/levels", "level1.stl");
520 le_level_subset = new LevelSubset;
523 selected_game_object = NULL;
527 show_selections = true;
531 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
532 le_level_changed = false;
533 le_help_shown = false;
535 le_mouse_pressed[LEFT] = false;
536 le_mouse_pressed[RIGHT] = false;
538 le_mouse_clicked[LEFT] = false;
539 le_mouse_clicked[RIGHT] = false;
541 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
543 select_tilegroup_menu_effect.init(false);
544 select_objects_menu_effect.init(false);
545 display_level_info.init(false);
548 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
549 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
550 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
551 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
552 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
553 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
554 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
555 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
556 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
557 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
558 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
559 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
560 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
561 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
562 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
563 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
564 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
565 le_object_properties_bt->set_active(false);
567 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
568 mouse_select_object->set_mid(16,16);
570 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
571 le_tilemap_panel->set_button_size(32,10);
572 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
573 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
574 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
575 le_tilemap_panel->highlight_last(true);
576 le_tilemap_panel->set_last_clicked(TM_IA);
582 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
588 void update_level_settings_menu()
593 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
594 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
596 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
597 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
598 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
599 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
600 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
601 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
603 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
604 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
605 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
606 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
607 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
608 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
610 sprintf(str,"%d",le_world->get_level()->width);
611 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
612 sprintf(str,"%d",le_world->get_level()->height);
613 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
614 sprintf(str,"%d",le_world->get_level()->time_left);
615 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
616 sprintf(str,"%2.0f",le_world->get_level()->gravity);
617 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
618 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
619 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
620 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
621 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
622 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
623 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
624 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
625 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
626 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
627 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
628 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
629 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
630 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
631 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
634 void update_subset_settings_menu()
636 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
637 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
640 void apply_level_settings_menu()
645 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
646 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
648 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
650 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
654 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
656 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
661 le_world->get_level()->load_gfx();
664 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
666 le_world->get_level()->change_width(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
667 le_world->get_level()->change_height(atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
668 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
669 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
670 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
671 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
672 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
673 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
674 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
675 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
676 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
679 void save_subset_settings_menu()
681 le_level_subset->title = subset_settings_menu->item[2].input;
682 le_level_subset->description = subset_settings_menu->item[3].input;
683 le_level_subset->save();
684 le_level_changed = false;
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;
733 delete le_move_up_bt;
734 delete le_move_down_bt;
736 delete le_select_mode_one_bt;
737 delete le_select_mode_two_bt;
738 delete le_settings_bt;
739 delete le_tilegroup_bt;
740 delete le_objects_bt;
741 delete le_tilemap_panel;
742 delete le_object_select_bt;
743 delete le_object_properties_bt;
744 delete mouse_select_object;
746 delete le_level_subset;
749 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
750 i != tilegroups_map.end(); ++i)
754 for(ButtonPanelMap::iterator i = objects_map.begin();
755 i != objects_map.end(); ++i)
761 void le_drawminimap()
767 if(screen->w - 64 > le_world->get_level()->width * 4)
769 else if(screen->w - 64 > le_world->get_level()->width * 2)
773 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
775 for (int y = 0; y < 15; ++y)
776 for (int x = 0; x < le_world->get_level()->width; ++x)
779 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
781 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
783 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
787 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, 15*4, 200, 200, 200, 128);
789 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
790 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, 15*4, 200, 200, 200, 200);
791 fillrect(left_offset + (pos_x/32)*mini_tile_width + 19*mini_tile_width - 2, 0, 2, 15*4, 200, 200, 200, 200);
792 fillrect(left_offset + (pos_x/32)*mini_tile_width, 15*4-2, 19*mini_tile_width, 2, 200, 200, 200, 200);
796 void le_drawinterface()
803 /* draw a grid (if selected) */
806 for(x = 0; x < 19; x++)
807 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
808 for(y = 0; y < 15; y++)
809 fillrect(0, y*32 - ((int)pos_y % 32), screen->w - 32, 1, 225, 225, 225,255);
813 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
816 if(show_selections && MouseCursor::current() != mouse_select_object)
818 if(le_selection_mode == CURSOR)
820 if(le_current.IsTile())
821 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
823 else if(le_selection_mode == SQUARE)
826 le_highlight_selection();
827 /* draw current selection */
828 w = selection.x2 - selection.x1;
829 h = selection.y2 - selection.y1;
830 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
831 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
832 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
833 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
838 /* draw button bar */
839 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
841 if(le_current.IsTile())
843 Tile::draw(19 * 32, 14 * 32, le_current.tile);
844 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
845 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
847 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
849 le_current.obj->draw_on_screen(19 * 32, 14 * 32);
850 le_current.obj->draw_on_screen(cursor_x,cursor_y);
853 if(mouse_select_object && selected_game_object != NULL)
855 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,selected_game_object->base.width,3,255,0,0,255);
856 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255);
857 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y+selected_game_object->base.height,selected_game_object->base.width,3,255,0,0,255);
858 fillrect(selected_game_object->base.x-pos_x+selected_game_object->base.width,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255);
863 le_save_level_bt->draw();
865 le_test_level_bt->draw();
866 le_next_level_bt->draw();
867 le_previous_level_bt->draw();
868 le_rubber_bt->draw();
869 if(le_selection_mode == SQUARE)
870 le_select_mode_one_bt->draw();
871 else if(le_selection_mode == CURSOR)
872 le_select_mode_two_bt->draw();
873 le_settings_bt->draw();
874 le_move_right_bt->draw();
875 le_move_left_bt->draw();
876 le_move_up_bt->draw();
877 le_move_down_bt->draw();
878 le_tilegroup_bt->draw();
879 le_objects_bt->draw();
880 if(!cur_tilegroup.empty())
881 tilegroups_map[cur_tilegroup]->draw();
882 else if(!cur_objects.empty())
884 objects_map[cur_objects]->draw();
887 le_tilemap_panel->draw();
889 if(!cur_objects.empty())
891 le_object_select_bt->draw();
892 le_object_properties_bt->draw();
895 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
896 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
899 white_small_text->draw("F1 for Help", 10, 430, 1);
901 if(display_level_info.check())
902 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
907 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
909 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
919 /* Draw the real background */
920 if(le_world->get_level()->bkgd_image[0] != '\0')
922 s = (int)((float)pos_x * ((float)le_world->get_level()->bkgd_speed/100.0f)) % screen->w;
923 le_world->get_level()->img_bkgd->draw_part(s,0,0,0,
924 le_world->get_level()->img_bkgd->w - s - 32, le_world->get_level()->img_bkgd->h);
925 le_world->get_level()->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
926 le_world->get_level()->img_bkgd->h);
930 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
933 if(le_current.IsTile())
935 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
936 if(!TileManager::instance()->get(le_current.tile)->images.empty())
937 fillrect(cursor_x-pos_x,cursor_y-pos_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);
939 if(le_current.IsObject())
941 le_current.obj->move_to(cursor_x, cursor_y);
944 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
946 for (y = 0; y < 15; ++y)
947 for (x = 0; x < 20; ++x)
950 if(active_tm == TM_BG)
955 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->bg_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
957 if(active_tm == TM_IA)
962 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->ia_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
964 if(active_tm == TM_FG)
969 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->fg_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
971 /* draw whats inside stuff when cursor is selecting those */
972 /* (draw them all the time - is this the right behaviour?) */
973 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y + (int)(pos_x / 32)][x + (int)(pos_x / 32)]);
974 if(edit_image && !edit_image->editor_images.empty())
975 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
979 /* Draw the Bad guys: */
980 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
982 /* to support frames: img_bsod_left[(frame / 5) % 4] */
990 /* Draw the player: */
991 /* for now, the position is fixed at (100, 240) */
992 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
995 void le_change_object_properties(GameObject *pobj)
997 Surface* cap_screen = Surface::CaptureScreen();
998 Menu* object_properties_menu = new Menu();
1001 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
1002 object_properties_menu->additem(MN_HL,"",0,0);
1004 if(pobj->type() == "BadGuy")
1006 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1007 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1008 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1010 string_list_add_item(object_properties_menu->get_item_by_id(1).list,badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1012 object_properties_menu->get_item_by_id(1).list->active_item = i;
1014 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1017 object_properties_menu->additem(MN_HL,"",0,0);
1018 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1020 Menu::set_current(object_properties_menu);
1026 while (SDL_PollEvent(&event))
1028 object_properties_menu->event(event);
1031 cap_screen->draw(0,0);
1033 object_properties_menu->draw();
1034 object_properties_menu->action();
1036 switch (object_properties_menu->check())
1039 if(pobj->type() == "BadGuy")
1041 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1042 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1043 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1045 std::list<BadGuy*>::iterator it;
1046 for(it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1049 le_world->get_level()->badguy_data[i].kind = pbad->kind;
1050 le_world->get_level()->badguy_data[i].stay_on_platform = pbad->stay_on_platform;
1052 (*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);
1060 if(Menu::current() == NULL)
1063 mouse_cursor->draw();
1069 Menu::set_current(0);
1070 delete object_properties_menu;
1074 void le_checkevents()
1081 keymod = SDL_GetModState();
1083 while(SDL_PollEvent(&event))
1085 if (Menu::current())
1087 Menu::current()->event(event);
1088 if(!le_world && !Menu::current())
1089 Menu::set_current(leveleditor_menu);
1093 mouse_cursor->set_state(MC_NORMAL);
1095 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1096 if(event.type == SDL_KEYDOWN
1097 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1098 && (event.motion.x > 0
1099 && event.motion.x < screen->w - 64 &&
1100 event.motion.y > 0 && event.motion.y < screen->h)))
1104 case SDL_KEYDOWN: // key pressed
1105 key = event.key.keysym.sym;
1109 Menu::set_current(leveleditor_menu);
1112 if(le_world != NULL)
1120 cursor_x = (le_world->get_level()->width * 32) - 32;
1124 le_show_grid = !le_show_grid;
1130 case SDL_MOUSEBUTTONDOWN:
1131 if(event.button.button == SDL_BUTTON_LEFT)
1133 le_mouse_pressed[LEFT] = true;
1135 selection.x1 = event.motion.x + pos_x;
1136 selection.y1 = event.motion.y + pos_y;
1137 selection.x2 = event.motion.x + pos_x;
1138 selection.y2 = event.motion.y + pos_y;
1140 else if(event.button.button == SDL_BUTTON_RIGHT)
1142 le_mouse_pressed[RIGHT] = true;
1145 case SDL_MOUSEBUTTONUP:
1146 if(event.button.button == SDL_BUTTON_LEFT)
1148 le_mouse_pressed[LEFT] = false;
1149 le_mouse_clicked[LEFT] = true;
1151 else if(event.button.button == SDL_BUTTON_RIGHT)
1153 le_mouse_pressed[RIGHT] = false;
1154 le_mouse_clicked[RIGHT] = true;
1157 case SDL_MOUSEMOTION:
1159 if(!Menu::current())
1164 if(le_current.IsTile())
1166 cursor_x = ((int)(pos_x + x) / 32) * 32;
1167 cursor_y = ((int)(pos_y + y) / 32) * 32;
1175 if(le_mouse_pressed[LEFT])
1177 selection.x2 = x + pos_x;
1178 selection.y2 = y + pos_y;
1181 if(le_mouse_pressed[RIGHT])
1183 pos_x += -1 * event.motion.xrel;
1184 pos_y += -1 * event.motion.yrel;
1192 else if(event.type == SDL_QUIT) /* window closing */
1198 if(le_world != NULL)
1200 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 &&
1201 event.motion.y > 0 && event.motion.y < screen->h)))
1203 le_mouse_pressed[LEFT] = false;
1204 le_mouse_pressed[RIGHT] = false;
1206 if(!Menu::current())
1208 /* Check for button events */
1209 le_test_level_bt->event(event);
1210 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1212 le_save_level_bt->event(event);
1213 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1214 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1215 le_exit_bt->event(event);
1216 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1218 Menu::set_current(leveleditor_menu);
1220 le_next_level_bt->event(event);
1221 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1223 if(le_level < le_level_subset->levels)
1225 le_goto_level(le_level+1);
1231 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1232 if(confirm_dialog(str))
1234 new_lev.init_defaults();
1235 new_lev.save(le_level_subset->name.c_str(),le_level+1);
1236 le_level_subset->levels = le_level;
1237 le_goto_level(le_level);
1241 le_previous_level_bt->event(event);
1242 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1245 le_goto_level(le_level -1);
1247 le_rubber_bt->event(event);
1248 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1251 if(!cur_objects.empty())
1253 le_object_select_bt->event(event);
1254 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1256 MouseCursor::set_current(mouse_select_object);
1259 le_object_properties_bt->event(event);
1260 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1262 le_change_object_properties(selected_game_object);
1267 if(le_selection_mode == SQUARE)
1269 le_select_mode_one_bt->event(event);
1270 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1271 le_selection_mode = CURSOR;
1275 le_select_mode_two_bt->event(event);
1276 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1277 le_selection_mode = SQUARE;
1279 ButtonPanelMap::iterator it;
1280 le_tilegroup_bt->event(event);
1281 switch (le_tilegroup_bt->get_state())
1283 case BUTTON_CLICKED:
1284 Menu::set_current(select_tilegroup_menu);
1285 select_tilegroup_menu_effect.start(200);
1286 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1288 case BUTTON_WHEELUP:
1289 if(cur_tilegroup.empty())
1291 cur_tilegroup = tilegroups_map.begin()->first;
1295 it = tilegroups_map.find(cur_tilegroup);
1296 if((++it) == tilegroups_map.end())
1298 cur_tilegroup = tilegroups_map.begin()->first;
1302 cur_tilegroup = (*it).first;
1308 case BUTTON_WHEELDOWN:
1309 it = tilegroups_map.find(cur_tilegroup);
1310 if(it == tilegroups_map.begin())
1312 cur_tilegroup = tilegroups_map.rbegin()->first;
1316 if(--it != --tilegroups_map.begin())
1317 cur_tilegroup = (*it).first;
1319 cur_tilegroup = tilegroups_map.rbegin()->first;
1327 le_objects_bt->event(event);
1328 switch (le_objects_bt->get_state())
1330 case BUTTON_CLICKED:
1331 Menu::set_current(select_objects_menu);
1332 select_objects_menu_effect.start(200);
1333 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1335 case BUTTON_WHEELUP:
1336 it = objects_map.find(cur_objects);
1337 if(it == objects_map.end())
1339 cur_objects = objects_map.begin()->first;
1343 if(++it != objects_map.end())
1344 cur_objects = (*it).first;
1346 cur_objects = objects_map.begin()->first;
1350 case BUTTON_WHEELDOWN:
1351 it = objects_map.find(cur_objects);
1352 if(it == objects_map.begin())
1354 cur_objects = objects_map.rbegin()->first;
1358 if(--it != --objects_map.begin())
1359 cur_objects = (*it).first;
1361 cur_objects = objects_map.rbegin()->first;
1370 le_settings_bt->event(event);
1371 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1373 update_level_settings_menu();
1374 Menu::set_current(level_settings_menu);
1376 if(!cur_tilegroup.empty())
1378 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1380 if(pbutton->get_state() == BUTTON_CLICKED)
1382 le_current.Tile(pbutton->get_tag());
1386 else if(!cur_objects.empty())
1388 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1390 if(pbutton->get_state() == BUTTON_CLICKED)
1392 le_current.Object(pbutton->get_game_object());
1397 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1399 if(pbutton->get_state() == BUTTON_CLICKED)
1401 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1407 le_settings_bt->event(event);
1408 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1410 Menu::set_current(0);
1412 le_tilegroup_bt->event(event);
1413 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1415 Menu::set_current(0);
1417 le_objects_bt->event(event);
1418 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1420 Menu::set_current(0);
1425 if(!Menu::current() && !show_minimap)
1427 if(le_mouse_pressed[LEFT])
1429 if(MouseCursor::current() != mouse_select_object)
1431 if(le_current.IsTile())
1432 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1435 else if(le_mouse_clicked[LEFT])
1437 if(MouseCursor::current() == mouse_select_object)
1440 bool object_got_hit = false;
1441 base_type cursor_base;
1442 if(le_current.IsTile())
1444 cursor_base.x = cursor_x;
1445 cursor_base.y = cursor_y;
1447 else if(le_current.IsObject())
1449 cursor_base.x = cursor_x + pos_x;
1450 cursor_base.y = cursor_y + pos_y;
1452 cursor_base.width = 32;
1453 cursor_base.height = 32;
1455 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1456 if(rectcollision(cursor_base,(*it)->base))
1458 selected_game_object = (*it);
1459 object_got_hit = true;
1465 selected_game_object = NULL;
1466 le_object_properties_bt->set_active(false);
1469 le_object_properties_bt->set_active(true);
1471 MouseCursor::set_current(mouse_cursor);
1476 if(le_current.IsObject())
1478 le_level_changed = true;
1479 std::string type = le_current.obj->type();
1480 if(type == "BadGuy")
1482 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1484 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1485 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1490 le_mouse_clicked[LEFT] = false;
1496 if(!Menu::current())
1498 show_minimap = false;
1500 le_move_left_bt->event(event);
1501 le_move_right_bt->event(event);
1502 le_move_up_bt->event(event);
1503 le_move_down_bt->event(event);
1504 switch(le_move_left_bt->get_state())
1506 case BUTTON_PRESSED:
1508 show_minimap = true;
1512 show_minimap = true;
1514 case BUTTON_CLICKED:
1515 show_minimap = true;
1521 switch(le_move_right_bt->get_state())
1523 case BUTTON_PRESSED:
1525 show_minimap = true;
1529 show_minimap = true;
1531 case BUTTON_CLICKED:
1532 show_minimap = true;
1538 switch(le_move_up_bt->get_state())
1540 case BUTTON_PRESSED:
1542 show_minimap = true;
1546 show_minimap = true;
1548 case BUTTON_CLICKED:
1549 show_minimap = true;
1555 switch(le_move_down_bt->get_state())
1557 case BUTTON_PRESSED:
1559 show_minimap = true;
1563 show_minimap = true;
1565 case BUTTON_CLICKED:
1566 show_minimap = true;
1572 /* checking if pos_x and pos_y is within the limits... */
1575 if(pos_x > (le_world->get_level()->width * 32) - screen->w)
1576 pos_x = (le_world->get_level()->width * 32) - screen->w;
1580 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1581 pos_y = (le_world->get_level()->height * 32) - screen->h;
1587 void le_highlight_selection()
1591 if(selection.x1 < selection.x2)
1601 if(selection.y1 < selection.y2)
1617 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1620 void le_change(float x, float y, int tm, unsigned int c)
1622 if(le_world != NULL)
1628 le_level_changed = true;
1630 switch(le_selection_mode)
1633 le_world->get_level()->change(x,y,tm,c);
1635 base_type cursor_base;
1638 cursor_base.width = 32;
1639 cursor_base.height = 32;
1641 /* if there is a bad guy over there, remove it */
1642 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1643 if(rectcollision(cursor_base,(*it)->base))
1646 le_world->bad_guys.erase(it);
1647 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1653 if(selection.x1 < selection.x2)
1663 if(selection.y1 < selection.y2)
1679 /* if there is a bad guy over there, remove it */
1680 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1681 it != le_world->bad_guys.end(); /* will be at end of loop */)
1683 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1684 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1687 it = le_world->bad_guys.erase(it);
1688 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1698 for(xx = x1; xx <= x2; xx++)
1699 for(yy = y1; yy <= y2; yy++)
1701 le_world->get_level()->change(xx*32, yy*32, tm, c);
1713 //Make sure a time value is set when testing the level
1714 if(le_world->get_level()->time_left == 0)
1715 le_world->get_level()->time_left = 250;
1717 le_world->get_level()->save("test", le_level);
1719 GameSession session("test",le_level, ST_GL_TEST);
1721 player_status.reset();
1723 music_manager->halt_music();
1725 Menu::set_current(NULL);
1726 World::set_current(le_world);
1731 bool tmp_show_grid = le_show_grid;
1732 SelectionMode temp_le_selection_mode = le_selection_mode;
1733 le_selection_mode = NONE;
1734 show_selections = true;
1735 le_show_grid = false;
1736 le_help_shown = true;
1738 drawgradient(Color(0,0,0), Color(255,255,255));
1742 unsigned int i, done_;
1745 " - Supertux level editor tutorial - ",
1747 "To make your map, click the ",
1748 "tilegroup button and choose a ",
1750 "Pick a tile and simply hold down ",
1751 "the left mouse button over the map",
1752 "to \"paint\" your selection over",
1755 "There are three layers for painting",
1756 "tiles upon, Background layer,",
1757 "the Interactive layer, and the",
1758 "Foreground layer, which can be",
1759 "toggled by the BkGrd, IntAct and",
1760 "FrGrd buttons. The Foreground and",
1761 "Background layers do not effect",
1762 "Tux in the gameplay, but lie in",
1763 "front of him or lie behind him in",
1769 " - Supertux level editor tutorial - ",
1771 "The tiles placed on",
1772 "the Interactive layer are those",
1773 "which actually effect Tux in the",
1776 "Click the objects menu to put ",
1777 "bad guys and other objects in the",
1778 "game. Unlike placing tiles, you",
1779 "cannot \"paint\" enemies. Click",
1780 "them onto the screen one at a time.",
1782 "To change the settings of your",
1783 "level, click the button with the",
1784 "screwdriver and wrench. From here",
1785 "you can change the background,",
1786 "music, length of the level,",
1792 " - Supertux level editor tutorial - ",
1794 "You may have more than one level.",
1795 "Pressing the up and down buttons",
1796 "above the button bar lets you",
1797 "choose which one you are working on.",
1799 "If you would like to speed up your",
1800 "level editing, a useful trick is",
1801 "to learn the keyboard shortcuts.",
1802 "They are easy to learn, just right-",
1803 "click on the buttons.",
1805 "Have fun making levels! If you make",
1806 "some good ones, send them to us on",
1807 "the SuperTux mailing list!",
1813 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1815 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1816 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1818 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1826 done_ = wait_for_event(event);
1830 drawgradient(Color(0,0,0), Color(255,255,255));
1834 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1836 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1837 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1839 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1847 done_ = wait_for_event(event);
1851 drawgradient(Color(0,0,0), Color(255,255,255));
1855 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1857 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1858 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1860 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1868 done_ = wait_for_event(event);
1872 show_selections = true;
1873 le_show_grid = tmp_show_grid;
1874 le_selection_mode = temp_le_selection_mode;
1875 le_help_shown = false;