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 show_selections;
107 static bool le_help_shown;
108 static int pos_x, cursor_x, cursor_y, fire;
110 static World* le_world;
111 static LevelSubset* le_level_subset;
112 static int le_show_grid;
114 static Surface* le_selection;
116 static TileOrObject le_current;
117 static bool le_mouse_pressed[2];
118 static bool le_mouse_clicked[2];
119 static Button* le_save_level_bt;
120 static Button* le_exit_bt;
121 static Button* le_test_level_bt;
122 static Button* le_next_level_bt;
123 static Button* le_previous_level_bt;
124 static Button* le_move_right_bt;
125 static Button* le_move_left_bt;
126 static Button* le_rubber_bt;
127 static Button* le_select_mode_one_bt;
128 static Button* le_select_mode_two_bt;
129 static Button* le_settings_bt;
130 static Button* le_tilegroup_bt;
131 static Button* le_objects_bt;
132 static ButtonPanel* le_tilemap_panel;
133 static Menu* leveleditor_menu;
134 static Menu* subset_load_menu;
135 static Menu* subset_new_menu;
136 static Menu* subset_settings_menu;
137 static Menu* level_settings_menu;
138 static Menu* select_tilegroup_menu;
139 static Menu* select_objects_menu;
140 static Timer select_tilegroup_menu_effect;
141 static Timer select_objects_menu_effect;
142 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
143 static ButtonPanelMap tilegroups_map;
144 static ButtonPanelMap objects_map;
145 static std::string cur_tilegroup;
146 static std::string cur_objects;
148 static square selection;
149 static int le_selection_mode;
150 static SDL_Event event;
151 TileMapType active_tm;
153 int leveleditor(char* filename)
155 int last_time, now_time, i;
164 clearscreen(0, 0, 0);
167 music_manager->halt_music();
169 while (SDL_PollEvent(&event))
173 if(le_load_level_subset(filename))
178 last_time = SDL_GetTicks();
183 if(Menu::current() == select_tilegroup_menu)
185 if(select_tilegroup_menu_effect.check())
187 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
191 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
193 else if(Menu::current() == select_objects_menu)
195 if(select_objects_menu_effect.check())
197 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
200 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
205 /* making events results to be in order */
208 if(pos_x > (le_world->get_level()->width * 32) - screen->w)
209 pos_x = (le_world->get_level()->width * 32) - screen->w;
215 clearscreen(0, 0, 0);
217 /* draw editor interface */
220 Menu* menu = Menu::current();
226 if(menu == leveleditor_menu)
228 switch (leveleditor_menu->check())
230 case MNID_RETURNLEVELEDITOR:
232 Menu::set_current(0);
234 Menu::set_current(leveleditor_menu);
236 case MNID_SUBSETSETTINGS:
237 update_subset_settings_menu();
239 case MNID_QUITLEVELEDITOR:
244 else if(menu == level_settings_menu)
246 switch (level_settings_menu->check())
249 apply_level_settings_menu();
250 Menu::set_current(NULL);
257 else if(menu == select_tilegroup_menu)
260 switch (it = select_tilegroup_menu->check())
265 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
266 Menu::set_current(0);
273 else if(menu == select_objects_menu)
276 switch (it = select_objects_menu->check())
281 cur_objects = select_objects_menu->get_item_by_id(it).text;
284 Menu::set_current(0);
289 else if(menu == subset_load_menu)
291 switch (i = subset_load_menu->check())
298 if(le_load_level_subset(level_subsets.item[i-1]))
304 else if(menu == subset_new_menu)
306 if(subset_new_menu->item[2].input[0] == '\0')
307 subset_new_menu->item[3].kind = MN_DEACTIVE;
310 subset_new_menu->item[3].kind = MN_ACTION;
312 switch (i = subset_new_menu->check())
314 case MNID_CREATESUBSET:
315 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
316 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
317 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
319 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
321 Menu::set_current(subset_settings_menu);
326 else if(menu == subset_settings_menu)
328 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 )
329 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
331 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
333 switch (i = subset_settings_menu->check())
335 case MNID_SUBSETSAVECHANGES:
336 save_subset_settings_menu();
337 Menu::set_current(leveleditor_menu);
343 mouse_cursor->draw();
351 ++global_frame_counter;
354 now_time = SDL_GetTicks();
355 if (now_time < last_time + FPS)
356 SDL_Delay(last_time + FPS - now_time); /* delay some time */
364 int le_load_level_subset(char *filename)
366 le_level_subset->load(filename);
367 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
371 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
373 Menu::set_current(NULL);
382 leveleditor_menu = new Menu();
383 subset_load_menu = new Menu();
384 subset_new_menu = new Menu();
385 subset_settings_menu = new Menu();
386 level_settings_menu = new Menu();
387 select_tilegroup_menu = new Menu();
388 select_objects_menu = new Menu();
390 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
391 leveleditor_menu->additem(MN_HL,"",0,0);
392 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
393 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
394 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
395 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
396 leveleditor_menu->additem(MN_HL,"",0,0);
397 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
399 Menu::set_current(leveleditor_menu);
401 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
402 subset_load_menu->additem(MN_HL, "", 0, 0);
404 for(i = 0; i < level_subsets.num_items; ++i)
406 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
408 subset_load_menu->additem(MN_HL,"",0,0);
409 subset_load_menu->additem(MN_BACK,"Back",0,0);
411 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
412 subset_new_menu->additem(MN_HL,"",0,0);
413 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
414 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
415 subset_new_menu->additem(MN_HL,"",0,0);
416 subset_new_menu->additem(MN_BACK,"Back",0,0);
418 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
419 subset_settings_menu->additem(MN_HL,"",0,0);
420 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
421 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
422 subset_settings_menu->additem(MN_HL,"",0,0);
423 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
424 subset_settings_menu->additem(MN_HL,"",0,0);
425 subset_settings_menu->additem(MN_BACK,"Back",0,0);
427 level_settings_menu->arrange_left = true;
428 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
429 level_settings_menu->additem(MN_HL,"",0,0);
430 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
431 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
432 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
433 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
434 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
435 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
436 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
437 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
438 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
439 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
440 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
441 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
442 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
443 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
444 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue",0,0,MNID_BottomBlue);
445 level_settings_menu->additem(MN_HL,"",0,0);
446 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
448 select_tilegroup_menu->arrange_left = true;
449 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
450 select_tilegroup_menu->additem(MN_HL,"",0,0);
451 select_tilegroup_menu->additem(MN_ACTION,"asd",0,0);
452 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
454 for(std::set<TileGroup>::iterator it = tilegroups->begin();
455 it != tilegroups->end(); ++it )
457 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
459 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
462 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
463 sit != (*it).tiles.end(); ++sit, ++i)
465 std::string imagefile = "/images/tilesets/" ;
466 bool only_editor_image = false;
467 if(!TileManager::instance()->get(*sit)->filenames.empty())
469 imagefile += TileManager::instance()->get(*sit)->filenames[0];
471 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
473 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
474 only_editor_image = true;
478 imagefile += "notile.png";
480 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
482 if(!only_editor_image)
483 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
485 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
486 button->add_icon(imagefile,32,32);
488 tilegroups_map[it->name]->additem(button, *sit);
491 select_tilegroup_menu->additem(MN_HL,"",0,0);
493 select_objects_menu->arrange_left = true;
494 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
495 select_objects_menu->additem(MN_HL,"",0,0);
496 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
497 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
499 for(int i = 0; i < NUM_BadGuyKinds; ++i)
501 BadGuy bad_tmp(0,0,BadGuyKind(i),false);
502 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
503 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));
506 select_objects_menu->additem(MN_HL,"",0,0);
514 level_subsets = dsubdirs("/levels", "level1.stl");
515 le_level_subset = new LevelSubset;
521 show_selections = true;
526 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
527 le_level_changed = false;
528 le_help_shown = false;
530 le_mouse_pressed[LEFT] = false;
531 le_mouse_pressed[RIGHT] = false;
533 le_mouse_clicked[LEFT] = false;
534 le_mouse_clicked[RIGHT] = false;
536 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
538 select_tilegroup_menu_effect.init(false);
539 select_objects_menu_effect.init(false);
542 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
543 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F9,screen->w-32,32);
544 le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
545 le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
546 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
547 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
548 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
549 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
550 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
551 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
552 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
553 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
554 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
556 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
557 le_tilemap_panel->set_button_size(32,10);
558 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
559 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
560 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
561 le_tilemap_panel->highlight_last(true);
562 le_tilemap_panel->set_last_clicked(TM_IA);
568 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
574 void update_level_settings_menu()
579 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
580 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
582 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
583 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
584 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
585 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
586 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
587 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
589 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
590 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
591 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
592 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
593 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
594 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
596 sprintf(str,"%d",le_world->get_level()->width);
597 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
598 sprintf(str,"%d",le_world->get_level()->time_left);
599 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
600 sprintf(str,"%2.0f",le_world->get_level()->gravity);
601 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
602 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
603 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
604 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
605 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
606 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
607 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
608 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
609 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
610 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
611 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
612 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
613 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
614 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
615 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
618 void update_subset_settings_menu()
620 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
621 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
624 void apply_level_settings_menu()
629 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
630 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
632 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
634 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
638 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
640 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
645 le_world->get_level()->load_gfx();
648 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
650 le_world->get_level()->change_size(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
651 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
652 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
653 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
654 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
655 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
656 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
657 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
658 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
659 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
662 void save_subset_settings_menu()
664 le_level_subset->title = subset_settings_menu->item[2].input;
665 le_level_subset->description = subset_settings_menu->item[3].input;
666 le_level_subset->save();
669 void le_unload_level()
676 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
677 if(confirm_dialog(str))
679 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
684 le_level_changed = false;
687 void le_goto_level(int levelnb)
690 le_world = new World(le_level_subset->name, levelnb);
695 SDL_EnableKeyRepeat(0, 0); // disables key repeating
699 delete leveleditor_menu;
700 delete subset_load_menu;
701 delete subset_new_menu;
702 delete subset_settings_menu;
703 delete level_settings_menu;
704 delete select_tilegroup_menu;
705 delete select_objects_menu;
706 delete le_save_level_bt;
708 delete le_test_level_bt;
709 delete le_next_level_bt;
710 delete le_previous_level_bt;
711 delete le_move_right_bt;
712 delete le_move_left_bt;
714 delete le_select_mode_one_bt;
715 delete le_select_mode_two_bt;
716 delete le_settings_bt;
717 delete le_tilegroup_bt;
718 delete le_objects_bt;
719 delete le_tilemap_panel;
721 delete le_level_subset;
724 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
725 i != tilegroups_map.end(); ++i)
729 for(ButtonPanelMap::iterator i = objects_map.begin();
730 i != objects_map.end(); ++i)
736 void le_drawminimap()
742 if(screen->w - 64 > le_world->get_level()->width * 4)
744 else if(screen->w - 64 > le_world->get_level()->width * 2)
748 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
750 for (int y = 0; y < 15; ++y)
751 for (int x = 0; x < le_world->get_level()->width; ++x)
754 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
756 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
758 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
762 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, 15*4, 200, 200, 200, 128);
764 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
765 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, 15*4, 200, 200, 200, 200);
766 fillrect(left_offset + (pos_x/32)*mini_tile_width + 19*mini_tile_width - 2, 0, 2, 15*4, 200, 200, 200, 200);
767 fillrect(left_offset + (pos_x/32)*mini_tile_width, 15*4-2, 19*mini_tile_width, 2, 200, 200, 200, 200);
771 void le_drawinterface()
778 /* draw a grid (if selected) */
781 for(x = 0; x < 19; x++)
782 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
783 for(y = 0; y < 15; y++)
784 fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
788 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
793 if(le_selection_mode == CURSOR)
795 if(le_current.IsTile())
796 le_selection->draw( cursor_x - pos_x, cursor_y);
798 else if(le_selection_mode == SQUARE)
801 le_highlight_selection();
802 /* draw current selection */
803 w = selection.x2 - selection.x1;
804 h = selection.y2 - selection.y1;
805 fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
806 fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
807 fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
808 fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
813 /* draw button bar */
814 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
816 if(le_current.IsTile())
818 Tile::draw(19 * 32, 14 * 32, le_current.tile);
819 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
820 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
822 if(le_current.IsObject())
824 le_current.obj->draw_on_screen(19 * 32, 14 * 32);
825 le_current.obj->draw_on_screen(cursor_x,cursor_y);
830 le_save_level_bt->draw();
832 le_test_level_bt->draw();
833 le_next_level_bt->draw();
834 le_previous_level_bt->draw();
835 le_rubber_bt->draw();
836 if(le_selection_mode == SQUARE)
837 le_select_mode_one_bt->draw();
838 else if(le_selection_mode == CURSOR)
839 le_select_mode_two_bt->draw();
840 le_settings_bt->draw();
841 le_move_right_bt->draw();
842 le_move_left_bt->draw();
843 le_tilegroup_bt->draw();
844 le_objects_bt->draw();
845 if(!cur_tilegroup.empty())
846 tilegroups_map[cur_tilegroup]->draw();
847 else if(!cur_objects.empty())
849 objects_map[cur_objects]->draw();
852 le_tilemap_panel->draw();
854 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
855 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
858 white_small_text->draw("F1 for Help", 10, 430, 1);
863 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
865 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
875 /* Draw the real background */
876 if(le_world->get_level()->bkgd_image[0] != '\0')
878 s = (int)((float)pos_x * ((float)le_world->get_level()->bkgd_speed/60.)) % screen->w;
879 le_world->get_level()->img_bkgd->draw_part(s,0,0,0,
880 le_world->get_level()->img_bkgd->w - s - 32, le_world->get_level()->img_bkgd->h);
881 le_world->get_level()->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
882 le_world->get_level()->img_bkgd->h);
886 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
889 if(le_current.IsTile())
891 Tile::draw(cursor_x-pos_x, cursor_y,le_current.tile,128);
892 if(!TileManager::instance()->get(le_current.tile)->images.empty())
893 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);
895 if(le_current.IsObject())
897 le_current.obj->move_to(cursor_x, cursor_y);
900 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
902 for (y = 0; y < 15; ++y)
903 for (x = 0; x < 20; ++x)
906 if(active_tm == TM_BG)
911 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->bg_tiles[y][x + (int)(pos_x / 32)],a);
913 if(active_tm == TM_IA)
918 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)],a);
920 if(active_tm == TM_FG)
925 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->fg_tiles[y][x + (int)(pos_x / 32)],a);
927 /* draw whats inside stuff when cursor is selecting those */
928 /* (draw them all the time - is this the right behaviour?) */
929 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)]);
930 if(edit_image && !edit_image->editor_images.empty())
931 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
935 /* Draw the Bad guys: */
936 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
938 /* to support frames: img_bsod_left[(frame / 5) % 4] */
945 /* Draw the player: */
946 /* for now, the position is fixed at (100, 240) */
947 largetux.walk_right->draw( 100 - pos_x, 240);
950 void le_change_object_properties(GameObject *pobj)
952 Menu* object_properties_menu = new Menu();
954 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
955 object_properties_menu->additem(MN_HL,"",0,0);
956 /*object_properties_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
957 object_properties_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
958 object_properties_menu->additem(MN_HL,"",0,0);
959 object_properties_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);*/
960 object_properties_menu->additem(MN_HL,"",0,0);
961 object_properties_menu->additem(MN_BACK,"Apply",0,0);
963 delete object_properties_menu;
967 void le_checkevents()
974 keymod = SDL_GetModState();
976 while(SDL_PollEvent(&event))
980 Menu::current()->event(event);
981 if(!le_world && !Menu::current())
982 Menu::set_current(leveleditor_menu);
986 mouse_cursor->set_state(MC_NORMAL);
988 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
989 if(event.type == SDL_KEYDOWN
990 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
991 && (event.motion.x > 0
992 && event.motion.x < screen->w - 64 &&
993 event.motion.y > 0 && event.motion.y < screen->h)))
997 case SDL_KEYDOWN: // key pressed
998 key = event.key.keysym.sym;
1002 Menu::set_current(leveleditor_menu);
1006 cursor_x -= KEY_CURSOR_SPEED;
1008 cursor_x -= KEY_CURSOR_FASTSPEED;
1010 if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
1011 pos_x = cursor_x - MOUSE_LEFT_MARGIN;
1016 cursor_x += KEY_CURSOR_SPEED;
1018 cursor_x += KEY_CURSOR_FASTSPEED;
1020 if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
1021 pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
1026 cursor_y -= KEY_CURSOR_SPEED;
1028 cursor_y -= KEY_CURSOR_FASTSPEED;
1035 cursor_y += KEY_CURSOR_SPEED;
1037 cursor_y += KEY_CURSOR_FASTSPEED;
1039 if(cursor_y > screen->h-32)
1040 cursor_y = screen->h-32;
1046 if(le_world != NULL)
1054 cursor_x = (le_world->get_level()->width * 32) - 32;
1058 le_show_grid = !le_show_grid;
1064 case SDL_KEYUP: /* key released */
1065 switch(event.key.keysym.sym)
1074 case SDL_MOUSEBUTTONDOWN:
1075 if(event.button.button == SDL_BUTTON_LEFT)
1077 le_mouse_pressed[LEFT] = true;
1079 selection.x1 = event.motion.x + pos_x;
1080 selection.y1 = event.motion.y;
1081 selection.x2 = event.motion.x + pos_x;
1082 selection.y2 = event.motion.y;
1084 else if(event.button.button == SDL_BUTTON_RIGHT)
1086 le_mouse_pressed[RIGHT] = true;
1089 case SDL_MOUSEBUTTONUP:
1090 if(event.button.button == SDL_BUTTON_LEFT)
1092 le_mouse_pressed[LEFT] = false;
1093 le_mouse_clicked[LEFT] = true;
1095 else if(event.button.button == SDL_BUTTON_RIGHT)
1097 le_mouse_pressed[RIGHT] = false;
1098 le_mouse_clicked[RIGHT] = true;
1101 case SDL_MOUSEMOTION:
1103 if(!Menu::current())
1108 if(le_current.IsTile())
1110 cursor_x = ((int)(pos_x + x) / 32) * 32;
1111 cursor_y = ((int) y / 32) * 32;
1119 if(le_mouse_pressed[LEFT])
1121 selection.x2 = x + pos_x;
1125 if(le_mouse_pressed[RIGHT])
1127 pos_x += -1 * event.motion.xrel;
1131 case SDL_QUIT: // window closed
1140 if(le_world != NULL)
1142 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 &&
1143 event.motion.y > 0 && event.motion.y < screen->h)))
1145 le_mouse_pressed[LEFT] = false;
1146 le_mouse_pressed[RIGHT] = false;
1148 if(!Menu::current())
1150 /* Check for button events */
1151 le_test_level_bt->event(event);
1152 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1154 le_save_level_bt->event(event);
1155 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1156 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1157 le_exit_bt->event(event);
1158 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1160 Menu::set_current(leveleditor_menu);
1162 le_next_level_bt->event(event);
1163 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1165 if(le_level < le_level_subset->levels)
1167 le_goto_level(++le_level);
1173 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1174 if(confirm_dialog(str))
1176 new_lev.init_defaults();
1177 new_lev.save(le_level_subset->name.c_str(),++le_level);
1178 le_level_subset->levels = le_level;
1179 le_goto_level(le_level);
1183 le_previous_level_bt->event(event);
1184 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1187 le_goto_level(--le_level);
1189 le_rubber_bt->event(event);
1190 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1193 if(le_selection_mode == SQUARE)
1195 le_select_mode_one_bt->event(event);
1196 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1197 le_selection_mode = CURSOR;
1201 le_select_mode_two_bt->event(event);
1202 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1203 le_selection_mode = SQUARE;
1205 ButtonPanelMap::iterator it;
1206 le_tilegroup_bt->event(event);
1207 switch (le_tilegroup_bt->get_state())
1209 case BUTTON_CLICKED:
1210 Menu::set_current(select_tilegroup_menu);
1211 select_tilegroup_menu_effect.start(200);
1212 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1214 case BUTTON_WHEELUP:
1215 if(cur_tilegroup.empty())
1217 cur_tilegroup = tilegroups_map.begin()->first;
1221 it = tilegroups_map.find(cur_tilegroup);
1222 if((++it) == tilegroups_map.end())
1224 cur_tilegroup = tilegroups_map.begin()->first;
1228 cur_tilegroup = (*it).first;
1234 case BUTTON_WHEELDOWN:
1235 it = tilegroups_map.find(cur_tilegroup);
1236 if(it == tilegroups_map.begin())
1238 cur_tilegroup = tilegroups_map.rbegin()->first;
1242 if(--it != --tilegroups_map.begin())
1243 cur_tilegroup = (*it).first;
1245 cur_tilegroup = tilegroups_map.rbegin()->first;
1253 le_objects_bt->event(event);
1254 switch (le_objects_bt->get_state())
1256 case BUTTON_CLICKED:
1257 Menu::set_current(select_objects_menu);
1258 select_objects_menu_effect.start(200);
1259 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1261 case BUTTON_WHEELUP:
1262 it = objects_map.find(cur_objects);
1263 if(it == objects_map.end())
1265 cur_objects = objects_map.begin()->first;
1269 if(++it != objects_map.end())
1270 cur_objects = (*it).first;
1272 cur_objects = objects_map.begin()->first;
1276 case BUTTON_WHEELDOWN:
1277 it = objects_map.find(cur_objects);
1278 if(it == objects_map.begin())
1280 cur_objects = objects_map.rbegin()->first;
1284 if(--it != --objects_map.begin())
1285 cur_objects = (*it).first;
1287 cur_objects = objects_map.rbegin()->first;
1296 le_settings_bt->event(event);
1297 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1299 update_level_settings_menu();
1300 Menu::set_current(level_settings_menu);
1302 if(!cur_tilegroup.empty())
1304 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1306 if(pbutton->get_state() == BUTTON_CLICKED)
1308 le_current.Tile(pbutton->get_tag());
1312 else if(!cur_objects.empty())
1314 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1316 if(pbutton->get_state() == BUTTON_CLICKED)
1318 le_current.Object(pbutton->get_game_object());
1323 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1325 if(pbutton->get_state() == BUTTON_CLICKED)
1327 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1333 le_settings_bt->event(event);
1334 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1336 Menu::set_current(0);
1338 le_tilegroup_bt->event(event);
1339 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1341 Menu::set_current(0);
1343 le_objects_bt->event(event);
1344 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1346 Menu::set_current(0);
1351 if(!Menu::current() && !show_minimap)
1353 if(le_mouse_pressed[LEFT])
1355 if(le_current.IsTile())
1356 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1358 else if(le_mouse_clicked[LEFT])
1360 if(le_current.IsObject())
1362 le_level_changed = true;
1363 std::string type = le_current.obj->type();
1364 if(type == "BadGuy")
1366 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1368 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1369 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1372 le_mouse_clicked[LEFT] = false;
1377 if(!Menu::current())
1379 show_minimap = false;
1381 le_move_left_bt->event(event);
1382 le_move_right_bt->event(event);
1383 switch(le_move_left_bt->get_state())
1385 case BUTTON_PRESSED:
1387 show_minimap = true;
1391 show_minimap = true;
1393 case BUTTON_CLICKED:
1394 show_minimap = true;
1400 switch(le_move_right_bt->get_state())
1402 case BUTTON_PRESSED:
1404 show_minimap = true;
1408 show_minimap = true;
1410 case BUTTON_CLICKED:
1411 show_minimap = true;
1421 void le_highlight_selection()
1425 if(selection.x1 < selection.x2)
1435 if(selection.y1 < selection.y2)
1451 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1454 void le_change(float x, float y, int tm, unsigned int c)
1456 if(le_world != NULL)
1462 le_level_changed = true;
1464 switch(le_selection_mode)
1467 le_world->get_level()->change(x,y,tm,c);
1469 base_type cursor_base;
1472 cursor_base.width = 32;
1473 cursor_base.height = 32;
1475 /* if there is a bad guy over there, remove it */
1476 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1477 if(rectcollision(cursor_base,(*it)->base))
1480 le_world->bad_guys.erase(it);
1481 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1487 if(selection.x1 < selection.x2)
1497 if(selection.y1 < selection.y2)
1513 /* if there is a bad guy over there, remove it */
1514 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1515 it != le_world->bad_guys.end(); /* will be at end of loop */)
1517 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1518 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1521 it = le_world->bad_guys.erase(it);
1522 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1532 for(xx = x1; xx <= x2; xx++)
1533 for(yy = y1; yy <= y2; yy++)
1535 le_world->get_level()->change(xx*32, yy*32, tm, c);
1547 //Make sure a time value is set when testing the level
1548 if(le_world->get_level()->time_left == 0)
1549 le_world->get_level()->time_left = 250;
1551 le_world->get_level()->save("test", le_level);
1553 GameSession session("test",le_level, ST_GL_TEST);
1555 player_status.reset();
1557 music_manager->halt_music();
1559 Menu::set_current(NULL);
1560 World::set_current(le_world);
1565 bool tmp_show_grid = le_show_grid;
1566 int temp_le_selection_mode = le_selection_mode;
1567 le_selection_mode = NONE;
1568 show_selections = true;
1569 le_show_grid = false;
1570 le_help_shown = true;
1572 drawgradient(Color(0,0,0), Color(255,255,255));
1576 unsigned int i, done_;
1579 " - Supertux level editor tutorial - ",
1581 "To make your map, click the ",
1582 "tilegroup button and choose a ",
1584 "Pick a tile and simply hold down ",
1585 "the left mouse button over the map",
1586 "to \"paint\" your selection over",
1589 "There are three layers for painting",
1590 "tiles upon, Background layer,",
1591 "the Interactive layer, and the",
1592 "Foreground layer, which can be",
1593 "toggled by the BkGrd, IntAct and",
1594 "FrGrd buttons. The Foreground and",
1595 "Background layers do not effect",
1596 "Tux in the gameplay, but lie in",
1597 "front of him or lie behind him in",
1603 " - Supertux level editor tutorial - ",
1605 "The tiles placed on",
1606 "the Interactive layer are those",
1607 "which actually effect Tux in the",
1610 "Click the objects menu to put ",
1611 "bad guys and other objects in the",
1612 "game. Unlike placing tiles, you",
1613 "cannot \"paint\" enemies. Click",
1614 "them onto the screen one at a time.",
1616 "To change the settings of your",
1617 "level, click the button with the",
1618 "screwdriver and wrench. From here",
1619 "you can change the background,",
1620 "music, length of the level,",
1626 " - Supertux level editor tutorial - ",
1628 "You may have more than one level.",
1629 "Pressing the up and down buttons",
1630 "above the button bar lets you",
1631 "choose which one you are working on.",
1633 "If you would like to speed up your",
1634 "level editing, a useful trick is",
1635 "to learn the keyboard shortcuts.",
1636 "They are easy to learn, just right-",
1637 "click on the buttons.",
1639 "Have fun making levels! If you make",
1640 "some good ones, send them to us on",
1641 "the SuperTux mailing list!",
1647 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1649 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1650 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1652 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1660 done_ = wait_for_event(event);
1664 drawgradient(Color(0,0,0), Color(255,255,255));
1668 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1670 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1671 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1673 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1681 done_ = wait_for_event(event);
1685 drawgradient(Color(0,0,0), Color(255,255,255));
1689 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1691 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1692 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1694 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1702 done_ = wait_for_event(event);
1706 show_selections = true;
1707 le_show_grid = tmp_show_grid;
1708 le_selection_mode = temp_le_selection_mode;
1709 le_help_shown = false;