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.
30 #include <SDL_image.h>
32 #include "leveleditor.h"
34 #include "screen/screen.h"
45 #include "resources.h"
46 #include "background.h"
51 /* definitions to aid development */
53 /* definitions that affect gameplay */
54 #define KEY_CURSOR_SPEED 32
55 #define KEY_CURSOR_FASTSPEED 64
57 /* when pagedown/up pressed speed:*/
58 #define PAGE_CURSOR_SPEED 13*32
60 #define MOUSE_LEFT_MARGIN 80
61 #define MOUSE_RIGHT_MARGIN (560-32)
64 #define KEYBOARD_SPEED 140
65 #define MOUSE_SPEED 40
68 #define SELECT_W 2 // size of the selections lines
69 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
71 /* own declerations */
72 /* crutial ones (main loop) */
75 int le_load_level_subset(char *filename);
77 void le_drawinterface();
78 void le_checkevents();
79 void le_change(float x, float y, int tm, unsigned int c);
82 void le_set_defaults(void);
83 void le_activate_bad_guys(void);
84 void le_goto_level(int levelnb);
85 void le_highlight_selection();
87 void apply_level_settings_menu();
88 void update_subset_settings_menu();
89 void save_subset_settings_menu();
93 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
95 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
96 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
97 //Returns true for a tile
98 bool IsTile() { return is_tile; };
99 //Returns true for a GameObject
100 bool IsObject() { return !is_tile; };
103 void Init() { tile = 0; obj = NULL; is_tile = true; };
105 bool is_tile; //true for tile (false for object)
110 /* leveleditor internals */
111 static string_list_type level_subsets;
112 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
113 static bool show_minimap;
114 static bool show_selections;
115 static bool le_help_shown;
116 static int pos_x, pos_y, cursor_x, cursor_y;
118 static World* le_world;
119 static LevelSubset* le_level_subset;
120 static int le_show_grid;
122 static Surface* le_selection;
124 static TileOrObject le_current;
125 static bool le_mouse_pressed[2];
126 static bool le_mouse_clicked[2];
127 static Button* le_save_level_bt;
128 static Button* le_exit_bt;
129 static Button* le_test_level_bt;
130 static Button* le_next_level_bt;
131 static Button* le_previous_level_bt;
132 static Button* le_move_right_bt;
133 static Button* le_move_left_bt;
134 static Button* le_move_up_bt;
135 static Button* le_move_down_bt;
136 static Button* le_rubber_bt;
137 static Button* le_select_mode_one_bt;
138 static Button* le_select_mode_two_bt;
139 static Button* le_settings_bt;
140 static Button* le_tilegroup_bt;
141 static Button* le_objects_bt;
142 static Button* le_object_select_bt;
143 static Button* le_object_properties_bt;
144 static ButtonPanel* le_tilemap_panel;
145 static Menu* leveleditor_menu;
146 static Menu* subset_load_menu;
147 static Menu* subset_new_menu;
148 static Menu* subset_settings_menu;
149 static Menu* level_settings_menu;
150 static Menu* select_tilegroup_menu;
151 static Menu* select_objects_menu;
152 static Timer select_tilegroup_menu_effect;
153 static Timer select_objects_menu_effect;
154 static Timer display_level_info;
155 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
156 static ButtonPanelMap tilegroups_map;
157 static ButtonPanelMap objects_map;
158 static std::string cur_tilegroup;
159 static std::string cur_objects;
160 static MouseCursor* mouse_select_object;
161 static MovingObject* selected_game_object;
163 static square selection;
164 static SelectionMode le_selection_mode;
165 static SDL_Event event;
166 TileMapType active_tm;
168 int leveleditor(char* filename)
170 int last_time, now_time, i;
179 clearscreen(0, 0, 0);
182 music_manager->halt_music();
184 while (SDL_PollEvent(&event))
188 if(le_load_level_subset(filename))
193 last_time = SDL_GetTicks();
198 if(Menu::current() == select_tilegroup_menu)
200 if(select_tilegroup_menu_effect.check())
202 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
206 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
208 else if(Menu::current() == select_objects_menu)
210 if(select_objects_menu_effect.check())
212 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
215 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
220 /* making events results to be in order */
226 clearscreen(0, 0, 0);
228 /* draw editor interface */
231 Menu* menu = Menu::current();
237 if(menu == leveleditor_menu)
239 switch (leveleditor_menu->check())
241 case MNID_RETURNLEVELEDITOR:
243 Menu::set_current(0);
245 Menu::set_current(leveleditor_menu);
247 case MNID_SUBSETSETTINGS:
248 update_subset_settings_menu();
250 case MNID_QUITLEVELEDITOR:
255 else if(menu == level_settings_menu)
257 switch (level_settings_menu->check())
260 apply_level_settings_menu();
261 Menu::set_current(NULL);
268 else if(menu == select_tilegroup_menu)
271 switch (it = select_tilegroup_menu->check())
276 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
277 Menu::set_current(0);
284 else if(menu == select_objects_menu)
287 switch (it = select_objects_menu->check())
292 cur_objects = select_objects_menu->get_item_by_id(it).text;
295 Menu::set_current(0);
300 else if(menu == subset_load_menu)
302 switch (i = subset_load_menu->check())
309 if(le_load_level_subset(level_subsets.item[i-1]))
315 else if(menu == subset_new_menu)
317 if(subset_new_menu->item[2].input[0] == '\0')
318 subset_new_menu->item[3].kind = MN_DEACTIVE;
321 subset_new_menu->item[3].kind = MN_ACTION;
323 switch (i = subset_new_menu->check())
325 case MNID_CREATESUBSET:
326 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
327 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
328 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
330 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
332 Menu::set_current(subset_settings_menu);
337 else if(menu == subset_settings_menu)
339 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 )
340 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
342 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
344 switch (i = subset_settings_menu->check())
346 case MNID_SUBSETSAVECHANGES:
347 save_subset_settings_menu();
348 Menu::set_current(leveleditor_menu);
354 MouseCursor::current()->draw();
362 ++global_frame_counter;
365 now_time = SDL_GetTicks();
366 if (now_time < last_time + FPS)
367 SDL_Delay(last_time + FPS - now_time); /* delay some time */
375 int le_load_level_subset(char *filename)
377 le_level_subset->load(filename);
378 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
382 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
384 Menu::set_current(NULL);
393 leveleditor_menu = new Menu();
394 subset_load_menu = new Menu();
395 subset_new_menu = new Menu();
396 subset_settings_menu = new Menu();
397 level_settings_menu = new Menu();
398 select_tilegroup_menu = new Menu();
399 select_objects_menu = new Menu();
401 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
402 leveleditor_menu->additem(MN_HL,"",0,0);
403 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
404 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
405 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
406 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
407 leveleditor_menu->additem(MN_HL,"",0,0);
408 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
410 Menu::set_current(leveleditor_menu);
412 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
413 subset_load_menu->additem(MN_HL, "", 0, 0);
415 for(i = 0; i < level_subsets.num_items; ++i)
417 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
419 subset_load_menu->additem(MN_HL,"",0,0);
420 subset_load_menu->additem(MN_BACK,"Back",0,0);
422 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
423 subset_new_menu->additem(MN_HL,"",0,0);
424 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
425 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
426 subset_new_menu->additem(MN_HL,"",0,0);
427 subset_new_menu->additem(MN_BACK,"Back",0,0);
429 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
430 subset_settings_menu->additem(MN_HL,"",0,0);
431 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
432 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
433 subset_settings_menu->additem(MN_HL,"",0,0);
434 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
435 subset_settings_menu->additem(MN_HL,"",0,0);
436 subset_settings_menu->additem(MN_BACK,"Back",0,0);
438 level_settings_menu->arrange_left = true;
439 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
440 level_settings_menu->additem(MN_HL,"",0,0);
441 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
442 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
443 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
444 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
445 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
446 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
447 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
448 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
449 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
450 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
451 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
452 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
453 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
454 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
455 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
456 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
457 level_settings_menu->additem(MN_HL,"",0,0);
458 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
460 select_tilegroup_menu->arrange_left = true;
461 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
462 select_tilegroup_menu->additem(MN_HL,"",0,0);
463 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
465 for(std::set<TileGroup>::iterator it = tilegroups->begin();
466 it != tilegroups->end(); ++it )
468 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
470 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
473 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
474 sit != (*it).tiles.end(); ++sit, ++i)
476 Tile& tile = *(TileManager::instance()->get(*sit));
478 if(tile.editor_images.size() > 0)
479 image = tile.editor_images[0];
480 else if(tile.images.size() > 0)
481 image = tile.images[0];
483 // TODO use some notile image...
486 Button* button = new Button(image, it->name, SDLKey(SDLK_a + i),
488 tilegroups_map[it->name]->additem(button, *sit);
491 select_tilegroup_menu->additem(MN_HL,"",0,0);
493 select_objects_menu->arrange_left = true;
494 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
495 select_objects_menu->additem(MN_HL,"",0,0);
497 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
498 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
500 DisplayManager dummy;
501 for(int i = 0; i < NUM_BadGuyKinds; ++i)
503 BadGuy bad_tmp(dummy, BadGuyKind(i), 0, 0);
504 objects_map["BadGuys"]->additem(new Button(0, "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
505 objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
508 objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
509 objects_map["BadGuys"]->manipulate_button(i)->get_pos().y
513 select_objects_menu->additem(MN_HL,"",0,0);
519 level_subsets = dsubdirs("/levels", "level1.stl");
520 le_level_subset = new LevelSubset;
523 selected_game_object = NULL;
527 show_selections = true;
530 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
531 le_level_changed = false;
532 le_help_shown = false;
534 le_mouse_pressed[LEFT] = false;
535 le_mouse_pressed[RIGHT] = false;
537 le_mouse_clicked[LEFT] = false;
538 le_mouse_clicked[RIGHT] = false;
540 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
542 select_tilegroup_menu_effect.init(false);
543 select_objects_menu_effect.init(false);
544 display_level_info.init(false);
547 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
548 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
549 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
550 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
551 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
552 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
553 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
554 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
555 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
556 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
557 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
558 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
559 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
560 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
561 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
562 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
563 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
564 le_object_properties_bt->set_active(false);
566 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
567 mouse_select_object->set_mid(16,16);
569 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
570 le_tilemap_panel->set_button_size(32,10);
571 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
572 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
573 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
574 le_tilemap_panel->highlight_last(true);
575 le_tilemap_panel->set_last_clicked(TM_IA);
581 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
587 void update_level_settings_menu()
592 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
593 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
595 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
596 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
597 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
598 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
599 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
600 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
602 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
603 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
604 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
605 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
606 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
607 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
609 sprintf(str,"%d",le_world->get_level()->width);
610 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
611 sprintf(str,"%d",le_world->get_level()->height);
612 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
613 sprintf(str,"%d",le_world->get_level()->time_left);
614 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
615 sprintf(str,"%2.0f",le_world->get_level()->gravity);
616 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
617 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
618 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
619 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
620 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
621 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
622 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
623 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
624 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
625 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
626 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
627 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
628 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
629 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
630 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
633 void update_subset_settings_menu()
635 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
636 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
639 void apply_level_settings_menu()
643 le_level_changed = true;
645 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
646 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
648 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
650 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
654 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
656 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
661 le_world->get_level()->load_gfx();
664 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
666 le_world->get_level()->resize(
667 atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
668 atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
669 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
670 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
671 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
672 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
673 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
674 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
675 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
676 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
677 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
680 void save_subset_settings_menu()
682 le_level_subset->title = subset_settings_menu->item[2].input;
683 le_level_subset->description = subset_settings_menu->item[3].input;
684 le_level_subset->save();
685 le_level_changed = false;
688 void le_unload_level()
695 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
696 if(confirm_dialog(str))
698 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 > le_world->get_level()->height * 4)
779 mini_tile_height = 4;
780 else if(screen->h > le_world->get_level()->height * 2)
781 mini_tile_height = 2;
783 mini_tile_height = 1;
785 Level* level = le_world->get_level();
786 for (int y = 0; y < le_world->get_level()->height; ++y)
787 for (int x = 0; x < le_world->get_level()->width; ++x)
790 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
791 mini_tile_width , mini_tile_height, level->bg_tiles[y * level->width + x]);
793 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
794 mini_tile_width , mini_tile_height, level->ia_tiles[y * level->width + x]);
796 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
797 mini_tile_width , mini_tile_height, level->fg_tiles[y + level->width + x]);
801 fillrect(left_offset, 0,
802 le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height,
805 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height,
806 (VISIBLE_TILES_X-3)*mini_tile_width, 2,
808 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height,
809 2, (VISIBLE_TILES_Y-1)*mini_tile_height,
811 fillrect(left_offset + (pos_x/32)*mini_tile_width + (VISIBLE_TILES_X-3)*mini_tile_width - 2, (pos_y/32)*mini_tile_height,
812 2, (VISIBLE_TILES_Y-1)*mini_tile_height,
814 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height + (VISIBLE_TILES_Y-1)*mini_tile_height - 2,
815 (VISIBLE_TILES_X-3)*mini_tile_width, 2,
819 void le_drawinterface()
826 /* draw a grid (if selected) */
829 for(x = 0; x < VISIBLE_TILES_X; x++)
830 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
831 for(y = 0; y < VISIBLE_TILES_Y; y++)
832 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
836 if(show_minimap) // use_gl because the minimap isn't shown correctly in software mode. Any idea? FIXME Possible reasons: SDL_SoftStretch is a hack itsself || an alpha blitting issue SDL can't handle in software mode
839 if(show_selections && MouseCursor::current() != mouse_select_object)
841 if(le_selection_mode == CURSOR)
843 if(le_current.IsTile())
844 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
846 else if(le_selection_mode == SQUARE)
849 le_highlight_selection();
850 /* draw current selection */
851 w = selection.x2 - selection.x1;
852 h = selection.y2 - selection.y1;
853 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
854 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
855 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
856 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
861 /* draw button bar */
862 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
864 if(le_current.IsTile())
866 Tile::draw(screen->w - 32, screen->h - 32, le_current.tile);
867 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
868 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
870 #if 0 // XXX FIXME TODO: Do we have a new solution for draw_on_screen()?
871 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
873 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
874 le_current.obj->draw_on_screen(cursor_x,cursor_y);
878 if(mouse_select_object && selected_game_object != NULL)
880 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,selected_game_object->base.width,3,255,0,0,255);
881 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255);
882 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y+selected_game_object->base.height,selected_game_object->base.width,3,255,0,0,255);
883 fillrect(selected_game_object->base.x-pos_x+selected_game_object->base.width,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255);
888 le_save_level_bt->draw();
890 le_test_level_bt->draw();
891 le_next_level_bt->draw();
892 le_previous_level_bt->draw();
893 le_rubber_bt->draw();
894 if(le_selection_mode == SQUARE)
895 le_select_mode_one_bt->draw();
896 else if(le_selection_mode == CURSOR)
897 le_select_mode_two_bt->draw();
898 le_settings_bt->draw();
899 le_move_right_bt->draw();
900 le_move_left_bt->draw();
901 le_move_up_bt->draw();
902 le_move_down_bt->draw();
903 le_tilegroup_bt->draw();
904 le_objects_bt->draw();
905 if(!cur_tilegroup.empty())
906 tilegroups_map[cur_tilegroup]->draw();
907 else if(!cur_objects.empty())
909 objects_map[cur_objects]->draw();
912 le_tilemap_panel->draw();
914 if(!cur_objects.empty())
916 le_object_select_bt->draw();
917 le_object_properties_bt->draw();
920 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
921 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
924 white_small_text->draw("F1 for Help", 10, 430, 1);
926 if(display_level_info.check())
927 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
932 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
934 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
944 /* Draw the real background */
945 le_world->background->draw(*le_world->camera, LAYER_BACKGROUND0);
947 if(le_current.IsTile())
949 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
950 if(!TileManager::instance()->get(le_current.tile)->images.empty())
951 fillrect(cursor_x-pos_x,cursor_y-pos_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);
953 #if 0 // XXX FIXME TODO: Do we have a new solution for move_to()?
954 if(le_current.IsObject())
956 le_current.obj->move_to(cursor_x, cursor_y);
960 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
962 Level* level = le_world->get_level();
963 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
964 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
967 if(active_tm == TM_BG)
972 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
973 level->bg_tiles[ (y + (int)(pos_y / 32)) * level->width +
974 (x + (int)(pos_x / 32))],a);
976 if(active_tm == TM_IA)
981 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
982 level->ia_tiles[ (y + (int)(pos_y / 32)) * level->width +
983 (x + (int)(pos_x / 32))],a);
986 if(active_tm == TM_FG)
991 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
992 level->fg_tiles[ (y + (int)(pos_y / 32)) * level->width +
993 (x + (int)(pos_x / 32))],a);
995 /* draw whats inside stuff when cursor is selecting those */
996 /* (draw them all the time - is this the right behaviour?) */
997 Tile* edit_image = TileManager::instance()->get(
999 [ (y + (int)(pos_y / 32)) * level->width + (x + (int)(pos_x / 32))]);
1000 if(edit_image && !edit_image->editor_images.empty())
1001 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
1005 /* Draw the Bad guys: */
1006 for (std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1007 it != le_world->gameobjects.end(); ++it)
1009 BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
1013 /* to support frames: img_bsod_left[(frame / 5) % 4] */
1015 viewport.set_translation(Vector(pos_x, pos_y));
1016 badguy->draw(viewport, 0);
1019 /* Draw the player: */
1020 /* for now, the position is fixed at (100, 240) */
1021 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
1024 void le_change_object_properties(GameObject *pobj)
1026 //Surface* cap_screen = Surface::CaptureScreen();
1028 Menu* object_properties_menu = new Menu();
1031 std::string type = typeid(pobj).name();
1032 object_properties_menu->additem(MN_LABEL, type + " Properties",0,0);
1033 object_properties_menu->additem(MN_HL,"",0,0);
1035 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1038 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1039 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1041 string_list_add_item(object_properties_menu->get_item_by_id(1).list,
1042 badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1044 object_properties_menu->get_item_by_id(1).list->active_item = i;
1046 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1049 object_properties_menu->additem(MN_HL,"",0,0);
1050 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1052 Menu::set_current(object_properties_menu);
1058 while (SDL_PollEvent(&event))
1060 object_properties_menu->event(event);
1063 //cap_screen->draw(0,0);
1065 object_properties_menu->draw();
1066 object_properties_menu->action();
1068 switch (object_properties_menu->check())
1072 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1074 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1075 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1076 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1085 if(Menu::current() == NULL)
1088 mouse_cursor->draw();
1093 //delete cap_screen;
1094 Menu::set_current(0);
1095 delete object_properties_menu;
1099 void le_checkevents()
1106 keymod = SDL_GetModState();
1108 while(SDL_PollEvent(&event))
1110 if (Menu::current())
1112 Menu::current()->event(event);
1113 if(!le_world && !Menu::current())
1114 Menu::set_current(leveleditor_menu);
1118 mouse_cursor->set_state(MC_NORMAL);
1120 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1121 if(event.type == SDL_KEYDOWN
1122 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1123 && (event.motion.x > 0
1124 && event.motion.x < screen->w - 64 &&
1125 event.motion.y > 0 && event.motion.y < screen->h)))
1129 case SDL_KEYDOWN: // key pressed
1130 key = event.key.keysym.sym;
1134 Menu::set_current(leveleditor_menu);
1137 if(le_world != NULL)
1145 cursor_x = (le_world->get_level()->width * 32) - 32;
1149 le_show_grid = !le_show_grid;
1155 case SDL_MOUSEBUTTONDOWN:
1156 if(event.button.button == SDL_BUTTON_LEFT)
1158 le_mouse_pressed[LEFT] = true;
1160 selection.x1 = event.motion.x + pos_x;
1161 selection.y1 = event.motion.y + pos_y;
1162 selection.x2 = event.motion.x + pos_x;
1163 selection.y2 = event.motion.y + pos_y;
1165 else if(event.button.button == SDL_BUTTON_RIGHT)
1167 le_mouse_pressed[RIGHT] = true;
1170 case SDL_MOUSEBUTTONUP:
1171 if(event.button.button == SDL_BUTTON_LEFT)
1173 le_mouse_pressed[LEFT] = false;
1174 le_mouse_clicked[LEFT] = true;
1176 else if(event.button.button == SDL_BUTTON_RIGHT)
1178 le_mouse_pressed[RIGHT] = false;
1179 le_mouse_clicked[RIGHT] = true;
1182 case SDL_MOUSEMOTION:
1184 if(!Menu::current())
1189 if(le_current.IsTile())
1191 cursor_x = ((int)(pos_x + x) / 32) * 32;
1192 cursor_y = ((int)(pos_y + y) / 32) * 32;
1200 if(le_mouse_pressed[LEFT])
1202 selection.x2 = x + pos_x;
1203 selection.y2 = y + pos_y;
1206 if(le_mouse_pressed[RIGHT])
1208 pos_x += -1 * event.motion.xrel;
1209 pos_y += -1 * event.motion.yrel;
1217 else if(event.type == SDL_QUIT) /* window closing */
1223 if(le_world != NULL)
1225 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 &&
1226 event.motion.y > 0 && event.motion.y < screen->h)))
1228 le_mouse_pressed[LEFT] = false;
1229 le_mouse_pressed[RIGHT] = false;
1231 if(!Menu::current())
1233 /* Check for button events */
1234 le_test_level_bt->event(event);
1235 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1237 le_save_level_bt->event(event);
1238 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1239 le_world->get_level()->save(le_level_subset->name.c_str(),le_level,
1241 le_exit_bt->event(event);
1242 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1244 Menu::set_current(leveleditor_menu);
1246 le_next_level_bt->event(event);
1247 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1249 if(le_level < le_level_subset->levels)
1251 le_goto_level(le_level+1);
1257 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1258 if(confirm_dialog(str))
1260 new_lev.init_defaults();
1261 new_lev.save(le_level_subset->name.c_str(),le_level+1, le_world);
1262 le_level_subset->levels = le_level;
1263 le_goto_level(le_level);
1267 le_previous_level_bt->event(event);
1268 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1271 le_goto_level(le_level -1);
1273 le_rubber_bt->event(event);
1274 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1277 if(!cur_objects.empty())
1279 le_object_select_bt->event(event);
1280 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1282 MouseCursor::set_current(mouse_select_object);
1285 le_object_properties_bt->event(event);
1286 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1288 le_change_object_properties(selected_game_object);
1293 if(le_selection_mode == SQUARE)
1295 le_select_mode_one_bt->event(event);
1296 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1297 le_selection_mode = CURSOR;
1301 le_select_mode_two_bt->event(event);
1302 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1303 le_selection_mode = SQUARE;
1305 ButtonPanelMap::iterator it;
1306 le_tilegroup_bt->event(event);
1307 switch (le_tilegroup_bt->get_state())
1309 case BUTTON_CLICKED:
1310 Menu::set_current(select_tilegroup_menu);
1311 select_tilegroup_menu_effect.start(200);
1312 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1314 case BUTTON_WHEELUP:
1315 if(cur_tilegroup.empty())
1317 cur_tilegroup = tilegroups_map.begin()->first;
1321 it = tilegroups_map.find(cur_tilegroup);
1322 if((++it) == tilegroups_map.end())
1324 cur_tilegroup = tilegroups_map.begin()->first;
1328 cur_tilegroup = (*it).first;
1334 case BUTTON_WHEELDOWN:
1335 it = tilegroups_map.find(cur_tilegroup);
1336 if(it == tilegroups_map.begin())
1338 cur_tilegroup = tilegroups_map.rbegin()->first;
1342 if(--it != --tilegroups_map.begin())
1343 cur_tilegroup = (*it).first;
1345 cur_tilegroup = tilegroups_map.rbegin()->first;
1353 le_objects_bt->event(event);
1354 switch (le_objects_bt->get_state())
1356 case BUTTON_CLICKED:
1357 Menu::set_current(select_objects_menu);
1358 select_objects_menu_effect.start(200);
1359 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1361 case BUTTON_WHEELUP:
1362 it = objects_map.find(cur_objects);
1363 if(it == objects_map.end())
1365 cur_objects = objects_map.begin()->first;
1369 if(++it != objects_map.end())
1370 cur_objects = (*it).first;
1372 cur_objects = objects_map.begin()->first;
1376 case BUTTON_WHEELDOWN:
1377 it = objects_map.find(cur_objects);
1378 if(it == objects_map.begin())
1380 cur_objects = objects_map.rbegin()->first;
1384 if(--it != --objects_map.begin())
1385 cur_objects = (*it).first;
1387 cur_objects = objects_map.rbegin()->first;
1396 le_settings_bt->event(event);
1397 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1399 update_level_settings_menu();
1400 Menu::set_current(level_settings_menu);
1402 if(!cur_tilegroup.empty())
1404 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1406 if(pbutton->get_state() == BUTTON_CLICKED)
1408 le_current.Tile(pbutton->get_tag());
1412 else if(!cur_objects.empty())
1414 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1416 if(pbutton->get_state() == BUTTON_CLICKED)
1418 #if 0 // TODO FIXME XXX: New solution for this?
1419 le_current.Object(pbutton->get_drawable());
1425 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1427 if(pbutton->get_state() == BUTTON_CLICKED)
1429 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1435 le_settings_bt->event(event);
1436 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1438 Menu::set_current(0);
1440 le_tilegroup_bt->event(event);
1441 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1443 Menu::set_current(0);
1445 le_objects_bt->event(event);
1446 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1448 Menu::set_current(0);
1453 if(!Menu::current() && !show_minimap)
1455 if(le_mouse_pressed[LEFT])
1457 if(MouseCursor::current() != mouse_select_object)
1459 if(le_current.IsTile())
1460 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1463 else if(le_mouse_clicked[LEFT])
1465 if(MouseCursor::current() == mouse_select_object)
1467 bool object_got_hit = false;
1468 base_type cursor_base;
1469 if(le_current.IsTile())
1471 cursor_base.x = cursor_x;
1472 cursor_base.y = cursor_y;
1474 else if(le_current.IsObject())
1476 cursor_base.x = cursor_x + pos_x;
1477 cursor_base.y = cursor_y + pos_y;
1479 cursor_base.width = 32;
1480 cursor_base.height = 32;
1482 for(std::vector<GameObject*>::iterator it =
1483 le_world->gameobjects.begin();
1484 it != le_world->gameobjects.end(); ++it) {
1485 MovingObject* mobj = dynamic_cast<MovingObject*> (*it);
1489 if(rectcollision(cursor_base, mobj->base))
1491 selected_game_object = mobj;
1492 object_got_hit = true;
1499 selected_game_object = NULL;
1500 le_object_properties_bt->set_active(false);
1503 le_object_properties_bt->set_active(true);
1505 MouseCursor::set_current(mouse_cursor);
1511 if(le_current.IsObject())
1513 le_level_changed = true;
1514 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1518 Camera& camera = *le_world->camera;
1519 DisplayManager dummy;
1521 le_world->bad_guys.push_back(
1522 new BadGuy(dummy, pbadguy->kind,
1523 cursor_x + camera.get_translation().x,
1524 cursor_y + camera.get_translation().y));
1525 le_world->gameobjects.push_back(le_world->bad_guys.back());
1531 le_mouse_clicked[LEFT] = false;
1537 if(!Menu::current())
1539 show_minimap = false;
1541 if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_TAB)
1542 show_minimap = true;
1544 le_move_left_bt->event(event);
1545 le_move_right_bt->event(event);
1546 le_move_up_bt->event(event);
1547 le_move_down_bt->event(event);
1548 switch(le_move_left_bt->get_state())
1550 case BUTTON_PRESSED:
1551 pos_x -= KEYBOARD_SPEED;
1552 show_minimap = true;
1555 pos_x -= MOUSE_SPEED;
1556 show_minimap = true;
1558 case BUTTON_CLICKED:
1559 show_minimap = true;
1565 switch(le_move_right_bt->get_state())
1567 case BUTTON_PRESSED:
1568 pos_x += KEYBOARD_SPEED;
1569 show_minimap = true;
1572 pos_x += MOUSE_SPEED;
1573 show_minimap = true;
1575 case BUTTON_CLICKED:
1576 show_minimap = true;
1582 switch(le_move_up_bt->get_state())
1584 case BUTTON_PRESSED:
1585 pos_y -= KEYBOARD_SPEED;
1586 show_minimap = true;
1589 pos_y -= MOUSE_SPEED;
1590 show_minimap = true;
1592 case BUTTON_CLICKED:
1593 show_minimap = true;
1599 switch(le_move_down_bt->get_state())
1601 case BUTTON_PRESSED:
1602 pos_y += KEYBOARD_SPEED;
1603 show_minimap = true;
1606 pos_y += MOUSE_SPEED;
1607 show_minimap = true;
1609 case BUTTON_CLICKED:
1610 show_minimap = true;
1616 /* checking if pos_x and pos_y is within the limits... */
1617 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1618 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1622 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1623 pos_y = (le_world->get_level()->height * 32) - screen->h;
1629 void le_highlight_selection()
1633 if(selection.x1 < selection.x2)
1643 if(selection.y1 < selection.y2)
1659 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1662 void le_change(float x, float y, int tm, unsigned int c)
1664 if(le_world != NULL)
1669 le_level_changed = true;
1671 switch(le_selection_mode)
1674 le_world->get_level()->change(x,y,tm,c);
1676 base_type cursor_base;
1679 cursor_base.width = 32;
1680 cursor_base.height = 32;
1682 /* if there is a bad guy over there, remove it */
1684 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1685 it != le_world->gameobjects.end(); ++it) {
1686 BadGuy* badguy = dynamic_cast<BadGuy*>((*it));
1689 if(rectcollision(cursor_base, badguy->base))
1692 //le_world->bad_guys.erase(it);
1693 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1701 if(selection.x1 < selection.x2)
1711 if(selection.y1 < selection.y2)
1727 /* if there is a bad guy over there, remove it */
1729 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1730 it != le_world->gameobjects.end(); ++it /* will be at end of loop */)
1732 MovingObject* pmobject = dynamic_cast<MovingObject*> (*it);
1735 if(pmobject->base.x/32 >= x1 && pmobject->base.x/32 <= x2
1736 && pmobject->base.y/32 >= y1 && pmobject->base.y/32 <= y2)
1739 //it = le_world->gameobjects.erase(it);
1740 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1750 for(xx = x1; xx <= x2; xx++)
1751 for(yy = y1; yy <= y2; yy++)
1753 le_world->get_level()->change(xx*32, yy*32, tm, c);
1765 //Make sure a time value is set when testing the level
1766 if(le_world->get_level()->time_left == 0)
1767 le_world->get_level()->time_left = 250;
1769 le_world->get_level()->save("test", le_level, le_world);
1771 GameSession session("test",le_level, ST_GL_TEST);
1773 player_status.reset();
1775 music_manager->halt_music();
1777 Menu::set_current(NULL);
1778 World::set_current(le_world);
1783 bool tmp_show_grid = le_show_grid;
1784 SelectionMode temp_le_selection_mode = le_selection_mode;
1785 le_selection_mode = NONE;
1786 show_selections = true;
1787 le_show_grid = false;
1788 le_help_shown = true;
1790 drawgradient(Color(0,0,0), Color(255,255,255));
1794 unsigned int i, done_;
1797 " - Supertux level editor tutorial - ",
1799 "To make your map, click the ",
1800 "tilegroup button and choose a ",
1802 "Pick a tile and simply hold down ",
1803 "the left mouse button over the map",
1804 "to \"paint\" your selection over",
1807 "There are three layers for painting",
1808 "tiles upon, Background layer,",
1809 "the Interactive layer, and the",
1810 "Foreground layer, which can be",
1811 "toggled by the BkGrd, IntAct and",
1812 "FrGrd buttons. The Foreground and",
1813 "Background layers do not effect",
1814 "Tux in the gameplay, but lie in",
1815 "front of him or lie behind him in",
1821 " - Supertux level editor tutorial - ",
1823 "The tiles placed on",
1824 "the Interactive layer are those",
1825 "which actually effect Tux in the",
1828 "Click the objects menu to put ",
1829 "bad guys and other objects in the",
1830 "game. Unlike placing tiles, you",
1831 "cannot \"paint\" enemies. Click",
1832 "them onto the screen one at a time.",
1834 "To change the settings of your",
1835 "level, click the button with the",
1836 "screwdriver and wrench. From here",
1837 "you can change the background,",
1838 "music, length of the level,",
1844 " - Supertux level editor tutorial - ",
1846 "You may have more than one level.",
1847 "Pressing the up and down buttons",
1848 "above the button bar lets you",
1849 "choose which one you are working on.",
1851 "If you would like to speed up your",
1852 "level editing, a useful trick is",
1853 "to learn the keyboard shortcuts.",
1854 "They are easy to learn, just right-",
1855 "click on the buttons.",
1857 "Have fun making levels! If you make",
1858 "some good ones, send them to us on",
1859 "the SuperTux mailing list!",
1865 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1867 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1868 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1870 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1878 done_ = wait_for_event(event);
1882 drawgradient(Color(0,0,0), Color(255,255,255));
1886 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1888 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1889 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1891 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1899 done_ = wait_for_event(event);
1903 drawgradient(Color(0,0,0), Color(255,255,255));
1907 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1909 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1910 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1912 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1920 done_ = wait_for_event(event);
1924 show_selections = true;
1925 le_show_grid = tmp_show_grid;
1926 le_selection_mode = temp_le_selection_mode;
1927 le_help_shown = false;