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"
45 #include "resources.h"
46 #include "music_manager.h"
47 #include "background.h"
48 #include "display_manager.h"
50 /* definitions to aid development */
52 /* definitions that affect gameplay */
53 #define KEY_CURSOR_SPEED 32
54 #define KEY_CURSOR_FASTSPEED 64
56 /* when pagedown/up pressed speed:*/
57 #define PAGE_CURSOR_SPEED 13*32
59 #define MOUSE_LEFT_MARGIN 80
60 #define MOUSE_RIGHT_MARGIN (560-32)
63 #define KEYBOARD_SPEED 140
64 #define MOUSE_SPEED 40
67 #define SELECT_W 2 // size of the selections lines
68 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
70 /* own declerations */
71 /* crutial ones (main loop) */
74 int le_load_level_subset(char *filename);
76 void le_drawinterface();
77 void le_checkevents();
78 void le_change(float x, float y, int tm, unsigned int c);
81 void le_set_defaults(void);
82 void le_activate_bad_guys(void);
83 void le_goto_level(int levelnb);
84 void le_highlight_selection();
86 void apply_level_settings_menu();
87 void update_subset_settings_menu();
88 void save_subset_settings_menu();
92 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
94 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
95 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
96 //Returns true for a tile
97 bool IsTile() { return is_tile; };
98 //Returns true for a GameObject
99 bool IsObject() { return !is_tile; };
102 void Init() { tile = 0; obj = NULL; is_tile = true; };
104 bool is_tile; //true for tile (false for object)
109 /* leveleditor internals */
110 static string_list_type level_subsets;
111 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
112 static bool show_minimap;
113 static bool show_selections;
114 static bool le_help_shown;
115 static int pos_x, pos_y, cursor_x, cursor_y;
117 static World* le_world;
118 static LevelSubset* le_level_subset;
119 static int le_show_grid;
121 static Surface* le_selection;
123 static TileOrObject le_current;
124 static bool le_mouse_pressed[2];
125 static bool le_mouse_clicked[2];
126 static Button* le_save_level_bt;
127 static Button* le_exit_bt;
128 static Button* le_test_level_bt;
129 static Button* le_next_level_bt;
130 static Button* le_previous_level_bt;
131 static Button* le_move_right_bt;
132 static Button* le_move_left_bt;
133 static Button* le_move_up_bt;
134 static Button* le_move_down_bt;
135 static Button* le_rubber_bt;
136 static Button* le_select_mode_one_bt;
137 static Button* le_select_mode_two_bt;
138 static Button* le_settings_bt;
139 static Button* le_tilegroup_bt;
140 static Button* le_objects_bt;
141 static Button* le_object_select_bt;
142 static Button* le_object_properties_bt;
143 static ButtonPanel* le_tilemap_panel;
144 static Menu* leveleditor_menu;
145 static Menu* subset_load_menu;
146 static Menu* subset_new_menu;
147 static Menu* subset_settings_menu;
148 static Menu* level_settings_menu;
149 static Menu* select_tilegroup_menu;
150 static Menu* select_objects_menu;
151 static Timer select_tilegroup_menu_effect;
152 static Timer select_objects_menu_effect;
153 static Timer display_level_info;
154 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
155 static ButtonPanelMap tilegroups_map;
156 static ButtonPanelMap objects_map;
157 static std::string cur_tilegroup;
158 static std::string cur_objects;
159 static MouseCursor* mouse_select_object;
160 static MovingObject* selected_game_object;
162 static square selection;
163 static SelectionMode le_selection_mode;
164 static SDL_Event event;
165 TileMapType active_tm;
167 int leveleditor(char* filename)
169 int last_time, now_time, i;
178 clearscreen(0, 0, 0);
181 music_manager->halt_music();
183 while (SDL_PollEvent(&event))
187 if(le_load_level_subset(filename))
192 last_time = SDL_GetTicks();
197 if(Menu::current() == select_tilegroup_menu)
199 if(select_tilegroup_menu_effect.check())
201 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
205 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
207 else if(Menu::current() == select_objects_menu)
209 if(select_objects_menu_effect.check())
211 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
214 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
219 /* making events results to be in order */
225 clearscreen(0, 0, 0);
227 /* draw editor interface */
230 Menu* menu = Menu::current();
236 if(menu == leveleditor_menu)
238 switch (leveleditor_menu->check())
240 case MNID_RETURNLEVELEDITOR:
242 Menu::set_current(0);
244 Menu::set_current(leveleditor_menu);
246 case MNID_SUBSETSETTINGS:
247 update_subset_settings_menu();
249 case MNID_QUITLEVELEDITOR:
254 else if(menu == level_settings_menu)
256 switch (level_settings_menu->check())
259 apply_level_settings_menu();
260 Menu::set_current(NULL);
267 else if(menu == select_tilegroup_menu)
270 switch (it = select_tilegroup_menu->check())
275 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
276 Menu::set_current(0);
283 else if(menu == select_objects_menu)
286 switch (it = select_objects_menu->check())
291 cur_objects = select_objects_menu->get_item_by_id(it).text;
294 Menu::set_current(0);
299 else if(menu == subset_load_menu)
301 switch (i = subset_load_menu->check())
308 if(le_load_level_subset(level_subsets.item[i-1]))
314 else if(menu == subset_new_menu)
316 if(subset_new_menu->item[2].input[0] == '\0')
317 subset_new_menu->item[3].kind = MN_DEACTIVE;
320 subset_new_menu->item[3].kind = MN_ACTION;
322 switch (i = subset_new_menu->check())
324 case MNID_CREATESUBSET:
325 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
326 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
327 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
329 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
331 Menu::set_current(subset_settings_menu);
336 else if(menu == subset_settings_menu)
338 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 )
339 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
341 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
343 switch (i = subset_settings_menu->check())
345 case MNID_SUBSETSAVECHANGES:
346 save_subset_settings_menu();
347 Menu::set_current(leveleditor_menu);
353 MouseCursor::current()->draw();
361 ++global_frame_counter;
364 now_time = SDL_GetTicks();
365 if (now_time < last_time + FPS)
366 SDL_Delay(last_time + FPS - now_time); /* delay some time */
374 int le_load_level_subset(char *filename)
376 le_level_subset->load(filename);
377 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
381 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
383 Menu::set_current(NULL);
392 leveleditor_menu = new Menu();
393 subset_load_menu = new Menu();
394 subset_new_menu = new Menu();
395 subset_settings_menu = new Menu();
396 level_settings_menu = new Menu();
397 select_tilegroup_menu = new Menu();
398 select_objects_menu = new Menu();
400 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
401 leveleditor_menu->additem(MN_HL,"",0,0);
402 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
403 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
404 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
405 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
406 leveleditor_menu->additem(MN_HL,"",0,0);
407 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
409 Menu::set_current(leveleditor_menu);
411 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
412 subset_load_menu->additem(MN_HL, "", 0, 0);
414 for(i = 0; i < level_subsets.num_items; ++i)
416 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
418 subset_load_menu->additem(MN_HL,"",0,0);
419 subset_load_menu->additem(MN_BACK,"Back",0,0);
421 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
422 subset_new_menu->additem(MN_HL,"",0,0);
423 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
424 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
425 subset_new_menu->additem(MN_HL,"",0,0);
426 subset_new_menu->additem(MN_BACK,"Back",0,0);
428 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
429 subset_settings_menu->additem(MN_HL,"",0,0);
430 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
431 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
432 subset_settings_menu->additem(MN_HL,"",0,0);
433 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
434 subset_settings_menu->additem(MN_HL,"",0,0);
435 subset_settings_menu->additem(MN_BACK,"Back",0,0);
437 level_settings_menu->arrange_left = true;
438 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
439 level_settings_menu->additem(MN_HL,"",0,0);
440 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
441 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
442 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
443 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
444 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
445 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
446 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
447 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
448 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
449 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
450 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
451 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
452 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
453 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
454 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
455 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
456 level_settings_menu->additem(MN_HL,"",0,0);
457 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
459 select_tilegroup_menu->arrange_left = true;
460 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
461 select_tilegroup_menu->additem(MN_HL,"",0,0);
462 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
464 for(std::set<TileGroup>::iterator it = tilegroups->begin();
465 it != tilegroups->end(); ++it )
467 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
469 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
472 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
473 sit != (*it).tiles.end(); ++sit, ++i)
475 std::string imagefile = "/images/tilesets/" ;
476 bool only_editor_image = false;
477 if(!TileManager::instance()->get(*sit)->filenames.empty())
479 imagefile += TileManager::instance()->get(*sit)->filenames[0];
481 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
483 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
484 only_editor_image = true;
488 imagefile += "notile.png";
490 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
492 if(!only_editor_image)
493 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
495 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
496 button->add_icon(imagefile,32,32);
498 tilegroups_map[it->name]->additem(button, *sit);
501 select_tilegroup_menu->additem(MN_HL,"",0,0);
503 select_objects_menu->arrange_left = true;
504 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
505 select_objects_menu->additem(MN_HL,"",0,0);
507 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
508 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
510 DisplayManager dummy;
511 for(int i = 0; i < NUM_BadGuyKinds; ++i)
513 BadGuy bad_tmp(dummy, BadGuyKind(i), 0, 0);
514 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
515 objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
518 objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
519 objects_map["BadGuys"]->manipulate_button(i)->get_pos().y
523 select_objects_menu->additem(MN_HL,"",0,0);
529 level_subsets = dsubdirs("/levels", "level1.stl");
530 le_level_subset = new LevelSubset;
533 selected_game_object = NULL;
537 show_selections = true;
540 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
541 le_level_changed = false;
542 le_help_shown = false;
544 le_mouse_pressed[LEFT] = false;
545 le_mouse_pressed[RIGHT] = false;
547 le_mouse_clicked[LEFT] = false;
548 le_mouse_clicked[RIGHT] = false;
550 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
552 select_tilegroup_menu_effect.init(false);
553 select_objects_menu_effect.init(false);
554 display_level_info.init(false);
557 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
558 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
559 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
560 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
561 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
562 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
563 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
564 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
565 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
566 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
567 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
568 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
569 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
570 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
571 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
572 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
573 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
574 le_object_properties_bt->set_active(false);
576 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
577 mouse_select_object->set_mid(16,16);
579 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
580 le_tilemap_panel->set_button_size(32,10);
581 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
582 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
583 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
584 le_tilemap_panel->highlight_last(true);
585 le_tilemap_panel->set_last_clicked(TM_IA);
591 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
597 void update_level_settings_menu()
602 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
603 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
605 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
606 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
607 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
608 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
609 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
610 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
612 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
613 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
614 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
615 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
616 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
617 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
619 sprintf(str,"%d",le_world->get_level()->width);
620 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
621 sprintf(str,"%d",le_world->get_level()->height);
622 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
623 sprintf(str,"%d",le_world->get_level()->time_left);
624 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
625 sprintf(str,"%2.0f",le_world->get_level()->gravity);
626 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
627 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
628 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
629 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
630 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
631 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
632 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
633 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
634 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
635 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
636 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
637 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
638 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
639 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
640 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
643 void update_subset_settings_menu()
645 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
646 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
649 void apply_level_settings_menu()
653 le_level_changed = true;
655 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
656 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
658 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
660 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
664 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
666 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
671 le_world->get_level()->load_gfx();
674 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
676 le_world->get_level()->resize(
677 atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
678 atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
679 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
680 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
681 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
682 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
683 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
684 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
685 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
686 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
687 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
690 void save_subset_settings_menu()
692 le_level_subset->title = subset_settings_menu->item[2].input;
693 le_level_subset->description = subset_settings_menu->item[3].input;
694 le_level_subset->save();
695 le_level_changed = false;
698 void le_unload_level()
705 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
706 if(confirm_dialog(str))
708 le_world->get_level()->save(le_level_subset->name.c_str(), le_level,
714 le_level_changed = false;
717 void le_goto_level(int levelnb)
720 le_world = new World(le_level_subset->name, levelnb);
721 display_level_info.start(2500);
727 SDL_EnableKeyRepeat(0, 0); // disables key repeating
731 delete leveleditor_menu;
732 delete subset_load_menu;
733 delete subset_new_menu;
734 delete subset_settings_menu;
735 delete level_settings_menu;
736 delete select_tilegroup_menu;
737 delete select_objects_menu;
738 delete le_save_level_bt;
740 delete le_test_level_bt;
741 delete le_next_level_bt;
742 delete le_previous_level_bt;
743 delete le_move_right_bt;
744 delete le_move_left_bt;
745 delete le_move_up_bt;
746 delete le_move_down_bt;
748 delete le_select_mode_one_bt;
749 delete le_select_mode_two_bt;
750 delete le_settings_bt;
751 delete le_tilegroup_bt;
752 delete le_objects_bt;
753 delete le_tilemap_panel;
754 delete le_object_select_bt;
755 delete le_object_properties_bt;
756 delete mouse_select_object;
758 delete le_level_subset;
761 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
762 i != tilegroups_map.end(); ++i)
766 for(ButtonPanelMap::iterator i = objects_map.begin();
767 i != objects_map.end(); ++i)
773 void le_drawminimap()
779 if(screen->w - 64 > le_world->get_level()->width * 4)
781 else if(screen->w - 64 > le_world->get_level()->width * 2)
785 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
787 int mini_tile_height;
788 if(screen->h - 64 > le_world->get_level()->height * 4)
789 mini_tile_height = 4;
790 else if(screen->h - 64 > le_world->get_level()->height * 2)
791 mini_tile_height = 2;
793 mini_tile_height = 1;
795 Level* level = le_world->get_level();
796 for (int y = 0; y < le_world->get_level()->height; ++y)
797 for (int x = 0; x < le_world->get_level()->width; ++x)
800 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
801 mini_tile_width , 4, level->bg_tiles[y * level->width + x]);
803 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
804 mini_tile_width , 4, level->ia_tiles[y * level->width + x]);
806 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
807 mini_tile_width , 4, level->fg_tiles[y + level->width + x]);
811 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 128);
813 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
814 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 200);
815 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);
816 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);
820 void le_drawinterface()
827 /* draw a grid (if selected) */
830 for(x = 0; x < VISIBLE_TILES_X; x++)
831 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
832 for(y = 0; y < VISIBLE_TILES_Y; y++)
833 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
837 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
840 if(show_selections && MouseCursor::current() != mouse_select_object)
842 if(le_selection_mode == CURSOR)
844 if(le_current.IsTile())
845 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
847 else if(le_selection_mode == SQUARE)
850 le_highlight_selection();
851 /* draw current selection */
852 w = selection.x2 - selection.x1;
853 h = selection.y2 - selection.y1;
854 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
855 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
856 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
857 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
862 /* draw button bar */
863 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
865 if(le_current.IsTile())
867 Tile::draw(screen->w - 32, screen->h - 32, le_current.tile);
868 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
869 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
871 #if 0 // XXX FIXME TODO: Do we have a new solution for draw_on_screen()?
872 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
874 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
875 le_current.obj->draw_on_screen(cursor_x,cursor_y);
879 if(mouse_select_object && selected_game_object != NULL)
881 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);
882 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);
883 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);
884 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);
889 le_save_level_bt->draw();
891 le_test_level_bt->draw();
892 le_next_level_bt->draw();
893 le_previous_level_bt->draw();
894 le_rubber_bt->draw();
895 if(le_selection_mode == SQUARE)
896 le_select_mode_one_bt->draw();
897 else if(le_selection_mode == CURSOR)
898 le_select_mode_two_bt->draw();
899 le_settings_bt->draw();
900 le_move_right_bt->draw();
901 le_move_left_bt->draw();
902 le_move_up_bt->draw();
903 le_move_down_bt->draw();
904 le_tilegroup_bt->draw();
905 le_objects_bt->draw();
906 if(!cur_tilegroup.empty())
907 tilegroups_map[cur_tilegroup]->draw();
908 else if(!cur_objects.empty())
910 objects_map[cur_objects]->draw();
913 le_tilemap_panel->draw();
915 if(!cur_objects.empty())
917 le_object_select_bt->draw();
918 le_object_properties_bt->draw();
921 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
922 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
925 white_small_text->draw("F1 for Help", 10, 430, 1);
927 if(display_level_info.check())
928 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
933 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
935 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
945 /* Draw the real background */
946 le_world->background->draw(*le_world->camera, LAYER_BACKGROUND0);
948 if(le_current.IsTile())
950 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
951 if(!TileManager::instance()->get(le_current.tile)->images.empty())
952 fillrect(cursor_x-pos_x,cursor_y-pos_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);
954 #if 0 // XXX FIXME TODO: Do we have a new solution for move_to()?
955 if(le_current.IsObject())
957 le_current.obj->move_to(cursor_x, cursor_y);
961 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
963 Level* level = le_world->get_level();
964 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
965 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
968 if(active_tm == TM_BG)
973 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
974 level->bg_tiles[ (y + (int)(pos_y / 32)) * level->width +
975 (x + (int)(pos_x / 32))],a);
977 if(active_tm == TM_IA)
982 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
983 level->ia_tiles[ (y + (int)(pos_y / 32)) * level->width +
984 (x + (int)(pos_x / 32))],a);
987 if(active_tm == TM_FG)
992 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
993 level->fg_tiles[ (y + (int)(pos_y / 32)) * level->width +
994 (x + (int)(pos_x / 32))],a);
996 /* draw whats inside stuff when cursor is selecting those */
997 /* (draw them all the time - is this the right behaviour?) */
998 Tile* edit_image = TileManager::instance()->get(
1000 [ (y + (int)(pos_y / 32)) * level->width + (x + (int)(pos_x / 32))]);
1001 if(edit_image && !edit_image->editor_images.empty())
1002 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
1006 /* Draw the Bad guys: */
1007 for (std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1008 it != le_world->gameobjects.end(); ++it)
1010 BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
1014 /* to support frames: img_bsod_left[(frame / 5) % 4] */
1016 viewport.set_translation(Vector(pos_x, pos_y));
1017 badguy->draw(viewport, 0);
1020 /* Draw the player: */
1021 /* for now, the position is fixed at (100, 240) */
1022 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
1025 void le_change_object_properties(GameObject *pobj)
1027 Surface* cap_screen = Surface::CaptureScreen();
1028 Menu* object_properties_menu = new Menu();
1031 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();
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 le_move_left_bt->event(event);
1542 le_move_right_bt->event(event);
1543 le_move_up_bt->event(event);
1544 le_move_down_bt->event(event);
1545 switch(le_move_left_bt->get_state())
1547 case BUTTON_PRESSED:
1548 pos_x -= KEYBOARD_SPEED;
1549 show_minimap = true;
1552 pos_x -= MOUSE_SPEED;
1553 show_minimap = true;
1555 case BUTTON_CLICKED:
1556 show_minimap = true;
1562 switch(le_move_right_bt->get_state())
1564 case BUTTON_PRESSED:
1565 pos_x += KEYBOARD_SPEED;
1566 show_minimap = true;
1569 pos_x += MOUSE_SPEED;
1570 show_minimap = true;
1572 case BUTTON_CLICKED:
1573 show_minimap = true;
1579 switch(le_move_up_bt->get_state())
1581 case BUTTON_PRESSED:
1582 pos_y -= KEYBOARD_SPEED;
1583 show_minimap = true;
1586 pos_y -= MOUSE_SPEED;
1587 show_minimap = true;
1589 case BUTTON_CLICKED:
1590 show_minimap = true;
1596 switch(le_move_down_bt->get_state())
1598 case BUTTON_PRESSED:
1599 pos_y += KEYBOARD_SPEED;
1600 show_minimap = true;
1603 pos_y += MOUSE_SPEED;
1604 show_minimap = true;
1606 case BUTTON_CLICKED:
1607 show_minimap = true;
1613 /* checking if pos_x and pos_y is within the limits... */
1614 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1615 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1619 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1620 pos_y = (le_world->get_level()->height * 32) - screen->h;
1628 void le_highlight_selection()
1632 if(selection.x1 < selection.x2)
1642 if(selection.y1 < selection.y2)
1658 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1661 void le_change(float x, float y, int tm, unsigned int c)
1663 if(le_world != NULL)
1668 le_level_changed = true;
1670 switch(le_selection_mode)
1673 le_world->get_level()->change(x,y,tm,c);
1675 base_type cursor_base;
1678 cursor_base.width = 32;
1679 cursor_base.height = 32;
1681 /* if there is a bad guy over there, remove it */
1683 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1684 it != le_world->gameobjects.end(); ++it) {
1685 BadGuy* badguy = dynamic_cast<BadGuy*>((*it));
1688 if(rectcollision(cursor_base, badguy->base))
1691 //le_world->bad_guys.erase(it);
1692 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1700 if(selection.x1 < selection.x2)
1710 if(selection.y1 < selection.y2)
1726 /* if there is a bad guy over there, remove it */
1728 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1729 it != le_world->gameobjects.end(); ++it /* will be at end of loop */)
1731 MovingObject* pmobject = dynamic_cast<MovingObject*> (*it);
1734 if(pmobject->base.x/32 >= x1 && pmobject->base.x/32 <= x2
1735 && pmobject->base.y/32 >= y1 && pmobject->base.y/32 <= y2)
1738 //it = le_world->gameobjects.erase(it);
1739 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1749 for(xx = x1; xx <= x2; xx++)
1750 for(yy = y1; yy <= y2; yy++)
1752 le_world->get_level()->change(xx*32, yy*32, tm, c);
1764 //Make sure a time value is set when testing the level
1765 if(le_world->get_level()->time_left == 0)
1766 le_world->get_level()->time_left = 250;
1768 le_world->get_level()->save("test", le_level, le_world);
1770 GameSession session("test",le_level, ST_GL_TEST);
1772 player_status.reset();
1774 music_manager->halt_music();
1776 Menu::set_current(NULL);
1777 World::set_current(le_world);
1782 bool tmp_show_grid = le_show_grid;
1783 SelectionMode temp_le_selection_mode = le_selection_mode;
1784 le_selection_mode = NONE;
1785 show_selections = true;
1786 le_show_grid = false;
1787 le_help_shown = true;
1789 drawgradient(Color(0,0,0), Color(255,255,255));
1793 unsigned int i, done_;
1796 " - Supertux level editor tutorial - ",
1798 "To make your map, click the ",
1799 "tilegroup button and choose a ",
1801 "Pick a tile and simply hold down ",
1802 "the left mouse button over the map",
1803 "to \"paint\" your selection over",
1806 "There are three layers for painting",
1807 "tiles upon, Background layer,",
1808 "the Interactive layer, and the",
1809 "Foreground layer, which can be",
1810 "toggled by the BkGrd, IntAct and",
1811 "FrGrd buttons. The Foreground and",
1812 "Background layers do not effect",
1813 "Tux in the gameplay, but lie in",
1814 "front of him or lie behind him in",
1820 " - Supertux level editor tutorial - ",
1822 "The tiles placed on",
1823 "the Interactive layer are those",
1824 "which actually effect Tux in the",
1827 "Click the objects menu to put ",
1828 "bad guys and other objects in the",
1829 "game. Unlike placing tiles, you",
1830 "cannot \"paint\" enemies. Click",
1831 "them onto the screen one at a time.",
1833 "To change the settings of your",
1834 "level, click the button with the",
1835 "screwdriver and wrench. From here",
1836 "you can change the background,",
1837 "music, length of the level,",
1843 " - Supertux level editor tutorial - ",
1845 "You may have more than one level.",
1846 "Pressing the up and down buttons",
1847 "above the button bar lets you",
1848 "choose which one you are working on.",
1850 "If you would like to speed up your",
1851 "level editing, a useful trick is",
1852 "to learn the keyboard shortcuts.",
1853 "They are easy to learn, just right-",
1854 "click on the buttons.",
1856 "Have fun making levels! If you make",
1857 "some good ones, send them to us on",
1858 "the SuperTux mailing list!",
1864 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1866 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1867 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1869 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1877 done_ = wait_for_event(event);
1881 drawgradient(Color(0,0,0), Color(255,255,255));
1885 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1887 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1888 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1890 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1898 done_ = wait_for_event(event);
1902 drawgradient(Color(0,0,0), Color(255,255,255));
1906 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1908 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1909 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1911 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1919 done_ = wait_for_event(event);
1923 show_selections = true;
1924 le_show_grid = tmp_show_grid;
1925 le_selection_mode = temp_le_selection_mode;
1926 le_help_shown = false;