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"
45 #include "display_manager.h"
47 /* definitions to aid development */
49 /* definitions that affect gameplay */
50 #define KEY_CURSOR_SPEED 32
51 #define KEY_CURSOR_FASTSPEED 64
53 /* when pagedown/up pressed speed:*/
54 #define PAGE_CURSOR_SPEED 13*32
56 #define MOUSE_LEFT_MARGIN 80
57 #define MOUSE_RIGHT_MARGIN (560-32)
60 #define KEYBOARD_SPEED 140
61 #define MOUSE_SPEED 40
64 #define SELECT_W 2 // size of the selections lines
65 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
67 /* own declerations */
68 /* crutial ones (main loop) */
71 int le_load_level_subset(char *filename);
73 void le_drawinterface();
74 void le_checkevents();
75 void le_change(float x, float y, int tm, unsigned int c);
78 void le_set_defaults(void);
79 void le_activate_bad_guys(void);
80 void le_goto_level(int levelnb);
81 void le_highlight_selection();
83 void apply_level_settings_menu();
84 void update_subset_settings_menu();
85 void save_subset_settings_menu();
89 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
91 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
92 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
93 //Returns true for a tile
94 bool IsTile() { return is_tile; };
95 //Returns true for a GameObject
96 bool IsObject() { return !is_tile; };
99 void Init() { tile = 0; obj = NULL; is_tile = true; };
101 bool is_tile; //true for tile (false for object)
106 /* leveleditor internals */
107 static string_list_type level_subsets;
108 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
109 static bool show_minimap;
110 static bool show_selections;
111 static bool le_help_shown;
112 static int pos_x, pos_y, cursor_x, cursor_y;
114 static World* le_world;
115 static LevelSubset* le_level_subset;
116 static int le_show_grid;
118 static Surface* le_selection;
120 static TileOrObject le_current;
121 static bool le_mouse_pressed[2];
122 static bool le_mouse_clicked[2];
123 static Button* le_save_level_bt;
124 static Button* le_exit_bt;
125 static Button* le_test_level_bt;
126 static Button* le_next_level_bt;
127 static Button* le_previous_level_bt;
128 static Button* le_move_right_bt;
129 static Button* le_move_left_bt;
130 static Button* le_move_up_bt;
131 static Button* le_move_down_bt;
132 static Button* le_rubber_bt;
133 static Button* le_select_mode_one_bt;
134 static Button* le_select_mode_two_bt;
135 static Button* le_settings_bt;
136 static Button* le_tilegroup_bt;
137 static Button* le_objects_bt;
138 static Button* le_object_select_bt;
139 static Button* le_object_properties_bt;
140 static ButtonPanel* le_tilemap_panel;
141 static Menu* leveleditor_menu;
142 static Menu* subset_load_menu;
143 static Menu* subset_new_menu;
144 static Menu* subset_settings_menu;
145 static Menu* level_settings_menu;
146 static Menu* select_tilegroup_menu;
147 static Menu* select_objects_menu;
148 static Timer select_tilegroup_menu_effect;
149 static Timer select_objects_menu_effect;
150 static Timer display_level_info;
151 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
152 static ButtonPanelMap tilegroups_map;
153 static ButtonPanelMap objects_map;
154 static std::string cur_tilegroup;
155 static std::string cur_objects;
156 static MouseCursor* mouse_select_object;
157 static MovingObject* selected_game_object;
159 static square selection;
160 static SelectionMode le_selection_mode;
161 static SDL_Event event;
162 TileMapType active_tm;
164 int leveleditor(char* filename)
166 int last_time, now_time, i;
175 clearscreen(0, 0, 0);
178 music_manager->halt_music();
180 while (SDL_PollEvent(&event))
184 if(le_load_level_subset(filename))
189 last_time = SDL_GetTicks();
194 if(Menu::current() == select_tilegroup_menu)
196 if(select_tilegroup_menu_effect.check())
198 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
202 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
204 else if(Menu::current() == select_objects_menu)
206 if(select_objects_menu_effect.check())
208 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
211 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
216 /* making events results to be in order */
222 clearscreen(0, 0, 0);
224 /* draw editor interface */
227 Menu* menu = Menu::current();
233 if(menu == leveleditor_menu)
235 switch (leveleditor_menu->check())
237 case MNID_RETURNLEVELEDITOR:
239 Menu::set_current(0);
241 Menu::set_current(leveleditor_menu);
243 case MNID_SUBSETSETTINGS:
244 update_subset_settings_menu();
246 case MNID_QUITLEVELEDITOR:
251 else if(menu == level_settings_menu)
253 switch (level_settings_menu->check())
256 apply_level_settings_menu();
257 Menu::set_current(NULL);
264 else if(menu == select_tilegroup_menu)
267 switch (it = select_tilegroup_menu->check())
272 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
273 Menu::set_current(0);
280 else if(menu == select_objects_menu)
283 switch (it = select_objects_menu->check())
288 cur_objects = select_objects_menu->get_item_by_id(it).text;
291 Menu::set_current(0);
296 else if(menu == subset_load_menu)
298 switch (i = subset_load_menu->check())
305 if(le_load_level_subset(level_subsets.item[i-1]))
311 else if(menu == subset_new_menu)
313 if(subset_new_menu->item[2].input[0] == '\0')
314 subset_new_menu->item[3].kind = MN_DEACTIVE;
317 subset_new_menu->item[3].kind = MN_ACTION;
319 switch (i = subset_new_menu->check())
321 case MNID_CREATESUBSET:
322 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
323 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
324 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
326 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
328 Menu::set_current(subset_settings_menu);
333 else if(menu == subset_settings_menu)
335 if(le_level_subset->title.compare(subset_settings_menu->get_item_by_id(MNID_SUBSETTITLE).input) == 0 && le_level_subset->description.compare(subset_settings_menu->get_item_by_id(MNID_SUBSETDESCRIPTION).input) == 0 )
336 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
338 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
340 switch (i = subset_settings_menu->check())
342 case MNID_SUBSETSAVECHANGES:
343 save_subset_settings_menu();
344 Menu::set_current(leveleditor_menu);
350 MouseCursor::current()->draw();
358 ++global_frame_counter;
361 now_time = SDL_GetTicks();
362 if (now_time < last_time + FPS)
363 SDL_Delay(last_time + FPS - now_time); /* delay some time */
371 int le_load_level_subset(char *filename)
373 le_level_subset->load(filename);
374 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
378 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
380 Menu::set_current(NULL);
389 leveleditor_menu = new Menu();
390 subset_load_menu = new Menu();
391 subset_new_menu = new Menu();
392 subset_settings_menu = new Menu();
393 level_settings_menu = new Menu();
394 select_tilegroup_menu = new Menu();
395 select_objects_menu = new Menu();
397 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
398 leveleditor_menu->additem(MN_HL,"",0,0);
399 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
400 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
401 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
402 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
403 leveleditor_menu->additem(MN_HL,"",0,0);
404 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
406 Menu::set_current(leveleditor_menu);
408 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
409 subset_load_menu->additem(MN_HL, "", 0, 0);
411 for(i = 0; i < level_subsets.num_items; ++i)
413 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
415 subset_load_menu->additem(MN_HL,"",0,0);
416 subset_load_menu->additem(MN_BACK,"Back",0,0);
418 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
419 subset_new_menu->additem(MN_HL,"",0,0);
420 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
421 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
422 subset_new_menu->additem(MN_HL,"",0,0);
423 subset_new_menu->additem(MN_BACK,"Back",0,0);
425 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
426 subset_settings_menu->additem(MN_HL,"",0,0);
427 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
428 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
429 subset_settings_menu->additem(MN_HL,"",0,0);
430 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
431 subset_settings_menu->additem(MN_HL,"",0,0);
432 subset_settings_menu->additem(MN_BACK,"Back",0,0);
434 level_settings_menu->arrange_left = true;
435 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
436 level_settings_menu->additem(MN_HL,"",0,0);
437 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
438 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
439 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
440 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
441 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
442 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
443 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
444 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
445 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
446 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
447 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
448 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
449 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
450 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
451 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
452 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
453 level_settings_menu->additem(MN_HL,"",0,0);
454 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
456 select_tilegroup_menu->arrange_left = true;
457 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
458 select_tilegroup_menu->additem(MN_HL,"",0,0);
459 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
461 for(std::set<TileGroup>::iterator it = tilegroups->begin();
462 it != tilegroups->end(); ++it )
464 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
466 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
469 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
470 sit != (*it).tiles.end(); ++sit, ++i)
472 std::string imagefile = "/images/tilesets/" ;
473 bool only_editor_image = false;
474 if(!TileManager::instance()->get(*sit)->filenames.empty())
476 imagefile += TileManager::instance()->get(*sit)->filenames[0];
478 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
480 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
481 only_editor_image = true;
485 imagefile += "notile.png";
487 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
489 if(!only_editor_image)
490 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
492 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
493 button->add_icon(imagefile,32,32);
495 tilegroups_map[it->name]->additem(button, *sit);
498 select_tilegroup_menu->additem(MN_HL,"",0,0);
500 select_objects_menu->arrange_left = true;
501 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
502 select_objects_menu->additem(MN_HL,"",0,0);
505 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
506 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
508 DisplayManager dummy;
509 for(int i = 0; i < NUM_BadGuyKinds; ++i)
511 BadGuy bad_tmp(dummy, 0,0,BadGuyKind(i),false);
512 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
513 objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
515 objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
516 objects_map["BadGuys"]->manipulate_button(i)->get_pos().y,
517 BadGuyKind(i), false));
521 select_objects_menu->additem(MN_HL,"",0,0);
529 level_subsets = dsubdirs("/levels", "level1.stl");
530 le_level_subset = new LevelSubset;
533 selected_game_object = NULL;
537 show_selections = true;
541 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
542 le_level_changed = false;
543 le_help_shown = false;
545 le_mouse_pressed[LEFT] = false;
546 le_mouse_pressed[RIGHT] = false;
548 le_mouse_clicked[LEFT] = false;
549 le_mouse_clicked[RIGHT] = false;
551 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
553 select_tilegroup_menu_effect.init(false);
554 select_objects_menu_effect.init(false);
555 display_level_info.init(false);
558 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
559 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
560 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
561 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
562 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
563 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
564 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
565 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
566 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
567 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
568 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
569 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
570 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
571 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
572 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
573 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
574 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
575 le_object_properties_bt->set_active(false);
577 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
578 mouse_select_object->set_mid(16,16);
580 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
581 le_tilemap_panel->set_button_size(32,10);
582 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
583 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
584 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
585 le_tilemap_panel->highlight_last(true);
586 le_tilemap_panel->set_last_clicked(TM_IA);
592 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
598 void update_level_settings_menu()
603 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
604 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
606 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
607 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
608 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
609 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
610 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
611 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
613 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
614 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
615 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
616 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
617 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
618 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
620 sprintf(str,"%d",le_world->get_level()->width);
621 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
622 sprintf(str,"%d",le_world->get_level()->height);
623 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
624 sprintf(str,"%d",le_world->get_level()->time_left);
625 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
626 sprintf(str,"%2.0f",le_world->get_level()->gravity);
627 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
628 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
629 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
630 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
631 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
632 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
633 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
634 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
635 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
636 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
637 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
638 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
639 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
640 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
641 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
644 void update_subset_settings_menu()
646 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
647 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
650 void apply_level_settings_menu()
654 le_level_changed = true;
656 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
657 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
659 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
661 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
665 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
667 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
672 le_world->get_level()->load_gfx();
675 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
677 le_world->get_level()->resize(
678 atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
679 atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
680 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
681 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
682 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
683 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
684 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
685 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
686 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
687 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
688 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
691 void save_subset_settings_menu()
693 le_level_subset->title = subset_settings_menu->item[2].input;
694 le_level_subset->description = subset_settings_menu->item[3].input;
695 le_level_subset->save();
696 le_level_changed = false;
699 void le_unload_level()
706 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
707 if(confirm_dialog(str))
709 le_world->get_level()->save(le_level_subset->name.c_str(), le_level,
715 le_level_changed = false;
718 void le_goto_level(int levelnb)
721 le_world = new World(le_level_subset->name, levelnb);
722 display_level_info.start(2500);
728 SDL_EnableKeyRepeat(0, 0); // disables key repeating
732 delete leveleditor_menu;
733 delete subset_load_menu;
734 delete subset_new_menu;
735 delete subset_settings_menu;
736 delete level_settings_menu;
737 delete select_tilegroup_menu;
738 delete select_objects_menu;
739 delete le_save_level_bt;
741 delete le_test_level_bt;
742 delete le_next_level_bt;
743 delete le_previous_level_bt;
744 delete le_move_right_bt;
745 delete le_move_left_bt;
746 delete le_move_up_bt;
747 delete le_move_down_bt;
749 delete le_select_mode_one_bt;
750 delete le_select_mode_two_bt;
751 delete le_settings_bt;
752 delete le_tilegroup_bt;
753 delete le_objects_bt;
754 delete le_tilemap_panel;
755 delete le_object_select_bt;
756 delete le_object_properties_bt;
757 delete mouse_select_object;
759 delete le_level_subset;
762 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
763 i != tilegroups_map.end(); ++i)
767 for(ButtonPanelMap::iterator i = objects_map.begin();
768 i != objects_map.end(); ++i)
774 void le_drawminimap()
780 if(screen->w - 64 > le_world->get_level()->width * 4)
782 else if(screen->w - 64 > le_world->get_level()->width * 2)
786 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
788 int mini_tile_height;
789 if(screen->h - 64 > le_world->get_level()->height * 4)
790 mini_tile_height = 4;
791 else if(screen->h - 64 > le_world->get_level()->height * 2)
792 mini_tile_height = 2;
794 mini_tile_height = 1;
796 Level* level = le_world->get_level();
797 for (int y = 0; y < le_world->get_level()->height; ++y)
798 for (int x = 0; x < le_world->get_level()->width; ++x)
801 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
802 mini_tile_width , 4, level->bg_tiles[y * level->width + x]);
804 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
805 mini_tile_width , 4, level->ia_tiles[y * level->width + x]);
807 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
808 mini_tile_width , 4, level->fg_tiles[y + level->width + x]);
812 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 128);
814 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
815 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 200);
816 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);
817 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);
821 void le_drawinterface()
828 /* draw a grid (if selected) */
831 for(x = 0; x < VISIBLE_TILES_X; x++)
832 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
833 for(y = 0; y < VISIBLE_TILES_Y; y++)
834 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
838 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
841 if(show_selections && MouseCursor::current() != mouse_select_object)
843 if(le_selection_mode == CURSOR)
845 if(le_current.IsTile())
846 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
848 else if(le_selection_mode == SQUARE)
851 le_highlight_selection();
852 /* draw current selection */
853 w = selection.x2 - selection.x1;
854 h = selection.y2 - selection.y1;
855 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
856 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
857 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
858 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
863 /* draw button bar */
864 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
866 if(le_current.IsTile())
868 Tile::draw(screen->w - 32, screen->h - 32, le_current.tile);
869 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
870 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
872 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
874 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
875 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->get_level()->draw_bg();
947 if(le_current.IsTile())
949 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
950 if(!TileManager::instance()->get(le_current.tile)->images.empty())
951 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);
953 if(le_current.IsObject())
955 le_current.obj->move_to(cursor_x, cursor_y);
958 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
960 Level* level = le_world->get_level();
961 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
962 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
965 if(active_tm == TM_BG)
970 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
971 level->bg_tiles[ (y + (int)(pos_y / 32)) * level->width +
972 (x + (int)(pos_x / 32))],a);
974 if(active_tm == TM_IA)
979 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
980 level->ia_tiles[ (y + (int)(pos_y / 32)) * level->width +
981 (x + (int)(pos_x / 32))],a);
984 if(active_tm == TM_FG)
989 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
990 level->fg_tiles[ (y + (int)(pos_y / 32)) * level->width +
991 (x + (int)(pos_x / 32))],a);
993 /* draw whats inside stuff when cursor is selecting those */
994 /* (draw them all the time - is this the right behaviour?) */
995 Tile* edit_image = TileManager::instance()->get(
997 [ (y + (int)(pos_y / 32)) * level->width + (x + (int)(pos_x / 32))]);
998 if(edit_image && !edit_image->editor_images.empty())
999 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
1003 /* Draw the Bad guys: */
1004 for (std::vector<_GameObject*>::iterator it = le_world->gameobjects.begin();
1005 it != le_world->gameobjects.end(); ++it)
1007 BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
1011 /* to support frames: img_bsod_left[(frame / 5) % 4] */
1013 viewport.set_translation(Vector(pos_x, pos_y));
1014 badguy->draw(viewport, 0);
1017 /* Draw the player: */
1018 /* for now, the position is fixed at (100, 240) */
1019 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
1022 void le_change_object_properties(_GameObject *pobj)
1024 Surface* cap_screen = Surface::CaptureScreen();
1025 Menu* object_properties_menu = new Menu();
1028 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
1029 object_properties_menu->additem(MN_HL,"",0,0);
1031 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1034 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1035 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1037 string_list_add_item(object_properties_menu->get_item_by_id(1).list,
1038 badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1040 object_properties_menu->get_item_by_id(1).list->active_item = i;
1042 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1045 object_properties_menu->additem(MN_HL,"",0,0);
1046 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1048 Menu::set_current(object_properties_menu);
1054 while (SDL_PollEvent(&event))
1056 object_properties_menu->event(event);
1059 cap_screen->draw(0,0);
1061 object_properties_menu->draw();
1062 object_properties_menu->action();
1064 switch (object_properties_menu->check())
1068 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1070 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1071 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1072 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1081 if(Menu::current() == NULL)
1084 mouse_cursor->draw();
1090 Menu::set_current(0);
1091 delete object_properties_menu;
1095 void le_checkevents()
1102 keymod = SDL_GetModState();
1104 while(SDL_PollEvent(&event))
1106 if (Menu::current())
1108 Menu::current()->event(event);
1109 if(!le_world && !Menu::current())
1110 Menu::set_current(leveleditor_menu);
1114 mouse_cursor->set_state(MC_NORMAL);
1116 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1117 if(event.type == SDL_KEYDOWN
1118 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1119 && (event.motion.x > 0
1120 && event.motion.x < screen->w - 64 &&
1121 event.motion.y > 0 && event.motion.y < screen->h)))
1125 case SDL_KEYDOWN: // key pressed
1126 key = event.key.keysym.sym;
1130 Menu::set_current(leveleditor_menu);
1133 if(le_world != NULL)
1141 cursor_x = (le_world->get_level()->width * 32) - 32;
1145 le_show_grid = !le_show_grid;
1151 case SDL_MOUSEBUTTONDOWN:
1152 if(event.button.button == SDL_BUTTON_LEFT)
1154 le_mouse_pressed[LEFT] = true;
1156 selection.x1 = event.motion.x + pos_x;
1157 selection.y1 = event.motion.y + pos_y;
1158 selection.x2 = event.motion.x + pos_x;
1159 selection.y2 = event.motion.y + pos_y;
1161 else if(event.button.button == SDL_BUTTON_RIGHT)
1163 le_mouse_pressed[RIGHT] = true;
1166 case SDL_MOUSEBUTTONUP:
1167 if(event.button.button == SDL_BUTTON_LEFT)
1169 le_mouse_pressed[LEFT] = false;
1170 le_mouse_clicked[LEFT] = true;
1172 else if(event.button.button == SDL_BUTTON_RIGHT)
1174 le_mouse_pressed[RIGHT] = false;
1175 le_mouse_clicked[RIGHT] = true;
1178 case SDL_MOUSEMOTION:
1180 if(!Menu::current())
1185 if(le_current.IsTile())
1187 cursor_x = ((int)(pos_x + x) / 32) * 32;
1188 cursor_y = ((int)(pos_y + y) / 32) * 32;
1196 if(le_mouse_pressed[LEFT])
1198 selection.x2 = x + pos_x;
1199 selection.y2 = y + pos_y;
1202 if(le_mouse_pressed[RIGHT])
1204 pos_x += -1 * event.motion.xrel;
1205 pos_y += -1 * event.motion.yrel;
1213 else if(event.type == SDL_QUIT) /* window closing */
1219 if(le_world != NULL)
1221 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 &&
1222 event.motion.y > 0 && event.motion.y < screen->h)))
1224 le_mouse_pressed[LEFT] = false;
1225 le_mouse_pressed[RIGHT] = false;
1227 if(!Menu::current())
1229 /* Check for button events */
1230 le_test_level_bt->event(event);
1231 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1233 le_save_level_bt->event(event);
1234 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1235 le_world->get_level()->save(le_level_subset->name.c_str(),le_level,
1237 le_exit_bt->event(event);
1238 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1240 Menu::set_current(leveleditor_menu);
1242 le_next_level_bt->event(event);
1243 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1245 if(le_level < le_level_subset->levels)
1247 le_goto_level(le_level+1);
1253 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1254 if(confirm_dialog(str))
1256 new_lev.init_defaults();
1257 new_lev.save(le_level_subset->name.c_str(),le_level+1, le_world);
1258 le_level_subset->levels = le_level;
1259 le_goto_level(le_level);
1263 le_previous_level_bt->event(event);
1264 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1267 le_goto_level(le_level -1);
1269 le_rubber_bt->event(event);
1270 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1273 if(!cur_objects.empty())
1275 le_object_select_bt->event(event);
1276 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1278 MouseCursor::set_current(mouse_select_object);
1281 le_object_properties_bt->event(event);
1282 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1284 le_change_object_properties(selected_game_object);
1289 if(le_selection_mode == SQUARE)
1291 le_select_mode_one_bt->event(event);
1292 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1293 le_selection_mode = CURSOR;
1297 le_select_mode_two_bt->event(event);
1298 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1299 le_selection_mode = SQUARE;
1301 ButtonPanelMap::iterator it;
1302 le_tilegroup_bt->event(event);
1303 switch (le_tilegroup_bt->get_state())
1305 case BUTTON_CLICKED:
1306 Menu::set_current(select_tilegroup_menu);
1307 select_tilegroup_menu_effect.start(200);
1308 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1310 case BUTTON_WHEELUP:
1311 if(cur_tilegroup.empty())
1313 cur_tilegroup = tilegroups_map.begin()->first;
1317 it = tilegroups_map.find(cur_tilegroup);
1318 if((++it) == tilegroups_map.end())
1320 cur_tilegroup = tilegroups_map.begin()->first;
1324 cur_tilegroup = (*it).first;
1330 case BUTTON_WHEELDOWN:
1331 it = tilegroups_map.find(cur_tilegroup);
1332 if(it == tilegroups_map.begin())
1334 cur_tilegroup = tilegroups_map.rbegin()->first;
1338 if(--it != --tilegroups_map.begin())
1339 cur_tilegroup = (*it).first;
1341 cur_tilegroup = tilegroups_map.rbegin()->first;
1349 le_objects_bt->event(event);
1350 switch (le_objects_bt->get_state())
1352 case BUTTON_CLICKED:
1353 Menu::set_current(select_objects_menu);
1354 select_objects_menu_effect.start(200);
1355 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1357 case BUTTON_WHEELUP:
1358 it = objects_map.find(cur_objects);
1359 if(it == objects_map.end())
1361 cur_objects = objects_map.begin()->first;
1365 if(++it != objects_map.end())
1366 cur_objects = (*it).first;
1368 cur_objects = objects_map.begin()->first;
1372 case BUTTON_WHEELDOWN:
1373 it = objects_map.find(cur_objects);
1374 if(it == objects_map.begin())
1376 cur_objects = objects_map.rbegin()->first;
1380 if(--it != --objects_map.begin())
1381 cur_objects = (*it).first;
1383 cur_objects = objects_map.rbegin()->first;
1392 le_settings_bt->event(event);
1393 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1395 update_level_settings_menu();
1396 Menu::set_current(level_settings_menu);
1398 if(!cur_tilegroup.empty())
1400 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1402 if(pbutton->get_state() == BUTTON_CLICKED)
1404 le_current.Tile(pbutton->get_tag());
1408 else if(!cur_objects.empty())
1410 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1412 if(pbutton->get_state() == BUTTON_CLICKED)
1414 #if 0 // TODO fixme!!
1415 le_current.Object(pbutton->get_drawable());
1421 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1423 if(pbutton->get_state() == BUTTON_CLICKED)
1425 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1431 le_settings_bt->event(event);
1432 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1434 Menu::set_current(0);
1436 le_tilegroup_bt->event(event);
1437 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1439 Menu::set_current(0);
1441 le_objects_bt->event(event);
1442 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1444 Menu::set_current(0);
1449 if(!Menu::current() && !show_minimap)
1451 if(le_mouse_pressed[LEFT])
1453 if(MouseCursor::current() != mouse_select_object)
1455 if(le_current.IsTile())
1456 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1459 else if(le_mouse_clicked[LEFT])
1461 if(MouseCursor::current() == mouse_select_object)
1463 bool object_got_hit = false;
1464 base_type cursor_base;
1465 if(le_current.IsTile())
1467 cursor_base.x = cursor_x;
1468 cursor_base.y = cursor_y;
1470 else if(le_current.IsObject())
1472 cursor_base.x = cursor_x + pos_x;
1473 cursor_base.y = cursor_y + pos_y;
1475 cursor_base.width = 32;
1476 cursor_base.height = 32;
1478 for(std::vector<_GameObject*>::iterator it =
1479 le_world->gameobjects.begin();
1480 it != le_world->gameobjects.end(); ++it) {
1481 MovingObject* mobj = dynamic_cast<MovingObject*> (*it);
1485 if(rectcollision(cursor_base, mobj->base))
1487 selected_game_object = mobj;
1488 object_got_hit = true;
1495 selected_game_object = NULL;
1496 le_object_properties_bt->set_active(false);
1499 le_object_properties_bt->set_active(true);
1501 MouseCursor::set_current(mouse_cursor);
1507 if(le_current.IsObject())
1509 le_level_changed = true;
1510 std::string type = le_current.obj->type();
1511 if(type == "BadGuy")
1513 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1515 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1516 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1522 le_mouse_clicked[LEFT] = false;
1528 if(!Menu::current())
1530 show_minimap = false;
1532 le_move_left_bt->event(event);
1533 le_move_right_bt->event(event);
1534 le_move_up_bt->event(event);
1535 le_move_down_bt->event(event);
1536 switch(le_move_left_bt->get_state())
1538 case BUTTON_PRESSED:
1539 pos_x -= KEYBOARD_SPEED;
1540 show_minimap = true;
1543 pos_x -= MOUSE_SPEED;
1544 show_minimap = true;
1546 case BUTTON_CLICKED:
1547 show_minimap = true;
1553 switch(le_move_right_bt->get_state())
1555 case BUTTON_PRESSED:
1556 pos_x += KEYBOARD_SPEED;
1557 show_minimap = true;
1560 pos_x += MOUSE_SPEED;
1561 show_minimap = true;
1563 case BUTTON_CLICKED:
1564 show_minimap = true;
1570 switch(le_move_up_bt->get_state())
1572 case BUTTON_PRESSED:
1573 pos_y -= KEYBOARD_SPEED;
1574 show_minimap = true;
1577 pos_y -= MOUSE_SPEED;
1578 show_minimap = true;
1580 case BUTTON_CLICKED:
1581 show_minimap = true;
1587 switch(le_move_down_bt->get_state())
1589 case BUTTON_PRESSED:
1590 pos_y += KEYBOARD_SPEED;
1591 show_minimap = true;
1594 pos_y += MOUSE_SPEED;
1595 show_minimap = true;
1597 case BUTTON_CLICKED:
1598 show_minimap = true;
1604 /* checking if pos_x and pos_y is within the limits... */
1605 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1606 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1610 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1611 pos_y = (le_world->get_level()->height * 32) - screen->h;
1619 void le_highlight_selection()
1623 if(selection.x1 < selection.x2)
1633 if(selection.y1 < selection.y2)
1649 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1652 void le_change(float x, float y, int tm, unsigned int c)
1654 if(le_world != NULL)
1659 le_level_changed = true;
1661 switch(le_selection_mode)
1664 le_world->get_level()->change(x,y,tm,c);
1666 base_type cursor_base;
1669 cursor_base.width = 32;
1670 cursor_base.height = 32;
1672 /* if there is a bad guy over there, remove it */
1675 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1676 if(rectcollision(cursor_base,(*it)->base))
1679 le_world->bad_guys.erase(it);
1680 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1687 if(selection.x1 < selection.x2)
1697 if(selection.y1 < selection.y2)
1713 /* if there is a bad guy over there, remove it */
1716 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1717 it != le_world->bad_guys.end(); /* will be at end of loop */)
1719 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1720 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1723 it = le_world->bad_guys.erase(it);
1724 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1735 for(xx = x1; xx <= x2; xx++)
1736 for(yy = y1; yy <= y2; yy++)
1738 le_world->get_level()->change(xx*32, yy*32, tm, c);
1750 //Make sure a time value is set when testing the level
1751 if(le_world->get_level()->time_left == 0)
1752 le_world->get_level()->time_left = 250;
1754 le_world->get_level()->save("test", le_level, le_world);
1756 GameSession session("test",le_level, ST_GL_TEST);
1758 player_status.reset();
1760 music_manager->halt_music();
1762 Menu::set_current(NULL);
1763 World::set_current(le_world);
1768 bool tmp_show_grid = le_show_grid;
1769 SelectionMode temp_le_selection_mode = le_selection_mode;
1770 le_selection_mode = NONE;
1771 show_selections = true;
1772 le_show_grid = false;
1773 le_help_shown = true;
1775 drawgradient(Color(0,0,0), Color(255,255,255));
1779 unsigned int i, done_;
1782 " - Supertux level editor tutorial - ",
1784 "To make your map, click the ",
1785 "tilegroup button and choose a ",
1787 "Pick a tile and simply hold down ",
1788 "the left mouse button over the map",
1789 "to \"paint\" your selection over",
1792 "There are three layers for painting",
1793 "tiles upon, Background layer,",
1794 "the Interactive layer, and the",
1795 "Foreground layer, which can be",
1796 "toggled by the BkGrd, IntAct and",
1797 "FrGrd buttons. The Foreground and",
1798 "Background layers do not effect",
1799 "Tux in the gameplay, but lie in",
1800 "front of him or lie behind him in",
1806 " - Supertux level editor tutorial - ",
1808 "The tiles placed on",
1809 "the Interactive layer are those",
1810 "which actually effect Tux in the",
1813 "Click the objects menu to put ",
1814 "bad guys and other objects in the",
1815 "game. Unlike placing tiles, you",
1816 "cannot \"paint\" enemies. Click",
1817 "them onto the screen one at a time.",
1819 "To change the settings of your",
1820 "level, click the button with the",
1821 "screwdriver and wrench. From here",
1822 "you can change the background,",
1823 "music, length of the level,",
1829 " - Supertux level editor tutorial - ",
1831 "You may have more than one level.",
1832 "Pressing the up and down buttons",
1833 "above the button bar lets you",
1834 "choose which one you are working on.",
1836 "If you would like to speed up your",
1837 "level editing, a useful trick is",
1838 "to learn the keyboard shortcuts.",
1839 "They are easy to learn, just right-",
1840 "click on the buttons.",
1842 "Have fun making levels! If you make",
1843 "some good ones, send them to us on",
1844 "the SuperTux mailing list!",
1850 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1852 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1853 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1855 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1863 done_ = wait_for_event(event);
1867 drawgradient(Color(0,0,0), Color(255,255,255));
1871 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1873 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1874 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1876 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1884 done_ = wait_for_event(event);
1888 drawgradient(Color(0,0,0), Color(255,255,255));
1892 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1894 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1895 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1897 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1905 done_ = wait_for_event(event);
1909 show_selections = true;
1910 le_show_grid = tmp_show_grid;
1911 le_selection_mode = temp_le_selection_mode;
1912 le_help_shown = false;