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; };
95 void Init() { tile = 0; obj = NULL; is_tile = true; };
97 bool is_tile; //true for tile (false for object)
102 /* leveleditor internals */
103 static string_list_type level_subsets;
104 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
105 static bool show_minimap;
106 static bool le_help_shown;
107 static int pos_x, cursor_x, cursor_y, fire;
109 static World* le_world;
110 static LevelSubset* le_level_subset;
111 static int le_show_grid;
113 static Surface* le_selection;
115 static TileOrObject le_current;
116 static bool le_mouse_pressed[2];
117 static bool le_mouse_clicked[2];
118 static Button* le_save_level_bt;
119 static Button* le_exit_bt;
120 static Button* le_test_level_bt;
121 static Button* le_next_level_bt;
122 static Button* le_previous_level_bt;
123 static Button* le_move_right_bt;
124 static Button* le_move_left_bt;
125 static Button* le_rubber_bt;
126 static Button* le_select_mode_one_bt;
127 static Button* le_select_mode_two_bt;
128 static Button* le_settings_bt;
129 static Button* le_tilegroup_bt;
130 static Button* le_objects_bt;
131 static ButtonPanel* le_tilemap_panel;
132 static Menu* leveleditor_menu;
133 static Menu* subset_load_menu;
134 static Menu* subset_new_menu;
135 static Menu* subset_settings_menu;
136 static Menu* level_settings_menu;
137 static Menu* select_tilegroup_menu;
138 static Menu* select_objects_menu;
139 static Timer select_tilegroup_menu_effect;
140 static Timer select_objects_menu_effect;
141 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
142 static ButtonPanelMap tilegroups_map;
143 static ButtonPanelMap objects_map;
144 static std::string cur_tilegroup;
145 static std::string cur_objects;
147 static square selection;
148 static int le_selection_mode;
149 static SDL_Event event;
150 TileMapType active_tm;
152 int leveleditor(char* filename)
154 int last_time, now_time, i;
163 clearscreen(0, 0, 0);
166 music_manager->halt_music();
168 while (SDL_PollEvent(&event))
172 if(le_load_level_subset(filename))
177 last_time = SDL_GetTicks();
182 if(Menu::current() == select_tilegroup_menu)
184 if(select_tilegroup_menu_effect.check())
186 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
190 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
192 else if(Menu::current() == select_objects_menu)
194 if(select_objects_menu_effect.check())
196 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
199 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
204 /* making events results to be in order */
207 if(pos_x > (le_world->get_level()->width * 32) - screen->w)
208 pos_x = (le_world->get_level()->width * 32) - screen->w;
214 clearscreen(0, 0, 0);
216 /* draw editor interface */
219 Menu* menu = Menu::current();
225 if(menu == leveleditor_menu)
227 switch (leveleditor_menu->check())
229 case MNID_RETURNLEVELEDITOR:
231 Menu::set_current(0);
233 Menu::set_current(leveleditor_menu);
235 case MNID_SUBSETSETTINGS:
236 update_subset_settings_menu();
238 case MNID_QUITLEVELEDITOR:
243 else if(menu == level_settings_menu)
245 switch (level_settings_menu->check())
248 apply_level_settings_menu();
249 Menu::set_current(NULL);
256 else if(menu == select_tilegroup_menu)
259 switch (it = select_tilegroup_menu->check())
264 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
265 Menu::set_current(0);
272 else if(menu == select_objects_menu)
275 switch (it = select_objects_menu->check())
280 cur_objects = select_objects_menu->get_item_by_id(it).text;
283 Menu::set_current(0);
288 else if(menu == subset_load_menu)
290 switch (i = subset_load_menu->check())
297 if(le_load_level_subset(level_subsets.item[i-1]))
303 else if(menu == subset_new_menu)
305 if(subset_new_menu->item[2].input[0] == '\0')
306 subset_new_menu->item[3].kind = MN_DEACTIVE;
309 subset_new_menu->item[3].kind = MN_ACTION;
311 switch (i = subset_new_menu->check())
313 case MNID_CREATESUBSET:
314 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
315 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
316 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
318 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
320 Menu::set_current(subset_settings_menu);
325 else if(menu == subset_settings_menu)
327 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 )
328 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
330 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
332 switch (i = subset_settings_menu->check())
334 case MNID_SUBSETSAVECHANGES:
335 save_subset_settings_menu();
336 Menu::set_current(leveleditor_menu);
342 mouse_cursor->draw();
350 ++global_frame_counter;
353 now_time = SDL_GetTicks();
354 if (now_time < last_time + FPS)
355 SDL_Delay(last_time + FPS - now_time); /* delay some time */
363 int le_load_level_subset(char *filename)
365 le_level_subset->load(filename);
366 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
370 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
372 Menu::set_current(NULL);
381 leveleditor_menu = new Menu();
382 subset_load_menu = new Menu();
383 subset_new_menu = new Menu();
384 subset_settings_menu = new Menu();
385 level_settings_menu = new Menu();
386 select_tilegroup_menu = new Menu();
387 select_objects_menu = new Menu();
389 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
390 leveleditor_menu->additem(MN_HL,"",0,0);
391 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
392 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
393 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
394 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
395 leveleditor_menu->additem(MN_HL,"",0,0);
396 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
398 Menu::set_current(leveleditor_menu);
400 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
401 subset_load_menu->additem(MN_HL, "", 0, 0);
403 for(i = 0; i < level_subsets.num_items; ++i)
405 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
407 subset_load_menu->additem(MN_HL,"",0,0);
408 subset_load_menu->additem(MN_BACK,"Back",0,0);
410 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
411 subset_new_menu->additem(MN_HL,"",0,0);
412 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
413 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
414 subset_new_menu->additem(MN_HL,"",0,0);
415 subset_new_menu->additem(MN_BACK,"Back",0,0);
417 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
418 subset_settings_menu->additem(MN_HL,"",0,0);
419 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
420 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
421 subset_settings_menu->additem(MN_HL,"",0,0);
422 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
423 subset_settings_menu->additem(MN_HL,"",0,0);
424 subset_settings_menu->additem(MN_BACK,"Back",0,0);
426 level_settings_menu->arrange_left = true;
427 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
428 level_settings_menu->additem(MN_HL,"",0,0);
429 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
430 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
431 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
432 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
433 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
434 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
435 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
436 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
437 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
438 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
439 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
440 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
441 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
442 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
443 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue",0,0,MNID_BottomBlue);
444 level_settings_menu->additem(MN_HL,"",0,0);
445 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
447 select_tilegroup_menu->arrange_left = true;
448 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
449 select_tilegroup_menu->additem(MN_HL,"",0,0);
450 select_tilegroup_menu->additem(MN_ACTION,"asd",0,0);
451 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
453 for(std::set<TileGroup>::iterator it = tilegroups->begin();
454 it != tilegroups->end(); ++it )
456 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
458 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
461 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
462 sit != (*it).tiles.end(); ++sit, ++i)
464 std::string imagefile = "/images/tilesets/" ;
465 bool only_editor_image = false;
466 if(!TileManager::instance()->get(*sit)->filenames.empty())
468 imagefile += TileManager::instance()->get(*sit)->filenames[0];
470 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
472 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
473 only_editor_image = true;
477 imagefile += "notile.png";
479 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
481 if(!only_editor_image)
482 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
484 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
485 button->add_icon(imagefile,32,32);
487 tilegroups_map[it->name]->additem(button, *sit);
490 select_tilegroup_menu->additem(MN_HL,"",0,0);
492 select_objects_menu->arrange_left = true;
493 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
494 select_objects_menu->additem(MN_HL,"",0,0);
495 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
496 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
498 for(int i = 0; i < NUM_BadGuyKinds; ++i)
500 BadGuy bad_tmp(0,0,BadGuyKind(i),false);
501 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
502 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));
505 select_objects_menu->additem(MN_HL,"",0,0);
513 level_subsets = dsubdirs("/levels", "level1.stl");
514 le_level_subset = new LevelSubset;
524 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
525 le_level_changed = false;
526 le_help_shown = false;
528 le_mouse_pressed[LEFT] = false;
529 le_mouse_pressed[RIGHT] = false;
531 le_mouse_clicked[LEFT] = false;
532 le_mouse_clicked[RIGHT] = false;
534 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
536 select_tilegroup_menu_effect.init(false);
537 select_objects_menu_effect.init(false);
540 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
541 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F6,screen->w-32,32);
542 le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
543 le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
544 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
545 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
546 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
547 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
548 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
549 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
550 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
551 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
552 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F7,screen->w-64,80);
554 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
555 le_tilemap_panel->set_button_size(32,10);
556 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
557 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
558 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
559 le_tilemap_panel->highlight_last(true);
560 le_tilemap_panel->set_last_clicked(TM_IA);
566 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
572 void update_level_settings_menu()
577 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
578 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
580 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
581 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
582 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
583 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
584 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
585 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
587 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
588 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
589 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
590 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
591 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
592 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
594 sprintf(str,"%d",le_world->get_level()->width);
595 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
596 sprintf(str,"%d",le_world->get_level()->time_left);
597 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
598 sprintf(str,"%2.0f",le_world->get_level()->gravity);
599 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
600 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
601 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
602 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
603 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
604 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
605 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
606 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
607 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
608 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
609 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
610 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
611 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
612 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
613 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
616 void update_subset_settings_menu()
618 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
619 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
622 void apply_level_settings_menu()
627 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
628 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
630 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
632 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
636 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
638 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
643 le_world->get_level()->load_gfx();
646 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
648 le_world->get_level()->change_size(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
649 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
650 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
651 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
652 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
653 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
654 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
655 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
656 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
657 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
660 void save_subset_settings_menu()
662 le_level_subset->title = subset_settings_menu->item[2].input;
663 le_level_subset->description = subset_settings_menu->item[3].input;
664 le_level_subset->save();
667 void le_unload_level()
674 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
675 if(confirm_dialog(str))
677 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
682 le_level_changed = false;
685 void le_goto_level(int levelnb)
688 le_world = new World(le_level_subset->name, levelnb);
693 SDL_EnableKeyRepeat(0, 0); // disables key repeating
697 delete leveleditor_menu;
698 delete subset_load_menu;
699 delete subset_new_menu;
700 delete subset_settings_menu;
701 delete level_settings_menu;
702 delete select_tilegroup_menu;
703 delete select_objects_menu;
704 delete le_save_level_bt;
706 delete le_test_level_bt;
707 delete le_next_level_bt;
708 delete le_previous_level_bt;
709 delete le_move_right_bt;
710 delete le_move_left_bt;
712 delete le_select_mode_one_bt;
713 delete le_select_mode_two_bt;
714 delete le_settings_bt;
715 delete le_tilegroup_bt;
716 delete le_objects_bt;
717 delete le_tilemap_panel;
719 delete le_level_subset;
722 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
723 i != tilegroups_map.end(); ++i)
727 for(ButtonPanelMap::iterator i = objects_map.begin();
728 i != objects_map.end(); ++i)
734 void le_drawminimap()
740 if(screen->w - 64 > le_world->get_level()->width * 4)
742 else if(screen->w - 64 > le_world->get_level()->width * 2)
746 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
748 for (int y = 0; y < 15; ++y)
749 for (int x = 0; x < le_world->get_level()->width; ++x)
752 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
754 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
756 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
760 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, 15*4, 200, 200, 200, 128);
762 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
763 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, 15*4, 200, 200, 200, 200);
764 fillrect(left_offset + (pos_x/32)*mini_tile_width + 19*mini_tile_width - 2, 0, 2, 15*4, 200, 200, 200, 200);
765 fillrect(left_offset + (pos_x/32)*mini_tile_width, 15*4-2, 19*mini_tile_width, 2, 200, 200, 200, 200);
769 void le_drawinterface()
776 /* draw a grid (if selected) */
779 for(x = 0; x < 19; x++)
780 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
781 for(y = 0; y < 15; y++)
782 fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
786 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
789 if(le_selection_mode == CURSOR)
791 if(le_current.IsTile())
792 le_selection->draw( cursor_x - pos_x, cursor_y);
794 else if(le_selection_mode == SQUARE)
797 le_highlight_selection();
798 /* draw current selection */
799 w = selection.x2 - selection.x1;
800 h = selection.y2 - selection.y1;
801 fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
802 fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
803 fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
804 fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
808 /* draw button bar */
809 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
811 if(le_current.IsTile())
813 Tile::draw(19 * 32, 14 * 32, le_current.tile);
814 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
815 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
817 if(le_current.IsObject())
819 le_current.obj->draw_on_screen(19 * 32, 14 * 32);
820 le_current.obj->draw_on_screen(cursor_x,cursor_y);
825 le_save_level_bt->draw();
827 le_test_level_bt->draw();
828 le_next_level_bt->draw();
829 le_previous_level_bt->draw();
830 le_rubber_bt->draw();
831 if(le_selection_mode == SQUARE)
832 le_select_mode_one_bt->draw();
833 else if(le_selection_mode == CURSOR)
834 le_select_mode_two_bt->draw();
835 le_settings_bt->draw();
836 le_move_right_bt->draw();
837 le_move_left_bt->draw();
838 le_tilegroup_bt->draw();
839 le_objects_bt->draw();
840 if(!cur_tilegroup.empty())
841 tilegroups_map[cur_tilegroup]->draw();
842 else if(!cur_objects.empty())
844 objects_map[cur_objects]->draw();
847 le_tilemap_panel->draw();
849 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
850 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
853 white_small_text->draw("F1 for Help", 10, 430, 1);
858 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
860 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
870 /* Draw the real background */
871 if(le_world->get_level()->bkgd_image[0] != '\0')
873 s = (int)((float)pos_x * ((float)le_world->get_level()->bkgd_speed/60.)) % screen->w;
874 le_world->get_level()->img_bkgd->draw_part(s,0,0,0,
875 le_world->get_level()->img_bkgd->w - s - 32, le_world->get_level()->img_bkgd->h);
876 le_world->get_level()->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
877 le_world->get_level()->img_bkgd->h);
881 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
884 if(le_current.IsTile())
886 Tile::draw(cursor_x-pos_x, cursor_y,le_current.tile,128);
887 if(!TileManager::instance()->get(le_current.tile)->images.empty())
888 fillrect(cursor_x-pos_x,cursor_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);
890 if(le_current.IsObject())
892 le_current.obj->move_to(cursor_x, cursor_y);
895 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
897 for (y = 0; y < 15; ++y)
898 for (x = 0; x < 20; ++x)
901 if(active_tm == TM_BG)
906 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->bg_tiles[y][x + (int)(pos_x / 32)],a);
908 if(active_tm == TM_IA)
913 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)],a);
915 if(active_tm == TM_FG)
920 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->fg_tiles[y][x + (int)(pos_x / 32)],a);
922 /* draw whats inside stuff when cursor is selecting those */
923 /* (draw them all the time - is this the right behaviour?) */
924 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)]);
925 if(edit_image && !edit_image->editor_images.empty())
926 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
930 /* Draw the Bad guys: */
931 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
933 /* to support frames: img_bsod_left[(frame / 5) % 4] */
940 /* Draw the player: */
941 /* for now, the position is fixed at (100, 240) */
942 largetux.walk_right->draw( 100 - pos_x, 240);
945 void le_change_object_properties(GameObject *pobj)
947 Menu* object_properties_menu = new Menu();
949 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
950 object_properties_menu->additem(MN_HL,"",0,0);
951 /*object_properties_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
952 object_properties_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
953 object_properties_menu->additem(MN_HL,"",0,0);
954 object_properties_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);*/
955 object_properties_menu->additem(MN_HL,"",0,0);
956 object_properties_menu->additem(MN_BACK,"Apply",0,0);
958 delete object_properties_menu;
962 void le_checkevents()
969 keymod = SDL_GetModState();
971 while(SDL_PollEvent(&event))
975 Menu::current()->event(event);
976 if(!le_world && !Menu::current())
977 Menu::set_current(leveleditor_menu);
981 mouse_cursor->set_state(MC_NORMAL);
983 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
984 if(event.type == SDL_KEYDOWN
985 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
986 && (event.motion.x > 0
987 && event.motion.x < screen->w - 64 &&
988 event.motion.y > 0 && event.motion.y < screen->h)))
992 case SDL_KEYDOWN: // key pressed
993 key = event.key.keysym.sym;
997 Menu::set_current(leveleditor_menu);
1001 cursor_x -= KEY_CURSOR_SPEED;
1003 cursor_x -= KEY_CURSOR_FASTSPEED;
1005 if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
1006 pos_x = cursor_x - MOUSE_LEFT_MARGIN;
1011 cursor_x += KEY_CURSOR_SPEED;
1013 cursor_x += KEY_CURSOR_FASTSPEED;
1015 if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
1016 pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
1021 cursor_y -= KEY_CURSOR_SPEED;
1023 cursor_y -= KEY_CURSOR_FASTSPEED;
1030 cursor_y += KEY_CURSOR_SPEED;
1032 cursor_y += KEY_CURSOR_FASTSPEED;
1034 if(cursor_y > screen->h-32)
1035 cursor_y = screen->h-32;
1041 if(le_world != NULL)
1049 cursor_x = (le_world->get_level()->width * 32) - 32;
1053 le_show_grid = !le_show_grid;
1059 case SDL_KEYUP: /* key released */
1060 switch(event.key.keysym.sym)
1069 case SDL_MOUSEBUTTONDOWN:
1070 if(event.button.button == SDL_BUTTON_LEFT)
1072 le_mouse_pressed[LEFT] = true;
1074 selection.x1 = event.motion.x + pos_x;
1075 selection.y1 = event.motion.y;
1076 selection.x2 = event.motion.x + pos_x;
1077 selection.y2 = event.motion.y;
1079 else if(event.button.button == SDL_BUTTON_RIGHT)
1081 le_mouse_pressed[RIGHT] = true;
1084 case SDL_MOUSEBUTTONUP:
1085 if(event.button.button == SDL_BUTTON_LEFT)
1087 le_mouse_pressed[LEFT] = false;
1088 le_mouse_clicked[LEFT] = true;
1090 else if(event.button.button == SDL_BUTTON_RIGHT)
1092 le_mouse_pressed[RIGHT] = false;
1093 le_mouse_clicked[RIGHT] = true;
1096 case SDL_MOUSEMOTION:
1098 if(!Menu::current())
1103 if(le_current.IsTile())
1105 cursor_x = ((int)(pos_x + x) / 32) * 32;
1106 cursor_y = ((int) y / 32) * 32;
1114 if(le_mouse_pressed[LEFT])
1116 selection.x2 = x + pos_x;
1120 if(le_mouse_pressed[RIGHT])
1122 pos_x += -1 * event.motion.xrel;
1126 case SDL_QUIT: // window closed
1135 if(le_world != NULL)
1137 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 &&
1138 event.motion.y > 0 && event.motion.y < screen->h)))
1140 le_mouse_pressed[LEFT] = false;
1141 le_mouse_pressed[RIGHT] = false;
1143 if(!Menu::current())
1145 /* Check for button events */
1146 le_test_level_bt->event(event);
1147 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1149 le_save_level_bt->event(event);
1150 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1151 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1152 le_exit_bt->event(event);
1153 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1155 Menu::set_current(leveleditor_menu);
1157 le_next_level_bt->event(event);
1158 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1160 if(le_level < le_level_subset->levels)
1162 le_goto_level(++le_level);
1168 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1169 if(confirm_dialog(str))
1171 new_lev.init_defaults();
1172 new_lev.save(le_level_subset->name.c_str(),++le_level);
1173 le_level_subset->levels = le_level;
1174 le_goto_level(le_level);
1178 le_previous_level_bt->event(event);
1179 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1182 le_goto_level(--le_level);
1184 le_rubber_bt->event(event);
1185 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1188 if(le_selection_mode == SQUARE)
1190 le_select_mode_one_bt->event(event);
1191 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1192 le_selection_mode = CURSOR;
1196 le_select_mode_two_bt->event(event);
1197 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1198 le_selection_mode = SQUARE;
1200 ButtonPanelMap::iterator it;
1201 le_tilegroup_bt->event(event);
1202 switch (le_tilegroup_bt->get_state())
1204 case BUTTON_CLICKED:
1205 Menu::set_current(select_tilegroup_menu);
1206 select_tilegroup_menu_effect.start(200);
1207 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1209 case BUTTON_WHEELUP:
1210 if(cur_tilegroup.empty())
1212 cur_tilegroup = tilegroups_map.begin()->first;
1216 it = tilegroups_map.find(cur_tilegroup);
1217 if((++it) == tilegroups_map.end())
1219 cur_tilegroup = tilegroups_map.begin()->first;
1223 cur_tilegroup = (*it).first;
1229 case BUTTON_WHEELDOWN:
1230 it = tilegroups_map.find(cur_tilegroup);
1231 if(it == tilegroups_map.begin())
1233 cur_tilegroup = tilegroups_map.rbegin()->first;
1237 if(--it != --tilegroups_map.begin())
1238 cur_tilegroup = (*it).first;
1240 cur_tilegroup = tilegroups_map.rbegin()->first;
1248 le_objects_bt->event(event);
1249 switch (le_objects_bt->get_state())
1251 case BUTTON_CLICKED:
1252 Menu::set_current(select_objects_menu);
1253 select_objects_menu_effect.start(200);
1254 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1256 case BUTTON_WHEELUP:
1257 it = objects_map.find(cur_objects);
1258 if(it == objects_map.end())
1260 cur_objects = objects_map.begin()->first;
1264 if(++it != objects_map.end())
1265 cur_objects = (*it).first;
1267 cur_objects = objects_map.begin()->first;
1271 case BUTTON_WHEELDOWN:
1272 it = objects_map.find(cur_objects);
1273 if(it == objects_map.begin())
1275 cur_objects = objects_map.rbegin()->first;
1279 if(--it != --objects_map.begin())
1280 cur_objects = (*it).first;
1282 cur_objects = objects_map.rbegin()->first;
1291 le_settings_bt->event(event);
1292 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1294 update_level_settings_menu();
1295 Menu::set_current(level_settings_menu);
1297 if(!cur_tilegroup.empty())
1299 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1301 if(pbutton->get_state() == BUTTON_CLICKED)
1303 le_current.Tile(pbutton->get_tag());
1307 else if(!cur_objects.empty())
1309 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1311 if(pbutton->get_state() == BUTTON_CLICKED)
1313 le_current.Object(pbutton->get_game_object());
1318 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1320 if(pbutton->get_state() == BUTTON_CLICKED)
1322 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1328 le_settings_bt->event(event);
1329 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1331 Menu::set_current(0);
1333 le_tilegroup_bt->event(event);
1334 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1336 Menu::set_current(0);
1338 le_objects_bt->event(event);
1339 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1341 Menu::set_current(0);
1346 if(!Menu::current() && !show_minimap)
1348 if(le_mouse_pressed[LEFT])
1350 if(le_current.IsTile())
1351 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1353 else if(le_mouse_clicked[LEFT])
1355 if(le_current.IsObject())
1357 le_level_changed = true;
1358 std::string type = le_current.obj->type();
1359 if(type == "BadGuy")
1361 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1363 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1364 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1367 le_mouse_clicked[LEFT] = false;
1372 if(!Menu::current())
1374 show_minimap = false;
1376 le_move_left_bt->event(event);
1377 le_move_right_bt->event(event);
1378 switch(le_move_left_bt->get_state())
1380 case BUTTON_PRESSED:
1382 show_minimap = true;
1386 show_minimap = true;
1388 case BUTTON_CLICKED:
1389 show_minimap = true;
1395 switch(le_move_right_bt->get_state())
1397 case BUTTON_PRESSED:
1399 show_minimap = true;
1403 show_minimap = true;
1405 case BUTTON_CLICKED:
1406 show_minimap = true;
1416 void le_highlight_selection()
1420 if(selection.x1 < selection.x2)
1430 if(selection.y1 < selection.y2)
1446 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1449 void le_change(float x, float y, int tm, unsigned int c)
1451 if(le_world != NULL)
1457 le_level_changed = true;
1459 switch(le_selection_mode)
1462 le_world->get_level()->change(x,y,tm,c);
1464 base_type cursor_base;
1467 cursor_base.width = 32;
1468 cursor_base.height = 32;
1470 /* if there is a bad guy over there, remove it */
1471 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1472 if(rectcollision(cursor_base,(*it)->base))
1475 le_world->bad_guys.erase(it);
1476 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1482 if(selection.x1 < selection.x2)
1492 if(selection.y1 < selection.y2)
1508 /* if there is a bad guy over there, remove it */
1509 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1510 it != le_world->bad_guys.end(); /* will be at end of loop */)
1512 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1513 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1516 it = le_world->bad_guys.erase(it);
1517 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1527 for(xx = x1; xx <= x2; xx++)
1528 for(yy = y1; yy <= y2; yy++)
1530 le_world->get_level()->change(xx*32, yy*32, tm, c);
1542 //Make sure a time value is set when testing the level
1543 if(le_world->get_level()->time_left == 0)
1544 le_world->get_level()->time_left = 250;
1546 le_world->get_level()->save("test", le_level);
1548 GameSession session("test",le_level, ST_GL_TEST);
1550 player_status.reset();
1552 music_manager->halt_music();
1554 Menu::set_current(NULL);
1555 World::set_current(le_world);
1560 bool tmp_show_grid = le_show_grid;
1561 int temp_le_selection_mode = le_selection_mode;
1562 le_selection_mode = NONE;
1563 le_show_grid = false;
1564 le_help_shown = true;
1566 drawgradient(Color(0,0,0), Color(255,255,255));
1570 unsigned int i, done_;
1573 " - Supertux level editor tutorial - ",
1575 "To make your map, click the ",
1576 "tilegroup button and choose a ",
1578 "Pick a tile and simply hold down ",
1579 "the left mouse button over the map",
1580 "to \"paint\" your selection over",
1582 "There are three layers for painting",
1583 "tiles upon, Background layer,",
1584 "the Interactive layer, and the",
1585 "Foreground layer, which can be",
1586 "toggled by the BkGrd, IntAct and",
1587 "FrGrd buttons. The Foreground and",
1588 "Background layers do not effect",
1589 "Tux in the gameplay, but lie in",
1590 "front of him or lie behind him in",
1596 " - Supertux level editor tutorial - ",
1598 "The tiles placed on",
1599 "the Interactive layer are those",
1600 "which actually effect Tux in the",
1602 "Click the objects menu to put ",
1603 "bad guys and other objects in the",
1604 "game. Unlike placing tiles, you",
1605 "cannot \"paint\" enemies. Click",
1606 "them onto the screen one at a time.",
1607 "To change the settings of your",
1608 "level, click the button with the",
1609 "screwdriver and wrench. From here",
1610 "you can change the background,",
1611 "music, length of the level, and more.",
1612 "You may have more than one levelset.",
1613 "Pressing the up and down buttons",
1614 "above the button bar lets you choose",
1615 "which one you are working on.",
1616 "If you would like to speed up your",
1617 "level editing, a useful trick is",
1618 "to learn the keyboard shortcuts. They",
1619 "are easy to learn, just right-",
1620 "Have fun making levels! If you make",
1621 "some good ones, send them to us on",
1622 "the SuperTux mailing list!",
1627 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1629 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1630 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1632 gold_text->drawf("Press Any Key to Continue - Page 1/2", 0, 0, A_LEFT, A_BOTTOM, 1);
1640 done_ = wait_for_event(event);
1644 drawgradient(Color(0,0,0), Color(255,255,255));
1648 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1650 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1651 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1653 gold_text->drawf("Press Any Key to Continue - Page 2/2", 0, 0, A_LEFT, A_BOTTOM, 1);
1661 done_ = wait_for_event(event);
1665 le_show_grid = tmp_show_grid;
1666 le_help_shown = false;
1667 le_selection_mode = temp_le_selection_mode;