4 // Copyright (C) 2003 Ricardo Cruz <rick2@aeiou.pt>
5 // Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <SDL_image.h>
30 #include "leveleditor.h"
43 #include "resources.h"
44 #include "music_manager.h"
46 /* definitions to aid development */
48 /* definitions that affect gameplay */
49 #define KEY_CURSOR_SPEED 32
50 #define KEY_CURSOR_FASTSPEED 64
52 /* when pagedown/up pressed speed:*/
53 #define PAGE_CURSOR_SPEED 13*32
55 #define MOUSE_LEFT_MARGIN 80
56 #define MOUSE_RIGHT_MARGIN (560-32)
57 /* right_margin should noticed that the cursor is 32 pixels,
58 so it should subtract that value */
59 #define MOUSE_POS_SPEED 20
62 #define SELECT_W 2 // size of the selections lines
63 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
65 /* own declerations */
66 /* crutial ones (main loop) */
69 int le_load_level_subset(char *filename);
71 void le_drawinterface();
72 void le_checkevents();
73 void le_change(float x, float y, int tm, unsigned int c);
76 void le_set_defaults(void);
77 void le_activate_bad_guys(void);
78 void le_goto_level(int levelnb);
79 void le_highlight_selection();
81 void apply_level_settings_menu();
82 void update_subset_settings_menu();
83 void save_subset_settings_menu();
87 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
89 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
90 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
91 //Returns true for a tile
92 bool IsTile() { return is_tile; };
93 //Returns true for a GameObject
94 bool IsObject() { return !is_tile; };
97 void Init() { tile = 0; obj = NULL; is_tile = true; };
99 bool is_tile; //true for tile (false for object)
104 /* leveleditor internals */
105 static string_list_type level_subsets;
106 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
107 static bool show_minimap;
108 static bool show_selections;
109 static bool le_help_shown;
110 static int pos_x, pos_y, cursor_x, cursor_y;
112 static World* le_world;
113 static LevelSubset* le_level_subset;
114 static int le_show_grid;
116 static Surface* le_selection;
118 static TileOrObject le_current;
119 static bool le_mouse_pressed[2];
120 static bool le_mouse_clicked[2];
121 static Button* le_save_level_bt;
122 static Button* le_exit_bt;
123 static Button* le_test_level_bt;
124 static Button* le_next_level_bt;
125 static Button* le_previous_level_bt;
126 static Button* le_move_right_bt;
127 static Button* le_move_left_bt;
128 static Button* le_move_up_bt;
129 static Button* le_move_down_bt;
130 static Button* le_rubber_bt;
131 static Button* le_select_mode_one_bt;
132 static Button* le_select_mode_two_bt;
133 static Button* le_settings_bt;
134 static Button* le_tilegroup_bt;
135 static Button* le_objects_bt;
136 static Button* le_object_select_bt;
137 static Button* le_object_properties_bt;
138 static ButtonPanel* le_tilemap_panel;
139 static Menu* leveleditor_menu;
140 static Menu* subset_load_menu;
141 static Menu* subset_new_menu;
142 static Menu* subset_settings_menu;
143 static Menu* level_settings_menu;
144 static Menu* select_tilegroup_menu;
145 static Menu* select_objects_menu;
146 static Timer select_tilegroup_menu_effect;
147 static Timer select_objects_menu_effect;
148 static Timer display_level_info;
149 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
150 static ButtonPanelMap tilegroups_map;
151 static ButtonPanelMap objects_map;
152 static std::string cur_tilegroup;
153 static std::string cur_objects;
154 static MouseCursor* mouse_select_object;
155 static GameObject* selected_game_object;
157 static square selection;
158 static SelectionMode le_selection_mode;
159 static SDL_Event event;
160 TileMapType active_tm;
162 int leveleditor(char* filename)
164 int last_time, now_time, i;
173 clearscreen(0, 0, 0);
176 music_manager->halt_music();
178 while (SDL_PollEvent(&event))
182 if(le_load_level_subset(filename))
187 last_time = SDL_GetTicks();
192 if(Menu::current() == select_tilegroup_menu)
194 if(select_tilegroup_menu_effect.check())
196 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
200 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
202 else if(Menu::current() == select_objects_menu)
204 if(select_objects_menu_effect.check())
206 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
209 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
214 /* making events results to be in order */
220 clearscreen(0, 0, 0);
222 /* draw editor interface */
225 Menu* menu = Menu::current();
231 if(menu == leveleditor_menu)
233 switch (leveleditor_menu->check())
235 case MNID_RETURNLEVELEDITOR:
237 Menu::set_current(0);
239 Menu::set_current(leveleditor_menu);
241 case MNID_SUBSETSETTINGS:
242 update_subset_settings_menu();
244 case MNID_QUITLEVELEDITOR:
249 else if(menu == level_settings_menu)
251 switch (level_settings_menu->check())
254 apply_level_settings_menu();
255 Menu::set_current(NULL);
262 else if(menu == select_tilegroup_menu)
265 switch (it = select_tilegroup_menu->check())
270 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
271 Menu::set_current(0);
278 else if(menu == select_objects_menu)
281 switch (it = select_objects_menu->check())
286 cur_objects = select_objects_menu->get_item_by_id(it).text;
289 Menu::set_current(0);
294 else if(menu == subset_load_menu)
296 switch (i = subset_load_menu->check())
303 if(le_load_level_subset(level_subsets.item[i-1]))
309 else if(menu == subset_new_menu)
311 if(subset_new_menu->item[2].input[0] == '\0')
312 subset_new_menu->item[3].kind = MN_DEACTIVE;
315 subset_new_menu->item[3].kind = MN_ACTION;
317 switch (i = subset_new_menu->check())
319 case MNID_CREATESUBSET:
320 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
321 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
322 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
324 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
326 Menu::set_current(subset_settings_menu);
331 else if(menu == subset_settings_menu)
333 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 )
334 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
336 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
338 switch (i = subset_settings_menu->check())
340 case MNID_SUBSETSAVECHANGES:
341 save_subset_settings_menu();
342 Menu::set_current(leveleditor_menu);
348 MouseCursor::current()->draw();
356 ++global_frame_counter;
359 now_time = SDL_GetTicks();
360 if (now_time < last_time + FPS)
361 SDL_Delay(last_time + FPS - now_time); /* delay some time */
369 int le_load_level_subset(char *filename)
371 le_level_subset->load(filename);
372 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
376 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
378 Menu::set_current(NULL);
387 leveleditor_menu = new Menu();
388 subset_load_menu = new Menu();
389 subset_new_menu = new Menu();
390 subset_settings_menu = new Menu();
391 level_settings_menu = new Menu();
392 select_tilegroup_menu = new Menu();
393 select_objects_menu = new Menu();
395 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
396 leveleditor_menu->additem(MN_HL,"",0,0);
397 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
398 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
399 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
400 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
401 leveleditor_menu->additem(MN_HL,"",0,0);
402 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
404 Menu::set_current(leveleditor_menu);
406 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
407 subset_load_menu->additem(MN_HL, "", 0, 0);
409 for(i = 0; i < level_subsets.num_items; ++i)
411 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
413 subset_load_menu->additem(MN_HL,"",0,0);
414 subset_load_menu->additem(MN_BACK,"Back",0,0);
416 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
417 subset_new_menu->additem(MN_HL,"",0,0);
418 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
419 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
420 subset_new_menu->additem(MN_HL,"",0,0);
421 subset_new_menu->additem(MN_BACK,"Back",0,0);
423 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
424 subset_settings_menu->additem(MN_HL,"",0,0);
425 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
426 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
427 subset_settings_menu->additem(MN_HL,"",0,0);
428 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
429 subset_settings_menu->additem(MN_HL,"",0,0);
430 subset_settings_menu->additem(MN_BACK,"Back",0,0);
432 level_settings_menu->arrange_left = true;
433 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
434 level_settings_menu->additem(MN_HL,"",0,0);
435 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
436 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
437 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
438 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
439 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
440 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
441 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
442 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
443 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
444 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
445 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
446 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
447 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
448 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
449 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
450 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
451 level_settings_menu->additem(MN_HL,"",0,0);
452 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
454 select_tilegroup_menu->arrange_left = true;
455 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
456 select_tilegroup_menu->additem(MN_HL,"",0,0);
457 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
459 for(std::set<TileGroup>::iterator it = tilegroups->begin();
460 it != tilegroups->end(); ++it )
462 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
464 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
467 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
468 sit != (*it).tiles.end(); ++sit, ++i)
470 std::string imagefile = "/images/tilesets/" ;
471 bool only_editor_image = false;
472 if(!TileManager::instance()->get(*sit)->filenames.empty())
474 imagefile += TileManager::instance()->get(*sit)->filenames[0];
476 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
478 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
479 only_editor_image = true;
483 imagefile += "notile.png";
485 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
487 if(!only_editor_image)
488 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
490 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
491 button->add_icon(imagefile,32,32);
493 tilegroups_map[it->name]->additem(button, *sit);
496 select_tilegroup_menu->additem(MN_HL,"",0,0);
498 select_objects_menu->arrange_left = true;
499 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
500 select_objects_menu->additem(MN_HL,"",0,0);
501 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
502 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
504 for(int i = 0; i < NUM_BadGuyKinds; ++i)
506 BadGuy bad_tmp(0,0,BadGuyKind(i),false);
507 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
508 objects_map["BadGuys"]->manipulate_button(i)->set_game_object(new BadGuy(objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,objects_map["BadGuys"]->manipulate_button(i)->get_pos().y,BadGuyKind(i),false));
511 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;
531 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
532 le_level_changed = false;
533 le_help_shown = false;
535 le_mouse_pressed[LEFT] = false;
536 le_mouse_pressed[RIGHT] = false;
538 le_mouse_clicked[LEFT] = false;
539 le_mouse_clicked[RIGHT] = false;
541 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
543 select_tilegroup_menu_effect.init(false);
544 select_objects_menu_effect.init(false);
545 display_level_info.init(false);
548 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
549 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
550 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
551 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
552 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
553 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
554 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
555 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
556 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
557 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
558 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
559 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
560 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
561 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
562 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
563 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
564 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
565 le_object_properties_bt->set_active(false);
567 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
568 mouse_select_object->set_mid(16,16);
570 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
571 le_tilemap_panel->set_button_size(32,10);
572 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
573 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
574 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
575 le_tilemap_panel->highlight_last(true);
576 le_tilemap_panel->set_last_clicked(TM_IA);
582 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
588 void update_level_settings_menu()
593 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
594 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
596 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
597 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
598 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
599 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
600 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
601 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
603 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
604 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
605 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
606 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
607 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
608 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
610 sprintf(str,"%d",le_world->get_level()->width);
611 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
612 sprintf(str,"%d",le_world->get_level()->height);
613 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
614 sprintf(str,"%d",le_world->get_level()->time_left);
615 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
616 sprintf(str,"%2.0f",le_world->get_level()->gravity);
617 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
618 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
619 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
620 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
621 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
622 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
623 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
624 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
625 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
626 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
627 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
628 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
629 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
630 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
631 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
634 void update_subset_settings_menu()
636 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
637 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
640 void apply_level_settings_menu()
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()->change_width(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
667 le_world->get_level()->change_height(atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
668 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
669 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
670 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
671 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
672 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
673 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
674 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
675 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
676 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
679 void save_subset_settings_menu()
681 le_level_subset->title = subset_settings_menu->item[2].input;
682 le_level_subset->description = subset_settings_menu->item[3].input;
683 le_level_subset->save();
684 le_level_changed = false;
687 void le_unload_level()
694 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
695 if(confirm_dialog(str))
697 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
702 le_level_changed = false;
705 void le_goto_level(int levelnb)
708 le_world = new World(le_level_subset->name, levelnb);
709 display_level_info.start(2500);
715 SDL_EnableKeyRepeat(0, 0); // disables key repeating
719 delete leveleditor_menu;
720 delete subset_load_menu;
721 delete subset_new_menu;
722 delete subset_settings_menu;
723 delete level_settings_menu;
724 delete select_tilegroup_menu;
725 delete select_objects_menu;
726 delete le_save_level_bt;
728 delete le_test_level_bt;
729 delete le_next_level_bt;
730 delete le_previous_level_bt;
731 delete le_move_right_bt;
732 delete le_move_left_bt;
733 delete le_move_up_bt;
734 delete le_move_down_bt;
736 delete le_select_mode_one_bt;
737 delete le_select_mode_two_bt;
738 delete le_settings_bt;
739 delete le_tilegroup_bt;
740 delete le_objects_bt;
741 delete le_tilemap_panel;
742 delete le_object_select_bt;
743 delete le_object_properties_bt;
744 delete mouse_select_object;
746 delete le_level_subset;
749 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
750 i != tilegroups_map.end(); ++i)
754 for(ButtonPanelMap::iterator i = objects_map.begin();
755 i != objects_map.end(); ++i)
761 void le_drawminimap()
767 if(screen->w - 64 > le_world->get_level()->width * 4)
769 else if(screen->w - 64 > le_world->get_level()->width * 2)
773 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
775 int mini_tile_height;
776 if(screen->h - 64 > le_world->get_level()->height * 4)
777 mini_tile_height = 4;
778 else if(screen->h - 64 > le_world->get_level()->height * 2)
779 mini_tile_height = 2;
781 mini_tile_height = 1;
783 for (int y = 0; y < le_world->get_level()->height; ++y)
784 for (int x = 0; x < le_world->get_level()->width; ++x)
787 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
789 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
791 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
795 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 128);
797 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
798 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 200);
799 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);
800 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);
804 void le_drawinterface()
811 /* draw a grid (if selected) */
814 for(x = 0; x < 19; x++)
815 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
816 for(y = 0; y < 16; y++)
817 fillrect(0, y*32 - ((int)pos_y % 32), screen->w - 32, 1, 225, 225, 225,255);
821 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
824 if(show_selections && MouseCursor::current() != mouse_select_object)
826 if(le_selection_mode == CURSOR)
828 if(le_current.IsTile())
829 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
831 else if(le_selection_mode == SQUARE)
834 le_highlight_selection();
835 /* draw current selection */
836 w = selection.x2 - selection.x1;
837 h = selection.y2 - selection.y1;
838 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
839 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
840 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
841 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
846 /* draw button bar */
847 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
849 if(le_current.IsTile())
851 Tile::draw(19 * 32, 14 * 32, le_current.tile);
852 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
853 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
855 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
857 le_current.obj->draw_on_screen(19 * 32, 14 * 32);
858 le_current.obj->draw_on_screen(cursor_x,cursor_y);
861 if(mouse_select_object && selected_game_object != NULL)
863 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);
864 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);
865 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);
866 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);
871 le_save_level_bt->draw();
873 le_test_level_bt->draw();
874 le_next_level_bt->draw();
875 le_previous_level_bt->draw();
876 le_rubber_bt->draw();
877 if(le_selection_mode == SQUARE)
878 le_select_mode_one_bt->draw();
879 else if(le_selection_mode == CURSOR)
880 le_select_mode_two_bt->draw();
881 le_settings_bt->draw();
882 le_move_right_bt->draw();
883 le_move_left_bt->draw();
884 le_move_up_bt->draw();
885 le_move_down_bt->draw();
886 le_tilegroup_bt->draw();
887 le_objects_bt->draw();
888 if(!cur_tilegroup.empty())
889 tilegroups_map[cur_tilegroup]->draw();
890 else if(!cur_objects.empty())
892 objects_map[cur_objects]->draw();
895 le_tilemap_panel->draw();
897 if(!cur_objects.empty())
899 le_object_select_bt->draw();
900 le_object_properties_bt->draw();
903 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
904 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
907 white_small_text->draw("F1 for Help", 10, 430, 1);
909 if(display_level_info.check())
910 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
915 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
917 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
927 /* Draw the real background */
928 if(le_world->get_level()->bkgd_image[0] != '\0')
930 s = (int)((float)pos_x * ((float)le_world->get_level()->bkgd_speed/100.0f)) % screen->w;
931 le_world->get_level()->img_bkgd->draw_part(s,0,0,0,
932 le_world->get_level()->img_bkgd->w - s - 32, le_world->get_level()->img_bkgd->h);
933 le_world->get_level()->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
934 le_world->get_level()->img_bkgd->h);
938 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
941 if(le_current.IsTile())
943 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
944 if(!TileManager::instance()->get(le_current.tile)->images.empty())
945 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);
947 if(le_current.IsObject())
949 le_current.obj->move_to(cursor_x, cursor_y);
952 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
954 for (y = 0; y < 16 && y < (unsigned)le_world->get_level()->height; ++y)
955 for (x = 0; x < 20; ++x)
958 if(active_tm == TM_BG)
963 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->bg_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
965 if(active_tm == TM_IA)
970 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->ia_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
972 if(active_tm == TM_FG)
977 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->fg_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
979 /* draw whats inside stuff when cursor is selecting those */
980 /* (draw them all the time - is this the right behaviour?) */
981 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)]);
982 if(edit_image && !edit_image->editor_images.empty())
983 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
987 /* Draw the Bad guys: */
988 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
990 /* to support frames: img_bsod_left[(frame / 5) % 4] */
998 /* Draw the player: */
999 /* for now, the position is fixed at (100, 240) */
1000 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
1003 void le_change_object_properties(GameObject *pobj)
1005 Surface* cap_screen = Surface::CaptureScreen();
1006 Menu* object_properties_menu = new Menu();
1009 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
1010 object_properties_menu->additem(MN_HL,"",0,0);
1012 if(pobj->type() == "BadGuy")
1014 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1015 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1016 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1018 string_list_add_item(object_properties_menu->get_item_by_id(1).list,badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1020 object_properties_menu->get_item_by_id(1).list->active_item = i;
1022 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1025 object_properties_menu->additem(MN_HL,"",0,0);
1026 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1028 Menu::set_current(object_properties_menu);
1034 while (SDL_PollEvent(&event))
1036 object_properties_menu->event(event);
1039 cap_screen->draw(0,0);
1041 object_properties_menu->draw();
1042 object_properties_menu->action();
1044 switch (object_properties_menu->check())
1047 if(pobj->type() == "BadGuy")
1049 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1050 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1051 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1053 std::list<BadGuy*>::iterator it;
1054 for(it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1057 le_world->get_level()->badguy_data[i].kind = pbad->kind;
1058 le_world->get_level()->badguy_data[i].stay_on_platform = pbad->stay_on_platform;
1060 (*it) = new BadGuy(le_world->get_level()->badguy_data[i].x,le_world->get_level()->badguy_data[i].y,le_world->get_level()->badguy_data[i].kind,le_world->get_level()->badguy_data[i].stay_on_platform);
1068 if(Menu::current() == NULL)
1071 mouse_cursor->draw();
1077 Menu::set_current(0);
1078 delete object_properties_menu;
1082 void le_checkevents()
1089 keymod = SDL_GetModState();
1091 while(SDL_PollEvent(&event))
1093 if (Menu::current())
1095 Menu::current()->event(event);
1096 if(!le_world && !Menu::current())
1097 Menu::set_current(leveleditor_menu);
1101 mouse_cursor->set_state(MC_NORMAL);
1103 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1104 if(event.type == SDL_KEYDOWN
1105 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1106 && (event.motion.x > 0
1107 && event.motion.x < screen->w - 64 &&
1108 event.motion.y > 0 && event.motion.y < screen->h)))
1112 case SDL_KEYDOWN: // key pressed
1113 key = event.key.keysym.sym;
1117 Menu::set_current(leveleditor_menu);
1120 if(le_world != NULL)
1128 cursor_x = (le_world->get_level()->width * 32) - 32;
1132 le_show_grid = !le_show_grid;
1138 case SDL_MOUSEBUTTONDOWN:
1139 if(event.button.button == SDL_BUTTON_LEFT)
1141 le_mouse_pressed[LEFT] = true;
1143 selection.x1 = event.motion.x + pos_x;
1144 selection.y1 = event.motion.y + pos_y;
1145 selection.x2 = event.motion.x + pos_x;
1146 selection.y2 = event.motion.y + pos_y;
1148 else if(event.button.button == SDL_BUTTON_RIGHT)
1150 le_mouse_pressed[RIGHT] = true;
1153 case SDL_MOUSEBUTTONUP:
1154 if(event.button.button == SDL_BUTTON_LEFT)
1156 le_mouse_pressed[LEFT] = false;
1157 le_mouse_clicked[LEFT] = true;
1159 else if(event.button.button == SDL_BUTTON_RIGHT)
1161 le_mouse_pressed[RIGHT] = false;
1162 le_mouse_clicked[RIGHT] = true;
1165 case SDL_MOUSEMOTION:
1167 if(!Menu::current())
1172 if(le_current.IsTile())
1174 cursor_x = ((int)(pos_x + x) / 32) * 32;
1175 cursor_y = ((int)(pos_y + y) / 32) * 32;
1183 if(le_mouse_pressed[LEFT])
1185 selection.x2 = x + pos_x;
1186 selection.y2 = y + pos_y;
1189 if(le_mouse_pressed[RIGHT])
1191 pos_x += -1 * event.motion.xrel;
1192 pos_y += -1 * event.motion.yrel;
1200 else if(event.type == SDL_QUIT) /* window closing */
1206 if(le_world != NULL)
1208 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 &&
1209 event.motion.y > 0 && event.motion.y < screen->h)))
1211 le_mouse_pressed[LEFT] = false;
1212 le_mouse_pressed[RIGHT] = false;
1214 if(!Menu::current())
1216 /* Check for button events */
1217 le_test_level_bt->event(event);
1218 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1220 le_save_level_bt->event(event);
1221 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1222 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1223 le_exit_bt->event(event);
1224 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1226 Menu::set_current(leveleditor_menu);
1228 le_next_level_bt->event(event);
1229 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1231 if(le_level < le_level_subset->levels)
1233 le_goto_level(le_level+1);
1239 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1240 if(confirm_dialog(str))
1242 new_lev.init_defaults();
1243 new_lev.save(le_level_subset->name.c_str(),le_level+1);
1244 le_level_subset->levels = le_level;
1245 le_goto_level(le_level);
1249 le_previous_level_bt->event(event);
1250 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1253 le_goto_level(le_level -1);
1255 le_rubber_bt->event(event);
1256 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1259 if(!cur_objects.empty())
1261 le_object_select_bt->event(event);
1262 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1264 MouseCursor::set_current(mouse_select_object);
1267 le_object_properties_bt->event(event);
1268 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1270 le_change_object_properties(selected_game_object);
1275 if(le_selection_mode == SQUARE)
1277 le_select_mode_one_bt->event(event);
1278 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1279 le_selection_mode = CURSOR;
1283 le_select_mode_two_bt->event(event);
1284 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1285 le_selection_mode = SQUARE;
1287 ButtonPanelMap::iterator it;
1288 le_tilegroup_bt->event(event);
1289 switch (le_tilegroup_bt->get_state())
1291 case BUTTON_CLICKED:
1292 Menu::set_current(select_tilegroup_menu);
1293 select_tilegroup_menu_effect.start(200);
1294 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1296 case BUTTON_WHEELUP:
1297 if(cur_tilegroup.empty())
1299 cur_tilegroup = tilegroups_map.begin()->first;
1303 it = tilegroups_map.find(cur_tilegroup);
1304 if((++it) == tilegroups_map.end())
1306 cur_tilegroup = tilegroups_map.begin()->first;
1310 cur_tilegroup = (*it).first;
1316 case BUTTON_WHEELDOWN:
1317 it = tilegroups_map.find(cur_tilegroup);
1318 if(it == tilegroups_map.begin())
1320 cur_tilegroup = tilegroups_map.rbegin()->first;
1324 if(--it != --tilegroups_map.begin())
1325 cur_tilegroup = (*it).first;
1327 cur_tilegroup = tilegroups_map.rbegin()->first;
1335 le_objects_bt->event(event);
1336 switch (le_objects_bt->get_state())
1338 case BUTTON_CLICKED:
1339 Menu::set_current(select_objects_menu);
1340 select_objects_menu_effect.start(200);
1341 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1343 case BUTTON_WHEELUP:
1344 it = objects_map.find(cur_objects);
1345 if(it == objects_map.end())
1347 cur_objects = objects_map.begin()->first;
1351 if(++it != objects_map.end())
1352 cur_objects = (*it).first;
1354 cur_objects = objects_map.begin()->first;
1358 case BUTTON_WHEELDOWN:
1359 it = objects_map.find(cur_objects);
1360 if(it == objects_map.begin())
1362 cur_objects = objects_map.rbegin()->first;
1366 if(--it != --objects_map.begin())
1367 cur_objects = (*it).first;
1369 cur_objects = objects_map.rbegin()->first;
1378 le_settings_bt->event(event);
1379 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1381 update_level_settings_menu();
1382 Menu::set_current(level_settings_menu);
1384 if(!cur_tilegroup.empty())
1386 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1388 if(pbutton->get_state() == BUTTON_CLICKED)
1390 le_current.Tile(pbutton->get_tag());
1394 else if(!cur_objects.empty())
1396 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1398 if(pbutton->get_state() == BUTTON_CLICKED)
1400 le_current.Object(pbutton->get_game_object());
1405 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1407 if(pbutton->get_state() == BUTTON_CLICKED)
1409 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1415 le_settings_bt->event(event);
1416 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1418 Menu::set_current(0);
1420 le_tilegroup_bt->event(event);
1421 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1423 Menu::set_current(0);
1425 le_objects_bt->event(event);
1426 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1428 Menu::set_current(0);
1433 if(!Menu::current() && !show_minimap)
1435 if(le_mouse_pressed[LEFT])
1437 if(MouseCursor::current() != mouse_select_object)
1439 if(le_current.IsTile())
1440 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1443 else if(le_mouse_clicked[LEFT])
1445 if(MouseCursor::current() == mouse_select_object)
1448 bool object_got_hit = false;
1449 base_type cursor_base;
1450 if(le_current.IsTile())
1452 cursor_base.x = cursor_x;
1453 cursor_base.y = cursor_y;
1455 else if(le_current.IsObject())
1457 cursor_base.x = cursor_x + pos_x;
1458 cursor_base.y = cursor_y + pos_y;
1460 cursor_base.width = 32;
1461 cursor_base.height = 32;
1463 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1464 if(rectcollision(cursor_base,(*it)->base))
1466 selected_game_object = (*it);
1467 object_got_hit = true;
1473 selected_game_object = NULL;
1474 le_object_properties_bt->set_active(false);
1477 le_object_properties_bt->set_active(true);
1479 MouseCursor::set_current(mouse_cursor);
1484 if(le_current.IsObject())
1486 le_level_changed = true;
1487 std::string type = le_current.obj->type();
1488 if(type == "BadGuy")
1490 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1492 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1493 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1498 le_mouse_clicked[LEFT] = false;
1504 if(!Menu::current())
1506 show_minimap = false;
1508 le_move_left_bt->event(event);
1509 le_move_right_bt->event(event);
1510 le_move_up_bt->event(event);
1511 le_move_down_bt->event(event);
1512 switch(le_move_left_bt->get_state())
1514 case BUTTON_PRESSED:
1516 show_minimap = true;
1520 show_minimap = true;
1522 case BUTTON_CLICKED:
1523 show_minimap = true;
1529 switch(le_move_right_bt->get_state())
1531 case BUTTON_PRESSED:
1533 show_minimap = true;
1537 show_minimap = true;
1539 case BUTTON_CLICKED:
1540 show_minimap = true;
1546 switch(le_move_up_bt->get_state())
1548 case BUTTON_PRESSED:
1550 show_minimap = true;
1554 show_minimap = true;
1556 case BUTTON_CLICKED:
1557 show_minimap = true;
1563 switch(le_move_down_bt->get_state())
1565 case BUTTON_PRESSED:
1567 show_minimap = true;
1571 show_minimap = true;
1573 case BUTTON_CLICKED:
1574 show_minimap = true;
1580 /* checking if pos_x and pos_y is within the limits... */
1583 if(pos_x > (le_world->get_level()->width * 32) - screen->w)
1584 pos_x = (le_world->get_level()->width * 32) - screen->w;
1588 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1589 pos_y = (le_world->get_level()->height * 32) - screen->h;
1595 void le_highlight_selection()
1599 if(selection.x1 < selection.x2)
1609 if(selection.y1 < selection.y2)
1625 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1628 void le_change(float x, float y, int tm, unsigned int c)
1630 if(le_world != NULL)
1636 le_level_changed = true;
1638 switch(le_selection_mode)
1641 le_world->get_level()->change(x,y,tm,c);
1643 base_type cursor_base;
1646 cursor_base.width = 32;
1647 cursor_base.height = 32;
1649 /* if there is a bad guy over there, remove it */
1650 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1651 if(rectcollision(cursor_base,(*it)->base))
1654 le_world->bad_guys.erase(it);
1655 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1661 if(selection.x1 < selection.x2)
1671 if(selection.y1 < selection.y2)
1687 /* if there is a bad guy over there, remove it */
1688 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1689 it != le_world->bad_guys.end(); /* will be at end of loop */)
1691 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1692 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1695 it = le_world->bad_guys.erase(it);
1696 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1706 for(xx = x1; xx <= x2; xx++)
1707 for(yy = y1; yy <= y2; yy++)
1709 le_world->get_level()->change(xx*32, yy*32, tm, c);
1721 //Make sure a time value is set when testing the level
1722 if(le_world->get_level()->time_left == 0)
1723 le_world->get_level()->time_left = 250;
1725 le_world->get_level()->save("test", le_level);
1727 GameSession session("test",le_level, ST_GL_TEST);
1729 player_status.reset();
1731 music_manager->halt_music();
1733 Menu::set_current(NULL);
1734 World::set_current(le_world);
1739 bool tmp_show_grid = le_show_grid;
1740 SelectionMode temp_le_selection_mode = le_selection_mode;
1741 le_selection_mode = NONE;
1742 show_selections = true;
1743 le_show_grid = false;
1744 le_help_shown = true;
1746 drawgradient(Color(0,0,0), Color(255,255,255));
1750 unsigned int i, done_;
1753 " - Supertux level editor tutorial - ",
1755 "To make your map, click the ",
1756 "tilegroup button and choose a ",
1758 "Pick a tile and simply hold down ",
1759 "the left mouse button over the map",
1760 "to \"paint\" your selection over",
1763 "There are three layers for painting",
1764 "tiles upon, Background layer,",
1765 "the Interactive layer, and the",
1766 "Foreground layer, which can be",
1767 "toggled by the BkGrd, IntAct and",
1768 "FrGrd buttons. The Foreground and",
1769 "Background layers do not effect",
1770 "Tux in the gameplay, but lie in",
1771 "front of him or lie behind him in",
1777 " - Supertux level editor tutorial - ",
1779 "The tiles placed on",
1780 "the Interactive layer are those",
1781 "which actually effect Tux in the",
1784 "Click the objects menu to put ",
1785 "bad guys and other objects in the",
1786 "game. Unlike placing tiles, you",
1787 "cannot \"paint\" enemies. Click",
1788 "them onto the screen one at a time.",
1790 "To change the settings of your",
1791 "level, click the button with the",
1792 "screwdriver and wrench. From here",
1793 "you can change the background,",
1794 "music, length of the level,",
1800 " - Supertux level editor tutorial - ",
1802 "You may have more than one level.",
1803 "Pressing the up and down buttons",
1804 "above the button bar lets you",
1805 "choose which one you are working on.",
1807 "If you would like to speed up your",
1808 "level editing, a useful trick is",
1809 "to learn the keyboard shortcuts.",
1810 "They are easy to learn, just right-",
1811 "click on the buttons.",
1813 "Have fun making levels! If you make",
1814 "some good ones, send them to us on",
1815 "the SuperTux mailing list!",
1821 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1823 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1824 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1826 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1834 done_ = wait_for_event(event);
1838 drawgradient(Color(0,0,0), Color(255,255,255));
1842 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1844 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1845 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1847 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1855 done_ = wait_for_event(event);
1859 drawgradient(Color(0,0,0), Color(255,255,255));
1863 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1865 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1866 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1868 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1876 done_ = wait_for_event(event);
1880 show_selections = true;
1881 le_show_grid = tmp_show_grid;
1882 le_selection_mode = temp_le_selection_mode;
1883 le_help_shown = false;