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>
31 #include "leveleditor.h"
44 #include "resources.h"
45 #include "music_manager.h"
46 #include "background.h"
47 #include "display_manager.h"
49 /* definitions to aid development */
51 /* definitions that affect gameplay */
52 #define KEY_CURSOR_SPEED 32
53 #define KEY_CURSOR_FASTSPEED 64
55 /* when pagedown/up pressed speed:*/
56 #define PAGE_CURSOR_SPEED 13*32
58 #define MOUSE_LEFT_MARGIN 80
59 #define MOUSE_RIGHT_MARGIN (560-32)
62 #define KEYBOARD_SPEED 140
63 #define MOUSE_SPEED 40
66 #define SELECT_W 2 // size of the selections lines
67 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
69 /* own declerations */
70 /* crutial ones (main loop) */
73 int le_load_level_subset(char *filename);
75 void le_drawinterface();
76 void le_checkevents();
77 void le_change(float x, float y, int tm, unsigned int c);
80 void le_set_defaults(void);
81 void le_activate_bad_guys(void);
82 void le_goto_level(int levelnb);
83 void le_highlight_selection();
85 void apply_level_settings_menu();
86 void update_subset_settings_menu();
87 void save_subset_settings_menu();
91 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
93 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
94 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
95 //Returns true for a tile
96 bool IsTile() { return is_tile; };
97 //Returns true for a GameObject
98 bool IsObject() { return !is_tile; };
101 void Init() { tile = 0; obj = NULL; is_tile = true; };
103 bool is_tile; //true for tile (false for object)
108 /* leveleditor internals */
109 static string_list_type level_subsets;
110 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
111 static bool show_minimap;
112 static bool show_selections;
113 static bool le_help_shown;
114 static int pos_x, pos_y, cursor_x, cursor_y;
116 static World* le_world;
117 static LevelSubset* le_level_subset;
118 static int le_show_grid;
120 static Surface* le_selection;
122 static TileOrObject le_current;
123 static bool le_mouse_pressed[2];
124 static bool le_mouse_clicked[2];
125 static Button* le_save_level_bt;
126 static Button* le_exit_bt;
127 static Button* le_test_level_bt;
128 static Button* le_next_level_bt;
129 static Button* le_previous_level_bt;
130 static Button* le_move_right_bt;
131 static Button* le_move_left_bt;
132 static Button* le_move_up_bt;
133 static Button* le_move_down_bt;
134 static Button* le_rubber_bt;
135 static Button* le_select_mode_one_bt;
136 static Button* le_select_mode_two_bt;
137 static Button* le_settings_bt;
138 static Button* le_tilegroup_bt;
139 static Button* le_objects_bt;
140 static Button* le_object_select_bt;
141 static Button* le_object_properties_bt;
142 static ButtonPanel* le_tilemap_panel;
143 static Menu* leveleditor_menu;
144 static Menu* subset_load_menu;
145 static Menu* subset_new_menu;
146 static Menu* subset_settings_menu;
147 static Menu* level_settings_menu;
148 static Menu* select_tilegroup_menu;
149 static Menu* select_objects_menu;
150 static Timer select_tilegroup_menu_effect;
151 static Timer select_objects_menu_effect;
152 static Timer display_level_info;
153 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
154 static ButtonPanelMap tilegroups_map;
155 static ButtonPanelMap objects_map;
156 static std::string cur_tilegroup;
157 static std::string cur_objects;
158 static MouseCursor* mouse_select_object;
159 static MovingObject* selected_game_object;
161 static square selection;
162 static SelectionMode le_selection_mode;
163 static SDL_Event event;
164 TileMapType active_tm;
166 int leveleditor(char* filename)
168 int last_time, now_time, i;
177 clearscreen(0, 0, 0);
180 music_manager->halt_music();
182 while (SDL_PollEvent(&event))
186 if(le_load_level_subset(filename))
191 last_time = SDL_GetTicks();
196 if(Menu::current() == select_tilegroup_menu)
198 if(select_tilegroup_menu_effect.check())
200 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
204 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
206 else if(Menu::current() == select_objects_menu)
208 if(select_objects_menu_effect.check())
210 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
213 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
218 /* making events results to be in order */
224 clearscreen(0, 0, 0);
226 /* draw editor interface */
229 Menu* menu = Menu::current();
235 if(menu == leveleditor_menu)
237 switch (leveleditor_menu->check())
239 case MNID_RETURNLEVELEDITOR:
241 Menu::set_current(0);
243 Menu::set_current(leveleditor_menu);
245 case MNID_SUBSETSETTINGS:
246 update_subset_settings_menu();
248 case MNID_QUITLEVELEDITOR:
253 else if(menu == level_settings_menu)
255 switch (level_settings_menu->check())
258 apply_level_settings_menu();
259 Menu::set_current(NULL);
266 else if(menu == select_tilegroup_menu)
269 switch (it = select_tilegroup_menu->check())
274 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
275 Menu::set_current(0);
282 else if(menu == select_objects_menu)
285 switch (it = select_objects_menu->check())
290 cur_objects = select_objects_menu->get_item_by_id(it).text;
293 Menu::set_current(0);
298 else if(menu == subset_load_menu)
300 switch (i = subset_load_menu->check())
307 if(le_load_level_subset(level_subsets.item[i-1]))
313 else if(menu == subset_new_menu)
315 if(subset_new_menu->item[2].input[0] == '\0')
316 subset_new_menu->item[3].kind = MN_DEACTIVE;
319 subset_new_menu->item[3].kind = MN_ACTION;
321 switch (i = subset_new_menu->check())
323 case MNID_CREATESUBSET:
324 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
325 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
326 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
328 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
330 Menu::set_current(subset_settings_menu);
335 else if(menu == subset_settings_menu)
337 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 )
338 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
340 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
342 switch (i = subset_settings_menu->check())
344 case MNID_SUBSETSAVECHANGES:
345 save_subset_settings_menu();
346 Menu::set_current(leveleditor_menu);
352 MouseCursor::current()->draw();
360 ++global_frame_counter;
363 now_time = SDL_GetTicks();
364 if (now_time < last_time + FPS)
365 SDL_Delay(last_time + FPS - now_time); /* delay some time */
373 int le_load_level_subset(char *filename)
375 le_level_subset->load(filename);
376 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
380 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
382 Menu::set_current(NULL);
391 leveleditor_menu = new Menu();
392 subset_load_menu = new Menu();
393 subset_new_menu = new Menu();
394 subset_settings_menu = new Menu();
395 level_settings_menu = new Menu();
396 select_tilegroup_menu = new Menu();
397 select_objects_menu = new Menu();
399 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
400 leveleditor_menu->additem(MN_HL,"",0,0);
401 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
402 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
403 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
404 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
405 leveleditor_menu->additem(MN_HL,"",0,0);
406 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
408 Menu::set_current(leveleditor_menu);
410 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
411 subset_load_menu->additem(MN_HL, "", 0, 0);
413 for(i = 0; i < level_subsets.num_items; ++i)
415 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
417 subset_load_menu->additem(MN_HL,"",0,0);
418 subset_load_menu->additem(MN_BACK,"Back",0,0);
420 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
421 subset_new_menu->additem(MN_HL,"",0,0);
422 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
423 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
424 subset_new_menu->additem(MN_HL,"",0,0);
425 subset_new_menu->additem(MN_BACK,"Back",0,0);
427 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
428 subset_settings_menu->additem(MN_HL,"",0,0);
429 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
430 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
431 subset_settings_menu->additem(MN_HL,"",0,0);
432 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
433 subset_settings_menu->additem(MN_HL,"",0,0);
434 subset_settings_menu->additem(MN_BACK,"Back",0,0);
436 level_settings_menu->arrange_left = true;
437 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
438 level_settings_menu->additem(MN_HL,"",0,0);
439 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
440 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
441 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
442 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
443 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
444 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
445 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
446 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
447 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
448 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
449 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
450 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
451 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
452 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
453 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
454 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
455 level_settings_menu->additem(MN_HL,"",0,0);
456 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
458 select_tilegroup_menu->arrange_left = true;
459 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
460 select_tilegroup_menu->additem(MN_HL,"",0,0);
461 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
463 for(std::set<TileGroup>::iterator it = tilegroups->begin();
464 it != tilegroups->end(); ++it )
466 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
468 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
471 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
472 sit != (*it).tiles.end(); ++sit, ++i)
474 std::string imagefile = "/images/tilesets/" ;
475 bool only_editor_image = false;
476 if(!TileManager::instance()->get(*sit)->filenames.empty())
478 imagefile += TileManager::instance()->get(*sit)->filenames[0];
480 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
482 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
483 only_editor_image = true;
487 imagefile += "notile.png";
489 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
491 if(!only_editor_image)
492 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
494 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
495 button->add_icon(imagefile,32,32);
497 tilegroups_map[it->name]->additem(button, *sit);
500 select_tilegroup_menu->additem(MN_HL,"",0,0);
502 select_objects_menu->arrange_left = true;
503 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
504 select_objects_menu->additem(MN_HL,"",0,0);
506 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
507 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
509 DisplayManager dummy;
510 for(int i = 0; i < NUM_BadGuyKinds; ++i)
512 BadGuy bad_tmp(dummy, BadGuyKind(i), 0, 0);
513 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
514 objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
517 objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
518 objects_map["BadGuys"]->manipulate_button(i)->get_pos().y
522 select_objects_menu->additem(MN_HL,"",0,0);
528 level_subsets = dsubdirs("/levels", "level1.stl");
529 le_level_subset = new LevelSubset;
532 selected_game_object = NULL;
536 show_selections = true;
539 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
540 le_level_changed = false;
541 le_help_shown = false;
543 le_mouse_pressed[LEFT] = false;
544 le_mouse_pressed[RIGHT] = false;
546 le_mouse_clicked[LEFT] = false;
547 le_mouse_clicked[RIGHT] = false;
549 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
551 select_tilegroup_menu_effect.init(false);
552 select_objects_menu_effect.init(false);
553 display_level_info.init(false);
556 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
557 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
558 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
559 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
560 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
561 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
562 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
563 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
564 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
565 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
566 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
567 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
568 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
569 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
570 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
571 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
572 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
573 le_object_properties_bt->set_active(false);
575 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
576 mouse_select_object->set_mid(16,16);
578 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
579 le_tilemap_panel->set_button_size(32,10);
580 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
581 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
582 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
583 le_tilemap_panel->highlight_last(true);
584 le_tilemap_panel->set_last_clicked(TM_IA);
590 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
596 void update_level_settings_menu()
601 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
602 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
604 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
605 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
606 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
607 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
608 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
609 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
611 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
612 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
613 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
614 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
615 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
616 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
618 sprintf(str,"%d",le_world->get_level()->width);
619 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
620 sprintf(str,"%d",le_world->get_level()->height);
621 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
622 sprintf(str,"%d",le_world->get_level()->time_left);
623 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
624 sprintf(str,"%2.0f",le_world->get_level()->gravity);
625 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
626 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
627 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
628 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
629 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
630 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
631 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
632 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
633 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
634 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
635 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
636 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
637 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
638 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
639 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
642 void update_subset_settings_menu()
644 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
645 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
648 void apply_level_settings_menu()
652 le_level_changed = true;
654 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
655 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
657 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
659 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
663 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
665 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
670 le_world->get_level()->load_gfx();
673 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
675 le_world->get_level()->resize(
676 atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
677 atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
678 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
679 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
680 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
681 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
682 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
683 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
684 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
685 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
686 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
689 void save_subset_settings_menu()
691 le_level_subset->title = subset_settings_menu->item[2].input;
692 le_level_subset->description = subset_settings_menu->item[3].input;
693 le_level_subset->save();
694 le_level_changed = false;
697 void le_unload_level()
704 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
705 if(confirm_dialog(str))
707 le_world->get_level()->save(le_level_subset->name.c_str(), le_level,
713 le_level_changed = false;
716 void le_goto_level(int levelnb)
719 le_world = new World(le_level_subset->name, levelnb);
720 display_level_info.start(2500);
726 SDL_EnableKeyRepeat(0, 0); // disables key repeating
730 delete leveleditor_menu;
731 delete subset_load_menu;
732 delete subset_new_menu;
733 delete subset_settings_menu;
734 delete level_settings_menu;
735 delete select_tilegroup_menu;
736 delete select_objects_menu;
737 delete le_save_level_bt;
739 delete le_test_level_bt;
740 delete le_next_level_bt;
741 delete le_previous_level_bt;
742 delete le_move_right_bt;
743 delete le_move_left_bt;
744 delete le_move_up_bt;
745 delete le_move_down_bt;
747 delete le_select_mode_one_bt;
748 delete le_select_mode_two_bt;
749 delete le_settings_bt;
750 delete le_tilegroup_bt;
751 delete le_objects_bt;
752 delete le_tilemap_panel;
753 delete le_object_select_bt;
754 delete le_object_properties_bt;
755 delete mouse_select_object;
757 delete le_level_subset;
760 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
761 i != tilegroups_map.end(); ++i)
765 for(ButtonPanelMap::iterator i = objects_map.begin();
766 i != objects_map.end(); ++i)
772 void le_drawminimap()
778 if(screen->w - 64 > le_world->get_level()->width * 4)
780 else if(screen->w - 64 > le_world->get_level()->width * 2)
784 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
786 int mini_tile_height;
787 if(screen->h - 64 > le_world->get_level()->height * 4)
788 mini_tile_height = 4;
789 else if(screen->h - 64 > le_world->get_level()->height * 2)
790 mini_tile_height = 2;
792 mini_tile_height = 1;
794 Level* level = le_world->get_level();
795 for (int y = 0; y < le_world->get_level()->height; ++y)
796 for (int x = 0; x < le_world->get_level()->width; ++x)
799 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
800 mini_tile_width , 4, level->bg_tiles[y * level->width + x]);
802 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
803 mini_tile_width , 4, level->ia_tiles[y * level->width + x]);
805 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
806 mini_tile_width , 4, level->fg_tiles[y + level->width + x]);
810 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 128);
812 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
813 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 200);
814 fillrect(left_offset + (pos_x/32)*mini_tile_width + 19*mini_tile_width - 2, 0, 2, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 200);
815 fillrect(left_offset + (pos_x/32)*mini_tile_width, le_world->get_level()->height*mini_tile_height-2, 19*mini_tile_width, 2, 200, 200, 200, 200);
819 void le_drawinterface()
826 /* draw a grid (if selected) */
829 for(x = 0; x < VISIBLE_TILES_X; x++)
830 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
831 for(y = 0; y < VISIBLE_TILES_Y; y++)
832 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
836 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
839 if(show_selections && MouseCursor::current() != mouse_select_object)
841 if(le_selection_mode == CURSOR)
843 if(le_current.IsTile())
844 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
846 else if(le_selection_mode == SQUARE)
849 le_highlight_selection();
850 /* draw current selection */
851 w = selection.x2 - selection.x1;
852 h = selection.y2 - selection.y1;
853 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
854 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
855 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
856 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
861 /* draw button bar */
862 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
864 if(le_current.IsTile())
866 Tile::draw(screen->w - 32, screen->h - 32, le_current.tile);
867 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
868 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
870 #if 0 // XXX FIXME TODO: Do we have a new solution for draw_on_screen()?
871 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
873 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
874 le_current.obj->draw_on_screen(cursor_x,cursor_y);
878 if(mouse_select_object && selected_game_object != NULL)
880 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);
881 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);
882 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);
883 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);
888 le_save_level_bt->draw();
890 le_test_level_bt->draw();
891 le_next_level_bt->draw();
892 le_previous_level_bt->draw();
893 le_rubber_bt->draw();
894 if(le_selection_mode == SQUARE)
895 le_select_mode_one_bt->draw();
896 else if(le_selection_mode == CURSOR)
897 le_select_mode_two_bt->draw();
898 le_settings_bt->draw();
899 le_move_right_bt->draw();
900 le_move_left_bt->draw();
901 le_move_up_bt->draw();
902 le_move_down_bt->draw();
903 le_tilegroup_bt->draw();
904 le_objects_bt->draw();
905 if(!cur_tilegroup.empty())
906 tilegroups_map[cur_tilegroup]->draw();
907 else if(!cur_objects.empty())
909 objects_map[cur_objects]->draw();
912 le_tilemap_panel->draw();
914 if(!cur_objects.empty())
916 le_object_select_bt->draw();
917 le_object_properties_bt->draw();
920 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
921 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
924 white_small_text->draw("F1 for Help", 10, 430, 1);
926 if(display_level_info.check())
927 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
932 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
934 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
944 /* Draw the real background */
945 le_world->background->draw(le_world->displaymanager.get_viewport(),
948 if(le_current.IsTile())
950 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
951 if(!TileManager::instance()->get(le_current.tile)->images.empty())
952 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);
954 #if 0 // XXX FIXME TODO: Do we have a new solution for move_to()?
955 if(le_current.IsObject())
957 le_current.obj->move_to(cursor_x, cursor_y);
961 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
963 Level* level = le_world->get_level();
964 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
965 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
968 if(active_tm == TM_BG)
973 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
974 level->bg_tiles[ (y + (int)(pos_y / 32)) * level->width +
975 (x + (int)(pos_x / 32))],a);
977 if(active_tm == TM_IA)
982 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
983 level->ia_tiles[ (y + (int)(pos_y / 32)) * level->width +
984 (x + (int)(pos_x / 32))],a);
987 if(active_tm == TM_FG)
992 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
993 level->fg_tiles[ (y + (int)(pos_y / 32)) * level->width +
994 (x + (int)(pos_x / 32))],a);
996 /* draw whats inside stuff when cursor is selecting those */
997 /* (draw them all the time - is this the right behaviour?) */
998 Tile* edit_image = TileManager::instance()->get(
1000 [ (y + (int)(pos_y / 32)) * level->width + (x + (int)(pos_x / 32))]);
1001 if(edit_image && !edit_image->editor_images.empty())
1002 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
1006 /* Draw the Bad guys: */
1007 for (std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1008 it != le_world->gameobjects.end(); ++it)
1010 BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
1014 /* to support frames: img_bsod_left[(frame / 5) % 4] */
1016 viewport.set_translation(Vector(pos_x, pos_y));
1017 badguy->draw(viewport, 0);
1020 /* Draw the player: */
1021 /* for now, the position is fixed at (100, 240) */
1022 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
1025 void le_change_object_properties(GameObject *pobj)
1027 Surface* cap_screen = Surface::CaptureScreen();
1028 Menu* object_properties_menu = new Menu();
1031 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
1032 object_properties_menu->additem(MN_HL,"",0,0);
1034 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1037 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1038 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1040 string_list_add_item(object_properties_menu->get_item_by_id(1).list,
1041 badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1043 object_properties_menu->get_item_by_id(1).list->active_item = i;
1045 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1048 object_properties_menu->additem(MN_HL,"",0,0);
1049 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1051 Menu::set_current(object_properties_menu);
1057 while (SDL_PollEvent(&event))
1059 object_properties_menu->event(event);
1062 cap_screen->draw(0,0);
1064 object_properties_menu->draw();
1065 object_properties_menu->action();
1067 switch (object_properties_menu->check())
1071 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1073 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1074 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1075 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1084 if(Menu::current() == NULL)
1087 mouse_cursor->draw();
1093 Menu::set_current(0);
1094 delete object_properties_menu;
1098 void le_checkevents()
1105 keymod = SDL_GetModState();
1107 while(SDL_PollEvent(&event))
1109 if (Menu::current())
1111 Menu::current()->event(event);
1112 if(!le_world && !Menu::current())
1113 Menu::set_current(leveleditor_menu);
1117 mouse_cursor->set_state(MC_NORMAL);
1119 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1120 if(event.type == SDL_KEYDOWN
1121 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1122 && (event.motion.x > 0
1123 && event.motion.x < screen->w - 64 &&
1124 event.motion.y > 0 && event.motion.y < screen->h)))
1128 case SDL_KEYDOWN: // key pressed
1129 key = event.key.keysym.sym;
1133 Menu::set_current(leveleditor_menu);
1136 if(le_world != NULL)
1144 cursor_x = (le_world->get_level()->width * 32) - 32;
1148 le_show_grid = !le_show_grid;
1154 case SDL_MOUSEBUTTONDOWN:
1155 if(event.button.button == SDL_BUTTON_LEFT)
1157 le_mouse_pressed[LEFT] = true;
1159 selection.x1 = event.motion.x + pos_x;
1160 selection.y1 = event.motion.y + pos_y;
1161 selection.x2 = event.motion.x + pos_x;
1162 selection.y2 = event.motion.y + pos_y;
1164 else if(event.button.button == SDL_BUTTON_RIGHT)
1166 le_mouse_pressed[RIGHT] = true;
1169 case SDL_MOUSEBUTTONUP:
1170 if(event.button.button == SDL_BUTTON_LEFT)
1172 le_mouse_pressed[LEFT] = false;
1173 le_mouse_clicked[LEFT] = true;
1175 else if(event.button.button == SDL_BUTTON_RIGHT)
1177 le_mouse_pressed[RIGHT] = false;
1178 le_mouse_clicked[RIGHT] = true;
1181 case SDL_MOUSEMOTION:
1183 if(!Menu::current())
1188 if(le_current.IsTile())
1190 cursor_x = ((int)(pos_x + x) / 32) * 32;
1191 cursor_y = ((int)(pos_y + y) / 32) * 32;
1199 if(le_mouse_pressed[LEFT])
1201 selection.x2 = x + pos_x;
1202 selection.y2 = y + pos_y;
1205 if(le_mouse_pressed[RIGHT])
1207 pos_x += -1 * event.motion.xrel;
1208 pos_y += -1 * event.motion.yrel;
1216 else if(event.type == SDL_QUIT) /* window closing */
1222 if(le_world != NULL)
1224 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 &&
1225 event.motion.y > 0 && event.motion.y < screen->h)))
1227 le_mouse_pressed[LEFT] = false;
1228 le_mouse_pressed[RIGHT] = false;
1230 if(!Menu::current())
1232 /* Check for button events */
1233 le_test_level_bt->event(event);
1234 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1236 le_save_level_bt->event(event);
1237 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1238 le_world->get_level()->save(le_level_subset->name.c_str(),le_level,
1240 le_exit_bt->event(event);
1241 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1243 Menu::set_current(leveleditor_menu);
1245 le_next_level_bt->event(event);
1246 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1248 if(le_level < le_level_subset->levels)
1250 le_goto_level(le_level+1);
1256 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1257 if(confirm_dialog(str))
1259 new_lev.init_defaults();
1260 new_lev.save(le_level_subset->name.c_str(),le_level+1, le_world);
1261 le_level_subset->levels = le_level;
1262 le_goto_level(le_level);
1266 le_previous_level_bt->event(event);
1267 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1270 le_goto_level(le_level -1);
1272 le_rubber_bt->event(event);
1273 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1276 if(!cur_objects.empty())
1278 le_object_select_bt->event(event);
1279 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1281 MouseCursor::set_current(mouse_select_object);
1284 le_object_properties_bt->event(event);
1285 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1287 le_change_object_properties(selected_game_object);
1292 if(le_selection_mode == SQUARE)
1294 le_select_mode_one_bt->event(event);
1295 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1296 le_selection_mode = CURSOR;
1300 le_select_mode_two_bt->event(event);
1301 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1302 le_selection_mode = SQUARE;
1304 ButtonPanelMap::iterator it;
1305 le_tilegroup_bt->event(event);
1306 switch (le_tilegroup_bt->get_state())
1308 case BUTTON_CLICKED:
1309 Menu::set_current(select_tilegroup_menu);
1310 select_tilegroup_menu_effect.start(200);
1311 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1313 case BUTTON_WHEELUP:
1314 if(cur_tilegroup.empty())
1316 cur_tilegroup = tilegroups_map.begin()->first;
1320 it = tilegroups_map.find(cur_tilegroup);
1321 if((++it) == tilegroups_map.end())
1323 cur_tilegroup = tilegroups_map.begin()->first;
1327 cur_tilegroup = (*it).first;
1333 case BUTTON_WHEELDOWN:
1334 it = tilegroups_map.find(cur_tilegroup);
1335 if(it == tilegroups_map.begin())
1337 cur_tilegroup = tilegroups_map.rbegin()->first;
1341 if(--it != --tilegroups_map.begin())
1342 cur_tilegroup = (*it).first;
1344 cur_tilegroup = tilegroups_map.rbegin()->first;
1352 le_objects_bt->event(event);
1353 switch (le_objects_bt->get_state())
1355 case BUTTON_CLICKED:
1356 Menu::set_current(select_objects_menu);
1357 select_objects_menu_effect.start(200);
1358 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1360 case BUTTON_WHEELUP:
1361 it = objects_map.find(cur_objects);
1362 if(it == objects_map.end())
1364 cur_objects = objects_map.begin()->first;
1368 if(++it != objects_map.end())
1369 cur_objects = (*it).first;
1371 cur_objects = objects_map.begin()->first;
1375 case BUTTON_WHEELDOWN:
1376 it = objects_map.find(cur_objects);
1377 if(it == objects_map.begin())
1379 cur_objects = objects_map.rbegin()->first;
1383 if(--it != --objects_map.begin())
1384 cur_objects = (*it).first;
1386 cur_objects = objects_map.rbegin()->first;
1395 le_settings_bt->event(event);
1396 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1398 update_level_settings_menu();
1399 Menu::set_current(level_settings_menu);
1401 if(!cur_tilegroup.empty())
1403 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1405 if(pbutton->get_state() == BUTTON_CLICKED)
1407 le_current.Tile(pbutton->get_tag());
1411 else if(!cur_objects.empty())
1413 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1415 if(pbutton->get_state() == BUTTON_CLICKED)
1417 #if 0 // TODO FIXME XXX: New solution for this?
1418 le_current.Object(pbutton->get_drawable());
1424 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1426 if(pbutton->get_state() == BUTTON_CLICKED)
1428 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1434 le_settings_bt->event(event);
1435 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1437 Menu::set_current(0);
1439 le_tilegroup_bt->event(event);
1440 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1442 Menu::set_current(0);
1444 le_objects_bt->event(event);
1445 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1447 Menu::set_current(0);
1452 if(!Menu::current() && !show_minimap)
1454 if(le_mouse_pressed[LEFT])
1456 if(MouseCursor::current() != mouse_select_object)
1458 if(le_current.IsTile())
1459 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1462 else if(le_mouse_clicked[LEFT])
1464 if(MouseCursor::current() == mouse_select_object)
1466 bool object_got_hit = false;
1467 base_type cursor_base;
1468 if(le_current.IsTile())
1470 cursor_base.x = cursor_x;
1471 cursor_base.y = cursor_y;
1473 else if(le_current.IsObject())
1475 cursor_base.x = cursor_x + pos_x;
1476 cursor_base.y = cursor_y + pos_y;
1478 cursor_base.width = 32;
1479 cursor_base.height = 32;
1481 for(std::vector<GameObject*>::iterator it =
1482 le_world->gameobjects.begin();
1483 it != le_world->gameobjects.end(); ++it) {
1484 MovingObject* mobj = dynamic_cast<MovingObject*> (*it);
1488 if(rectcollision(cursor_base, mobj->base))
1490 selected_game_object = mobj;
1491 object_got_hit = true;
1498 selected_game_object = NULL;
1499 le_object_properties_bt->set_active(false);
1502 le_object_properties_bt->set_active(true);
1504 MouseCursor::set_current(mouse_cursor);
1510 if(le_current.IsObject())
1512 le_level_changed = true;
1513 std::string type = le_current.obj->type();
1515 if(type == "BadGuy")
1517 ViewPort viewport(le_world->displaymanager.get_viewport());
1518 DisplayManager dummy;
1519 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1521 le_world->bad_guys.push_back(new BadGuy(dummy, pbadguy->kind, cursor_x + viewport.get_translation().x, cursor_y + viewport.get_translation().y));
1522 le_world->gameobjects.push_back(le_world->bad_guys.back());
1528 le_mouse_clicked[LEFT] = false;
1534 if(!Menu::current())
1536 show_minimap = false;
1538 le_move_left_bt->event(event);
1539 le_move_right_bt->event(event);
1540 le_move_up_bt->event(event);
1541 le_move_down_bt->event(event);
1542 switch(le_move_left_bt->get_state())
1544 case BUTTON_PRESSED:
1545 pos_x -= KEYBOARD_SPEED;
1546 show_minimap = true;
1549 pos_x -= MOUSE_SPEED;
1550 show_minimap = true;
1552 case BUTTON_CLICKED:
1553 show_minimap = true;
1559 switch(le_move_right_bt->get_state())
1561 case BUTTON_PRESSED:
1562 pos_x += KEYBOARD_SPEED;
1563 show_minimap = true;
1566 pos_x += MOUSE_SPEED;
1567 show_minimap = true;
1569 case BUTTON_CLICKED:
1570 show_minimap = true;
1576 switch(le_move_up_bt->get_state())
1578 case BUTTON_PRESSED:
1579 pos_y -= KEYBOARD_SPEED;
1580 show_minimap = true;
1583 pos_y -= MOUSE_SPEED;
1584 show_minimap = true;
1586 case BUTTON_CLICKED:
1587 show_minimap = true;
1593 switch(le_move_down_bt->get_state())
1595 case BUTTON_PRESSED:
1596 pos_y += KEYBOARD_SPEED;
1597 show_minimap = true;
1600 pos_y += MOUSE_SPEED;
1601 show_minimap = true;
1603 case BUTTON_CLICKED:
1604 show_minimap = true;
1610 /* checking if pos_x and pos_y is within the limits... */
1611 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1612 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1616 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1617 pos_y = (le_world->get_level()->height * 32) - screen->h;
1625 void le_highlight_selection()
1629 if(selection.x1 < selection.x2)
1639 if(selection.y1 < selection.y2)
1655 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1658 void le_change(float x, float y, int tm, unsigned int c)
1660 if(le_world != NULL)
1665 le_level_changed = true;
1667 switch(le_selection_mode)
1670 le_world->get_level()->change(x,y,tm,c);
1672 base_type cursor_base;
1675 cursor_base.width = 32;
1676 cursor_base.height = 32;
1678 /* if there is a bad guy over there, remove it */
1680 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1681 it != le_world->gameobjects.end(); ++it)
1682 if ((*it)->type() == "BadGuy")
1684 BadGuy* pbadguy = dynamic_cast<BadGuy*>((*it));
1685 if(rectcollision(cursor_base, pbadguy->base))
1688 //le_world->bad_guys.erase(it);
1689 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1696 if(selection.x1 < selection.x2)
1706 if(selection.y1 < selection.y2)
1722 /* if there is a bad guy over there, remove it */
1724 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1725 it != le_world->gameobjects.end(); ++it /* will be at end of loop */)
1727 if ((*it)->type() == "BadGuy")
1729 MovingObject* pmobject = dynamic_cast<MovingObject*> (*it);
1730 if(pmobject->base.x/32 >= x1 && pmobject->base.x/32 <= x2
1731 && pmobject->base.y/32 >= y1 && pmobject->base.y/32 <= y2)
1734 //it = le_world->gameobjects.erase(it);
1735 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1745 for(xx = x1; xx <= x2; xx++)
1746 for(yy = y1; yy <= y2; yy++)
1748 le_world->get_level()->change(xx*32, yy*32, tm, c);
1760 //Make sure a time value is set when testing the level
1761 if(le_world->get_level()->time_left == 0)
1762 le_world->get_level()->time_left = 250;
1764 le_world->get_level()->save("test", le_level, le_world);
1766 GameSession session("test",le_level, ST_GL_TEST);
1768 player_status.reset();
1770 music_manager->halt_music();
1772 Menu::set_current(NULL);
1773 World::set_current(le_world);
1778 bool tmp_show_grid = le_show_grid;
1779 SelectionMode temp_le_selection_mode = le_selection_mode;
1780 le_selection_mode = NONE;
1781 show_selections = true;
1782 le_show_grid = false;
1783 le_help_shown = true;
1785 drawgradient(Color(0,0,0), Color(255,255,255));
1789 unsigned int i, done_;
1792 " - Supertux level editor tutorial - ",
1794 "To make your map, click the ",
1795 "tilegroup button and choose a ",
1797 "Pick a tile and simply hold down ",
1798 "the left mouse button over the map",
1799 "to \"paint\" your selection over",
1802 "There are three layers for painting",
1803 "tiles upon, Background layer,",
1804 "the Interactive layer, and the",
1805 "Foreground layer, which can be",
1806 "toggled by the BkGrd, IntAct and",
1807 "FrGrd buttons. The Foreground and",
1808 "Background layers do not effect",
1809 "Tux in the gameplay, but lie in",
1810 "front of him or lie behind him in",
1816 " - Supertux level editor tutorial - ",
1818 "The tiles placed on",
1819 "the Interactive layer are those",
1820 "which actually effect Tux in the",
1823 "Click the objects menu to put ",
1824 "bad guys and other objects in the",
1825 "game. Unlike placing tiles, you",
1826 "cannot \"paint\" enemies. Click",
1827 "them onto the screen one at a time.",
1829 "To change the settings of your",
1830 "level, click the button with the",
1831 "screwdriver and wrench. From here",
1832 "you can change the background,",
1833 "music, length of the level,",
1839 " - Supertux level editor tutorial - ",
1841 "You may have more than one level.",
1842 "Pressing the up and down buttons",
1843 "above the button bar lets you",
1844 "choose which one you are working on.",
1846 "If you would like to speed up your",
1847 "level editing, a useful trick is",
1848 "to learn the keyboard shortcuts.",
1849 "They are easy to learn, just right-",
1850 "click on the buttons.",
1852 "Have fun making levels! If you make",
1853 "some good ones, send them to us on",
1854 "the SuperTux mailing list!",
1860 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1862 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1863 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1865 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1873 done_ = wait_for_event(event);
1877 drawgradient(Color(0,0,0), Color(255,255,255));
1881 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1883 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1884 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1886 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1894 done_ = wait_for_event(event);
1898 drawgradient(Color(0,0,0), Color(255,255,255));
1902 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1904 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1905 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1907 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1915 done_ = wait_for_event(event);
1919 show_selections = true;
1920 le_show_grid = tmp_show_grid;
1921 le_selection_mode = temp_le_selection_mode;
1922 le_help_shown = false;