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"
48 #include "resources.h"
49 #include "background.h"
51 /* definitions to aid development */
53 /* definitions that affect gameplay */
54 #define KEY_CURSOR_SPEED 32
55 #define KEY_CURSOR_FASTSPEED 64
57 /* when pagedown/up pressed speed:*/
58 #define PAGE_CURSOR_SPEED 13*32
60 #define MOUSE_LEFT_MARGIN 80
61 #define MOUSE_RIGHT_MARGIN (560-32)
64 #define KEYBOARD_SPEED 140
65 #define MOUSE_SPEED 40
68 #define SELECT_W 2 // size of the selections lines
69 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
71 enum { TM_IA, TM_BG, TM_FG };
73 /* own declerations */
74 /* crutial ones (main loop) */
77 int le_load_level_subset(char *filename);
78 void le_drawlevel(DrawingContext& context);
79 void le_drawinterface(DrawingContext& context);
80 void le_checkevents();
81 void le_change(float x, float y, int tm, unsigned int c);
84 void le_set_defaults(void);
85 void le_activate_bad_guys(void);
86 void le_goto_level(int levelnb);
87 void le_highlight_selection();
89 void apply_level_settings_menu();
90 void update_subset_settings_menu();
91 void save_subset_settings_menu();
95 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
97 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
98 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
99 //Returns true for a tile
100 bool IsTile() { return is_tile; };
101 //Returns true for a GameObject
102 bool IsObject() { return !is_tile; };
105 void Init() { tile = 0; obj = NULL; is_tile = true; };
107 bool is_tile; //true for tile (false for object)
112 /* leveleditor internals */
113 static string_list_type level_subsets;
114 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
115 static bool show_minimap;
116 static bool show_selections;
117 static bool le_help_shown;
118 static int pos_x, pos_y, cursor_x, cursor_y;
119 static int le_levelnb;
120 static Level* le_level;
121 static LevelSubset* le_level_subset;
122 static int le_show_grid;
124 static Surface* le_selection;
126 static TileOrObject le_current;
127 static bool le_mouse_pressed[2];
128 static bool le_mouse_clicked[2];
129 static Button* le_save_level_bt;
130 static Button* le_exit_bt;
131 static Button* le_test_level_bt;
132 static Button* le_next_level_bt;
133 static Button* le_previous_level_bt;
134 static Button* le_move_right_bt;
135 static Button* le_move_left_bt;
136 static Button* le_move_up_bt;
137 static Button* le_move_down_bt;
138 static Button* le_rubber_bt;
139 static Button* le_select_mode_one_bt;
140 static Button* le_select_mode_two_bt;
141 static Button* le_settings_bt;
142 static Button* le_tilegroup_bt;
143 static Button* le_objects_bt;
144 static Button* le_object_select_bt;
145 static Button* le_object_properties_bt;
146 static ButtonPanel* le_tilemap_panel;
147 static int active_tm;
148 static Menu* leveleditor_menu;
149 static Menu* subset_load_menu;
150 static Menu* subset_new_menu;
151 static Menu* subset_settings_menu;
152 static Menu* level_settings_menu;
153 static Menu* select_tilegroup_menu;
154 static Menu* select_objects_menu;
155 static Timer select_tilegroup_menu_effect;
156 static Timer select_objects_menu_effect;
157 static Timer display_level_info;
158 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
159 static ButtonPanelMap tilegroups_map;
160 static ButtonPanelMap objects_map;
161 static std::string cur_tilegroup;
162 static std::string cur_objects;
163 static MouseCursor* mouse_select_object;
164 static MovingObject* selected_game_object;
166 static square selection;
167 static SelectionMode le_selection_mode;
168 static SDL_Event event;
170 int leveleditor(char* filename)
172 int last_time, now_time, i;
173 DrawingContext context;
181 sound_manager->halt_music();
183 while (SDL_PollEvent(&event))
187 if(le_load_level_subset(filename))
192 last_time = SDL_GetTicks();
197 if(Menu::current() == select_tilegroup_menu)
199 if(select_tilegroup_menu_effect.check())
201 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
205 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
207 else if(Menu::current() == select_objects_menu)
209 if(select_objects_menu_effect.check())
211 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
214 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
219 /* making events results to be in order */
222 le_drawlevel(context);
225 fillrect(0, 0, screen->w, screen->h, 0, 0, 0);
227 /* draw editor interface */
228 le_drawinterface(context);
230 Menu* menu = Menu::current();
236 if(menu == leveleditor_menu)
238 switch (leveleditor_menu->check())
240 case MNID_RETURNLEVELEDITOR:
242 Menu::set_current(0);
244 Menu::set_current(leveleditor_menu);
246 case MNID_SUBSETSETTINGS:
247 update_subset_settings_menu();
249 case MNID_QUITLEVELEDITOR:
254 else if(menu == level_settings_menu)
256 switch (level_settings_menu->check())
259 apply_level_settings_menu();
260 Menu::set_current(NULL);
267 else if(menu == select_tilegroup_menu)
270 switch (it = select_tilegroup_menu->check())
275 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
276 Menu::set_current(0);
283 else if(menu == select_objects_menu)
286 switch (it = select_objects_menu->check())
291 cur_objects = select_objects_menu->get_item_by_id(it).text;
294 Menu::set_current(0);
299 else if(menu == subset_load_menu)
301 switch (i = subset_load_menu->check())
308 if(le_load_level_subset(level_subsets.item[i-1]))
314 else if(menu == subset_new_menu)
316 if(subset_new_menu->item[2].input[0] == '\0')
317 subset_new_menu->item[3].kind = MN_DEACTIVE;
320 subset_new_menu->item[3].kind = MN_ACTION;
322 switch (i = subset_new_menu->check())
324 case MNID_CREATESUBSET:
325 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
326 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
327 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
329 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
331 Menu::set_current(subset_settings_menu);
336 else if(menu == subset_settings_menu)
338 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 )
339 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
341 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
343 switch (i = subset_settings_menu->check())
345 case MNID_SUBSETSAVECHANGES:
346 save_subset_settings_menu();
347 Menu::set_current(leveleditor_menu);
353 MouseCursor::current()->draw(context);
361 ++global_frame_counter;
364 now_time = SDL_GetTicks();
365 if (now_time < last_time + FPS)
366 SDL_Delay(last_time + FPS - now_time); /* delay some time */
368 context.do_drawing();
374 int le_load_level_subset(char *filename)
376 le_level_subset->load(filename);
377 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
379 le_goto_level(le_levelnb);
381 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
383 Menu::set_current(NULL);
392 leveleditor_menu = new Menu();
393 subset_load_menu = new Menu();
394 subset_new_menu = new Menu();
395 subset_settings_menu = new Menu();
396 level_settings_menu = new Menu();
397 select_tilegroup_menu = new Menu();
398 select_objects_menu = new Menu();
400 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
401 leveleditor_menu->additem(MN_HL,"",0,0);
402 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
403 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
404 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
405 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
406 leveleditor_menu->additem(MN_HL,"",0,0);
407 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
409 Menu::set_current(leveleditor_menu);
411 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
412 subset_load_menu->additem(MN_HL, "", 0, 0);
414 for(i = 0; i < level_subsets.num_items; ++i)
416 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
418 subset_load_menu->additem(MN_HL,"",0,0);
419 subset_load_menu->additem(MN_BACK,"Back",0,0);
421 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
422 subset_new_menu->additem(MN_HL,"",0,0);
423 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
424 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
425 subset_new_menu->additem(MN_HL,"",0,0);
426 subset_new_menu->additem(MN_BACK,"Back",0,0);
428 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
429 subset_settings_menu->additem(MN_HL,"",0,0);
430 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
431 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
432 subset_settings_menu->additem(MN_HL,"",0,0);
433 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
434 subset_settings_menu->additem(MN_HL,"",0,0);
435 subset_settings_menu->additem(MN_BACK,"Back",0,0);
437 level_settings_menu->arrange_left = true;
438 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
439 level_settings_menu->additem(MN_HL,"",0,0);
440 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
441 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
442 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
443 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
444 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
445 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
446 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
447 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
448 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
449 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
450 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
451 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
452 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
453 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
454 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
455 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
456 level_settings_menu->additem(MN_HL,"",0,0);
457 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
459 select_tilegroup_menu->arrange_left = true;
460 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
461 select_tilegroup_menu->additem(MN_HL,"",0,0);
462 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
464 for(std::set<TileGroup>::iterator it = tilegroups->begin();
465 it != tilegroups->end(); ++it )
467 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
469 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
472 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
473 sit != (*it).tiles.end(); ++sit, ++i)
475 Tile& tile = *(TileManager::instance()->get(*sit));
477 if(tile.editor_images.size() > 0)
478 image = tile.editor_images[0];
479 else if(tile.images.size() > 0)
480 image = tile.images[0];
482 // TODO use some notile image...
485 Button* button = new Button(image, it->name, SDLKey(SDLK_a + i),
487 tilegroups_map[it->name]->additem(button, *sit);
490 select_tilegroup_menu->additem(MN_HL,"",0,0);
492 select_objects_menu->arrange_left = true;
493 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
494 select_objects_menu->additem(MN_HL,"",0,0);
496 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
497 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
499 for(int i = 0; i < NUM_BadGuyKinds; ++i)
501 // BadGuy bad_tmp(BadGuyKind(i), 0, 0);
502 // objects_map["BadGuys"]->additem(new Button(0, "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
503 /* FIXME: maybe addbutton should already have a parameter for the surface
504 objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
505 BadGuy(BadGuyKind(i),
506 objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
507 objects_map["BadGuys"]->manipulate_button(i)->get_pos().y
511 select_objects_menu->additem(MN_HL,"",0,0);
517 level_subsets = dsubdirs("/levels", "level1.stl");
518 le_level_subset = new LevelSubset;
522 selected_game_object = NULL;
526 show_selections = true;
529 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
530 le_level_changed = false;
531 le_help_shown = false;
533 le_mouse_pressed[LEFT] = false;
534 le_mouse_pressed[RIGHT] = false;
536 le_mouse_clicked[LEFT] = false;
537 le_mouse_clicked[RIGHT] = false;
539 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
541 select_tilegroup_menu_effect.init(false);
542 select_objects_menu_effect.init(false);
543 display_level_info.init(false);
546 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
547 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
548 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
549 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
550 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
551 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
552 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
553 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
554 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
555 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
556 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
557 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
558 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
559 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
560 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
561 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
562 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
563 le_object_properties_bt->set_active(false);
565 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
566 mouse_select_object->set_mid(16,16);
568 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
569 le_tilemap_panel->set_button_size(32,10);
570 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
571 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0), TM_IA);
572 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
573 le_tilemap_panel->highlight_last(true);
574 le_tilemap_panel->set_last_clicked(TM_IA);
580 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
586 void update_level_settings_menu()
591 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_level->name.c_str());
592 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_level->author.c_str());
594 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
595 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
596 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
597 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
598 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
599 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
601 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_level->get_sector("main")->song_title.c_str())) != -1)
602 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
603 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_level->get_sector("main")->background->get_image().c_str())) != -1)
604 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
605 /* if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_level->get_sector("main")->particlesystem.c_str())) != -1)
606 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;*/
608 sprintf(str,"%d",le_level->get_sector("main")->solids->get_width());
609 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
610 sprintf(str,"%d",le_level->get_sector("main")->solids->get_height());
611 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
612 sprintf(str,"%d",le_level->time_left);
613 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
614 sprintf(str,"%2.0f",le_level->get_sector("main")->gravity);
615 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
616 sprintf(str,"%2.2f", le_level->get_sector("main")->background->get_speed());
617 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
618 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_top().red);
619 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
620 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_top().green);
621 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
622 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_top().blue);
623 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
624 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_bottom().red);
625 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
626 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_bottom().green);
627 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
628 sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_bottom().blue);
629 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
632 void update_subset_settings_menu()
634 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
635 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
638 void apply_level_settings_menu()
642 le_level_changed = true;
644 le_level->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
645 le_level->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
647 if(le_level->get_sector("main")->background->get_image().compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
649 le_level->get_sector("main")->background->set_image(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list), atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input));
653 /* if(le_level->get_sector("main")->particlesystem.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
655 le_level->->get_sector("main")->particlesystem = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
660 le_level->load_gfx();
663 le_level->get_sector("main")->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
665 le_level->get_sector("main")->solids->resize(
666 atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
667 atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
668 le_level->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
669 le_level->get_sector("main")->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
670 le_level->get_sector("main")->background->set_gradient(Color(
671 atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input),
672 atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input),
673 atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input)), Color(
674 atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input),
675 atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input),
676 atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input)));
679 void save_subset_settings_menu()
681 le_level_subset->title = subset_settings_menu->item[2].input;
682 le_level_subset->description = subset_settings_menu->item[3].input;
683 le_level_subset->save();
684 le_level_changed = false;
687 void le_unload_level()
692 // TODO get level number
693 sprintf(str,"Save changes to level %d of %s?", 0/*le_level*/,le_level_subset->name.c_str());
694 Surface* surf = new Surface(le_level->get_sector("main")->background->get_image(), false);
695 if(confirm_dialog(surf, str))
697 le_level->save(le_level_subset->get_level_filename(le_levelnb));
704 le_level_changed = false;
707 void le_goto_level(int levelnb)
710 le_level = new Level();
711 le_level->load(le_level_subset->get_level_filename(levelnb));
712 display_level_info.start(2500);
713 le_levelnb = levelnb;
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()
767 // if(le_level == NULL)
771 if((unsigned)screen->w - 64 > le_level->get_sector("main")->solids->get_width() * 4)
773 else if((unsigned)screen->w - 64 > le_level->get_sector("main")->solids->get_width() * 2)
777 int left_offset = (screen->w - 64 - le_level->get_sector("main")->solids->get_width()*mini_tile_width) / 2;
779 int mini_tile_height;
780 if((unsigned)screen->h > le_level->get_sector("main")->solids->get_height() * 4)
781 mini_tile_height = 4;
782 else if((unsigned)screen->h > le_level->get_sector("main")->solids->get_height() * 2)
783 mini_tile_height = 2;
785 mini_tile_height = 1;
787 for (unsigned int y = 0; y < le_level->get_sector("main")->solids->get_height(); ++y)
788 for (unsigned int x = 0; x < le_level->get_sector("main")->solids->get_width(); ++x)
791 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
792 mini_tile_width , mini_tile_height, le_level->bg_tiles[y * le_level->get_sector("main")->solids->get_width() + x]);
794 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
795 mini_tile_width , mini_tile_height, le_level->ia_tiles[y * le_level->get_sector("main")->solids->get_width() + x]);
797 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
798 mini_tile_width , mini_tile_height, le_level->fg_tiles[y + le_level->get_sector("main")->solids->get_width() + x]);
802 fillrect(left_offset, 0,
803 le_level->get_sector("main")->solids->get_width()*mini_tile_width, le_level->get_sector("main")->solids->get_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,
821 void le_drawinterface(DrawingContext &context)
828 /* draw a grid (if selected) */
831 for(x = 0; x < VISIBLE_TILES_X; x++)
832 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
833 for(y = 0; y < VISIBLE_TILES_Y; y++)
834 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
838 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
841 if(show_selections && MouseCursor::current() != mouse_select_object)
843 if(le_selection_mode == CURSOR)
845 if(le_current.IsTile())
846 context.draw_surface(le_selection, Vector(cursor_x - pos_x, cursor_y - pos_y), LAYER_GUI);
848 else if(le_selection_mode == SQUARE)
851 le_highlight_selection();
852 /* draw current selection */
853 w = selection.x2 - selection.x1;
854 h = selection.y2 - selection.y1;
855 context.draw_filled_rect(Vector(selection.x1 - pos_x, selection.y1 - pos_y), Vector(w, SELECT_W), Color(SELECT_CLR), LAYER_GUI);
856 context.draw_filled_rect(Vector(selection.x1 - pos_x + w, selection.y1 - pos_y), Vector(SELECT_W, h), Color(SELECT_CLR), LAYER_GUI);
857 context.draw_filled_rect(Vector(selection.x1 - pos_x, selection.y1 - pos_y + h), Vector(w, SELECT_W), Color(SELECT_CLR), LAYER_GUI);
858 context.draw_filled_rect(Vector(selection.x1 - pos_x, selection.y1 - pos_y), Vector(SELECT_W, h), Color(SELECT_CLR), LAYER_GUI);
863 /* draw button bar */
864 context.draw_filled_rect(Vector(screen->w - 64, 0), Vector(64, screen->h), Color(50, 50, 50,255), LAYER_GUI);
866 if(le_current.IsTile())
868 // le_level->get_sector("main")->solids->draw(context);
870 /*screen->w - 32, screen->h - 32, le_current.tile);
871 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
872 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);*/
874 #if 0 // XXX FIXME TODO: Do we have a new solution for draw_on_screen()?
875 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
877 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
878 le_current.obj->draw_on_screen(cursor_x,cursor_y);
882 if(mouse_select_object && selected_game_object != NULL)
884 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);
885 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);
886 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);
887 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);
892 le_save_level_bt->draw(context);
893 le_exit_bt->draw(context);
894 le_test_level_bt->draw(context);
895 le_next_level_bt->draw(context);
896 le_previous_level_bt->draw(context);
897 le_rubber_bt->draw(context);
898 if(le_selection_mode == SQUARE)
899 le_select_mode_one_bt->draw(context);
900 else if(le_selection_mode == CURSOR)
901 le_select_mode_two_bt->draw(context);
902 le_settings_bt->draw(context);
903 le_move_right_bt->draw(context);
904 le_move_left_bt->draw(context);
905 le_move_up_bt->draw(context);
906 le_move_down_bt->draw(context);
907 le_tilegroup_bt->draw(context);
908 le_objects_bt->draw(context);
909 if(!cur_tilegroup.empty())
910 tilegroups_map[cur_tilegroup]->draw(context);
911 else if(!cur_objects.empty())
913 objects_map[cur_objects]->draw(context);
916 le_tilemap_panel->draw(context);
918 if(!cur_objects.empty())
920 le_object_select_bt->draw(context);
921 le_object_properties_bt->draw(context);
924 sprintf(str, "%d/%d", le_levelnb,le_level_subset->levels);
925 context.draw_text(white_text, str, Vector((le_level_subset->levels < 10) ? -10 : 0, 16), LAYER_GUI);
928 context.draw_text(white_small_text, "F1 for Help", Vector(10, 430), LAYER_GUI);
930 if(display_level_info.check())
931 context.draw_text_center(white_text, le_level->name.c_str(), Vector(0, 0), LAYER_GUI);
936 context.draw_text(white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", Vector(10, 430), LAYER_GUI);
938 context.draw_text(white_small_text, "No Level Subset loaded", Vector(10, 430), LAYER_GUI);
943 void le_drawlevel(DrawingContext& context)
948 /* Draw the real background */
949 le_level->get_sector("main")->background->draw(context);
951 if(le_current.IsTile())
953 le_level->get_sector("main")->solids->draw(context);
955 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
956 if(!TileManager::instance()->get(le_current.tile)->images.empty())
957 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);*/
959 #if 0 // XXX FIXME TODO: Do we have a new solution for move_to()?
960 if(le_current.IsObject())
962 le_current.obj->move_to(cursor_x, cursor_y);
966 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
969 le_level->get_sector("main")->solids->draw(context);
971 // FIXME: make tiles to be drawn semi-transparent when not selected
973 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_level->get_section("main")->height; ++y)
974 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
977 if(active_tm == TM_BG)
982 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
983 le_level->bg_tiles[ (y + (int)(pos_y / 32)) * le_level->get_sector("main")->solids->get_width() +
984 (x + (int)(pos_x / 32))],a);
986 if(active_tm == TM_IA)
991 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
992 le_level->ia_tiles[ (y + (int)(pos_y / 32)) * le_level->get_section("main")->width +
993 (x + (int)(pos_x / 32))],a);
996 if(active_tm == TM_FG)
1001 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
1002 le_level->fg_tiles[ (y + (int)(pos_y / 32)) * le_level->get_sector("main")->solids->get_width() +
1003 (x + (int)(pos_x / 32))],a);
1005 /* draw whats inside stuff when cursor is selecting those */
1006 /* (draw them all the time - is this the right behaviour?) */
1007 Tile* edit_image = TileManager::instance()->get(
1009 [ (y + (int)(pos_y / 32)) * le_level->get_section("main")->width + (x + (int)(pos_x / 32))]);
1010 if(edit_image && !edit_image->editor_images.empty())
1011 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
1015 /* Draw the Bad guys: */
1016 for (std::vector<GameObject*>::iterator it = le_level->get_sector("main")->gameobjects.begin();
1017 it != le_level->get_sector("main")->gameobjects.end(); ++it)
1019 BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
1023 /* to support frames: img_bsod_left[(frame / 5) % 4] */
1024 badguy->draw(context);
1027 /* Draw the player: */
1028 /* for now, the position is fixed at (100, 240) */
1029 largetux.walk_right->draw(context, Vector(100 - pos_x, 240 - pos_y), LAYER_OBJECTS-1);
1032 void le_change_object_properties(GameObject *pobj)
1034 DrawingContext context;
1036 Menu* object_properties_menu = new Menu();
1039 std::string type = typeid(pobj).name();
1040 object_properties_menu->additem(MN_LABEL, type + " Properties",0,0);
1041 object_properties_menu->additem(MN_HL,"",0,0);
1043 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1046 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1047 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1049 string_list_add_item(object_properties_menu->get_item_by_id(1).list,
1050 badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1052 object_properties_menu->get_item_by_id(1).list->active_item = i;
1054 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1057 object_properties_menu->additem(MN_HL,"",0,0);
1058 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1060 Menu::set_current(object_properties_menu);
1066 while (SDL_PollEvent(&event))
1068 object_properties_menu->event(event);
1071 //cap_screen->draw(0,0);
1073 object_properties_menu->draw(context);
1074 object_properties_menu->action();
1076 switch (object_properties_menu->check())
1080 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1082 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1083 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1084 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1093 if(Menu::current() == NULL)
1096 mouse_cursor->draw(context);
1097 // context.draw_filled_rect();
1101 //delete cap_screen;
1102 Menu::set_current(0);
1103 delete object_properties_menu;
1107 void le_checkevents()
1114 keymod = SDL_GetModState();
1116 while(SDL_PollEvent(&event))
1118 if (Menu::current())
1120 Menu::current()->event(event);
1121 if(!le_level && !Menu::current())
1122 Menu::set_current(leveleditor_menu);
1126 mouse_cursor->set_state(MC_NORMAL);
1128 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1129 if(event.type == SDL_KEYDOWN
1130 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1131 && (event.motion.x > 0
1132 && event.motion.x < screen->w - 64 &&
1133 event.motion.y > 0 && event.motion.y < screen->h)))
1137 case SDL_KEYDOWN: // key pressed
1138 key = event.key.keysym.sym;
1142 Menu::set_current(leveleditor_menu);
1145 if(le_level != NULL)
1153 cursor_x = (le_level->get_sector("main")->solids->get_width() * 32) - 32;
1157 le_show_grid = !le_show_grid;
1163 case SDL_MOUSEBUTTONDOWN:
1164 if(event.button.button == SDL_BUTTON_LEFT)
1166 le_mouse_pressed[LEFT] = true;
1168 selection.x1 = event.motion.x + pos_x;
1169 selection.y1 = event.motion.y + pos_y;
1170 selection.x2 = event.motion.x + pos_x;
1171 selection.y2 = event.motion.y + pos_y;
1173 else if(event.button.button == SDL_BUTTON_RIGHT)
1175 le_mouse_pressed[RIGHT] = true;
1178 case SDL_MOUSEBUTTONUP:
1179 if(event.button.button == SDL_BUTTON_LEFT)
1181 le_mouse_pressed[LEFT] = false;
1182 le_mouse_clicked[LEFT] = true;
1184 else if(event.button.button == SDL_BUTTON_RIGHT)
1186 le_mouse_pressed[RIGHT] = false;
1187 le_mouse_clicked[RIGHT] = true;
1190 case SDL_MOUSEMOTION:
1192 if(!Menu::current())
1197 if(le_current.IsTile())
1199 cursor_x = ((int)(pos_x + x) / 32) * 32;
1200 cursor_y = ((int)(pos_y + y) / 32) * 32;
1208 if(le_mouse_pressed[LEFT])
1210 selection.x2 = x + pos_x;
1211 selection.y2 = y + pos_y;
1214 if(le_mouse_pressed[RIGHT])
1216 pos_x += -1 * event.motion.xrel;
1217 pos_y += -1 * event.motion.yrel;
1225 else if(event.type == SDL_QUIT) /* window closing */
1231 if(le_level != NULL)
1233 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 &&
1234 event.motion.y > 0 && event.motion.y < screen->h)))
1236 le_mouse_pressed[LEFT] = false;
1237 le_mouse_pressed[RIGHT] = false;
1239 if(!Menu::current())
1241 /* Check for button events */
1242 le_test_level_bt->event(event);
1243 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1245 le_save_level_bt->event(event);
1246 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1247 le_level->save(le_level_subset->name.c_str());
1248 le_exit_bt->event(event);
1249 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1251 Menu::set_current(leveleditor_menu);
1253 le_next_level_bt->event(event);
1254 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1256 if(le_levelnb < le_level_subset->levels)
1258 le_goto_level(le_levelnb+1);
1264 sprintf(str,"Level %d doesn't exist. Create it?",le_levelnb+1);
1265 Surface* surf = new Surface(le_level->get_sector("main")->background->get_image(), false);
1266 if(confirm_dialog(surf, str))
1268 new_lev.save(le_level_subset->name.c_str());
1269 le_level_subset->levels = le_levelnb;
1270 le_goto_level(le_levelnb);
1276 le_previous_level_bt->event(event);
1277 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1280 le_goto_level(le_levelnb -1);
1282 le_rubber_bt->event(event);
1283 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1286 if(!cur_objects.empty())
1288 le_object_select_bt->event(event);
1289 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1291 MouseCursor::set_current(mouse_select_object);
1294 le_object_properties_bt->event(event);
1295 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1297 le_change_object_properties(selected_game_object);
1302 if(le_selection_mode == SQUARE)
1304 le_select_mode_one_bt->event(event);
1305 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1306 le_selection_mode = CURSOR;
1310 le_select_mode_two_bt->event(event);
1311 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1312 le_selection_mode = SQUARE;
1314 ButtonPanelMap::iterator it;
1315 le_tilegroup_bt->event(event);
1316 switch (le_tilegroup_bt->get_state())
1318 case BUTTON_CLICKED:
1319 Menu::set_current(select_tilegroup_menu);
1320 select_tilegroup_menu_effect.start(200);
1321 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1323 case BUTTON_WHEELUP:
1324 if(cur_tilegroup.empty())
1326 cur_tilegroup = tilegroups_map.begin()->first;
1330 it = tilegroups_map.find(cur_tilegroup);
1331 if((++it) == tilegroups_map.end())
1333 cur_tilegroup = tilegroups_map.begin()->first;
1337 cur_tilegroup = (*it).first;
1343 case BUTTON_WHEELDOWN:
1344 it = tilegroups_map.find(cur_tilegroup);
1345 if(it == tilegroups_map.begin())
1347 cur_tilegroup = tilegroups_map.rbegin()->first;
1351 if(--it != --tilegroups_map.begin())
1352 cur_tilegroup = (*it).first;
1354 cur_tilegroup = tilegroups_map.rbegin()->first;
1362 le_objects_bt->event(event);
1363 switch (le_objects_bt->get_state())
1365 case BUTTON_CLICKED:
1366 Menu::set_current(select_objects_menu);
1367 select_objects_menu_effect.start(200);
1368 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1370 case BUTTON_WHEELUP:
1371 it = objects_map.find(cur_objects);
1372 if(it == objects_map.end())
1374 cur_objects = objects_map.begin()->first;
1378 if(++it != objects_map.end())
1379 cur_objects = (*it).first;
1381 cur_objects = objects_map.begin()->first;
1385 case BUTTON_WHEELDOWN:
1386 it = objects_map.find(cur_objects);
1387 if(it == objects_map.begin())
1389 cur_objects = objects_map.rbegin()->first;
1393 if(--it != --objects_map.begin())
1394 cur_objects = (*it).first;
1396 cur_objects = objects_map.rbegin()->first;
1405 le_settings_bt->event(event);
1406 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1408 update_level_settings_menu();
1409 Menu::set_current(level_settings_menu);
1411 if(!cur_tilegroup.empty())
1413 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1415 if(pbutton->get_state() == BUTTON_CLICKED)
1417 le_current.Tile(pbutton->get_tag());
1421 else if(!cur_objects.empty())
1423 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1425 if(pbutton->get_state() == BUTTON_CLICKED)
1427 #if 0 // TODO FIXME XXX: New solution for this?
1428 le_current.Object(pbutton->get_drawable());
1434 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1436 if(pbutton->get_state() == BUTTON_CLICKED)
1438 active_tm = pbutton->get_tag();
1444 le_settings_bt->event(event);
1445 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1447 Menu::set_current(0);
1449 le_tilegroup_bt->event(event);
1450 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1452 Menu::set_current(0);
1454 le_objects_bt->event(event);
1455 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1457 Menu::set_current(0);
1462 if(!Menu::current() && !show_minimap)
1464 if(le_mouse_pressed[LEFT])
1466 if(MouseCursor::current() != mouse_select_object)
1468 if(le_current.IsTile())
1469 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1472 else if(le_mouse_clicked[LEFT])
1474 if(MouseCursor::current() == mouse_select_object)
1476 bool object_got_hit = false;
1477 base_type cursor_base;
1478 if(le_current.IsTile())
1480 cursor_base.x = cursor_x;
1481 cursor_base.y = cursor_y;
1483 else if(le_current.IsObject())
1485 cursor_base.x = cursor_x + pos_x;
1486 cursor_base.y = cursor_y + pos_y;
1488 cursor_base.width = 32;
1489 cursor_base.height = 32;
1491 for(std::vector<GameObject*>::iterator it =
1492 le_level->get_sector("main")->gameobjects.begin();
1493 it != le_level->get_sector("main")->gameobjects.end(); ++it) {
1494 MovingObject* mobj = dynamic_cast<MovingObject*> (*it);
1498 if(rectcollision(cursor_base, mobj->base))
1500 selected_game_object = mobj;
1501 object_got_hit = true;
1508 selected_game_object = NULL;
1509 le_object_properties_bt->set_active(false);
1512 le_object_properties_bt->set_active(true);
1514 MouseCursor::set_current(mouse_cursor);
1521 //FIXME: objects interactions with the level editor should have a major improvement
1522 if(le_current.IsObject())
1524 le_level_changed = true;
1525 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1529 Camera& camera = *le_level->get_sector("main")->camera;
1531 le_level->get_sector("main")->bad_guys.push_back(
1532 new BadGuy(pbadguy->kind,
1533 cursor_x + camera.get_translation().x,
1534 cursor_y + camera.get_translation().y));
1535 le_level->get_sector("main")->gameobjects.push_back(le_level->get_sector("main")->bad_guys.back());
1542 le_mouse_clicked[LEFT] = false;
1548 if(!Menu::current())
1550 show_minimap = false;
1552 if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_TAB)
1553 show_minimap = true;
1555 le_move_left_bt->event(event);
1556 le_move_right_bt->event(event);
1557 le_move_up_bt->event(event);
1558 le_move_down_bt->event(event);
1559 switch(le_move_left_bt->get_state())
1561 case BUTTON_PRESSED:
1562 pos_x -= KEYBOARD_SPEED;
1563 show_minimap = true;
1566 pos_x -= MOUSE_SPEED;
1567 show_minimap = true;
1569 case BUTTON_CLICKED:
1570 show_minimap = true;
1576 switch(le_move_right_bt->get_state())
1578 case BUTTON_PRESSED:
1579 pos_x += KEYBOARD_SPEED;
1580 show_minimap = true;
1583 pos_x += MOUSE_SPEED;
1584 show_minimap = true;
1586 case BUTTON_CLICKED:
1587 show_minimap = true;
1593 switch(le_move_up_bt->get_state())
1595 case BUTTON_PRESSED:
1596 pos_y -= KEYBOARD_SPEED;
1597 show_minimap = true;
1600 pos_y -= MOUSE_SPEED;
1601 show_minimap = true;
1603 case BUTTON_CLICKED:
1604 show_minimap = true;
1610 switch(le_move_down_bt->get_state())
1612 case BUTTON_PRESSED:
1613 pos_y += KEYBOARD_SPEED;
1614 show_minimap = true;
1617 pos_y += MOUSE_SPEED;
1618 show_minimap = true;
1620 case BUTTON_CLICKED:
1621 show_minimap = true;
1627 /* checking if pos_x and pos_y is within the limits... */
1628 if((unsigned)pos_x > (le_level->get_sector("main")->solids->get_width() * 32 + 32*2) - screen->w)
1629 pos_x = (le_level->get_sector("main")->solids->get_width() * 32 + 32*2) - screen->w;
1633 if((unsigned)pos_y > (le_level->get_sector("main")->solids->get_height() * 32) - screen->h)
1634 pos_y = (le_level->get_sector("main")->solids->get_height() * 32) - screen->h;
1640 void le_highlight_selection()
1644 if(selection.x1 < selection.x2)
1654 if(selection.y1 < selection.y2)
1670 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1673 void le_change(float x, float y, int tm, unsigned int c)
1675 if(le_level != NULL)
1680 le_level_changed = true;
1682 switch(le_selection_mode)
1685 le_change(x,y,tm,c);
1687 base_type cursor_base;
1690 cursor_base.width = 32;
1691 cursor_base.height = 32;
1693 /* if there is a bad guy over there, remove it */
1695 for(std::vector<GameObject*>::iterator it = le_level->get_sector("main")->gameobjects.begin();
1696 it != le_level->get_sector("main")->gameobjects.end(); ++it) {
1697 BadGuy* badguy = dynamic_cast<BadGuy*>((*it));
1700 if(rectcollision(cursor_base, badguy->base))
1703 le_level->get_sector("main")->gameobjects.erase(std::remove(le_level->get_sector("main")->gameobjects.begin(),
1704 le_level->get_sector("main")->gameobjects.end(), *it),
1705 le_level->get_sector("main")->gameobjects.end());
1713 if(selection.x1 < selection.x2)
1723 if(selection.y1 < selection.y2)
1739 /* if there is a bad guy over there, remove it */
1741 for(std::vector<GameObject*>::iterator it = le_level->get_sector("main")->gameobjects.begin();
1742 it != le_level->get_sector("main")->gameobjects.end(); ++it /* will be at end of loop */)
1744 MovingObject* pmobject = dynamic_cast<MovingObject*> (*it);
1747 if(pmobject->base.x/32 >= x1 && pmobject->base.x/32 <= x2
1748 && pmobject->base.y/32 >= y1 && pmobject->base.y/32 <= y2)
1751 le_level->get_sector("main")->gameobjects.erase(std::remove(le_level->get_sector("main")->gameobjects.begin(), le_level->get_sector("main")->gameobjects.end(), *it), le_level->get_sector("main")->gameobjects.end());
1761 for(xx = x1; xx <= x2; xx++)
1762 for(yy = y1; yy <= y2; yy++)
1764 le_change(xx*32, yy*32, tm, c);
1776 //Make sure a time value is set when testing the level
1777 if(le_level->time_left == 0)
1778 le_level->time_left = 250;
1780 le_level->save("test.stl");
1782 GameSession session("test.stl", ST_GL_TEST);
1784 player_status.reset();
1786 sound_manager->halt_music();
1788 Menu::set_current(NULL);
1793 DrawingContext context;
1795 bool tmp_show_grid = le_show_grid;
1796 SelectionMode temp_le_selection_mode = le_selection_mode;
1797 le_selection_mode = NONE;
1798 show_selections = true;
1799 le_show_grid = false;
1800 le_help_shown = true;
1807 " - Supertux level editor tutorial - ",
1809 "To make your map, click the ",
1810 "tilegroup button and choose a ",
1812 "Pick a tile and simply hold down ",
1813 "the left mouse button over the map",
1814 "to \"paint\" your selection over",
1817 "There are three layers for painting",
1818 "tiles upon, Background layer,",
1819 "the Interactive layer, and the",
1820 "Foreground layer, which can be",
1821 "toggled by the BkGrd, IntAct and",
1822 "FrGrd buttons. The Foreground and",
1823 "Background layers do not effect",
1824 "Tux in the gameplay, but lie in",
1825 "front of him or lie behind him in",
1831 " - Supertux level editor tutorial - ",
1833 "The tiles placed on",
1834 "the Interactive layer are those",
1835 "which actually effect Tux in the",
1838 "Click the objects menu to put ",
1839 "bad guys and other objects in the",
1840 "game. Unlike placing tiles, you",
1841 "cannot \"paint\" enemies. Click",
1842 "them onto the screen one at a time.",
1844 "To change the settings of your",
1845 "level, click the button with the",
1846 "screwdriver and wrench. From here",
1847 "you can change the background,",
1848 "music, length of the level,",
1854 " - Supertux level editor tutorial - ",
1856 "You may have more than one level.",
1857 "Pressing the up and down buttons",
1858 "above the button bar lets you",
1859 "choose which one you are working on.",
1861 "If you would like to speed up your",
1862 "level editing, a useful trick is",
1863 "to learn the keyboard shortcuts.",
1864 "They are easy to learn, just right-",
1865 "click on the buttons.",
1867 "Have fun making levels! If you make",
1868 "some good ones, send them to us on",
1869 "the SuperTux mailing list!",
1873 char **text[] = { text1, text2, text3 };
1876 for(int i = 0; i < 3; i++)
1878 context.draw_gradient(Color(0,0,0), Color(255,255,255), LAYER_BACKGROUND0);
1879 le_drawinterface(context);
1881 context.draw_text_center(blue_text, "- Help -", Vector(0, 30), LAYER_GUI);
1883 for(unsigned int t = 0; t < sizeof(text[i])/sizeof(char *); t++)
1884 context.draw_text(white_text, text[i][t], Vector(5, 80+(t*white_text->get_height())), LAYER_GUI);
1886 sprintf(str,"Press any key to continue - Page %d/%d?", i, sizeof(text));
1887 context.draw_text(gold_text, str, Vector(0, 0), LAYER_GUI);
1889 context.do_drawing();
1895 done_ = wait_for_event(event);
1900 show_selections = true;
1901 le_show_grid = tmp_show_grid;
1902 le_selection_mode = temp_le_selection_mode;
1903 le_help_shown = false;