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)
59 #define KEYBOARD_SPEED 140
60 #define MOUSE_SPEED 40
63 #define SELECT_W 2 // size of the selections lines
64 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
66 /* own declerations */
67 /* crutial ones (main loop) */
70 int le_load_level_subset(char *filename);
72 void le_drawinterface();
73 void le_checkevents();
74 void le_change(float x, float y, int tm, unsigned int c);
77 void le_set_defaults(void);
78 void le_activate_bad_guys(void);
79 void le_goto_level(int levelnb);
80 void le_highlight_selection();
82 void apply_level_settings_menu();
83 void update_subset_settings_menu();
84 void save_subset_settings_menu();
88 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
90 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
91 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
92 //Returns true for a tile
93 bool IsTile() { return is_tile; };
94 //Returns true for a GameObject
95 bool IsObject() { return !is_tile; };
98 void Init() { tile = 0; obj = NULL; is_tile = true; };
100 bool is_tile; //true for tile (false for object)
105 /* leveleditor internals */
106 static string_list_type level_subsets;
107 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
108 static bool show_minimap;
109 static bool show_selections;
110 static bool le_help_shown;
111 static int pos_x, pos_y, cursor_x, cursor_y;
113 static World* le_world;
114 static LevelSubset* le_level_subset;
115 static int le_show_grid;
117 static Surface* le_selection;
119 static TileOrObject le_current;
120 static bool le_mouse_pressed[2];
121 static bool le_mouse_clicked[2];
122 static Button* le_save_level_bt;
123 static Button* le_exit_bt;
124 static Button* le_test_level_bt;
125 static Button* le_next_level_bt;
126 static Button* le_previous_level_bt;
127 static Button* le_move_right_bt;
128 static Button* le_move_left_bt;
129 static Button* le_move_up_bt;
130 static Button* le_move_down_bt;
131 static Button* le_rubber_bt;
132 static Button* le_select_mode_one_bt;
133 static Button* le_select_mode_two_bt;
134 static Button* le_settings_bt;
135 static Button* le_tilegroup_bt;
136 static Button* le_objects_bt;
137 static Button* le_object_select_bt;
138 static Button* le_object_properties_bt;
139 static ButtonPanel* le_tilemap_panel;
140 static Menu* leveleditor_menu;
141 static Menu* subset_load_menu;
142 static Menu* subset_new_menu;
143 static Menu* subset_settings_menu;
144 static Menu* level_settings_menu;
145 static Menu* select_tilegroup_menu;
146 static Menu* select_objects_menu;
147 static Timer select_tilegroup_menu_effect;
148 static Timer select_objects_menu_effect;
149 static Timer display_level_info;
150 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
151 static ButtonPanelMap tilegroups_map;
152 static ButtonPanelMap objects_map;
153 static std::string cur_tilegroup;
154 static std::string cur_objects;
155 static MouseCursor* mouse_select_object;
156 static GameObject* selected_game_object;
158 static square selection;
159 static SelectionMode le_selection_mode;
160 static SDL_Event event;
161 TileMapType active_tm;
163 int leveleditor(char* filename)
165 int last_time, now_time, i;
174 clearscreen(0, 0, 0);
177 music_manager->halt_music();
179 while (SDL_PollEvent(&event))
183 if(le_load_level_subset(filename))
188 last_time = SDL_GetTicks();
193 if(Menu::current() == select_tilegroup_menu)
195 if(select_tilegroup_menu_effect.check())
197 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
201 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
203 else if(Menu::current() == select_objects_menu)
205 if(select_objects_menu_effect.check())
207 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
210 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
215 /* making events results to be in order */
221 clearscreen(0, 0, 0);
223 /* draw editor interface */
226 Menu* menu = Menu::current();
232 if(menu == leveleditor_menu)
234 switch (leveleditor_menu->check())
236 case MNID_RETURNLEVELEDITOR:
238 Menu::set_current(0);
240 Menu::set_current(leveleditor_menu);
242 case MNID_SUBSETSETTINGS:
243 update_subset_settings_menu();
245 case MNID_QUITLEVELEDITOR:
250 else if(menu == level_settings_menu)
252 switch (level_settings_menu->check())
255 apply_level_settings_menu();
256 Menu::set_current(NULL);
263 else if(menu == select_tilegroup_menu)
266 switch (it = select_tilegroup_menu->check())
271 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
272 Menu::set_current(0);
279 else if(menu == select_objects_menu)
282 switch (it = select_objects_menu->check())
287 cur_objects = select_objects_menu->get_item_by_id(it).text;
290 Menu::set_current(0);
295 else if(menu == subset_load_menu)
297 switch (i = subset_load_menu->check())
304 if(le_load_level_subset(level_subsets.item[i-1]))
310 else if(menu == subset_new_menu)
312 if(subset_new_menu->item[2].input[0] == '\0')
313 subset_new_menu->item[3].kind = MN_DEACTIVE;
316 subset_new_menu->item[3].kind = MN_ACTION;
318 switch (i = subset_new_menu->check())
320 case MNID_CREATESUBSET:
321 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
322 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
323 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
325 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
327 Menu::set_current(subset_settings_menu);
332 else if(menu == subset_settings_menu)
334 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 )
335 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
337 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
339 switch (i = subset_settings_menu->check())
341 case MNID_SUBSETSAVECHANGES:
342 save_subset_settings_menu();
343 Menu::set_current(leveleditor_menu);
349 MouseCursor::current()->draw();
357 ++global_frame_counter;
360 now_time = SDL_GetTicks();
361 if (now_time < last_time + FPS)
362 SDL_Delay(last_time + FPS - now_time); /* delay some time */
370 int le_load_level_subset(char *filename)
372 le_level_subset->load(filename);
373 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
377 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
379 Menu::set_current(NULL);
388 leveleditor_menu = new Menu();
389 subset_load_menu = new Menu();
390 subset_new_menu = new Menu();
391 subset_settings_menu = new Menu();
392 level_settings_menu = new Menu();
393 select_tilegroup_menu = new Menu();
394 select_objects_menu = new Menu();
396 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
397 leveleditor_menu->additem(MN_HL,"",0,0);
398 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
399 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
400 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
401 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
402 leveleditor_menu->additem(MN_HL,"",0,0);
403 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
405 Menu::set_current(leveleditor_menu);
407 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
408 subset_load_menu->additem(MN_HL, "", 0, 0);
410 for(i = 0; i < level_subsets.num_items; ++i)
412 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
414 subset_load_menu->additem(MN_HL,"",0,0);
415 subset_load_menu->additem(MN_BACK,"Back",0,0);
417 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
418 subset_new_menu->additem(MN_HL,"",0,0);
419 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
420 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
421 subset_new_menu->additem(MN_HL,"",0,0);
422 subset_new_menu->additem(MN_BACK,"Back",0,0);
424 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
425 subset_settings_menu->additem(MN_HL,"",0,0);
426 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
427 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
428 subset_settings_menu->additem(MN_HL,"",0,0);
429 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
430 subset_settings_menu->additem(MN_HL,"",0,0);
431 subset_settings_menu->additem(MN_BACK,"Back",0,0);
433 level_settings_menu->arrange_left = true;
434 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
435 level_settings_menu->additem(MN_HL,"",0,0);
436 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
437 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
438 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
439 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
440 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
441 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
442 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
443 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
444 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
445 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
446 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
447 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
448 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
449 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
450 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
451 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
452 level_settings_menu->additem(MN_HL,"",0,0);
453 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
455 select_tilegroup_menu->arrange_left = true;
456 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
457 select_tilegroup_menu->additem(MN_HL,"",0,0);
458 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
460 for(std::set<TileGroup>::iterator it = tilegroups->begin();
461 it != tilegroups->end(); ++it )
463 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
465 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
468 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
469 sit != (*it).tiles.end(); ++sit, ++i)
471 std::string imagefile = "/images/tilesets/" ;
472 bool only_editor_image = false;
473 if(!TileManager::instance()->get(*sit)->filenames.empty())
475 imagefile += TileManager::instance()->get(*sit)->filenames[0];
477 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
479 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
480 only_editor_image = true;
484 imagefile += "notile.png";
486 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
488 if(!only_editor_image)
489 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
491 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
492 button->add_icon(imagefile,32,32);
494 tilegroups_map[it->name]->additem(button, *sit);
497 select_tilegroup_menu->additem(MN_HL,"",0,0);
499 select_objects_menu->arrange_left = true;
500 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
501 select_objects_menu->additem(MN_HL,"",0,0);
502 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
503 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
505 for(int i = 0; i < NUM_BadGuyKinds; ++i)
507 BadGuy bad_tmp(0,0,BadGuyKind(i),false);
508 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
509 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));
512 select_objects_menu->additem(MN_HL,"",0,0);
520 level_subsets = dsubdirs("/levels", "level1.stl");
521 le_level_subset = new LevelSubset;
524 selected_game_object = NULL;
528 show_selections = true;
532 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
533 le_level_changed = false;
534 le_help_shown = false;
536 le_mouse_pressed[LEFT] = false;
537 le_mouse_pressed[RIGHT] = false;
539 le_mouse_clicked[LEFT] = false;
540 le_mouse_clicked[RIGHT] = false;
542 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
544 select_tilegroup_menu_effect.init(false);
545 select_objects_menu_effect.init(false);
546 display_level_info.init(false);
549 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
550 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
551 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
552 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
553 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
554 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
555 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
556 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
557 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
558 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
559 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
560 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
561 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
562 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
563 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
564 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
565 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
566 le_object_properties_bt->set_active(false);
568 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
569 mouse_select_object->set_mid(16,16);
571 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
572 le_tilemap_panel->set_button_size(32,10);
573 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
574 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
575 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
576 le_tilemap_panel->highlight_last(true);
577 le_tilemap_panel->set_last_clicked(TM_IA);
583 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
589 void update_level_settings_menu()
594 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
595 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
597 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
598 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
599 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
600 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
601 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
602 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
604 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
605 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
606 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
607 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
608 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
609 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
611 sprintf(str,"%d",le_world->get_level()->width);
612 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
613 sprintf(str,"%d",le_world->get_level()->height);
614 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
615 sprintf(str,"%d",le_world->get_level()->time_left);
616 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
617 sprintf(str,"%2.0f",le_world->get_level()->gravity);
618 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
619 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
620 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
621 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
622 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
623 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
624 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
625 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
626 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
627 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
628 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
629 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
630 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
631 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
632 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
635 void update_subset_settings_menu()
637 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
638 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
641 void apply_level_settings_menu()
646 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
647 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
649 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
651 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
655 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
657 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
662 le_world->get_level()->load_gfx();
665 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
667 le_world->get_level()->change_width(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
668 le_world->get_level()->change_height(atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
669 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
670 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
671 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
672 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
673 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
674 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
675 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
676 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
677 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
680 void save_subset_settings_menu()
682 le_level_subset->title = subset_settings_menu->item[2].input;
683 le_level_subset->description = subset_settings_menu->item[3].input;
684 le_level_subset->save();
685 le_level_changed = false;
688 void le_unload_level()
695 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
696 if(confirm_dialog(str))
698 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
703 le_level_changed = false;
706 void le_goto_level(int levelnb)
709 le_world = new World(le_level_subset->name, levelnb);
710 display_level_info.start(2500);
716 SDL_EnableKeyRepeat(0, 0); // disables key repeating
720 delete leveleditor_menu;
721 delete subset_load_menu;
722 delete subset_new_menu;
723 delete subset_settings_menu;
724 delete level_settings_menu;
725 delete select_tilegroup_menu;
726 delete select_objects_menu;
727 delete le_save_level_bt;
729 delete le_test_level_bt;
730 delete le_next_level_bt;
731 delete le_previous_level_bt;
732 delete le_move_right_bt;
733 delete le_move_left_bt;
734 delete le_move_up_bt;
735 delete le_move_down_bt;
737 delete le_select_mode_one_bt;
738 delete le_select_mode_two_bt;
739 delete le_settings_bt;
740 delete le_tilegroup_bt;
741 delete le_objects_bt;
742 delete le_tilemap_panel;
743 delete le_object_select_bt;
744 delete le_object_properties_bt;
745 delete mouse_select_object;
747 delete le_level_subset;
750 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
751 i != tilegroups_map.end(); ++i)
755 for(ButtonPanelMap::iterator i = objects_map.begin();
756 i != objects_map.end(); ++i)
762 void le_drawminimap()
768 if(screen->w - 64 > le_world->get_level()->width * 4)
770 else if(screen->w - 64 > le_world->get_level()->width * 2)
774 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
776 int mini_tile_height;
777 if(screen->h - 64 > le_world->get_level()->height * 4)
778 mini_tile_height = 4;
779 else if(screen->h - 64 > le_world->get_level()->height * 2)
780 mini_tile_height = 2;
782 mini_tile_height = 1;
784 for (int y = 0; y < le_world->get_level()->height; ++y)
785 for (int x = 0; x < le_world->get_level()->width; ++x)
788 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
790 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
792 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
796 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 128);
798 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
799 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 200);
800 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);
801 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);
805 void le_drawinterface()
812 /* draw a grid (if selected) */
815 for(x = 0; x < VISIBLE_TILES_X; x++)
816 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
817 for(y = 0; y < VISIBLE_TILES_Y; y++)
818 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
822 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
825 if(show_selections && MouseCursor::current() != mouse_select_object)
827 if(le_selection_mode == CURSOR)
829 if(le_current.IsTile())
830 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
832 else if(le_selection_mode == SQUARE)
835 le_highlight_selection();
836 /* draw current selection */
837 w = selection.x2 - selection.x1;
838 h = selection.y2 - selection.y1;
839 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
840 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
841 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
842 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
847 /* draw button bar */
848 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
850 if(le_current.IsTile())
852 Tile::draw(screen->w - 32, screen->h - 32, le_current.tile);
853 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
854 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
856 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
858 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
859 le_current.obj->draw_on_screen(cursor_x,cursor_y);
862 if(mouse_select_object && selected_game_object != NULL)
864 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);
865 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);
866 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);
867 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);
872 le_save_level_bt->draw();
874 le_test_level_bt->draw();
875 le_next_level_bt->draw();
876 le_previous_level_bt->draw();
877 le_rubber_bt->draw();
878 if(le_selection_mode == SQUARE)
879 le_select_mode_one_bt->draw();
880 else if(le_selection_mode == CURSOR)
881 le_select_mode_two_bt->draw();
882 le_settings_bt->draw();
883 le_move_right_bt->draw();
884 le_move_left_bt->draw();
885 le_move_up_bt->draw();
886 le_move_down_bt->draw();
887 le_tilegroup_bt->draw();
888 le_objects_bt->draw();
889 if(!cur_tilegroup.empty())
890 tilegroups_map[cur_tilegroup]->draw();
891 else if(!cur_objects.empty())
893 objects_map[cur_objects]->draw();
896 le_tilemap_panel->draw();
898 if(!cur_objects.empty())
900 le_object_select_bt->draw();
901 le_object_properties_bt->draw();
904 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
905 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
908 white_small_text->draw("F1 for Help", 10, 430, 1);
910 if(display_level_info.check())
911 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
916 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
918 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
928 /* Draw the real background */
929 if(le_world->get_level()->bkgd_image[0] != '\0')
931 s = (int)((float)pos_x * ((float)le_world->get_level()->bkgd_speed/100.0f)) % screen->w;
932 le_world->get_level()->img_bkgd->draw_part(s,0,0,0,
933 le_world->get_level()->img_bkgd->w - s - 32, le_world->get_level()->img_bkgd->h);
934 le_world->get_level()->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
935 le_world->get_level()->img_bkgd->h);
939 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
942 if(le_current.IsTile())
944 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
945 if(!TileManager::instance()->get(le_current.tile)->images.empty())
946 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);
948 if(le_current.IsObject())
950 le_current.obj->move_to(cursor_x, cursor_y);
953 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
955 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
956 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
959 if(active_tm == TM_BG)
964 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);
966 if(active_tm == TM_IA)
971 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);
973 if(active_tm == TM_FG)
978 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);
980 /* draw whats inside stuff when cursor is selecting those */
981 /* (draw them all the time - is this the right behaviour?) */
982 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)]);
983 if(edit_image && !edit_image->editor_images.empty())
984 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
988 /* Draw the Bad guys: */
989 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
991 /* to support frames: img_bsod_left[(frame / 5) % 4] */
999 /* Draw the player: */
1000 /* for now, the position is fixed at (100, 240) */
1001 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
1004 void le_change_object_properties(GameObject *pobj)
1006 Surface* cap_screen = Surface::CaptureScreen();
1007 Menu* object_properties_menu = new Menu();
1010 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
1011 object_properties_menu->additem(MN_HL,"",0,0);
1013 if(pobj->type() == "BadGuy")
1015 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1016 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1017 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1019 string_list_add_item(object_properties_menu->get_item_by_id(1).list,badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1021 object_properties_menu->get_item_by_id(1).list->active_item = i;
1023 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1026 object_properties_menu->additem(MN_HL,"",0,0);
1027 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1029 Menu::set_current(object_properties_menu);
1035 while (SDL_PollEvent(&event))
1037 object_properties_menu->event(event);
1040 cap_screen->draw(0,0);
1042 object_properties_menu->draw();
1043 object_properties_menu->action();
1045 switch (object_properties_menu->check())
1048 if(pobj->type() == "BadGuy")
1050 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1051 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1052 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1054 std::list<BadGuy*>::iterator it;
1055 for(it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1058 le_world->get_level()->badguy_data[i].kind = pbad->kind;
1059 le_world->get_level()->badguy_data[i].stay_on_platform = pbad->stay_on_platform;
1061 (*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);
1069 if(Menu::current() == NULL)
1072 mouse_cursor->draw();
1078 Menu::set_current(0);
1079 delete object_properties_menu;
1083 void le_checkevents()
1090 keymod = SDL_GetModState();
1092 while(SDL_PollEvent(&event))
1094 if (Menu::current())
1096 Menu::current()->event(event);
1097 if(!le_world && !Menu::current())
1098 Menu::set_current(leveleditor_menu);
1102 mouse_cursor->set_state(MC_NORMAL);
1104 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1105 if(event.type == SDL_KEYDOWN
1106 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1107 && (event.motion.x > 0
1108 && event.motion.x < screen->w - 64 &&
1109 event.motion.y > 0 && event.motion.y < screen->h)))
1113 case SDL_KEYDOWN: // key pressed
1114 key = event.key.keysym.sym;
1118 Menu::set_current(leveleditor_menu);
1121 if(le_world != NULL)
1129 cursor_x = (le_world->get_level()->width * 32) - 32;
1133 le_show_grid = !le_show_grid;
1139 case SDL_MOUSEBUTTONDOWN:
1140 if(event.button.button == SDL_BUTTON_LEFT)
1142 le_mouse_pressed[LEFT] = true;
1144 selection.x1 = event.motion.x + pos_x;
1145 selection.y1 = event.motion.y + pos_y;
1146 selection.x2 = event.motion.x + pos_x;
1147 selection.y2 = event.motion.y + pos_y;
1149 else if(event.button.button == SDL_BUTTON_RIGHT)
1151 le_mouse_pressed[RIGHT] = true;
1154 case SDL_MOUSEBUTTONUP:
1155 if(event.button.button == SDL_BUTTON_LEFT)
1157 le_mouse_pressed[LEFT] = false;
1158 le_mouse_clicked[LEFT] = true;
1160 else if(event.button.button == SDL_BUTTON_RIGHT)
1162 le_mouse_pressed[RIGHT] = false;
1163 le_mouse_clicked[RIGHT] = true;
1166 case SDL_MOUSEMOTION:
1168 if(!Menu::current())
1173 if(le_current.IsTile())
1175 cursor_x = ((int)(pos_x + x) / 32) * 32;
1176 cursor_y = ((int)(pos_y + y) / 32) * 32;
1184 if(le_mouse_pressed[LEFT])
1186 selection.x2 = x + pos_x;
1187 selection.y2 = y + pos_y;
1190 if(le_mouse_pressed[RIGHT])
1192 pos_x += -1 * event.motion.xrel;
1193 pos_y += -1 * event.motion.yrel;
1201 else if(event.type == SDL_QUIT) /* window closing */
1207 if(le_world != NULL)
1209 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 &&
1210 event.motion.y > 0 && event.motion.y < screen->h)))
1212 le_mouse_pressed[LEFT] = false;
1213 le_mouse_pressed[RIGHT] = false;
1215 if(!Menu::current())
1217 /* Check for button events */
1218 le_test_level_bt->event(event);
1219 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1221 le_save_level_bt->event(event);
1222 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1223 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1224 le_exit_bt->event(event);
1225 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1227 Menu::set_current(leveleditor_menu);
1229 le_next_level_bt->event(event);
1230 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1232 if(le_level < le_level_subset->levels)
1234 le_goto_level(le_level+1);
1240 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1241 if(confirm_dialog(str))
1243 new_lev.init_defaults();
1244 new_lev.save(le_level_subset->name.c_str(),le_level+1);
1245 le_level_subset->levels = le_level;
1246 le_goto_level(le_level);
1250 le_previous_level_bt->event(event);
1251 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1254 le_goto_level(le_level -1);
1256 le_rubber_bt->event(event);
1257 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1260 if(!cur_objects.empty())
1262 le_object_select_bt->event(event);
1263 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1265 MouseCursor::set_current(mouse_select_object);
1268 le_object_properties_bt->event(event);
1269 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1271 le_change_object_properties(selected_game_object);
1276 if(le_selection_mode == SQUARE)
1278 le_select_mode_one_bt->event(event);
1279 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1280 le_selection_mode = CURSOR;
1284 le_select_mode_two_bt->event(event);
1285 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1286 le_selection_mode = SQUARE;
1288 ButtonPanelMap::iterator it;
1289 le_tilegroup_bt->event(event);
1290 switch (le_tilegroup_bt->get_state())
1292 case BUTTON_CLICKED:
1293 Menu::set_current(select_tilegroup_menu);
1294 select_tilegroup_menu_effect.start(200);
1295 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1297 case BUTTON_WHEELUP:
1298 if(cur_tilegroup.empty())
1300 cur_tilegroup = tilegroups_map.begin()->first;
1304 it = tilegroups_map.find(cur_tilegroup);
1305 if((++it) == tilegroups_map.end())
1307 cur_tilegroup = tilegroups_map.begin()->first;
1311 cur_tilegroup = (*it).first;
1317 case BUTTON_WHEELDOWN:
1318 it = tilegroups_map.find(cur_tilegroup);
1319 if(it == tilegroups_map.begin())
1321 cur_tilegroup = tilegroups_map.rbegin()->first;
1325 if(--it != --tilegroups_map.begin())
1326 cur_tilegroup = (*it).first;
1328 cur_tilegroup = tilegroups_map.rbegin()->first;
1336 le_objects_bt->event(event);
1337 switch (le_objects_bt->get_state())
1339 case BUTTON_CLICKED:
1340 Menu::set_current(select_objects_menu);
1341 select_objects_menu_effect.start(200);
1342 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1344 case BUTTON_WHEELUP:
1345 it = objects_map.find(cur_objects);
1346 if(it == objects_map.end())
1348 cur_objects = objects_map.begin()->first;
1352 if(++it != objects_map.end())
1353 cur_objects = (*it).first;
1355 cur_objects = objects_map.begin()->first;
1359 case BUTTON_WHEELDOWN:
1360 it = objects_map.find(cur_objects);
1361 if(it == objects_map.begin())
1363 cur_objects = objects_map.rbegin()->first;
1367 if(--it != --objects_map.begin())
1368 cur_objects = (*it).first;
1370 cur_objects = objects_map.rbegin()->first;
1379 le_settings_bt->event(event);
1380 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1382 update_level_settings_menu();
1383 Menu::set_current(level_settings_menu);
1385 if(!cur_tilegroup.empty())
1387 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1389 if(pbutton->get_state() == BUTTON_CLICKED)
1391 le_current.Tile(pbutton->get_tag());
1395 else if(!cur_objects.empty())
1397 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1399 if(pbutton->get_state() == BUTTON_CLICKED)
1401 le_current.Object(pbutton->get_game_object());
1406 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1408 if(pbutton->get_state() == BUTTON_CLICKED)
1410 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1416 le_settings_bt->event(event);
1417 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1419 Menu::set_current(0);
1421 le_tilegroup_bt->event(event);
1422 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1424 Menu::set_current(0);
1426 le_objects_bt->event(event);
1427 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1429 Menu::set_current(0);
1434 if(!Menu::current() && !show_minimap)
1436 if(le_mouse_pressed[LEFT])
1438 if(MouseCursor::current() != mouse_select_object)
1440 if(le_current.IsTile())
1441 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1444 else if(le_mouse_clicked[LEFT])
1446 if(MouseCursor::current() == mouse_select_object)
1449 bool object_got_hit = false;
1450 base_type cursor_base;
1451 if(le_current.IsTile())
1453 cursor_base.x = cursor_x;
1454 cursor_base.y = cursor_y;
1456 else if(le_current.IsObject())
1458 cursor_base.x = cursor_x + pos_x;
1459 cursor_base.y = cursor_y + pos_y;
1461 cursor_base.width = 32;
1462 cursor_base.height = 32;
1464 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1465 if(rectcollision(cursor_base,(*it)->base))
1467 selected_game_object = (*it);
1468 object_got_hit = true;
1474 selected_game_object = NULL;
1475 le_object_properties_bt->set_active(false);
1478 le_object_properties_bt->set_active(true);
1480 MouseCursor::set_current(mouse_cursor);
1485 if(le_current.IsObject())
1487 le_level_changed = true;
1488 std::string type = le_current.obj->type();
1489 if(type == "BadGuy")
1491 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1493 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1494 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1499 le_mouse_clicked[LEFT] = false;
1505 if(!Menu::current())
1507 show_minimap = false;
1509 le_move_left_bt->event(event);
1510 le_move_right_bt->event(event);
1511 le_move_up_bt->event(event);
1512 le_move_down_bt->event(event);
1513 switch(le_move_left_bt->get_state())
1515 case BUTTON_PRESSED:
1516 pos_x -= KEYBOARD_SPEED;
1517 show_minimap = true;
1520 pos_x -= MOUSE_SPEED;
1521 show_minimap = true;
1523 case BUTTON_CLICKED:
1524 show_minimap = true;
1530 switch(le_move_right_bt->get_state())
1532 case BUTTON_PRESSED:
1533 pos_x += KEYBOARD_SPEED;
1534 show_minimap = true;
1537 pos_x += MOUSE_SPEED;
1538 show_minimap = true;
1540 case BUTTON_CLICKED:
1541 show_minimap = true;
1547 switch(le_move_up_bt->get_state())
1549 case BUTTON_PRESSED:
1550 pos_y -= KEYBOARD_SPEED;
1551 show_minimap = true;
1554 pos_y -= MOUSE_SPEED;
1555 show_minimap = true;
1557 case BUTTON_CLICKED:
1558 show_minimap = true;
1564 switch(le_move_down_bt->get_state())
1566 case BUTTON_PRESSED:
1567 pos_y += KEYBOARD_SPEED;
1568 show_minimap = true;
1571 pos_y += MOUSE_SPEED;
1572 show_minimap = true;
1574 case BUTTON_CLICKED:
1575 show_minimap = true;
1581 /* checking if pos_x and pos_y is within the limits... */
1582 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1583 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1587 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1588 pos_y = (le_world->get_level()->height * 32) - screen->h;
1596 void le_highlight_selection()
1600 if(selection.x1 < selection.x2)
1610 if(selection.y1 < selection.y2)
1626 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1629 void le_change(float x, float y, int tm, unsigned int c)
1631 if(le_world != NULL)
1637 le_level_changed = true;
1639 switch(le_selection_mode)
1642 le_world->get_level()->change(x,y,tm,c);
1644 base_type cursor_base;
1647 cursor_base.width = 32;
1648 cursor_base.height = 32;
1650 /* if there is a bad guy over there, remove it */
1651 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1652 if(rectcollision(cursor_base,(*it)->base))
1655 le_world->bad_guys.erase(it);
1656 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1662 if(selection.x1 < selection.x2)
1672 if(selection.y1 < selection.y2)
1688 /* if there is a bad guy over there, remove it */
1689 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1690 it != le_world->bad_guys.end(); /* will be at end of loop */)
1692 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1693 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1696 it = le_world->bad_guys.erase(it);
1697 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1707 for(xx = x1; xx <= x2; xx++)
1708 for(yy = y1; yy <= y2; yy++)
1710 le_world->get_level()->change(xx*32, yy*32, tm, c);
1722 //Make sure a time value is set when testing the level
1723 if(le_world->get_level()->time_left == 0)
1724 le_world->get_level()->time_left = 250;
1726 le_world->get_level()->save("test", le_level);
1728 GameSession session("test",le_level, ST_GL_TEST);
1730 player_status.reset();
1732 music_manager->halt_music();
1734 Menu::set_current(NULL);
1735 World::set_current(le_world);
1740 bool tmp_show_grid = le_show_grid;
1741 SelectionMode temp_le_selection_mode = le_selection_mode;
1742 le_selection_mode = NONE;
1743 show_selections = true;
1744 le_show_grid = false;
1745 le_help_shown = true;
1747 drawgradient(Color(0,0,0), Color(255,255,255));
1751 unsigned int i, done_;
1754 " - Supertux level editor tutorial - ",
1756 "To make your map, click the ",
1757 "tilegroup button and choose a ",
1759 "Pick a tile and simply hold down ",
1760 "the left mouse button over the map",
1761 "to \"paint\" your selection over",
1764 "There are three layers for painting",
1765 "tiles upon, Background layer,",
1766 "the Interactive layer, and the",
1767 "Foreground layer, which can be",
1768 "toggled by the BkGrd, IntAct and",
1769 "FrGrd buttons. The Foreground and",
1770 "Background layers do not effect",
1771 "Tux in the gameplay, but lie in",
1772 "front of him or lie behind him in",
1778 " - Supertux level editor tutorial - ",
1780 "The tiles placed on",
1781 "the Interactive layer are those",
1782 "which actually effect Tux in the",
1785 "Click the objects menu to put ",
1786 "bad guys and other objects in the",
1787 "game. Unlike placing tiles, you",
1788 "cannot \"paint\" enemies. Click",
1789 "them onto the screen one at a time.",
1791 "To change the settings of your",
1792 "level, click the button with the",
1793 "screwdriver and wrench. From here",
1794 "you can change the background,",
1795 "music, length of the level,",
1801 " - Supertux level editor tutorial - ",
1803 "You may have more than one level.",
1804 "Pressing the up and down buttons",
1805 "above the button bar lets you",
1806 "choose which one you are working on.",
1808 "If you would like to speed up your",
1809 "level editing, a useful trick is",
1810 "to learn the keyboard shortcuts.",
1811 "They are easy to learn, just right-",
1812 "click on the buttons.",
1814 "Have fun making levels! If you make",
1815 "some good ones, send them to us on",
1816 "the SuperTux mailing list!",
1822 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1824 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1825 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1827 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1835 done_ = wait_for_event(event);
1839 drawgradient(Color(0,0,0), Color(255,255,255));
1843 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1845 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1846 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1848 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1856 done_ = wait_for_event(event);
1860 drawgradient(Color(0,0,0), Color(255,255,255));
1864 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1866 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1867 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1869 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1877 done_ = wait_for_event(event);
1881 show_selections = true;
1882 le_show_grid = tmp_show_grid;
1883 le_selection_mode = temp_le_selection_mode;
1884 le_help_shown = false;