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"
45 #include "resources.h"
46 #include "music_manager.h"
47 #include "background.h"
48 #include "display_manager.h"
50 /* definitions to aid development */
52 /* definitions that affect gameplay */
53 #define KEY_CURSOR_SPEED 32
54 #define KEY_CURSOR_FASTSPEED 64
56 /* when pagedown/up pressed speed:*/
57 #define PAGE_CURSOR_SPEED 13*32
59 #define MOUSE_LEFT_MARGIN 80
60 #define MOUSE_RIGHT_MARGIN (560-32)
63 #define KEYBOARD_SPEED 140
64 #define MOUSE_SPEED 40
67 #define SELECT_W 2 // size of the selections lines
68 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
70 /* own declerations */
71 /* crutial ones (main loop) */
74 int le_load_level_subset(char *filename);
76 void le_drawinterface();
77 void le_checkevents();
78 void le_change(float x, float y, int tm, unsigned int c);
81 void le_set_defaults(void);
82 void le_activate_bad_guys(void);
83 void le_goto_level(int levelnb);
84 void le_highlight_selection();
86 void apply_level_settings_menu();
87 void update_subset_settings_menu();
88 void save_subset_settings_menu();
92 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
94 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
95 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
96 //Returns true for a tile
97 bool IsTile() { return is_tile; };
98 //Returns true for a GameObject
99 bool IsObject() { return !is_tile; };
102 void Init() { tile = 0; obj = NULL; is_tile = true; };
104 bool is_tile; //true for tile (false for object)
109 /* leveleditor internals */
110 static string_list_type level_subsets;
111 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
112 static bool show_minimap;
113 static bool show_selections;
114 static bool le_help_shown;
115 static int pos_x, pos_y, cursor_x, cursor_y;
117 static World* le_world;
118 static LevelSubset* le_level_subset;
119 static int le_show_grid;
121 static Surface* le_selection;
123 static TileOrObject le_current;
124 static bool le_mouse_pressed[2];
125 static bool le_mouse_clicked[2];
126 static Button* le_save_level_bt;
127 static Button* le_exit_bt;
128 static Button* le_test_level_bt;
129 static Button* le_next_level_bt;
130 static Button* le_previous_level_bt;
131 static Button* le_move_right_bt;
132 static Button* le_move_left_bt;
133 static Button* le_move_up_bt;
134 static Button* le_move_down_bt;
135 static Button* le_rubber_bt;
136 static Button* le_select_mode_one_bt;
137 static Button* le_select_mode_two_bt;
138 static Button* le_settings_bt;
139 static Button* le_tilegroup_bt;
140 static Button* le_objects_bt;
141 static Button* le_object_select_bt;
142 static Button* le_object_properties_bt;
143 static ButtonPanel* le_tilemap_panel;
144 static Menu* leveleditor_menu;
145 static Menu* subset_load_menu;
146 static Menu* subset_new_menu;
147 static Menu* subset_settings_menu;
148 static Menu* level_settings_menu;
149 static Menu* select_tilegroup_menu;
150 static Menu* select_objects_menu;
151 static Timer select_tilegroup_menu_effect;
152 static Timer select_objects_menu_effect;
153 static Timer display_level_info;
154 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
155 static ButtonPanelMap tilegroups_map;
156 static ButtonPanelMap objects_map;
157 static std::string cur_tilegroup;
158 static std::string cur_objects;
159 static MouseCursor* mouse_select_object;
160 static MovingObject* selected_game_object;
162 static square selection;
163 static SelectionMode le_selection_mode;
164 static SDL_Event event;
165 TileMapType active_tm;
167 int leveleditor(char* filename)
169 int last_time, now_time, i;
178 clearscreen(0, 0, 0);
181 music_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 */
225 clearscreen(0, 0, 0);
227 /* draw editor interface */
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();
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 */
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;
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 std::string imagefile = "/images/tilesets/" ;
476 bool only_editor_image = false;
477 if(!TileManager::instance()->get(*sit)->filenames.empty())
479 imagefile += TileManager::instance()->get(*sit)->filenames[0];
481 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
483 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
484 only_editor_image = true;
488 imagefile += "notile.png";
490 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
492 if(!only_editor_image)
493 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
495 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
496 button->add_icon(imagefile,32,32);
498 tilegroups_map[it->name]->additem(button, *sit);
501 select_tilegroup_menu->additem(MN_HL,"",0,0);
503 select_objects_menu->arrange_left = true;
504 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
505 select_objects_menu->additem(MN_HL,"",0,0);
507 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
508 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
510 DisplayManager dummy;
511 for(int i = 0; i < NUM_BadGuyKinds; ++i)
513 BadGuy bad_tmp(dummy, BadGuyKind(i), 0, 0);
514 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
515 objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
518 objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
519 objects_map["BadGuys"]->manipulate_button(i)->get_pos().y
523 select_objects_menu->additem(MN_HL,"",0,0);
529 level_subsets = dsubdirs("/levels", "level1.stl");
530 le_level_subset = new LevelSubset;
533 selected_game_object = NULL;
537 show_selections = true;
540 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
541 le_level_changed = false;
542 le_help_shown = false;
544 le_mouse_pressed[LEFT] = false;
545 le_mouse_pressed[RIGHT] = false;
547 le_mouse_clicked[LEFT] = false;
548 le_mouse_clicked[RIGHT] = false;
550 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
552 select_tilegroup_menu_effect.init(false);
553 select_objects_menu_effect.init(false);
554 display_level_info.init(false);
557 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
558 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
559 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
560 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
561 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
562 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
563 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
564 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
565 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
566 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
567 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
568 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
569 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
570 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
571 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
572 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
573 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
574 le_object_properties_bt->set_active(false);
576 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
577 mouse_select_object->set_mid(16,16);
579 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
580 le_tilemap_panel->set_button_size(32,10);
581 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
582 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
583 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
584 le_tilemap_panel->highlight_last(true);
585 le_tilemap_panel->set_last_clicked(TM_IA);
591 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
597 void update_level_settings_menu()
602 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
603 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
605 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
606 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
607 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
608 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
609 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
610 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
612 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
613 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
614 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
615 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
616 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
617 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
619 sprintf(str,"%d",le_world->get_level()->width);
620 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
621 sprintf(str,"%d",le_world->get_level()->height);
622 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
623 sprintf(str,"%d",le_world->get_level()->time_left);
624 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
625 sprintf(str,"%2.0f",le_world->get_level()->gravity);
626 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
627 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
628 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
629 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
630 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
631 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
632 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
633 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
634 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
635 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
636 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
637 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
638 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
639 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
640 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
643 void update_subset_settings_menu()
645 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
646 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
649 void apply_level_settings_menu()
653 le_level_changed = true;
655 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
656 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
658 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
660 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
664 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
666 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
671 le_world->get_level()->load_gfx();
674 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
676 le_world->get_level()->resize(
677 atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
678 atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
679 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
680 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
681 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
682 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
683 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
684 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
685 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
686 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
687 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
690 void save_subset_settings_menu()
692 le_level_subset->title = subset_settings_menu->item[2].input;
693 le_level_subset->description = subset_settings_menu->item[3].input;
694 le_level_subset->save();
695 le_level_changed = false;
698 void le_unload_level()
705 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
706 if(confirm_dialog(str))
708 le_world->get_level()->save(le_level_subset->name.c_str(), le_level,
714 le_level_changed = false;
717 void le_goto_level(int levelnb)
720 le_world = new World(le_level_subset->name, levelnb);
721 display_level_info.start(2500);
727 SDL_EnableKeyRepeat(0, 0); // disables key repeating
731 delete leveleditor_menu;
732 delete subset_load_menu;
733 delete subset_new_menu;
734 delete subset_settings_menu;
735 delete level_settings_menu;
736 delete select_tilegroup_menu;
737 delete select_objects_menu;
738 delete le_save_level_bt;
740 delete le_test_level_bt;
741 delete le_next_level_bt;
742 delete le_previous_level_bt;
743 delete le_move_right_bt;
744 delete le_move_left_bt;
745 delete le_move_up_bt;
746 delete le_move_down_bt;
748 delete le_select_mode_one_bt;
749 delete le_select_mode_two_bt;
750 delete le_settings_bt;
751 delete le_tilegroup_bt;
752 delete le_objects_bt;
753 delete le_tilemap_panel;
754 delete le_object_select_bt;
755 delete le_object_properties_bt;
756 delete mouse_select_object;
758 delete le_level_subset;
761 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
762 i != tilegroups_map.end(); ++i)
766 for(ButtonPanelMap::iterator i = objects_map.begin();
767 i != objects_map.end(); ++i)
773 void le_drawminimap()
779 if(screen->w - 64 > le_world->get_level()->width * 4)
781 else if(screen->w - 64 > le_world->get_level()->width * 2)
785 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
787 int mini_tile_height;
788 if(screen->h > le_world->get_level()->height * 4)
789 mini_tile_height = 4;
790 else if(screen->h > le_world->get_level()->height * 2)
791 mini_tile_height = 2;
793 mini_tile_height = 1;
795 Level* level = le_world->get_level();
796 for (int y = 0; y < le_world->get_level()->height; ++y)
797 for (int x = 0; x < le_world->get_level()->width; ++x)
800 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
801 mini_tile_width , mini_tile_height, level->bg_tiles[y * level->width + x]);
803 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
804 mini_tile_width , mini_tile_height, level->ia_tiles[y * level->width + x]);
806 Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height,
807 mini_tile_width , mini_tile_height, level->fg_tiles[y + level->width + x]);
811 fillrect(left_offset, 0,
812 le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height,
815 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height,
816 (VISIBLE_TILES_X-3)*mini_tile_width, 2,
818 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height,
819 2, (VISIBLE_TILES_Y-1)*mini_tile_height,
821 fillrect(left_offset + (pos_x/32)*mini_tile_width + (VISIBLE_TILES_X-3)*mini_tile_width - 2, (pos_y/32)*mini_tile_height,
822 2, (VISIBLE_TILES_Y-1)*mini_tile_height,
824 fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height + (VISIBLE_TILES_Y-1)*mini_tile_height - 2,
825 (VISIBLE_TILES_X-3)*mini_tile_width, 2,
829 void le_drawinterface()
836 /* draw a grid (if selected) */
839 for(x = 0; x < VISIBLE_TILES_X; x++)
840 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
841 for(y = 0; y < VISIBLE_TILES_Y; y++)
842 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
846 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
849 if(show_selections && MouseCursor::current() != mouse_select_object)
851 if(le_selection_mode == CURSOR)
853 if(le_current.IsTile())
854 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
856 else if(le_selection_mode == SQUARE)
859 le_highlight_selection();
860 /* draw current selection */
861 w = selection.x2 - selection.x1;
862 h = selection.y2 - selection.y1;
863 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
864 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
865 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
866 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
871 /* draw button bar */
872 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
874 if(le_current.IsTile())
876 Tile::draw(screen->w - 32, screen->h - 32, le_current.tile);
877 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
878 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
880 #if 0 // XXX FIXME TODO: Do we have a new solution for draw_on_screen()?
881 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
883 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
884 le_current.obj->draw_on_screen(cursor_x,cursor_y);
888 if(mouse_select_object && selected_game_object != NULL)
890 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);
891 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);
892 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);
893 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);
898 le_save_level_bt->draw();
900 le_test_level_bt->draw();
901 le_next_level_bt->draw();
902 le_previous_level_bt->draw();
903 le_rubber_bt->draw();
904 if(le_selection_mode == SQUARE)
905 le_select_mode_one_bt->draw();
906 else if(le_selection_mode == CURSOR)
907 le_select_mode_two_bt->draw();
908 le_settings_bt->draw();
909 le_move_right_bt->draw();
910 le_move_left_bt->draw();
911 le_move_up_bt->draw();
912 le_move_down_bt->draw();
913 le_tilegroup_bt->draw();
914 le_objects_bt->draw();
915 if(!cur_tilegroup.empty())
916 tilegroups_map[cur_tilegroup]->draw();
917 else if(!cur_objects.empty())
919 objects_map[cur_objects]->draw();
922 le_tilemap_panel->draw();
924 if(!cur_objects.empty())
926 le_object_select_bt->draw();
927 le_object_properties_bt->draw();
930 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
931 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
934 white_small_text->draw("F1 for Help", 10, 430, 1);
936 if(display_level_info.check())
937 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
942 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
944 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
954 /* Draw the real background */
955 le_world->background->draw(*le_world->camera, LAYER_BACKGROUND0);
957 if(le_current.IsTile())
959 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
960 if(!TileManager::instance()->get(le_current.tile)->images.empty())
961 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);
963 #if 0 // XXX FIXME TODO: Do we have a new solution for move_to()?
964 if(le_current.IsObject())
966 le_current.obj->move_to(cursor_x, cursor_y);
970 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
972 Level* level = le_world->get_level();
973 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->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 level->bg_tiles[ (y + (int)(pos_y / 32)) * level->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 level->ia_tiles[ (y + (int)(pos_y / 32)) * level->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 level->fg_tiles[ (y + (int)(pos_y / 32)) * level->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)) * level->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_world->gameobjects.begin();
1017 it != le_world->gameobjects.end(); ++it)
1019 BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
1023 /* to support frames: img_bsod_left[(frame / 5) % 4] */
1025 viewport.set_translation(Vector(pos_x, pos_y));
1026 badguy->draw(viewport, 0);
1029 /* Draw the player: */
1030 /* for now, the position is fixed at (100, 240) */
1031 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
1034 void le_change_object_properties(GameObject *pobj)
1036 Surface* cap_screen = Surface::CaptureScreen();
1037 Menu* object_properties_menu = new Menu();
1040 std::string type = typeid(pobj).name();
1041 object_properties_menu->additem(MN_LABEL, type + " Properties",0,0);
1042 object_properties_menu->additem(MN_HL,"",0,0);
1044 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1047 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1048 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1050 string_list_add_item(object_properties_menu->get_item_by_id(1).list,
1051 badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1053 object_properties_menu->get_item_by_id(1).list->active_item = i;
1055 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1058 object_properties_menu->additem(MN_HL,"",0,0);
1059 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1061 Menu::set_current(object_properties_menu);
1067 while (SDL_PollEvent(&event))
1069 object_properties_menu->event(event);
1072 cap_screen->draw(0,0);
1074 object_properties_menu->draw();
1075 object_properties_menu->action();
1077 switch (object_properties_menu->check())
1081 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1083 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1084 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1085 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1094 if(Menu::current() == NULL)
1097 mouse_cursor->draw();
1103 Menu::set_current(0);
1104 delete object_properties_menu;
1108 void le_checkevents()
1115 keymod = SDL_GetModState();
1117 while(SDL_PollEvent(&event))
1119 if (Menu::current())
1121 Menu::current()->event(event);
1122 if(!le_world && !Menu::current())
1123 Menu::set_current(leveleditor_menu);
1127 mouse_cursor->set_state(MC_NORMAL);
1129 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1130 if(event.type == SDL_KEYDOWN
1131 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1132 && (event.motion.x > 0
1133 && event.motion.x < screen->w - 64 &&
1134 event.motion.y > 0 && event.motion.y < screen->h)))
1138 case SDL_KEYDOWN: // key pressed
1139 key = event.key.keysym.sym;
1143 Menu::set_current(leveleditor_menu);
1146 if(le_world != NULL)
1154 cursor_x = (le_world->get_level()->width * 32) - 32;
1158 le_show_grid = !le_show_grid;
1164 case SDL_MOUSEBUTTONDOWN:
1165 if(event.button.button == SDL_BUTTON_LEFT)
1167 le_mouse_pressed[LEFT] = true;
1169 selection.x1 = event.motion.x + pos_x;
1170 selection.y1 = event.motion.y + pos_y;
1171 selection.x2 = event.motion.x + pos_x;
1172 selection.y2 = event.motion.y + pos_y;
1174 else if(event.button.button == SDL_BUTTON_RIGHT)
1176 le_mouse_pressed[RIGHT] = true;
1179 case SDL_MOUSEBUTTONUP:
1180 if(event.button.button == SDL_BUTTON_LEFT)
1182 le_mouse_pressed[LEFT] = false;
1183 le_mouse_clicked[LEFT] = true;
1185 else if(event.button.button == SDL_BUTTON_RIGHT)
1187 le_mouse_pressed[RIGHT] = false;
1188 le_mouse_clicked[RIGHT] = true;
1191 case SDL_MOUSEMOTION:
1193 if(!Menu::current())
1198 if(le_current.IsTile())
1200 cursor_x = ((int)(pos_x + x) / 32) * 32;
1201 cursor_y = ((int)(pos_y + y) / 32) * 32;
1209 if(le_mouse_pressed[LEFT])
1211 selection.x2 = x + pos_x;
1212 selection.y2 = y + pos_y;
1215 if(le_mouse_pressed[RIGHT])
1217 pos_x += -1 * event.motion.xrel;
1218 pos_y += -1 * event.motion.yrel;
1226 else if(event.type == SDL_QUIT) /* window closing */
1232 if(le_world != NULL)
1234 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 &&
1235 event.motion.y > 0 && event.motion.y < screen->h)))
1237 le_mouse_pressed[LEFT] = false;
1238 le_mouse_pressed[RIGHT] = false;
1240 if(!Menu::current())
1242 /* Check for button events */
1243 le_test_level_bt->event(event);
1244 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1246 le_save_level_bt->event(event);
1247 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1248 le_world->get_level()->save(le_level_subset->name.c_str(),le_level,
1250 le_exit_bt->event(event);
1251 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1253 Menu::set_current(leveleditor_menu);
1255 le_next_level_bt->event(event);
1256 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1258 if(le_level < le_level_subset->levels)
1260 le_goto_level(le_level+1);
1266 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1267 if(confirm_dialog(str))
1269 new_lev.init_defaults();
1270 new_lev.save(le_level_subset->name.c_str(),le_level+1, le_world);
1271 le_level_subset->levels = le_level;
1272 le_goto_level(le_level);
1276 le_previous_level_bt->event(event);
1277 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1280 le_goto_level(le_level -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 = static_cast<TileMapType>(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_world->gameobjects.begin();
1493 it != le_world->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);
1520 if(le_current.IsObject())
1522 le_level_changed = true;
1523 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1527 Camera& camera = *le_world->camera;
1528 DisplayManager dummy;
1530 le_world->bad_guys.push_back(
1531 new BadGuy(dummy, pbadguy->kind,
1532 cursor_x + camera.get_translation().x,
1533 cursor_y + camera.get_translation().y));
1534 le_world->gameobjects.push_back(le_world->bad_guys.back());
1540 le_mouse_clicked[LEFT] = false;
1546 if(!Menu::current())
1548 show_minimap = false;
1550 if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_TAB)
1551 show_minimap = true;
1553 le_move_left_bt->event(event);
1554 le_move_right_bt->event(event);
1555 le_move_up_bt->event(event);
1556 le_move_down_bt->event(event);
1557 switch(le_move_left_bt->get_state())
1559 case BUTTON_PRESSED:
1560 pos_x -= KEYBOARD_SPEED;
1561 show_minimap = true;
1564 pos_x -= MOUSE_SPEED;
1565 show_minimap = true;
1567 case BUTTON_CLICKED:
1568 show_minimap = true;
1574 switch(le_move_right_bt->get_state())
1576 case BUTTON_PRESSED:
1577 pos_x += KEYBOARD_SPEED;
1578 show_minimap = true;
1581 pos_x += MOUSE_SPEED;
1582 show_minimap = true;
1584 case BUTTON_CLICKED:
1585 show_minimap = true;
1591 switch(le_move_up_bt->get_state())
1593 case BUTTON_PRESSED:
1594 pos_y -= KEYBOARD_SPEED;
1595 show_minimap = true;
1598 pos_y -= MOUSE_SPEED;
1599 show_minimap = true;
1601 case BUTTON_CLICKED:
1602 show_minimap = true;
1608 switch(le_move_down_bt->get_state())
1610 case BUTTON_PRESSED:
1611 pos_y += KEYBOARD_SPEED;
1612 show_minimap = true;
1615 pos_y += MOUSE_SPEED;
1616 show_minimap = true;
1618 case BUTTON_CLICKED:
1619 show_minimap = true;
1625 /* checking if pos_x and pos_y is within the limits... */
1626 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1627 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1631 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1632 pos_y = (le_world->get_level()->height * 32) - screen->h;
1638 void le_highlight_selection()
1642 if(selection.x1 < selection.x2)
1652 if(selection.y1 < selection.y2)
1668 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1671 void le_change(float x, float y, int tm, unsigned int c)
1673 if(le_world != NULL)
1678 le_level_changed = true;
1680 switch(le_selection_mode)
1683 le_world->get_level()->change(x,y,tm,c);
1685 base_type cursor_base;
1688 cursor_base.width = 32;
1689 cursor_base.height = 32;
1691 /* if there is a bad guy over there, remove it */
1693 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1694 it != le_world->gameobjects.end(); ++it) {
1695 BadGuy* badguy = dynamic_cast<BadGuy*>((*it));
1698 if(rectcollision(cursor_base, badguy->base))
1701 //le_world->bad_guys.erase(it);
1702 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1710 if(selection.x1 < selection.x2)
1720 if(selection.y1 < selection.y2)
1736 /* if there is a bad guy over there, remove it */
1738 for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1739 it != le_world->gameobjects.end(); ++it /* will be at end of loop */)
1741 MovingObject* pmobject = dynamic_cast<MovingObject*> (*it);
1744 if(pmobject->base.x/32 >= x1 && pmobject->base.x/32 <= x2
1745 && pmobject->base.y/32 >= y1 && pmobject->base.y/32 <= y2)
1748 //it = le_world->gameobjects.erase(it);
1749 le_world->gameobjects.erase(std::remove(le_world->gameobjects.begin(), le_world->gameobjects.end(), *it), le_world->gameobjects.end());
1759 for(xx = x1; xx <= x2; xx++)
1760 for(yy = y1; yy <= y2; yy++)
1762 le_world->get_level()->change(xx*32, yy*32, tm, c);
1774 //Make sure a time value is set when testing the level
1775 if(le_world->get_level()->time_left == 0)
1776 le_world->get_level()->time_left = 250;
1778 le_world->get_level()->save("test", le_level, le_world);
1780 GameSession session("test",le_level, ST_GL_TEST);
1782 player_status.reset();
1784 music_manager->halt_music();
1786 Menu::set_current(NULL);
1787 World::set_current(le_world);
1792 bool tmp_show_grid = le_show_grid;
1793 SelectionMode temp_le_selection_mode = le_selection_mode;
1794 le_selection_mode = NONE;
1795 show_selections = true;
1796 le_show_grid = false;
1797 le_help_shown = true;
1799 drawgradient(Color(0,0,0), Color(255,255,255));
1803 unsigned int i, done_;
1806 " - Supertux level editor tutorial - ",
1808 "To make your map, click the ",
1809 "tilegroup button and choose a ",
1811 "Pick a tile and simply hold down ",
1812 "the left mouse button over the map",
1813 "to \"paint\" your selection over",
1816 "There are three layers for painting",
1817 "tiles upon, Background layer,",
1818 "the Interactive layer, and the",
1819 "Foreground layer, which can be",
1820 "toggled by the BkGrd, IntAct and",
1821 "FrGrd buttons. The Foreground and",
1822 "Background layers do not effect",
1823 "Tux in the gameplay, but lie in",
1824 "front of him or lie behind him in",
1830 " - Supertux level editor tutorial - ",
1832 "The tiles placed on",
1833 "the Interactive layer are those",
1834 "which actually effect Tux in the",
1837 "Click the objects menu to put ",
1838 "bad guys and other objects in the",
1839 "game. Unlike placing tiles, you",
1840 "cannot \"paint\" enemies. Click",
1841 "them onto the screen one at a time.",
1843 "To change the settings of your",
1844 "level, click the button with the",
1845 "screwdriver and wrench. From here",
1846 "you can change the background,",
1847 "music, length of the level,",
1853 " - Supertux level editor tutorial - ",
1855 "You may have more than one level.",
1856 "Pressing the up and down buttons",
1857 "above the button bar lets you",
1858 "choose which one you are working on.",
1860 "If you would like to speed up your",
1861 "level editing, a useful trick is",
1862 "to learn the keyboard shortcuts.",
1863 "They are easy to learn, just right-",
1864 "click on the buttons.",
1866 "Have fun making levels! If you make",
1867 "some good ones, send them to us on",
1868 "the SuperTux mailing list!",
1874 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1876 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1877 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1879 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1887 done_ = wait_for_event(event);
1891 drawgradient(Color(0,0,0), Color(255,255,255));
1895 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1897 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1898 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1900 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1908 done_ = wait_for_event(event);
1912 drawgradient(Color(0,0,0), Color(255,255,255));
1916 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1918 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1919 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1921 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1929 done_ = wait_for_event(event);
1933 show_selections = true;
1934 le_show_grid = tmp_show_grid;
1935 le_selection_mode = temp_le_selection_mode;
1936 le_help_shown = false;