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 if (le_world->get_level()->img_bkgd)
931 le_world->get_level()->draw_bg();
933 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
935 if(le_current.IsTile())
937 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
938 if(!TileManager::instance()->get(le_current.tile)->images.empty())
939 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);
941 if(le_current.IsObject())
943 le_current.obj->move_to(cursor_x, cursor_y);
946 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
948 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
949 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
952 if(active_tm == TM_BG)
957 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);
959 if(active_tm == TM_IA)
964 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);
966 if(active_tm == TM_FG)
971 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);
973 /* draw whats inside stuff when cursor is selecting those */
974 /* (draw them all the time - is this the right behaviour?) */
975 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)]);
976 if(edit_image && !edit_image->editor_images.empty())
977 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
981 /* Draw the Bad guys: */
982 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
984 /* to support frames: img_bsod_left[(frame / 5) % 4] */
992 /* Draw the player: */
993 /* for now, the position is fixed at (100, 240) */
994 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
997 void le_change_object_properties(GameObject *pobj)
999 Surface* cap_screen = Surface::CaptureScreen();
1000 Menu* object_properties_menu = new Menu();
1003 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
1004 object_properties_menu->additem(MN_HL,"",0,0);
1006 if(pobj->type() == "BadGuy")
1008 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1009 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1010 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1012 string_list_add_item(object_properties_menu->get_item_by_id(1).list,badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1014 object_properties_menu->get_item_by_id(1).list->active_item = i;
1016 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1019 object_properties_menu->additem(MN_HL,"",0,0);
1020 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1022 Menu::set_current(object_properties_menu);
1028 while (SDL_PollEvent(&event))
1030 object_properties_menu->event(event);
1033 cap_screen->draw(0,0);
1035 object_properties_menu->draw();
1036 object_properties_menu->action();
1038 switch (object_properties_menu->check())
1041 if(pobj->type() == "BadGuy")
1043 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1044 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1045 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1047 std::list<BadGuy*>::iterator it;
1048 for(it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1051 le_world->get_level()->badguy_data[i].kind = pbad->kind;
1052 le_world->get_level()->badguy_data[i].stay_on_platform = pbad->stay_on_platform;
1054 (*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);
1062 if(Menu::current() == NULL)
1065 mouse_cursor->draw();
1071 Menu::set_current(0);
1072 delete object_properties_menu;
1076 void le_checkevents()
1083 keymod = SDL_GetModState();
1085 while(SDL_PollEvent(&event))
1087 if (Menu::current())
1089 Menu::current()->event(event);
1090 if(!le_world && !Menu::current())
1091 Menu::set_current(leveleditor_menu);
1095 mouse_cursor->set_state(MC_NORMAL);
1097 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1098 if(event.type == SDL_KEYDOWN
1099 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1100 && (event.motion.x > 0
1101 && event.motion.x < screen->w - 64 &&
1102 event.motion.y > 0 && event.motion.y < screen->h)))
1106 case SDL_KEYDOWN: // key pressed
1107 key = event.key.keysym.sym;
1111 Menu::set_current(leveleditor_menu);
1114 if(le_world != NULL)
1122 cursor_x = (le_world->get_level()->width * 32) - 32;
1126 le_show_grid = !le_show_grid;
1132 case SDL_MOUSEBUTTONDOWN:
1133 if(event.button.button == SDL_BUTTON_LEFT)
1135 le_mouse_pressed[LEFT] = true;
1137 selection.x1 = event.motion.x + pos_x;
1138 selection.y1 = event.motion.y + pos_y;
1139 selection.x2 = event.motion.x + pos_x;
1140 selection.y2 = event.motion.y + pos_y;
1142 else if(event.button.button == SDL_BUTTON_RIGHT)
1144 le_mouse_pressed[RIGHT] = true;
1147 case SDL_MOUSEBUTTONUP:
1148 if(event.button.button == SDL_BUTTON_LEFT)
1150 le_mouse_pressed[LEFT] = false;
1151 le_mouse_clicked[LEFT] = true;
1153 else if(event.button.button == SDL_BUTTON_RIGHT)
1155 le_mouse_pressed[RIGHT] = false;
1156 le_mouse_clicked[RIGHT] = true;
1159 case SDL_MOUSEMOTION:
1161 if(!Menu::current())
1166 if(le_current.IsTile())
1168 cursor_x = ((int)(pos_x + x) / 32) * 32;
1169 cursor_y = ((int)(pos_y + y) / 32) * 32;
1177 if(le_mouse_pressed[LEFT])
1179 selection.x2 = x + pos_x;
1180 selection.y2 = y + pos_y;
1183 if(le_mouse_pressed[RIGHT])
1185 pos_x += -1 * event.motion.xrel;
1186 pos_y += -1 * event.motion.yrel;
1194 else if(event.type == SDL_QUIT) /* window closing */
1200 if(le_world != NULL)
1202 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 &&
1203 event.motion.y > 0 && event.motion.y < screen->h)))
1205 le_mouse_pressed[LEFT] = false;
1206 le_mouse_pressed[RIGHT] = false;
1208 if(!Menu::current())
1210 /* Check for button events */
1211 le_test_level_bt->event(event);
1212 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1214 le_save_level_bt->event(event);
1215 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1216 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1217 le_exit_bt->event(event);
1218 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1220 Menu::set_current(leveleditor_menu);
1222 le_next_level_bt->event(event);
1223 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1225 if(le_level < le_level_subset->levels)
1227 le_goto_level(le_level+1);
1233 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1234 if(confirm_dialog(str))
1236 new_lev.init_defaults();
1237 new_lev.save(le_level_subset->name.c_str(),le_level+1);
1238 le_level_subset->levels = le_level;
1239 le_goto_level(le_level);
1243 le_previous_level_bt->event(event);
1244 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1247 le_goto_level(le_level -1);
1249 le_rubber_bt->event(event);
1250 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1253 if(!cur_objects.empty())
1255 le_object_select_bt->event(event);
1256 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1258 MouseCursor::set_current(mouse_select_object);
1261 le_object_properties_bt->event(event);
1262 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1264 le_change_object_properties(selected_game_object);
1269 if(le_selection_mode == SQUARE)
1271 le_select_mode_one_bt->event(event);
1272 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1273 le_selection_mode = CURSOR;
1277 le_select_mode_two_bt->event(event);
1278 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1279 le_selection_mode = SQUARE;
1281 ButtonPanelMap::iterator it;
1282 le_tilegroup_bt->event(event);
1283 switch (le_tilegroup_bt->get_state())
1285 case BUTTON_CLICKED:
1286 Menu::set_current(select_tilegroup_menu);
1287 select_tilegroup_menu_effect.start(200);
1288 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1290 case BUTTON_WHEELUP:
1291 if(cur_tilegroup.empty())
1293 cur_tilegroup = tilegroups_map.begin()->first;
1297 it = tilegroups_map.find(cur_tilegroup);
1298 if((++it) == tilegroups_map.end())
1300 cur_tilegroup = tilegroups_map.begin()->first;
1304 cur_tilegroup = (*it).first;
1310 case BUTTON_WHEELDOWN:
1311 it = tilegroups_map.find(cur_tilegroup);
1312 if(it == tilegroups_map.begin())
1314 cur_tilegroup = tilegroups_map.rbegin()->first;
1318 if(--it != --tilegroups_map.begin())
1319 cur_tilegroup = (*it).first;
1321 cur_tilegroup = tilegroups_map.rbegin()->first;
1329 le_objects_bt->event(event);
1330 switch (le_objects_bt->get_state())
1332 case BUTTON_CLICKED:
1333 Menu::set_current(select_objects_menu);
1334 select_objects_menu_effect.start(200);
1335 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1337 case BUTTON_WHEELUP:
1338 it = objects_map.find(cur_objects);
1339 if(it == objects_map.end())
1341 cur_objects = objects_map.begin()->first;
1345 if(++it != objects_map.end())
1346 cur_objects = (*it).first;
1348 cur_objects = objects_map.begin()->first;
1352 case BUTTON_WHEELDOWN:
1353 it = objects_map.find(cur_objects);
1354 if(it == objects_map.begin())
1356 cur_objects = objects_map.rbegin()->first;
1360 if(--it != --objects_map.begin())
1361 cur_objects = (*it).first;
1363 cur_objects = objects_map.rbegin()->first;
1372 le_settings_bt->event(event);
1373 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1375 update_level_settings_menu();
1376 Menu::set_current(level_settings_menu);
1378 if(!cur_tilegroup.empty())
1380 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1382 if(pbutton->get_state() == BUTTON_CLICKED)
1384 le_current.Tile(pbutton->get_tag());
1388 else if(!cur_objects.empty())
1390 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1392 if(pbutton->get_state() == BUTTON_CLICKED)
1394 le_current.Object(pbutton->get_game_object());
1399 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1401 if(pbutton->get_state() == BUTTON_CLICKED)
1403 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1409 le_settings_bt->event(event);
1410 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1412 Menu::set_current(0);
1414 le_tilegroup_bt->event(event);
1415 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1417 Menu::set_current(0);
1419 le_objects_bt->event(event);
1420 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1422 Menu::set_current(0);
1427 if(!Menu::current() && !show_minimap)
1429 if(le_mouse_pressed[LEFT])
1431 if(MouseCursor::current() != mouse_select_object)
1433 if(le_current.IsTile())
1434 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1437 else if(le_mouse_clicked[LEFT])
1439 if(MouseCursor::current() == mouse_select_object)
1442 bool object_got_hit = false;
1443 base_type cursor_base;
1444 if(le_current.IsTile())
1446 cursor_base.x = cursor_x;
1447 cursor_base.y = cursor_y;
1449 else if(le_current.IsObject())
1451 cursor_base.x = cursor_x + pos_x;
1452 cursor_base.y = cursor_y + pos_y;
1454 cursor_base.width = 32;
1455 cursor_base.height = 32;
1457 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1458 if(rectcollision(cursor_base,(*it)->base))
1460 selected_game_object = (*it);
1461 object_got_hit = true;
1467 selected_game_object = NULL;
1468 le_object_properties_bt->set_active(false);
1471 le_object_properties_bt->set_active(true);
1473 MouseCursor::set_current(mouse_cursor);
1478 if(le_current.IsObject())
1480 le_level_changed = true;
1481 std::string type = le_current.obj->type();
1482 if(type == "BadGuy")
1484 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1486 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1487 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1492 le_mouse_clicked[LEFT] = false;
1498 if(!Menu::current())
1500 show_minimap = false;
1502 le_move_left_bt->event(event);
1503 le_move_right_bt->event(event);
1504 le_move_up_bt->event(event);
1505 le_move_down_bt->event(event);
1506 switch(le_move_left_bt->get_state())
1508 case BUTTON_PRESSED:
1509 pos_x -= KEYBOARD_SPEED;
1510 show_minimap = true;
1513 pos_x -= MOUSE_SPEED;
1514 show_minimap = true;
1516 case BUTTON_CLICKED:
1517 show_minimap = true;
1523 switch(le_move_right_bt->get_state())
1525 case BUTTON_PRESSED:
1526 pos_x += KEYBOARD_SPEED;
1527 show_minimap = true;
1530 pos_x += MOUSE_SPEED;
1531 show_minimap = true;
1533 case BUTTON_CLICKED:
1534 show_minimap = true;
1540 switch(le_move_up_bt->get_state())
1542 case BUTTON_PRESSED:
1543 pos_y -= KEYBOARD_SPEED;
1544 show_minimap = true;
1547 pos_y -= MOUSE_SPEED;
1548 show_minimap = true;
1550 case BUTTON_CLICKED:
1551 show_minimap = true;
1557 switch(le_move_down_bt->get_state())
1559 case BUTTON_PRESSED:
1560 pos_y += KEYBOARD_SPEED;
1561 show_minimap = true;
1564 pos_y += MOUSE_SPEED;
1565 show_minimap = true;
1567 case BUTTON_CLICKED:
1568 show_minimap = true;
1574 /* checking if pos_x and pos_y is within the limits... */
1575 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1576 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1580 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1581 pos_y = (le_world->get_level()->height * 32) - screen->h;
1589 void le_highlight_selection()
1593 if(selection.x1 < selection.x2)
1603 if(selection.y1 < selection.y2)
1619 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1622 void le_change(float x, float y, int tm, unsigned int c)
1624 if(le_world != NULL)
1630 le_level_changed = true;
1632 switch(le_selection_mode)
1635 le_world->get_level()->change(x,y,tm,c);
1637 base_type cursor_base;
1640 cursor_base.width = 32;
1641 cursor_base.height = 32;
1643 /* if there is a bad guy over there, remove it */
1644 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1645 if(rectcollision(cursor_base,(*it)->base))
1648 le_world->bad_guys.erase(it);
1649 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1655 if(selection.x1 < selection.x2)
1665 if(selection.y1 < selection.y2)
1681 /* if there is a bad guy over there, remove it */
1682 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1683 it != le_world->bad_guys.end(); /* will be at end of loop */)
1685 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1686 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1689 it = le_world->bad_guys.erase(it);
1690 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1700 for(xx = x1; xx <= x2; xx++)
1701 for(yy = y1; yy <= y2; yy++)
1703 le_world->get_level()->change(xx*32, yy*32, tm, c);
1715 //Make sure a time value is set when testing the level
1716 if(le_world->get_level()->time_left == 0)
1717 le_world->get_level()->time_left = 250;
1719 le_world->get_level()->save("test", le_level);
1721 GameSession session("test",le_level, ST_GL_TEST);
1723 player_status.reset();
1725 music_manager->halt_music();
1727 Menu::set_current(NULL);
1728 World::set_current(le_world);
1733 bool tmp_show_grid = le_show_grid;
1734 SelectionMode temp_le_selection_mode = le_selection_mode;
1735 le_selection_mode = NONE;
1736 show_selections = true;
1737 le_show_grid = false;
1738 le_help_shown = true;
1740 drawgradient(Color(0,0,0), Color(255,255,255));
1744 unsigned int i, done_;
1747 " - Supertux level editor tutorial - ",
1749 "To make your map, click the ",
1750 "tilegroup button and choose a ",
1752 "Pick a tile and simply hold down ",
1753 "the left mouse button over the map",
1754 "to \"paint\" your selection over",
1757 "There are three layers for painting",
1758 "tiles upon, Background layer,",
1759 "the Interactive layer, and the",
1760 "Foreground layer, which can be",
1761 "toggled by the BkGrd, IntAct and",
1762 "FrGrd buttons. The Foreground and",
1763 "Background layers do not effect",
1764 "Tux in the gameplay, but lie in",
1765 "front of him or lie behind him in",
1771 " - Supertux level editor tutorial - ",
1773 "The tiles placed on",
1774 "the Interactive layer are those",
1775 "which actually effect Tux in the",
1778 "Click the objects menu to put ",
1779 "bad guys and other objects in the",
1780 "game. Unlike placing tiles, you",
1781 "cannot \"paint\" enemies. Click",
1782 "them onto the screen one at a time.",
1784 "To change the settings of your",
1785 "level, click the button with the",
1786 "screwdriver and wrench. From here",
1787 "you can change the background,",
1788 "music, length of the level,",
1794 " - Supertux level editor tutorial - ",
1796 "You may have more than one level.",
1797 "Pressing the up and down buttons",
1798 "above the button bar lets you",
1799 "choose which one you are working on.",
1801 "If you would like to speed up your",
1802 "level editing, a useful trick is",
1803 "to learn the keyboard shortcuts.",
1804 "They are easy to learn, just right-",
1805 "click on the buttons.",
1807 "Have fun making levels! If you make",
1808 "some good ones, send them to us on",
1809 "the SuperTux mailing list!",
1815 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1817 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1818 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1820 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1828 done_ = wait_for_event(event);
1832 drawgradient(Color(0,0,0), Color(255,255,255));
1836 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1838 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1839 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1841 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1849 done_ = wait_for_event(event);
1853 drawgradient(Color(0,0,0), Color(255,255,255));
1857 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1859 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1860 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1862 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1870 done_ = wait_for_event(event);
1874 show_selections = true;
1875 le_show_grid = tmp_show_grid;
1876 le_selection_mode = temp_le_selection_mode;
1877 le_help_shown = false;