4 // Copyright (C) 2003 Ricardo Cruz <rick2@aeiou.pt>
5 // Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include <SDL_image.h>
32 #include "leveleditor.h"
34 #include "screen/screen.h"
45 #include "resources.h"
46 #include "music_manager.h"
47 #include "background.h"
52 /* definitions to aid development */
54 /* definitions that affect gameplay */
55 #define KEY_CURSOR_SPEED 32
56 #define KEY_CURSOR_FASTSPEED 64
58 /* when pagedown/up pressed speed:*/
59 #define PAGE_CURSOR_SPEED 13*32
61 #define MOUSE_LEFT_MARGIN 80
62 #define MOUSE_RIGHT_MARGIN (560-32)
65 #define KEYBOARD_SPEED 140
66 #define MOUSE_SPEED 40
69 #define SELECT_W 2 // size of the selections lines
70 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
72 /* own declerations */
73 /* crutial ones (main loop) */
76 int le_load_level_subset(char *filename);
78 void le_drawinterface();
79 void le_checkevents();
80 void le_change(float x, float y, int tm, unsigned int c);
83 void le_set_defaults(void);
84 void le_activate_bad_guys(void);
85 void le_goto_level(int levelnb);
86 void le_highlight_selection();
88 void apply_level_settings_menu();
89 void update_subset_settings_menu();
90 void save_subset_settings_menu();
94 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
96 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
97 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
98 //Returns true for a tile
99 bool IsTile() { return is_tile; };
100 //Returns true for a GameObject
101 bool IsObject() { return !is_tile; };
104 void Init() { tile = 0; obj = NULL; is_tile = true; };
106 bool is_tile; //true for tile (false for object)
111 /* leveleditor internals */
112 static string_list_type level_subsets;
113 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
114 static bool show_minimap;
115 static bool show_selections;
116 static bool le_help_shown;
117 static int pos_x, pos_y, cursor_x, cursor_y;
119 static World* le_world;
120 static LevelSubset* le_level_subset;
121 static int le_show_grid;
123 static Surface* le_selection;
125 static TileOrObject le_current;
126 static bool le_mouse_pressed[2];
127 static bool le_mouse_clicked[2];
128 static Button* le_save_level_bt;
129 static Button* le_exit_bt;
130 static Button* le_test_level_bt;
131 static Button* le_next_level_bt;
132 static Button* le_previous_level_bt;
133 static Button* le_move_right_bt;
134 static Button* le_move_left_bt;
135 static Button* le_move_up_bt;
136 static Button* le_move_down_bt;
137 static Button* le_rubber_bt;
138 static Button* le_select_mode_one_bt;
139 static Button* le_select_mode_two_bt;
140 static Button* le_settings_bt;
141 static Button* le_tilegroup_bt;
142 static Button* le_objects_bt;
143 static Button* le_object_select_bt;
144 static Button* le_object_properties_bt;
145 static ButtonPanel* le_tilemap_panel;
146 static Menu* leveleditor_menu;
147 static Menu* subset_load_menu;
148 static Menu* subset_new_menu;
149 static Menu* subset_settings_menu;
150 static Menu* level_settings_menu;
151 static Menu* select_tilegroup_menu;
152 static Menu* select_objects_menu;
153 static Timer select_tilegroup_menu_effect;
154 static Timer select_objects_menu_effect;
155 static Timer display_level_info;
156 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
157 static ButtonPanelMap tilegroups_map;
158 static ButtonPanelMap objects_map;
159 static std::string cur_tilegroup;
160 static std::string cur_objects;
161 static MouseCursor* mouse_select_object;
162 static MovingObject* selected_game_object;
164 static square selection;
165 static SelectionMode le_selection_mode;
166 static SDL_Event event;
167 TileMapType active_tm;
169 int leveleditor(char* filename)
171 int last_time, now_time, i;
180 clearscreen(0, 0, 0);
183 music_manager->halt_music();
185 while (SDL_PollEvent(&event))
189 if(le_load_level_subset(filename))
194 last_time = SDL_GetTicks();
199 if(Menu::current() == select_tilegroup_menu)
201 if(select_tilegroup_menu_effect.check())
203 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
207 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
209 else if(Menu::current() == select_objects_menu)
211 if(select_objects_menu_effect.check())
213 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
216 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
221 /* making events results to be in order */
227 clearscreen(0, 0, 0);
229 /* draw editor interface */
232 Menu* menu = Menu::current();
238 if(menu == leveleditor_menu)
240 switch (leveleditor_menu->check())
242 case MNID_RETURNLEVELEDITOR:
244 Menu::set_current(0);
246 Menu::set_current(leveleditor_menu);
248 case MNID_SUBSETSETTINGS:
249 update_subset_settings_menu();
251 case MNID_QUITLEVELEDITOR:
256 else if(menu == level_settings_menu)
258 switch (level_settings_menu->check())
261 apply_level_settings_menu();
262 Menu::set_current(NULL);
269 else if(menu == select_tilegroup_menu)
272 switch (it = select_tilegroup_menu->check())
277 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
278 Menu::set_current(0);
285 else if(menu == select_objects_menu)
288 switch (it = select_objects_menu->check())
293 cur_objects = select_objects_menu->get_item_by_id(it).text;
296 Menu::set_current(0);
301 else if(menu == subset_load_menu)
303 switch (i = subset_load_menu->check())
310 if(le_load_level_subset(level_subsets.item[i-1]))
316 else if(menu == subset_new_menu)
318 if(subset_new_menu->item[2].input[0] == '\0')
319 subset_new_menu->item[3].kind = MN_DEACTIVE;
322 subset_new_menu->item[3].kind = MN_ACTION;
324 switch (i = subset_new_menu->check())
326 case MNID_CREATESUBSET:
327 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
328 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
329 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
331 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
333 Menu::set_current(subset_settings_menu);
338 else if(menu == subset_settings_menu)
340 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 )
341 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
343 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
345 switch (i = subset_settings_menu->check())
347 case MNID_SUBSETSAVECHANGES:
348 save_subset_settings_menu();
349 Menu::set_current(leveleditor_menu);
355 MouseCursor::current()->draw();
363 ++global_frame_counter;
366 now_time = SDL_GetTicks();
367 if (now_time < last_time + FPS)
368 SDL_Delay(last_time + FPS - now_time); /* delay some time */
376 int le_load_level_subset(char *filename)
378 le_level_subset->load(filename);
379 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
383 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
385 Menu::set_current(NULL);
394 leveleditor_menu = new Menu();
395 subset_load_menu = new Menu();
396 subset_new_menu = new Menu();
397 subset_settings_menu = new Menu();
398 level_settings_menu = new Menu();
399 select_tilegroup_menu = new Menu();
400 select_objects_menu = new Menu();
402 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
403 leveleditor_menu->additem(MN_HL,"",0,0);
404 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
405 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
406 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
407 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
408 leveleditor_menu->additem(MN_HL,"",0,0);
409 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
411 Menu::set_current(leveleditor_menu);
413 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
414 subset_load_menu->additem(MN_HL, "", 0, 0);
416 for(i = 0; i < level_subsets.num_items; ++i)
418 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
420 subset_load_menu->additem(MN_HL,"",0,0);
421 subset_load_menu->additem(MN_BACK,"Back",0,0);
423 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
424 subset_new_menu->additem(MN_HL,"",0,0);
425 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
426 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
427 subset_new_menu->additem(MN_HL,"",0,0);
428 subset_new_menu->additem(MN_BACK,"Back",0,0);
430 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
431 subset_settings_menu->additem(MN_HL,"",0,0);
432 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
433 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
434 subset_settings_menu->additem(MN_HL,"",0,0);
435 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
436 subset_settings_menu->additem(MN_HL,"",0,0);
437 subset_settings_menu->additem(MN_BACK,"Back",0,0);
439 level_settings_menu->arrange_left = true;
440 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
441 level_settings_menu->additem(MN_HL,"",0,0);
442 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
443 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
444 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
445 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
446 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
447 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
448 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
449 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
450 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
451 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
452 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
453 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
454 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
455 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
456 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
457 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
458 level_settings_menu->additem(MN_HL,"",0,0);
459 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
461 select_tilegroup_menu->arrange_left = true;
462 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
463 select_tilegroup_menu->additem(MN_HL,"",0,0);
464 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
466 for(std::set<TileGroup>::iterator it = tilegroups->begin();
467 it != tilegroups->end(); ++it )
469 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
471 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
474 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
475 sit != (*it).tiles.end(); ++sit, ++i)
477 Tile& tile = *(TileManager::instance()->get(*sit));
479 if(tile.editor_images.size() > 0)
480 image = tile.editor_images[0];
481 else if(tile.images.size() > 0)
482 image = tile.images[0];
484 // TODO use some notile image...
487 Button* button = new Button(image, it->name, SDLKey(SDLK_a + i),
489 tilegroups_map[it->name]->additem(button, *sit);
492 select_tilegroup_menu->additem(MN_HL,"",0,0);
494 select_objects_menu->arrange_left = true;
495 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
496 select_objects_menu->additem(MN_HL,"",0,0);
498 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
499 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
501 DisplayManager dummy;
502 for(int i = 0; i < NUM_BadGuyKinds; ++i)
504 BadGuy bad_tmp(dummy, BadGuyKind(i), 0, 0);
505 objects_map["BadGuys"]->additem(new Button(0, "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
506 objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
509 objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
510 objects_map["BadGuys"]->manipulate_button(i)->get_pos().y
514 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;
531 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
532 le_level_changed = false;
533 le_help_shown = false;
535 le_mouse_pressed[LEFT] = false;
536 le_mouse_pressed[RIGHT] = false;
538 le_mouse_clicked[LEFT] = false;
539 le_mouse_clicked[RIGHT] = false;
541 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
543 select_tilegroup_menu_effect.init(false);
544 select_objects_menu_effect.init(false);
545 display_level_info.init(false);
548 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
549 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
550 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
551 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
552 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
553 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
554 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
555 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
556 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
557 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
558 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
559 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
560 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
561 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
562 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
563 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
564 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
565 le_object_properties_bt->set_active(false);
567 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
568 mouse_select_object->set_mid(16,16);
570 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
571 le_tilemap_panel->set_button_size(32,10);
572 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
573 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
574 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
575 le_tilemap_panel->highlight_last(true);
576 le_tilemap_panel->set_last_clicked(TM_IA);
582 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
588 void update_level_settings_menu()
593 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
594 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
596 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
597 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
598 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
599 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
600 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
601 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
603 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
604 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
605 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
606 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
607 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
608 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
610 sprintf(str,"%d",le_world->get_level()->width);
611 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
612 sprintf(str,"%d",le_world->get_level()->height);
613 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
614 sprintf(str,"%d",le_world->get_level()->time_left);
615 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
616 sprintf(str,"%2.0f",le_world->get_level()->gravity);
617 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
618 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
619 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
620 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
621 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
622 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
623 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
624 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
625 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
626 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
627 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
628 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
629 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
630 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
631 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
634 void update_subset_settings_menu()
636 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
637 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
640 void apply_level_settings_menu()
644 le_level_changed = true;
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()->resize(
668 atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
669 atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
670 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
671 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
672 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
673 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
674 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
675 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
676 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
677 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
678 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
681 void save_subset_settings_menu()
683 le_level_subset->title = subset_settings_menu->item[2].input;
684 le_level_subset->description = subset_settings_menu->item[3].input;
685 le_level_subset->save();
686 le_level_changed = false;
689 void le_unload_level()
696 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
697 if(confirm_dialog(str))
699 le_world->get_level()->save(le_level_subset->name.c_str(), le_level,
705 le_level_changed = false;
708 void le_goto_level(int levelnb)
711 le_world = new World(le_level_subset->name, levelnb);
712 display_level_info.start(2500);
718 SDL_EnableKeyRepeat(0, 0); // disables key repeating
722 delete leveleditor_menu;
723 delete subset_load_menu;
724 delete subset_new_menu;
725 delete subset_settings_menu;
726 delete level_settings_menu;
727 delete select_tilegroup_menu;
728 delete select_objects_menu;
729 delete le_save_level_bt;
731 delete le_test_level_bt;
732 delete le_next_level_bt;
733 delete le_previous_level_bt;
734 delete le_move_right_bt;
735 delete le_move_left_bt;
736 delete le_move_up_bt;
737 delete le_move_down_bt;
739 delete le_select_mode_one_bt;
740 delete le_select_mode_two_bt;
741 delete le_settings_bt;
742 delete le_tilegroup_bt;
743 delete le_objects_bt;
744 delete le_tilemap_panel;
745 delete le_object_select_bt;
746 delete le_object_properties_bt;
747 delete mouse_select_object;
749 delete le_level_subset;
752 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
753 i != tilegroups_map.end(); ++i)
757 for(ButtonPanelMap::iterator i = objects_map.begin();
758 i != objects_map.end(); ++i)
764 void le_drawminimap()
770 if(screen->w - 64 > le_world->get_level()->width * 4)
772 else if(screen->w - 64 > le_world->get_level()->width * 2)
776 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
778 int mini_tile_height;
779 if(screen->h > le_world->get_level()->height * 4)
780 mini_tile_height = 4;
781 else if(screen->h > le_world->get_level()->height * 2)
782 mini_tile_height = 2;
784 mini_tile_height = 1;
786 Level* level = le_world->get_level();
787 for (int y = 0; y < le_world->get_level()->height; ++y)
788 for (int x = 0; x < le_world->get_level()->width; ++x)
791 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
792 mini_tile_width , mini_tile_height, level->bg_tiles[y * level->width + x]);
794 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
795 mini_tile_width , mini_tile_height, level->ia_tiles[y * level->width + x]);
797 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
798 mini_tile_width , mini_tile_height, level->fg_tiles[y + level->width + x]);
802 fillrect(left_offset, 0,
803 le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height,
806 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height,
807 (VISIBLE_TILES_X-3)*mini_tile_width, 2,
809 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height,
810 2, (VISIBLE_TILES_Y-1)*mini_tile_height,
812 fillrect(left_offset + (pos_x/32)*mini_tile_width + (VISIBLE_TILES_X-3)*mini_tile_width - 2, (pos_y/32)*mini_tile_height,
813 2, (VISIBLE_TILES_Y-1)*mini_tile_height,
815 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height + (VISIBLE_TILES_Y-1)*mini_tile_height - 2,
816 (VISIBLE_TILES_X-3)*mini_tile_width, 2,
820 void le_drawinterface()
827 /* draw a grid (if selected) */
830 for(x = 0; x < VISIBLE_TILES_X; x++)
831 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
832 for(y = 0; y < VISIBLE_TILES_Y; y++)
833 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
837 if(show_minimap) // use_gl because the minimap isn't shown correctly in software mode. Any idea? FIXME Possible reasons: SDL_SoftStretch is a hack itsself || an alpha blitting issue SDL can't handle in software mode
840 if(show_selections && MouseCursor::current() != mouse_select_object)
842 if(le_selection_mode == CURSOR)
844 if(le_current.IsTile())
845 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
847 else if(le_selection_mode == SQUARE)
850 le_highlight_selection();
851 /* draw current selection */
852 w = selection.x2 - selection.x1;
853 h = selection.y2 - selection.y1;
854 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
855 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
856 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
857 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
862 /* draw button bar */
863 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
865 if(le_current.IsTile())
867 Tile::draw(screen->w - 32, screen->h - 32, le_current.tile);
868 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
869 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
871 #if 0 // XXX FIXME TODO: Do we have a new solution for draw_on_screen()?
872 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
874 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
875 le_current.obj->draw_on_screen(cursor_x,cursor_y);
879 if(mouse_select_object && selected_game_object != NULL)
881 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,selected_game_object->base.width,3,255,0,0,255);
882 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255);
883 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y+selected_game_object->base.height,selected_game_object->base.width,3,255,0,0,255);
884 fillrect(selected_game_object->base.x-pos_x+selected_game_object->base.width,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255);
889 le_save_level_bt->draw();
891 le_test_level_bt->draw();
892 le_next_level_bt->draw();
893 le_previous_level_bt->draw();
894 le_rubber_bt->draw();
895 if(le_selection_mode == SQUARE)
896 le_select_mode_one_bt->draw();
897 else if(le_selection_mode == CURSOR)
898 le_select_mode_two_bt->draw();
899 le_settings_bt->draw();
900 le_move_right_bt->draw();
901 le_move_left_bt->draw();
902 le_move_up_bt->draw();
903 le_move_down_bt->draw();
904 le_tilegroup_bt->draw();
905 le_objects_bt->draw();
906 if(!cur_tilegroup.empty())
907 tilegroups_map[cur_tilegroup]->draw();
908 else if(!cur_objects.empty())
910 objects_map[cur_objects]->draw();
913 le_tilemap_panel->draw();
915 if(!cur_objects.empty())
917 le_object_select_bt->draw();
918 le_object_properties_bt->draw();
921 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
922 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
925 white_small_text->draw("F1 for Help", 10, 430, 1);
927 if(display_level_info.check())
928 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
933 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
935 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
945 /* Draw the real background */
946 le_world->background->draw(*le_world->camera, LAYER_BACKGROUND0);
948 if(le_current.IsTile())
950 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
951 if(!TileManager::instance()->get(le_current.tile)->images.empty())
952 fillrect(cursor_x-pos_x,cursor_y-pos_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);
954 #if 0 // XXX FIXME TODO: Do we have a new solution for move_to()?
955 if(le_current.IsObject())
957 le_current.obj->move_to(cursor_x, cursor_y);
961 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
963 Level* level = le_world->get_level();
964 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
965 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
968 if(active_tm == TM_BG)
973 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
974 level->bg_tiles[ (y + (int)(pos_y / 32)) * level->width +
975 (x + (int)(pos_x / 32))],a);
977 if(active_tm == TM_IA)
982 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
983 level->ia_tiles[ (y + (int)(pos_y / 32)) * level->width +
984 (x + (int)(pos_x / 32))],a);
987 if(active_tm == TM_FG)
992 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
993 level->fg_tiles[ (y + (int)(pos_y / 32)) * level->width +
994 (x + (int)(pos_x / 32))],a);
996 /* draw whats inside stuff when cursor is selecting those */
997 /* (draw them all the time - is this the right behaviour?) */
998 Tile* edit_image = TileManager::instance()->get(
1000 [ (y + (int)(pos_y / 32)) * level->width + (x + (int)(pos_x / 32))]);
1001 if(edit_image && !edit_image->editor_images.empty())
1002 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
1006 /* Draw the Bad guys: */
1007 for (std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1008 it != le_world->gameobjects.end(); ++it)
1010 BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
1014 /* to support frames: img_bsod_left[(frame / 5) % 4] */
1016 viewport.set_translation(Vector(pos_x, pos_y));
1017 badguy->draw(viewport, 0);
1020 /* Draw the player: */
1021 /* for now, the position is fixed at (100, 240) */
1022 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
1025 void le_change_object_properties(GameObject *pobj)
1027 //Surface* cap_screen = Surface::CaptureScreen();
1029 Menu* object_properties_menu = new Menu();
1032 std::string type = typeid(pobj).name();
1033 object_properties_menu->additem(MN_LABEL, type + " Properties",0,0);
1034 object_properties_menu->additem(MN_HL,"",0,0);
1036 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1039 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1040 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1042 string_list_add_item(object_properties_menu->get_item_by_id(1).list,
1043 badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1045 object_properties_menu->get_item_by_id(1).list->active_item = i;
1047 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1050 object_properties_menu->additem(MN_HL,"",0,0);
1051 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1053 Menu::set_current(object_properties_menu);
1059 while (SDL_PollEvent(&event))
1061 object_properties_menu->event(event);
1064 //cap_screen->draw(0,0);
1066 object_properties_menu->draw();
1067 object_properties_menu->action();
1069 switch (object_properties_menu->check())
1073 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1075 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1076 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1077 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1086 if(Menu::current() == NULL)
1089 mouse_cursor->draw();
1094 //delete cap_screen;
1095 Menu::set_current(0);
1096 delete object_properties_menu;
1100 void le_checkevents()
1107 keymod = SDL_GetModState();
1109 while(SDL_PollEvent(&event))
1111 if (Menu::current())
1113 Menu::current()->event(event);
1114 if(!le_world && !Menu::current())
1115 Menu::set_current(leveleditor_menu);
1119 mouse_cursor->set_state(MC_NORMAL);
1121 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1122 if(event.type == SDL_KEYDOWN
1123 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1124 && (event.motion.x > 0
1125 && event.motion.x < screen->w - 64 &&
1126 event.motion.y > 0 && event.motion.y < screen->h)))
1130 case SDL_KEYDOWN: // key pressed
1131 key = event.key.keysym.sym;
1135 Menu::set_current(leveleditor_menu);
1138 if(le_world != NULL)
1146 cursor_x = (le_world->get_level()->width * 32) - 32;
1150 le_show_grid = !le_show_grid;
1156 case SDL_MOUSEBUTTONDOWN:
1157 if(event.button.button == SDL_BUTTON_LEFT)
1159 le_mouse_pressed[LEFT] = true;
1161 selection.x1 = event.motion.x + pos_x;
1162 selection.y1 = event.motion.y + pos_y;
1163 selection.x2 = event.motion.x + pos_x;
1164 selection.y2 = event.motion.y + pos_y;
1166 else if(event.button.button == SDL_BUTTON_RIGHT)
1168 le_mouse_pressed[RIGHT] = true;
1171 case SDL_MOUSEBUTTONUP:
1172 if(event.button.button == SDL_BUTTON_LEFT)
1174 le_mouse_pressed[LEFT] = false;
1175 le_mouse_clicked[LEFT] = true;
1177 else if(event.button.button == SDL_BUTTON_RIGHT)
1179 le_mouse_pressed[RIGHT] = false;
1180 le_mouse_clicked[RIGHT] = true;
1183 case SDL_MOUSEMOTION:
1185 if(!Menu::current())
1190 if(le_current.IsTile())
1192 cursor_x = ((int)(pos_x + x) / 32) * 32;
1193 cursor_y = ((int)(pos_y + y) / 32) * 32;
1201 if(le_mouse_pressed[LEFT])
1203 selection.x2 = x + pos_x;
1204 selection.y2 = y + pos_y;
1207 if(le_mouse_pressed[RIGHT])
1209 pos_x += -1 * event.motion.xrel;
1210 pos_y += -1 * event.motion.yrel;
1218 else if(event.type == SDL_QUIT) /* window closing */
1224 if(le_world != NULL)
1226 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 &&
1227 event.motion.y > 0 && event.motion.y < screen->h)))
1229 le_mouse_pressed[LEFT] = false;
1230 le_mouse_pressed[RIGHT] = false;
1232 if(!Menu::current())
1234 /* Check for button events */
1235 le_test_level_bt->event(event);
1236 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1238 le_save_level_bt->event(event);
1239 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1240 le_world->get_level()->save(le_level_subset->name.c_str(),le_level,
1242 le_exit_bt->event(event);
1243 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1245 Menu::set_current(leveleditor_menu);
1247 le_next_level_bt->event(event);
1248 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1250 if(le_level < le_level_subset->levels)
1252 le_goto_level(le_level+1);
1258 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1259 if(confirm_dialog(str))
1261 new_lev.init_defaults();
1262 new_lev.save(le_level_subset->name.c_str(),le_level+1, le_world);
1263 le_level_subset->levels = le_level;
1264 le_goto_level(le_level);
1268 le_previous_level_bt->event(event);
1269 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1272 le_goto_level(le_level -1);
1274 le_rubber_bt->event(event);
1275 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1278 if(!cur_objects.empty())
1280 le_object_select_bt->event(event);
1281 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1283 MouseCursor::set_current(mouse_select_object);
1286 le_object_properties_bt->event(event);
1287 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1289 le_change_object_properties(selected_game_object);
1294 if(le_selection_mode == SQUARE)
1296 le_select_mode_one_bt->event(event);
1297 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1298 le_selection_mode = CURSOR;
1302 le_select_mode_two_bt->event(event);
1303 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1304 le_selection_mode = SQUARE;
1306 ButtonPanelMap::iterator it;
1307 le_tilegroup_bt->event(event);
1308 switch (le_tilegroup_bt->get_state())
1310 case BUTTON_CLICKED:
1311 Menu::set_current(select_tilegroup_menu);
1312 select_tilegroup_menu_effect.start(200);
1313 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1315 case BUTTON_WHEELUP:
1316 if(cur_tilegroup.empty())
1318 cur_tilegroup = tilegroups_map.begin()->first;
1322 it = tilegroups_map.find(cur_tilegroup);
1323 if((++it) == tilegroups_map.end())
1325 cur_tilegroup = tilegroups_map.begin()->first;
1329 cur_tilegroup = (*it).first;
1335 case BUTTON_WHEELDOWN:
1336 it = tilegroups_map.find(cur_tilegroup);
1337 if(it == tilegroups_map.begin())
1339 cur_tilegroup = tilegroups_map.rbegin()->first;
1343 if(--it != --tilegroups_map.begin())
1344 cur_tilegroup = (*it).first;
1346 cur_tilegroup = tilegroups_map.rbegin()->first;
1354 le_objects_bt->event(event);
1355 switch (le_objects_bt->get_state())
1357 case BUTTON_CLICKED:
1358 Menu::set_current(select_objects_menu);
1359 select_objects_menu_effect.start(200);
1360 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1362 case BUTTON_WHEELUP:
1363 it = objects_map.find(cur_objects);
1364 if(it == objects_map.end())
1366 cur_objects = objects_map.begin()->first;
1370 if(++it != objects_map.end())
1371 cur_objects = (*it).first;
1373 cur_objects = objects_map.begin()->first;
1377 case BUTTON_WHEELDOWN:
1378 it = objects_map.find(cur_objects);
1379 if(it == objects_map.begin())
1381 cur_objects = objects_map.rbegin()->first;
1385 if(--it != --objects_map.begin())
1386 cur_objects = (*it).first;
1388 cur_objects = objects_map.rbegin()->first;
1397 le_settings_bt->event(event);
1398 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1400 update_level_settings_menu();
1401 Menu::set_current(level_settings_menu);
1403 if(!cur_tilegroup.empty())
1405 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1407 if(pbutton->get_state() == BUTTON_CLICKED)
1409 le_current.Tile(pbutton->get_tag());
1413 else if(!cur_objects.empty())
1415 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1417 if(pbutton->get_state() == BUTTON_CLICKED)
1419 #if 0 // TODO FIXME XXX: New solution for this?
1420 le_current.Object(pbutton->get_drawable());
1426 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1428 if(pbutton->get_state() == BUTTON_CLICKED)
1430 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1436 le_settings_bt->event(event);
1437 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1439 Menu::set_current(0);
1441 le_tilegroup_bt->event(event);
1442 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1444 Menu::set_current(0);
1446 le_objects_bt->event(event);
1447 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1449 Menu::set_current(0);
1454 if(!Menu::current() && !show_minimap)
1456 if(le_mouse_pressed[LEFT])
1458 if(MouseCursor::current() != mouse_select_object)
1460 if(le_current.IsTile())
1461 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1464 else if(le_mouse_clicked[LEFT])
1466 if(MouseCursor::current() == mouse_select_object)
1468 bool object_got_hit = false;
1469 base_type cursor_base;
1470 if(le_current.IsTile())
1472 cursor_base.x = cursor_x;
1473 cursor_base.y = cursor_y;
1475 else if(le_current.IsObject())
1477 cursor_base.x = cursor_x + pos_x;
1478 cursor_base.y = cursor_y + pos_y;
1480 cursor_base.width = 32;
1481 cursor_base.height = 32;
1483 for(std::vector<GameObject*>::iterator it =
1484 le_world->gameobjects.begin();
1485 it != le_world->gameobjects.end(); ++it) {
1486 MovingObject* mobj = dynamic_cast<MovingObject*> (*it);
1490 if(rectcollision(cursor_base, mobj->base))
1492 selected_game_object = mobj;
1493 object_got_hit = true;
1500 selected_game_object = NULL;
1501 le_object_properties_bt->set_active(false);
1504 le_object_properties_bt->set_active(true);
1506 MouseCursor::set_current(mouse_cursor);
1512 if(le_current.IsObject())
1514 le_level_changed = true;
1515 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1519 Camera& camera = *le_world->camera;
1520 DisplayManager dummy;
1522 le_world->bad_guys.push_back(
1523 new BadGuy(dummy, pbadguy->kind,
1524 cursor_x + camera.get_translation().x,
1525 cursor_y + camera.get_translation().y));
1526 le_world->gameobjects.push_back(le_world->bad_guys.back());
1532 le_mouse_clicked[LEFT] = false;
1538 if(!Menu::current())
1540 show_minimap = false;
1542 if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_TAB)
1543 show_minimap = true;
1545 le_move_left_bt->event(event);
1546 le_move_right_bt->event(event);
1547 le_move_up_bt->event(event);
1548 le_move_down_bt->event(event);
1549 switch(le_move_left_bt->get_state())
1551 case BUTTON_PRESSED:
1552 pos_x -= KEYBOARD_SPEED;
1553 show_minimap = true;
1556 pos_x -= MOUSE_SPEED;
1557 show_minimap = true;
1559 case BUTTON_CLICKED:
1560 show_minimap = true;
1566 switch(le_move_right_bt->get_state())
1568 case BUTTON_PRESSED:
1569 pos_x += KEYBOARD_SPEED;
1570 show_minimap = true;
1573 pos_x += MOUSE_SPEED;
1574 show_minimap = true;
1576 case BUTTON_CLICKED:
1577 show_minimap = true;
1583 switch(le_move_up_bt->get_state())
1585 case BUTTON_PRESSED:
1586 pos_y -= KEYBOARD_SPEED;
1587 show_minimap = true;
1590 pos_y -= MOUSE_SPEED;
1591 show_minimap = true;
1593 case BUTTON_CLICKED:
1594 show_minimap = true;
1600 switch(le_move_down_bt->get_state())
1602 case BUTTON_PRESSED:
1603 pos_y += KEYBOARD_SPEED;
1604 show_minimap = true;
1607 pos_y += MOUSE_SPEED;
1608 show_minimap = true;
1610 case BUTTON_CLICKED:
1611 show_minimap = true;
1617 /* checking if pos_x and pos_y is within the limits... */
1618 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1619 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1623 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1624 pos_y = (le_world->get_level()->height * 32) - screen->h;
1630 void le_highlight_selection()
1634 if(selection.x1 < selection.x2)
1644 if(selection.y1 < selection.y2)
1660 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1663 void le_change(float x, float y, int tm, unsigned int c)
1665 if(le_world != NULL)
1670 le_level_changed = true;
1672 switch(le_selection_mode)
1675 le_world->get_level()->change(x,y,tm,c);
1677 base_type cursor_base;
1680 cursor_base.width = 32;
1681 cursor_base.height = 32;
1683 /* if there is a bad guy over there, remove it */
1685 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1686 it != le_world->gameobjects.end(); ++it) {
1687 BadGuy* badguy = dynamic_cast<BadGuy*>((*it));
1690 if(rectcollision(cursor_base, badguy->base))
1693 //le_world->bad_guys.erase(it);
1694 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1702 if(selection.x1 < selection.x2)
1712 if(selection.y1 < selection.y2)
1728 /* if there is a bad guy over there, remove it */
1730 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1731 it != le_world->gameobjects.end(); ++it /* will be at end of loop */)
1733 MovingObject* pmobject = dynamic_cast<MovingObject*> (*it);
1736 if(pmobject->base.x/32 >= x1 && pmobject->base.x/32 <= x2
1737 && pmobject->base.y/32 >= y1 && pmobject->base.y/32 <= y2)
1740 //it = le_world->gameobjects.erase(it);
1741 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1751 for(xx = x1; xx <= x2; xx++)
1752 for(yy = y1; yy <= y2; yy++)
1754 le_world->get_level()->change(xx*32, yy*32, tm, c);
1766 //Make sure a time value is set when testing the level
1767 if(le_world->get_level()->time_left == 0)
1768 le_world->get_level()->time_left = 250;
1770 le_world->get_level()->save("test", le_level, le_world);
1772 GameSession session("test",le_level, ST_GL_TEST);
1774 player_status.reset();
1776 music_manager->halt_music();
1778 Menu::set_current(NULL);
1779 World::set_current(le_world);
1784 bool tmp_show_grid = le_show_grid;
1785 SelectionMode temp_le_selection_mode = le_selection_mode;
1786 le_selection_mode = NONE;
1787 show_selections = true;
1788 le_show_grid = false;
1789 le_help_shown = true;
1791 drawgradient(Color(0,0,0), Color(255,255,255));
1795 unsigned int i, done_;
1798 " - Supertux level editor tutorial - ",
1800 "To make your map, click the ",
1801 "tilegroup button and choose a ",
1803 "Pick a tile and simply hold down ",
1804 "the left mouse button over the map",
1805 "to \"paint\" your selection over",
1808 "There are three layers for painting",
1809 "tiles upon, Background layer,",
1810 "the Interactive layer, and the",
1811 "Foreground layer, which can be",
1812 "toggled by the BkGrd, IntAct and",
1813 "FrGrd buttons. The Foreground and",
1814 "Background layers do not effect",
1815 "Tux in the gameplay, but lie in",
1816 "front of him or lie behind him in",
1822 " - Supertux level editor tutorial - ",
1824 "The tiles placed on",
1825 "the Interactive layer are those",
1826 "which actually effect Tux in the",
1829 "Click the objects menu to put ",
1830 "bad guys and other objects in the",
1831 "game. Unlike placing tiles, you",
1832 "cannot \"paint\" enemies. Click",
1833 "them onto the screen one at a time.",
1835 "To change the settings of your",
1836 "level, click the button with the",
1837 "screwdriver and wrench. From here",
1838 "you can change the background,",
1839 "music, length of the level,",
1845 " - Supertux level editor tutorial - ",
1847 "You may have more than one level.",
1848 "Pressing the up and down buttons",
1849 "above the button bar lets you",
1850 "choose which one you are working on.",
1852 "If you would like to speed up your",
1853 "level editing, a useful trick is",
1854 "to learn the keyboard shortcuts.",
1855 "They are easy to learn, just right-",
1856 "click on the buttons.",
1858 "Have fun making levels! If you make",
1859 "some good ones, send them to us on",
1860 "the SuperTux mailing list!",
1866 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1868 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1869 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1871 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1879 done_ = wait_for_event(event);
1883 drawgradient(Color(0,0,0), Color(255,255,255));
1887 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1889 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1890 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1892 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1900 done_ = wait_for_event(event);
1904 drawgradient(Color(0,0,0), Color(255,255,255));
1908 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1910 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1911 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1913 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1921 done_ = wait_for_event(event);
1925 show_selections = true;
1926 le_show_grid = tmp_show_grid;
1927 le_selection_mode = temp_le_selection_mode;
1928 le_help_shown = false;