4 // Copyright (C) 2003 Ricardo Cruz <rick2@aeiou.pt>
5 // Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <SDL_image.h>
30 #include "leveleditor.h"
43 #include "resources.h"
44 #include "music_manager.h"
46 /* definitions to aid development */
48 /* definitions that affect gameplay */
49 #define KEY_CURSOR_SPEED 32
50 #define KEY_CURSOR_FASTSPEED 64
52 /* when pagedown/up pressed speed:*/
53 #define PAGE_CURSOR_SPEED 13*32
55 #define MOUSE_LEFT_MARGIN 80
56 #define MOUSE_RIGHT_MARGIN (560-32)
59 #define KEYBOARD_SPEED 140
60 #define MOUSE_SPEED 40
63 #define SELECT_W 2 // size of the selections lines
64 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
66 /* own declerations */
67 /* crutial ones (main loop) */
70 int le_load_level_subset(char *filename);
72 void le_drawinterface();
73 void le_checkevents();
74 void le_change(float x, float y, int tm, unsigned int c);
77 void le_set_defaults(void);
78 void le_activate_bad_guys(void);
79 void le_goto_level(int levelnb);
80 void le_highlight_selection();
82 void apply_level_settings_menu();
83 void update_subset_settings_menu();
84 void save_subset_settings_menu();
88 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
90 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
91 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
92 //Returns true for a tile
93 bool IsTile() { return is_tile; };
94 //Returns true for a GameObject
95 bool IsObject() { return !is_tile; };
98 void Init() { tile = 0; obj = NULL; is_tile = true; };
100 bool is_tile; //true for tile (false for object)
105 /* leveleditor internals */
106 static string_list_type level_subsets;
107 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
108 static bool show_minimap;
109 static bool show_selections;
110 static bool le_help_shown;
111 static int pos_x, pos_y, cursor_x, cursor_y;
113 static World* le_world;
114 static LevelSubset* le_level_subset;
115 static int le_show_grid;
117 static Surface* le_selection;
119 static TileOrObject le_current;
120 static bool le_mouse_pressed[2];
121 static bool le_mouse_clicked[2];
122 static Button* le_save_level_bt;
123 static Button* le_exit_bt;
124 static Button* le_test_level_bt;
125 static Button* le_next_level_bt;
126 static Button* le_previous_level_bt;
127 static Button* le_move_right_bt;
128 static Button* le_move_left_bt;
129 static Button* le_move_up_bt;
130 static Button* le_move_down_bt;
131 static Button* le_rubber_bt;
132 static Button* le_select_mode_one_bt;
133 static Button* le_select_mode_two_bt;
134 static Button* le_settings_bt;
135 static Button* le_tilegroup_bt;
136 static Button* le_objects_bt;
137 static Button* le_object_select_bt;
138 static Button* le_object_properties_bt;
139 static ButtonPanel* le_tilemap_panel;
140 static Menu* leveleditor_menu;
141 static Menu* subset_load_menu;
142 static Menu* subset_new_menu;
143 static Menu* subset_settings_menu;
144 static Menu* level_settings_menu;
145 static Menu* select_tilegroup_menu;
146 static Menu* select_objects_menu;
147 static Timer select_tilegroup_menu_effect;
148 static Timer select_objects_menu_effect;
149 static Timer display_level_info;
150 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
151 static ButtonPanelMap tilegroups_map;
152 static ButtonPanelMap objects_map;
153 static std::string cur_tilegroup;
154 static std::string cur_objects;
155 static MouseCursor* mouse_select_object;
156 static GameObject* selected_game_object;
158 static square selection;
159 static SelectionMode le_selection_mode;
160 static SDL_Event event;
161 TileMapType active_tm;
163 int leveleditor(char* filename)
165 int last_time, now_time, i;
174 clearscreen(0, 0, 0);
177 music_manager->halt_music();
179 while (SDL_PollEvent(&event))
183 if(le_load_level_subset(filename))
188 last_time = SDL_GetTicks();
193 if(Menu::current() == select_tilegroup_menu)
195 if(select_tilegroup_menu_effect.check())
197 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
201 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
203 else if(Menu::current() == select_objects_menu)
205 if(select_objects_menu_effect.check())
207 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
210 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
215 /* making events results to be in order */
221 clearscreen(0, 0, 0);
223 /* draw editor interface */
226 Menu* menu = Menu::current();
232 if(menu == leveleditor_menu)
234 switch (leveleditor_menu->check())
236 case MNID_RETURNLEVELEDITOR:
238 Menu::set_current(0);
240 Menu::set_current(leveleditor_menu);
242 case MNID_SUBSETSETTINGS:
243 update_subset_settings_menu();
245 case MNID_QUITLEVELEDITOR:
250 else if(menu == level_settings_menu)
252 switch (level_settings_menu->check())
255 apply_level_settings_menu();
256 Menu::set_current(NULL);
263 else if(menu == select_tilegroup_menu)
266 switch (it = select_tilegroup_menu->check())
271 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
272 Menu::set_current(0);
279 else if(menu == select_objects_menu)
282 switch (it = select_objects_menu->check())
287 cur_objects = select_objects_menu->get_item_by_id(it).text;
290 Menu::set_current(0);
295 else if(menu == subset_load_menu)
297 switch (i = subset_load_menu->check())
304 if(le_load_level_subset(level_subsets.item[i-1]))
310 else if(menu == subset_new_menu)
312 if(subset_new_menu->item[2].input[0] == '\0')
313 subset_new_menu->item[3].kind = MN_DEACTIVE;
316 subset_new_menu->item[3].kind = MN_ACTION;
318 switch (i = subset_new_menu->check())
320 case MNID_CREATESUBSET:
321 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
322 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
323 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
325 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
327 Menu::set_current(subset_settings_menu);
332 else if(menu == subset_settings_menu)
334 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 )
335 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
337 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
339 switch (i = subset_settings_menu->check())
341 case MNID_SUBSETSAVECHANGES:
342 save_subset_settings_menu();
343 Menu::set_current(leveleditor_menu);
349 MouseCursor::current()->draw();
357 ++global_frame_counter;
360 now_time = SDL_GetTicks();
361 if (now_time < last_time + FPS)
362 SDL_Delay(last_time + FPS - now_time); /* delay some time */
370 int le_load_level_subset(char *filename)
372 le_level_subset->load(filename);
373 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
377 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
379 Menu::set_current(NULL);
388 leveleditor_menu = new Menu();
389 subset_load_menu = new Menu();
390 subset_new_menu = new Menu();
391 subset_settings_menu = new Menu();
392 level_settings_menu = new Menu();
393 select_tilegroup_menu = new Menu();
394 select_objects_menu = new Menu();
396 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
397 leveleditor_menu->additem(MN_HL,"",0,0);
398 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
399 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
400 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
401 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
402 leveleditor_menu->additem(MN_HL,"",0,0);
403 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
405 Menu::set_current(leveleditor_menu);
407 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
408 subset_load_menu->additem(MN_HL, "", 0, 0);
410 for(i = 0; i < level_subsets.num_items; ++i)
412 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
414 subset_load_menu->additem(MN_HL,"",0,0);
415 subset_load_menu->additem(MN_BACK,"Back",0,0);
417 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
418 subset_new_menu->additem(MN_HL,"",0,0);
419 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
420 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
421 subset_new_menu->additem(MN_HL,"",0,0);
422 subset_new_menu->additem(MN_BACK,"Back",0,0);
424 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
425 subset_settings_menu->additem(MN_HL,"",0,0);
426 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
427 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
428 subset_settings_menu->additem(MN_HL,"",0,0);
429 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
430 subset_settings_menu->additem(MN_HL,"",0,0);
431 subset_settings_menu->additem(MN_BACK,"Back",0,0);
433 level_settings_menu->arrange_left = true;
434 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
435 level_settings_menu->additem(MN_HL,"",0,0);
436 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
437 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
438 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
439 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
440 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
441 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
442 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
443 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
444 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
445 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
446 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
447 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
448 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
449 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
450 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
451 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
452 level_settings_menu->additem(MN_HL,"",0,0);
453 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
455 select_tilegroup_menu->arrange_left = true;
456 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
457 select_tilegroup_menu->additem(MN_HL,"",0,0);
458 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
460 for(std::set<TileGroup>::iterator it = tilegroups->begin();
461 it != tilegroups->end(); ++it )
463 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
465 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
468 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
469 sit != (*it).tiles.end(); ++sit, ++i)
471 std::string imagefile = "/images/tilesets/" ;
472 bool only_editor_image = false;
473 if(!TileManager::instance()->get(*sit)->filenames.empty())
475 imagefile += TileManager::instance()->get(*sit)->filenames[0];
477 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
479 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
480 only_editor_image = true;
484 imagefile += "notile.png";
486 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
488 if(!only_editor_image)
489 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
491 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
492 button->add_icon(imagefile,32,32);
494 tilegroups_map[it->name]->additem(button, *sit);
497 select_tilegroup_menu->additem(MN_HL,"",0,0);
499 select_objects_menu->arrange_left = true;
500 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
501 select_objects_menu->additem(MN_HL,"",0,0);
502 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
503 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
505 for(int i = 0; i < NUM_BadGuyKinds; ++i)
507 BadGuy bad_tmp(0,0,BadGuyKind(i),false);
508 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
509 objects_map["BadGuys"]->manipulate_button(i)->set_game_object(new BadGuy(objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,objects_map["BadGuys"]->manipulate_button(i)->get_pos().y,BadGuyKind(i),false));
512 select_objects_menu->additem(MN_HL,"",0,0);
520 level_subsets = dsubdirs("/levels", "level1.stl");
521 le_level_subset = new LevelSubset;
524 selected_game_object = NULL;
528 show_selections = true;
532 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
533 le_level_changed = false;
534 le_help_shown = false;
536 le_mouse_pressed[LEFT] = false;
537 le_mouse_pressed[RIGHT] = false;
539 le_mouse_clicked[LEFT] = false;
540 le_mouse_clicked[RIGHT] = false;
542 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
544 select_tilegroup_menu_effect.init(false);
545 select_objects_menu_effect.init(false);
546 display_level_info.init(false);
549 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
550 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
551 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
552 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
553 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
554 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
555 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
556 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
557 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
558 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
559 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
560 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
561 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
562 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
563 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
564 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
565 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
566 le_object_properties_bt->set_active(false);
568 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
569 mouse_select_object->set_mid(16,16);
571 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
572 le_tilemap_panel->set_button_size(32,10);
573 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
574 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
575 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
576 le_tilemap_panel->highlight_last(true);
577 le_tilemap_panel->set_last_clicked(TM_IA);
583 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
589 void update_level_settings_menu()
594 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
595 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
597 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
598 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
599 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
600 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
601 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
602 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
604 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
605 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
606 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
607 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
608 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
609 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
611 sprintf(str,"%d",le_world->get_level()->width);
612 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
613 sprintf(str,"%d",le_world->get_level()->height);
614 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
615 sprintf(str,"%d",le_world->get_level()->time_left);
616 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
617 sprintf(str,"%2.0f",le_world->get_level()->gravity);
618 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
619 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
620 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
621 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
622 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
623 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
624 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
625 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
626 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
627 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
628 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
629 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
630 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
631 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
632 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
635 void update_subset_settings_menu()
637 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
638 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
641 void apply_level_settings_menu()
645 le_level_changed = true;
647 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
648 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
650 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
652 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
656 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
658 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
663 le_world->get_level()->load_gfx();
666 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
668 le_world->get_level()->change_width(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
669 le_world->get_level()->change_height(atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
670 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
671 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
672 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
673 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
674 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
675 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
676 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
677 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
678 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
681 void save_subset_settings_menu()
683 le_level_subset->title = subset_settings_menu->item[2].input;
684 le_level_subset->description = subset_settings_menu->item[3].input;
685 le_level_subset->save();
686 le_level_changed = false;
689 void le_unload_level()
696 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
697 if(confirm_dialog(str))
699 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
704 le_level_changed = false;
707 void le_goto_level(int levelnb)
710 le_world = new World(le_level_subset->name, levelnb);
711 display_level_info.start(2500);
717 SDL_EnableKeyRepeat(0, 0); // disables key repeating
721 delete leveleditor_menu;
722 delete subset_load_menu;
723 delete subset_new_menu;
724 delete subset_settings_menu;
725 delete level_settings_menu;
726 delete select_tilegroup_menu;
727 delete select_objects_menu;
728 delete le_save_level_bt;
730 delete le_test_level_bt;
731 delete le_next_level_bt;
732 delete le_previous_level_bt;
733 delete le_move_right_bt;
734 delete le_move_left_bt;
735 delete le_move_up_bt;
736 delete le_move_down_bt;
738 delete le_select_mode_one_bt;
739 delete le_select_mode_two_bt;
740 delete le_settings_bt;
741 delete le_tilegroup_bt;
742 delete le_objects_bt;
743 delete le_tilemap_panel;
744 delete le_object_select_bt;
745 delete le_object_properties_bt;
746 delete mouse_select_object;
748 delete le_level_subset;
751 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
752 i != tilegroups_map.end(); ++i)
756 for(ButtonPanelMap::iterator i = objects_map.begin();
757 i != objects_map.end(); ++i)
763 void le_drawminimap()
769 if(screen->w - 64 > le_world->get_level()->width * 4)
771 else if(screen->w - 64 > le_world->get_level()->width * 2)
775 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
777 int mini_tile_height;
778 if(screen->h - 64 > le_world->get_level()->height * 4)
779 mini_tile_height = 4;
780 else if(screen->h - 64 > le_world->get_level()->height * 2)
781 mini_tile_height = 2;
783 mini_tile_height = 1;
785 for (int y = 0; y < le_world->get_level()->height; ++y)
786 for (int x = 0; x < le_world->get_level()->width; ++x)
789 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
791 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
793 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
797 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 128);
799 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
800 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 200);
801 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);
802 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);
806 void le_drawinterface()
813 /* draw a grid (if selected) */
816 for(x = 0; x < VISIBLE_TILES_X; x++)
817 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
818 for(y = 0; y < VISIBLE_TILES_Y; y++)
819 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
823 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
826 if(show_selections && MouseCursor::current() != mouse_select_object)
828 if(le_selection_mode == CURSOR)
830 if(le_current.IsTile())
831 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
833 else if(le_selection_mode == SQUARE)
836 le_highlight_selection();
837 /* draw current selection */
838 w = selection.x2 - selection.x1;
839 h = selection.y2 - selection.y1;
840 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
841 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
842 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
843 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
848 /* draw button bar */
849 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
851 if(le_current.IsTile())
853 Tile::draw(screen->w - 32, screen->h - 32, le_current.tile);
854 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
855 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
857 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
859 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
860 le_current.obj->draw_on_screen(cursor_x,cursor_y);
863 if(mouse_select_object && selected_game_object != NULL)
865 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);
866 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);
867 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);
868 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);
873 le_save_level_bt->draw();
875 le_test_level_bt->draw();
876 le_next_level_bt->draw();
877 le_previous_level_bt->draw();
878 le_rubber_bt->draw();
879 if(le_selection_mode == SQUARE)
880 le_select_mode_one_bt->draw();
881 else if(le_selection_mode == CURSOR)
882 le_select_mode_two_bt->draw();
883 le_settings_bt->draw();
884 le_move_right_bt->draw();
885 le_move_left_bt->draw();
886 le_move_up_bt->draw();
887 le_move_down_bt->draw();
888 le_tilegroup_bt->draw();
889 le_objects_bt->draw();
890 if(!cur_tilegroup.empty())
891 tilegroups_map[cur_tilegroup]->draw();
892 else if(!cur_objects.empty())
894 objects_map[cur_objects]->draw();
897 le_tilemap_panel->draw();
899 if(!cur_objects.empty())
901 le_object_select_bt->draw();
902 le_object_properties_bt->draw();
905 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
906 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
909 white_small_text->draw("F1 for Help", 10, 430, 1);
911 if(display_level_info.check())
912 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
917 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
919 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
929 /* Draw the real background */
930 le_world->get_level()->draw_bg();
932 if(le_current.IsTile())
934 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
935 if(!TileManager::instance()->get(le_current.tile)->images.empty())
936 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);
938 if(le_current.IsObject())
940 le_current.obj->move_to(cursor_x, cursor_y);
943 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
945 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
946 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
949 if(active_tm == TM_BG)
954 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->bg_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
956 if(active_tm == TM_IA)
961 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->ia_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
963 if(active_tm == TM_FG)
968 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->fg_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
970 /* draw whats inside stuff when cursor is selecting those */
971 /* (draw them all the time - is this the right behaviour?) */
972 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)]);
973 if(edit_image && !edit_image->editor_images.empty())
974 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
978 /* Draw the Bad guys: */
979 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
981 /* to support frames: img_bsod_left[(frame / 5) % 4] */
989 /* Draw the player: */
990 /* for now, the position is fixed at (100, 240) */
991 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
994 void le_change_object_properties(GameObject *pobj)
996 Surface* cap_screen = Surface::CaptureScreen();
997 Menu* object_properties_menu = new Menu();
1000 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
1001 object_properties_menu->additem(MN_HL,"",0,0);
1003 if(pobj->type() == "BadGuy")
1005 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1006 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1007 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1009 string_list_add_item(object_properties_menu->get_item_by_id(1).list,badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1011 object_properties_menu->get_item_by_id(1).list->active_item = i;
1013 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1016 object_properties_menu->additem(MN_HL,"",0,0);
1017 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1019 Menu::set_current(object_properties_menu);
1025 while (SDL_PollEvent(&event))
1027 object_properties_menu->event(event);
1030 cap_screen->draw(0,0);
1032 object_properties_menu->draw();
1033 object_properties_menu->action();
1035 switch (object_properties_menu->check())
1038 if(pobj->type() == "BadGuy")
1040 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1041 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1042 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1044 std::list<BadGuy*>::iterator it;
1045 for(it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1048 le_world->get_level()->badguy_data[i].kind = pbad->kind;
1049 le_world->get_level()->badguy_data[i].stay_on_platform = pbad->stay_on_platform;
1051 (*it) = new BadGuy(le_world->get_level()->badguy_data[i].x,le_world->get_level()->badguy_data[i].y,le_world->get_level()->badguy_data[i].kind,le_world->get_level()->badguy_data[i].stay_on_platform);
1059 if(Menu::current() == NULL)
1062 mouse_cursor->draw();
1068 Menu::set_current(0);
1069 delete object_properties_menu;
1073 void le_checkevents()
1080 keymod = SDL_GetModState();
1082 while(SDL_PollEvent(&event))
1084 if (Menu::current())
1086 Menu::current()->event(event);
1087 if(!le_world && !Menu::current())
1088 Menu::set_current(leveleditor_menu);
1092 mouse_cursor->set_state(MC_NORMAL);
1094 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1095 if(event.type == SDL_KEYDOWN
1096 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1097 && (event.motion.x > 0
1098 && event.motion.x < screen->w - 64 &&
1099 event.motion.y > 0 && event.motion.y < screen->h)))
1103 case SDL_KEYDOWN: // key pressed
1104 key = event.key.keysym.sym;
1108 Menu::set_current(leveleditor_menu);
1111 if(le_world != NULL)
1119 cursor_x = (le_world->get_level()->width * 32) - 32;
1123 le_show_grid = !le_show_grid;
1129 case SDL_MOUSEBUTTONDOWN:
1130 if(event.button.button == SDL_BUTTON_LEFT)
1132 le_mouse_pressed[LEFT] = true;
1134 selection.x1 = event.motion.x + pos_x;
1135 selection.y1 = event.motion.y + pos_y;
1136 selection.x2 = event.motion.x + pos_x;
1137 selection.y2 = event.motion.y + pos_y;
1139 else if(event.button.button == SDL_BUTTON_RIGHT)
1141 le_mouse_pressed[RIGHT] = true;
1144 case SDL_MOUSEBUTTONUP:
1145 if(event.button.button == SDL_BUTTON_LEFT)
1147 le_mouse_pressed[LEFT] = false;
1148 le_mouse_clicked[LEFT] = true;
1150 else if(event.button.button == SDL_BUTTON_RIGHT)
1152 le_mouse_pressed[RIGHT] = false;
1153 le_mouse_clicked[RIGHT] = true;
1156 case SDL_MOUSEMOTION:
1158 if(!Menu::current())
1163 if(le_current.IsTile())
1165 cursor_x = ((int)(pos_x + x) / 32) * 32;
1166 cursor_y = ((int)(pos_y + y) / 32) * 32;
1174 if(le_mouse_pressed[LEFT])
1176 selection.x2 = x + pos_x;
1177 selection.y2 = y + pos_y;
1180 if(le_mouse_pressed[RIGHT])
1182 pos_x += -1 * event.motion.xrel;
1183 pos_y += -1 * event.motion.yrel;
1191 else if(event.type == SDL_QUIT) /* window closing */
1197 if(le_world != NULL)
1199 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 &&
1200 event.motion.y > 0 && event.motion.y < screen->h)))
1202 le_mouse_pressed[LEFT] = false;
1203 le_mouse_pressed[RIGHT] = false;
1205 if(!Menu::current())
1207 /* Check for button events */
1208 le_test_level_bt->event(event);
1209 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1211 le_save_level_bt->event(event);
1212 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1213 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1214 le_exit_bt->event(event);
1215 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1217 Menu::set_current(leveleditor_menu);
1219 le_next_level_bt->event(event);
1220 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1222 if(le_level < le_level_subset->levels)
1224 le_goto_level(le_level+1);
1230 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1231 if(confirm_dialog(str))
1233 new_lev.init_defaults();
1234 new_lev.save(le_level_subset->name.c_str(),le_level+1);
1235 le_level_subset->levels = le_level;
1236 le_goto_level(le_level);
1240 le_previous_level_bt->event(event);
1241 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1244 le_goto_level(le_level -1);
1246 le_rubber_bt->event(event);
1247 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1250 if(!cur_objects.empty())
1252 le_object_select_bt->event(event);
1253 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1255 MouseCursor::set_current(mouse_select_object);
1258 le_object_properties_bt->event(event);
1259 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1261 le_change_object_properties(selected_game_object);
1266 if(le_selection_mode == SQUARE)
1268 le_select_mode_one_bt->event(event);
1269 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1270 le_selection_mode = CURSOR;
1274 le_select_mode_two_bt->event(event);
1275 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1276 le_selection_mode = SQUARE;
1278 ButtonPanelMap::iterator it;
1279 le_tilegroup_bt->event(event);
1280 switch (le_tilegroup_bt->get_state())
1282 case BUTTON_CLICKED:
1283 Menu::set_current(select_tilegroup_menu);
1284 select_tilegroup_menu_effect.start(200);
1285 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1287 case BUTTON_WHEELUP:
1288 if(cur_tilegroup.empty())
1290 cur_tilegroup = tilegroups_map.begin()->first;
1294 it = tilegroups_map.find(cur_tilegroup);
1295 if((++it) == tilegroups_map.end())
1297 cur_tilegroup = tilegroups_map.begin()->first;
1301 cur_tilegroup = (*it).first;
1307 case BUTTON_WHEELDOWN:
1308 it = tilegroups_map.find(cur_tilegroup);
1309 if(it == tilegroups_map.begin())
1311 cur_tilegroup = tilegroups_map.rbegin()->first;
1315 if(--it != --tilegroups_map.begin())
1316 cur_tilegroup = (*it).first;
1318 cur_tilegroup = tilegroups_map.rbegin()->first;
1326 le_objects_bt->event(event);
1327 switch (le_objects_bt->get_state())
1329 case BUTTON_CLICKED:
1330 Menu::set_current(select_objects_menu);
1331 select_objects_menu_effect.start(200);
1332 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1334 case BUTTON_WHEELUP:
1335 it = objects_map.find(cur_objects);
1336 if(it == objects_map.end())
1338 cur_objects = objects_map.begin()->first;
1342 if(++it != objects_map.end())
1343 cur_objects = (*it).first;
1345 cur_objects = objects_map.begin()->first;
1349 case BUTTON_WHEELDOWN:
1350 it = objects_map.find(cur_objects);
1351 if(it == objects_map.begin())
1353 cur_objects = objects_map.rbegin()->first;
1357 if(--it != --objects_map.begin())
1358 cur_objects = (*it).first;
1360 cur_objects = objects_map.rbegin()->first;
1369 le_settings_bt->event(event);
1370 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1372 update_level_settings_menu();
1373 Menu::set_current(level_settings_menu);
1375 if(!cur_tilegroup.empty())
1377 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1379 if(pbutton->get_state() == BUTTON_CLICKED)
1381 le_current.Tile(pbutton->get_tag());
1385 else if(!cur_objects.empty())
1387 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1389 if(pbutton->get_state() == BUTTON_CLICKED)
1391 le_current.Object(pbutton->get_game_object());
1396 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1398 if(pbutton->get_state() == BUTTON_CLICKED)
1400 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1406 le_settings_bt->event(event);
1407 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1409 Menu::set_current(0);
1411 le_tilegroup_bt->event(event);
1412 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1414 Menu::set_current(0);
1416 le_objects_bt->event(event);
1417 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1419 Menu::set_current(0);
1424 if(!Menu::current() && !show_minimap)
1426 if(le_mouse_pressed[LEFT])
1428 if(MouseCursor::current() != mouse_select_object)
1430 if(le_current.IsTile())
1431 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1434 else if(le_mouse_clicked[LEFT])
1436 if(MouseCursor::current() == mouse_select_object)
1439 bool object_got_hit = false;
1440 base_type cursor_base;
1441 if(le_current.IsTile())
1443 cursor_base.x = cursor_x;
1444 cursor_base.y = cursor_y;
1446 else if(le_current.IsObject())
1448 cursor_base.x = cursor_x + pos_x;
1449 cursor_base.y = cursor_y + pos_y;
1451 cursor_base.width = 32;
1452 cursor_base.height = 32;
1454 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1455 if(rectcollision(cursor_base,(*it)->base))
1457 selected_game_object = (*it);
1458 object_got_hit = true;
1464 selected_game_object = NULL;
1465 le_object_properties_bt->set_active(false);
1468 le_object_properties_bt->set_active(true);
1470 MouseCursor::set_current(mouse_cursor);
1475 if(le_current.IsObject())
1477 le_level_changed = true;
1478 std::string type = le_current.obj->type();
1479 if(type == "BadGuy")
1481 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1483 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1484 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1489 le_mouse_clicked[LEFT] = false;
1495 if(!Menu::current())
1497 show_minimap = false;
1499 le_move_left_bt->event(event);
1500 le_move_right_bt->event(event);
1501 le_move_up_bt->event(event);
1502 le_move_down_bt->event(event);
1503 switch(le_move_left_bt->get_state())
1505 case BUTTON_PRESSED:
1506 pos_x -= KEYBOARD_SPEED;
1507 show_minimap = true;
1510 pos_x -= MOUSE_SPEED;
1511 show_minimap = true;
1513 case BUTTON_CLICKED:
1514 show_minimap = true;
1520 switch(le_move_right_bt->get_state())
1522 case BUTTON_PRESSED:
1523 pos_x += KEYBOARD_SPEED;
1524 show_minimap = true;
1527 pos_x += MOUSE_SPEED;
1528 show_minimap = true;
1530 case BUTTON_CLICKED:
1531 show_minimap = true;
1537 switch(le_move_up_bt->get_state())
1539 case BUTTON_PRESSED:
1540 pos_y -= KEYBOARD_SPEED;
1541 show_minimap = true;
1544 pos_y -= MOUSE_SPEED;
1545 show_minimap = true;
1547 case BUTTON_CLICKED:
1548 show_minimap = true;
1554 switch(le_move_down_bt->get_state())
1556 case BUTTON_PRESSED:
1557 pos_y += KEYBOARD_SPEED;
1558 show_minimap = true;
1561 pos_y += MOUSE_SPEED;
1562 show_minimap = true;
1564 case BUTTON_CLICKED:
1565 show_minimap = true;
1571 /* checking if pos_x and pos_y is within the limits... */
1572 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1573 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1577 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1578 pos_y = (le_world->get_level()->height * 32) - screen->h;
1586 void le_highlight_selection()
1590 if(selection.x1 < selection.x2)
1600 if(selection.y1 < selection.y2)
1616 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1619 void le_change(float x, float y, int tm, unsigned int c)
1621 if(le_world != NULL)
1627 le_level_changed = true;
1629 switch(le_selection_mode)
1632 le_world->get_level()->change(x,y,tm,c);
1634 base_type cursor_base;
1637 cursor_base.width = 32;
1638 cursor_base.height = 32;
1640 /* if there is a bad guy over there, remove it */
1641 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1642 if(rectcollision(cursor_base,(*it)->base))
1645 le_world->bad_guys.erase(it);
1646 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1652 if(selection.x1 < selection.x2)
1662 if(selection.y1 < selection.y2)
1678 /* if there is a bad guy over there, remove it */
1679 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1680 it != le_world->bad_guys.end(); /* will be at end of loop */)
1682 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1683 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1686 it = le_world->bad_guys.erase(it);
1687 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1697 for(xx = x1; xx <= x2; xx++)
1698 for(yy = y1; yy <= y2; yy++)
1700 le_world->get_level()->change(xx*32, yy*32, tm, c);
1712 //Make sure a time value is set when testing the level
1713 if(le_world->get_level()->time_left == 0)
1714 le_world->get_level()->time_left = 250;
1716 le_world->get_level()->save("test", le_level);
1718 GameSession session("test",le_level, ST_GL_TEST);
1720 player_status.reset();
1722 music_manager->halt_music();
1724 Menu::set_current(NULL);
1725 World::set_current(le_world);
1730 bool tmp_show_grid = le_show_grid;
1731 SelectionMode temp_le_selection_mode = le_selection_mode;
1732 le_selection_mode = NONE;
1733 show_selections = true;
1734 le_show_grid = false;
1735 le_help_shown = true;
1737 drawgradient(Color(0,0,0), Color(255,255,255));
1741 unsigned int i, done_;
1744 " - Supertux level editor tutorial - ",
1746 "To make your map, click the ",
1747 "tilegroup button and choose a ",
1749 "Pick a tile and simply hold down ",
1750 "the left mouse button over the map",
1751 "to \"paint\" your selection over",
1754 "There are three layers for painting",
1755 "tiles upon, Background layer,",
1756 "the Interactive layer, and the",
1757 "Foreground layer, which can be",
1758 "toggled by the BkGrd, IntAct and",
1759 "FrGrd buttons. The Foreground and",
1760 "Background layers do not effect",
1761 "Tux in the gameplay, but lie in",
1762 "front of him or lie behind him in",
1768 " - Supertux level editor tutorial - ",
1770 "The tiles placed on",
1771 "the Interactive layer are those",
1772 "which actually effect Tux in the",
1775 "Click the objects menu to put ",
1776 "bad guys and other objects in the",
1777 "game. Unlike placing tiles, you",
1778 "cannot \"paint\" enemies. Click",
1779 "them onto the screen one at a time.",
1781 "To change the settings of your",
1782 "level, click the button with the",
1783 "screwdriver and wrench. From here",
1784 "you can change the background,",
1785 "music, length of the level,",
1791 " - Supertux level editor tutorial - ",
1793 "You may have more than one level.",
1794 "Pressing the up and down buttons",
1795 "above the button bar lets you",
1796 "choose which one you are working on.",
1798 "If you would like to speed up your",
1799 "level editing, a useful trick is",
1800 "to learn the keyboard shortcuts.",
1801 "They are easy to learn, just right-",
1802 "click on the buttons.",
1804 "Have fun making levels! If you make",
1805 "some good ones, send them to us on",
1806 "the SuperTux mailing list!",
1812 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1814 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1815 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1817 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1825 done_ = wait_for_event(event);
1829 drawgradient(Color(0,0,0), Color(255,255,255));
1833 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1835 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1836 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1838 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1846 done_ = wait_for_event(event);
1850 drawgradient(Color(0,0,0), Color(255,255,255));
1854 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1856 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1857 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1859 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1867 done_ = wait_for_event(event);
1871 show_selections = true;
1872 le_show_grid = tmp_show_grid;
1873 le_selection_mode = temp_le_selection_mode;
1874 le_help_shown = false;