4 // Copyright (C) 2003 Ricardo Cruz <rick2@aeiou.pt>
5 // Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <SDL_image.h>
30 #include "leveleditor.h"
43 #include "resources.h"
44 #include "music_manager.h"
45 #include "background.h"
46 #include "display_manager.h"
48 /* definitions to aid development */
50 /* definitions that affect gameplay */
51 #define KEY_CURSOR_SPEED 32
52 #define KEY_CURSOR_FASTSPEED 64
54 /* when pagedown/up pressed speed:*/
55 #define PAGE_CURSOR_SPEED 13*32
57 #define MOUSE_LEFT_MARGIN 80
58 #define MOUSE_RIGHT_MARGIN (560-32)
61 #define KEYBOARD_SPEED 140
62 #define MOUSE_SPEED 40
65 #define SELECT_W 2 // size of the selections lines
66 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
68 /* own declerations */
69 /* crutial ones (main loop) */
72 int le_load_level_subset(char *filename);
74 void le_drawinterface();
75 void le_checkevents();
76 void le_change(float x, float y, int tm, unsigned int c);
79 void le_set_defaults(void);
80 void le_activate_bad_guys(void);
81 void le_goto_level(int levelnb);
82 void le_highlight_selection();
84 void apply_level_settings_menu();
85 void update_subset_settings_menu();
86 void save_subset_settings_menu();
90 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
92 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
93 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
94 //Returns true for a tile
95 bool IsTile() { return is_tile; };
96 //Returns true for a GameObject
97 bool IsObject() { return !is_tile; };
100 void Init() { tile = 0; obj = NULL; is_tile = true; };
102 bool is_tile; //true for tile (false for object)
107 /* leveleditor internals */
108 static string_list_type level_subsets;
109 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
110 static bool show_minimap;
111 static bool show_selections;
112 static bool le_help_shown;
113 static int pos_x, pos_y, cursor_x, cursor_y;
115 static World* le_world;
116 static LevelSubset* le_level_subset;
117 static int le_show_grid;
119 static Surface* le_selection;
121 static TileOrObject le_current;
122 static bool le_mouse_pressed[2];
123 static bool le_mouse_clicked[2];
124 static Button* le_save_level_bt;
125 static Button* le_exit_bt;
126 static Button* le_test_level_bt;
127 static Button* le_next_level_bt;
128 static Button* le_previous_level_bt;
129 static Button* le_move_right_bt;
130 static Button* le_move_left_bt;
131 static Button* le_move_up_bt;
132 static Button* le_move_down_bt;
133 static Button* le_rubber_bt;
134 static Button* le_select_mode_one_bt;
135 static Button* le_select_mode_two_bt;
136 static Button* le_settings_bt;
137 static Button* le_tilegroup_bt;
138 static Button* le_objects_bt;
139 static Button* le_object_select_bt;
140 static Button* le_object_properties_bt;
141 static ButtonPanel* le_tilemap_panel;
142 static Menu* leveleditor_menu;
143 static Menu* subset_load_menu;
144 static Menu* subset_new_menu;
145 static Menu* subset_settings_menu;
146 static Menu* level_settings_menu;
147 static Menu* select_tilegroup_menu;
148 static Menu* select_objects_menu;
149 static Timer select_tilegroup_menu_effect;
150 static Timer select_objects_menu_effect;
151 static Timer display_level_info;
152 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
153 static ButtonPanelMap tilegroups_map;
154 static ButtonPanelMap objects_map;
155 static std::string cur_tilegroup;
156 static std::string cur_objects;
157 static MouseCursor* mouse_select_object;
158 static MovingObject* selected_game_object;
160 static square selection;
161 static SelectionMode le_selection_mode;
162 static SDL_Event event;
163 TileMapType active_tm;
165 int leveleditor(char* filename)
167 int last_time, now_time, i;
176 clearscreen(0, 0, 0);
179 music_manager->halt_music();
181 while (SDL_PollEvent(&event))
185 if(le_load_level_subset(filename))
190 last_time = SDL_GetTicks();
195 if(Menu::current() == select_tilegroup_menu)
197 if(select_tilegroup_menu_effect.check())
199 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
203 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
205 else if(Menu::current() == select_objects_menu)
207 if(select_objects_menu_effect.check())
209 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
212 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
217 /* making events results to be in order */
223 clearscreen(0, 0, 0);
225 /* draw editor interface */
228 Menu* menu = Menu::current();
234 if(menu == leveleditor_menu)
236 switch (leveleditor_menu->check())
238 case MNID_RETURNLEVELEDITOR:
240 Menu::set_current(0);
242 Menu::set_current(leveleditor_menu);
244 case MNID_SUBSETSETTINGS:
245 update_subset_settings_menu();
247 case MNID_QUITLEVELEDITOR:
252 else if(menu == level_settings_menu)
254 switch (level_settings_menu->check())
257 apply_level_settings_menu();
258 Menu::set_current(NULL);
265 else if(menu == select_tilegroup_menu)
268 switch (it = select_tilegroup_menu->check())
273 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
274 Menu::set_current(0);
281 else if(menu == select_objects_menu)
284 switch (it = select_objects_menu->check())
289 cur_objects = select_objects_menu->get_item_by_id(it).text;
292 Menu::set_current(0);
297 else if(menu == subset_load_menu)
299 switch (i = subset_load_menu->check())
306 if(le_load_level_subset(level_subsets.item[i-1]))
312 else if(menu == subset_new_menu)
314 if(subset_new_menu->item[2].input[0] == '\0')
315 subset_new_menu->item[3].kind = MN_DEACTIVE;
318 subset_new_menu->item[3].kind = MN_ACTION;
320 switch (i = subset_new_menu->check())
322 case MNID_CREATESUBSET:
323 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
324 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
325 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
327 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
329 Menu::set_current(subset_settings_menu);
334 else if(menu == subset_settings_menu)
336 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 )
337 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
339 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
341 switch (i = subset_settings_menu->check())
343 case MNID_SUBSETSAVECHANGES:
344 save_subset_settings_menu();
345 Menu::set_current(leveleditor_menu);
351 MouseCursor::current()->draw();
359 ++global_frame_counter;
362 now_time = SDL_GetTicks();
363 if (now_time < last_time + FPS)
364 SDL_Delay(last_time + FPS - now_time); /* delay some time */
372 int le_load_level_subset(char *filename)
374 le_level_subset->load(filename);
375 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
379 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
381 Menu::set_current(NULL);
390 leveleditor_menu = new Menu();
391 subset_load_menu = new Menu();
392 subset_new_menu = new Menu();
393 subset_settings_menu = new Menu();
394 level_settings_menu = new Menu();
395 select_tilegroup_menu = new Menu();
396 select_objects_menu = new Menu();
398 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
399 leveleditor_menu->additem(MN_HL,"",0,0);
400 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
401 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
402 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
403 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
404 leveleditor_menu->additem(MN_HL,"",0,0);
405 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
407 Menu::set_current(leveleditor_menu);
409 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
410 subset_load_menu->additem(MN_HL, "", 0, 0);
412 for(i = 0; i < level_subsets.num_items; ++i)
414 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
416 subset_load_menu->additem(MN_HL,"",0,0);
417 subset_load_menu->additem(MN_BACK,"Back",0,0);
419 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
420 subset_new_menu->additem(MN_HL,"",0,0);
421 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
422 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
423 subset_new_menu->additem(MN_HL,"",0,0);
424 subset_new_menu->additem(MN_BACK,"Back",0,0);
426 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
427 subset_settings_menu->additem(MN_HL,"",0,0);
428 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
429 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
430 subset_settings_menu->additem(MN_HL,"",0,0);
431 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
432 subset_settings_menu->additem(MN_HL,"",0,0);
433 subset_settings_menu->additem(MN_BACK,"Back",0,0);
435 level_settings_menu->arrange_left = true;
436 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
437 level_settings_menu->additem(MN_HL,"",0,0);
438 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
439 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
440 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
441 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
442 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
443 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
444 level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT);
445 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
446 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
447 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
448 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
449 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
450 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
451 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
452 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
453 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
454 level_settings_menu->additem(MN_HL,"",0,0);
455 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
457 select_tilegroup_menu->arrange_left = true;
458 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
459 select_tilegroup_menu->additem(MN_HL,"",0,0);
460 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
462 for(std::set<TileGroup>::iterator it = tilegroups->begin();
463 it != tilegroups->end(); ++it )
465 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
467 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
470 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
471 sit != (*it).tiles.end(); ++sit, ++i)
473 std::string imagefile = "/images/tilesets/" ;
474 bool only_editor_image = false;
475 if(!TileManager::instance()->get(*sit)->filenames.empty())
477 imagefile += TileManager::instance()->get(*sit)->filenames[0];
479 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
481 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
482 only_editor_image = true;
486 imagefile += "notile.png";
488 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
490 if(!only_editor_image)
491 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
493 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
494 button->add_icon(imagefile,32,32);
496 tilegroups_map[it->name]->additem(button, *sit);
499 select_tilegroup_menu->additem(MN_HL,"",0,0);
501 select_objects_menu->arrange_left = true;
502 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
503 select_objects_menu->additem(MN_HL,"",0,0);
506 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
507 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
509 DisplayManager dummy;
510 for(int i = 0; i < NUM_BadGuyKinds; ++i)
512 BadGuy bad_tmp(dummy, 0,0,BadGuyKind(i),false);
513 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
514 objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
516 objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
517 objects_map["BadGuys"]->manipulate_button(i)->get_pos().y,
518 BadGuyKind(i), false));
522 select_objects_menu->additem(MN_HL,"",0,0);
528 level_subsets = dsubdirs("/levels", "level1.stl");
529 le_level_subset = new LevelSubset;
532 selected_game_object = NULL;
536 show_selections = true;
539 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
540 le_level_changed = false;
541 le_help_shown = false;
543 le_mouse_pressed[LEFT] = false;
544 le_mouse_pressed[RIGHT] = false;
546 le_mouse_clicked[LEFT] = false;
547 le_mouse_clicked[RIGHT] = false;
549 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
551 select_tilegroup_menu_effect.init(false);
552 select_objects_menu_effect.init(false);
553 display_level_info.init(false);
556 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
557 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
558 le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0);
559 le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
560 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
561 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
562 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
563 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
564 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
565 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0);
566 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
567 le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16);
568 le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32);
569 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
570 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
571 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
572 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
573 le_object_properties_bt->set_active(false);
575 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
576 mouse_select_object->set_mid(16,16);
578 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
579 le_tilemap_panel->set_button_size(32,10);
580 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
581 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
582 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
583 le_tilemap_panel->highlight_last(true);
584 le_tilemap_panel->set_last_clicked(TM_IA);
590 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
596 void update_level_settings_menu()
601 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
602 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
604 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
605 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
606 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
607 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
608 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
609 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
611 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
612 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
613 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
614 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
615 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
616 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
618 sprintf(str,"%d",le_world->get_level()->width);
619 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
620 sprintf(str,"%d",le_world->get_level()->height);
621 level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str);
622 sprintf(str,"%d",le_world->get_level()->time_left);
623 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
624 sprintf(str,"%2.0f",le_world->get_level()->gravity);
625 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
626 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
627 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
628 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
629 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
630 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
631 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
632 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
633 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
634 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
635 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
636 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
637 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
638 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
639 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
642 void update_subset_settings_menu()
644 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
645 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
648 void apply_level_settings_menu()
652 le_level_changed = true;
654 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
655 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
657 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
659 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
663 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
665 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
670 le_world->get_level()->load_gfx();
673 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
675 le_world->get_level()->resize(
676 atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
677 atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
678 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
679 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
680 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
681 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
682 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
683 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
684 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
685 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
686 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
689 void save_subset_settings_menu()
691 le_level_subset->title = subset_settings_menu->item[2].input;
692 le_level_subset->description = subset_settings_menu->item[3].input;
693 le_level_subset->save();
694 le_level_changed = false;
697 void le_unload_level()
704 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
705 if(confirm_dialog(str))
707 le_world->get_level()->save(le_level_subset->name.c_str(), le_level,
713 le_level_changed = false;
716 void le_goto_level(int levelnb)
719 le_world = new World(le_level_subset->name, levelnb);
720 display_level_info.start(2500);
726 SDL_EnableKeyRepeat(0, 0); // disables key repeating
730 delete leveleditor_menu;
731 delete subset_load_menu;
732 delete subset_new_menu;
733 delete subset_settings_menu;
734 delete level_settings_menu;
735 delete select_tilegroup_menu;
736 delete select_objects_menu;
737 delete le_save_level_bt;
739 delete le_test_level_bt;
740 delete le_next_level_bt;
741 delete le_previous_level_bt;
742 delete le_move_right_bt;
743 delete le_move_left_bt;
744 delete le_move_up_bt;
745 delete le_move_down_bt;
747 delete le_select_mode_one_bt;
748 delete le_select_mode_two_bt;
749 delete le_settings_bt;
750 delete le_tilegroup_bt;
751 delete le_objects_bt;
752 delete le_tilemap_panel;
753 delete le_object_select_bt;
754 delete le_object_properties_bt;
755 delete mouse_select_object;
757 delete le_level_subset;
760 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
761 i != tilegroups_map.end(); ++i)
765 for(ButtonPanelMap::iterator i = objects_map.begin();
766 i != objects_map.end(); ++i)
772 void le_drawminimap()
778 if(screen->w - 64 > le_world->get_level()->width * 4)
780 else if(screen->w - 64 > le_world->get_level()->width * 2)
784 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
786 int mini_tile_height;
787 if(screen->h - 64 > le_world->get_level()->height * 4)
788 mini_tile_height = 4;
789 else if(screen->h - 64 > le_world->get_level()->height * 2)
790 mini_tile_height = 2;
792 mini_tile_height = 1;
794 Level* level = le_world->get_level();
795 for (int y = 0; y < le_world->get_level()->height; ++y)
796 for (int x = 0; x < le_world->get_level()->width; ++x)
799 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
800 mini_tile_width , 4, level->bg_tiles[y * level->width + x]);
802 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
803 mini_tile_width , 4, level->ia_tiles[y * level->width + x]);
805 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
806 mini_tile_width , 4, level->fg_tiles[y + level->width + x]);
810 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 128);
812 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
813 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 200);
814 fillrect(left_offset + (pos_x/32)*mini_tile_width + 19*mini_tile_width - 2, 0, 2, le_world->get_level()->height*mini_tile_height, 200, 200, 200, 200);
815 fillrect(left_offset + (pos_x/32)*mini_tile_width, le_world->get_level()->height*mini_tile_height-2, 19*mini_tile_width, 2, 200, 200, 200, 200);
819 void le_drawinterface()
826 /* draw a grid (if selected) */
829 for(x = 0; x < VISIBLE_TILES_X; x++)
830 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
831 for(y = 0; y < VISIBLE_TILES_Y; y++)
832 fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255);
836 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
839 if(show_selections && MouseCursor::current() != mouse_select_object)
841 if(le_selection_mode == CURSOR)
843 if(le_current.IsTile())
844 le_selection->draw(cursor_x - pos_x, cursor_y - pos_y);
846 else if(le_selection_mode == SQUARE)
849 le_highlight_selection();
850 /* draw current selection */
851 w = selection.x2 - selection.x1;
852 h = selection.y2 - selection.y1;
853 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, w, SELECT_W, SELECT_CLR);
854 fillrect(selection.x1 - pos_x + w, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
855 fillrect(selection.x1 - pos_x, selection.y1 - pos_y + h, w, SELECT_W, SELECT_CLR);
856 fillrect(selection.x1 - pos_x, selection.y1 - pos_y, SELECT_W, h, SELECT_CLR);
861 /* draw button bar */
862 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
864 if(le_current.IsTile())
866 Tile::draw(screen->w - 32, screen->h - 32, le_current.tile);
867 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
868 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
870 #if 0 // XXX FIXME TODO
871 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
873 le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
874 le_current.obj->draw_on_screen(cursor_x,cursor_y);
878 if(mouse_select_object && selected_game_object != NULL)
880 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);
881 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);
882 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);
883 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);
888 le_save_level_bt->draw();
890 le_test_level_bt->draw();
891 le_next_level_bt->draw();
892 le_previous_level_bt->draw();
893 le_rubber_bt->draw();
894 if(le_selection_mode == SQUARE)
895 le_select_mode_one_bt->draw();
896 else if(le_selection_mode == CURSOR)
897 le_select_mode_two_bt->draw();
898 le_settings_bt->draw();
899 le_move_right_bt->draw();
900 le_move_left_bt->draw();
901 le_move_up_bt->draw();
902 le_move_down_bt->draw();
903 le_tilegroup_bt->draw();
904 le_objects_bt->draw();
905 if(!cur_tilegroup.empty())
906 tilegroups_map[cur_tilegroup]->draw();
907 else if(!cur_objects.empty())
909 objects_map[cur_objects]->draw();
912 le_tilemap_panel->draw();
914 if(!cur_objects.empty())
916 le_object_select_bt->draw();
917 le_object_properties_bt->draw();
920 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
921 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
924 white_small_text->draw("F1 for Help", 10, 430, 1);
926 if(display_level_info.check())
927 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
932 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
934 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
944 /* Draw the real background */
945 le_world->background->draw(le_world->displaymanager.get_viewport(),
948 if(le_current.IsTile())
950 Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128);
951 if(!TileManager::instance()->get(le_current.tile)->images.empty())
952 fillrect(cursor_x-pos_x,cursor_y-pos_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);
954 #if 0 // XXX FIXME TODO
955 if(le_current.IsObject())
957 le_current.obj->move_to(cursor_x, cursor_y);
961 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
963 Level* level = le_world->get_level();
964 for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
965 for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
968 if(active_tm == TM_BG)
973 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
974 level->bg_tiles[ (y + (int)(pos_y / 32)) * level->width +
975 (x + (int)(pos_x / 32))],a);
977 if(active_tm == TM_IA)
982 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
983 level->ia_tiles[ (y + (int)(pos_y / 32)) * level->width +
984 (x + (int)(pos_x / 32))],a);
987 if(active_tm == TM_FG)
992 Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
993 level->fg_tiles[ (y + (int)(pos_y / 32)) * level->width +
994 (x + (int)(pos_x / 32))],a);
996 /* draw whats inside stuff when cursor is selecting those */
997 /* (draw them all the time - is this the right behaviour?) */
998 Tile* edit_image = TileManager::instance()->get(
1000 [ (y + (int)(pos_y / 32)) * level->width + (x + (int)(pos_x / 32))]);
1001 if(edit_image && !edit_image->editor_images.empty())
1002 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
1006 /* Draw the Bad guys: */
1007 for (std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
1008 it != le_world->gameobjects.end(); ++it)
1010 BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
1014 /* to support frames: img_bsod_left[(frame / 5) % 4] */
1016 viewport.set_translation(Vector(pos_x, pos_y));
1017 badguy->draw(viewport, 0);
1020 /* Draw the player: */
1021 /* for now, the position is fixed at (100, 240) */
1022 largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
1025 void le_change_object_properties(GameObject *pobj)
1027 Surface* cap_screen = Surface::CaptureScreen();
1028 Menu* object_properties_menu = new Menu();
1031 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
1032 object_properties_menu->additem(MN_HL,"",0,0);
1034 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1037 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
1038 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1040 string_list_add_item(object_properties_menu->get_item_by_id(1).list,
1041 badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1043 object_properties_menu->get_item_by_id(1).list->active_item = i;
1045 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1048 object_properties_menu->additem(MN_HL,"",0,0);
1049 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1051 Menu::set_current(object_properties_menu);
1057 while (SDL_PollEvent(&event))
1059 object_properties_menu->event(event);
1062 cap_screen->draw(0,0);
1064 object_properties_menu->draw();
1065 object_properties_menu->action();
1067 switch (object_properties_menu->check())
1071 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1073 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1074 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1075 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1084 if(Menu::current() == NULL)
1087 mouse_cursor->draw();
1093 Menu::set_current(0);
1094 delete object_properties_menu;
1098 void le_checkevents()
1105 keymod = SDL_GetModState();
1107 while(SDL_PollEvent(&event))
1109 if (Menu::current())
1111 Menu::current()->event(event);
1112 if(!le_world && !Menu::current())
1113 Menu::set_current(leveleditor_menu);
1117 mouse_cursor->set_state(MC_NORMAL);
1119 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1120 if(event.type == SDL_KEYDOWN
1121 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1122 && (event.motion.x > 0
1123 && event.motion.x < screen->w - 64 &&
1124 event.motion.y > 0 && event.motion.y < screen->h)))
1128 case SDL_KEYDOWN: // key pressed
1129 key = event.key.keysym.sym;
1133 Menu::set_current(leveleditor_menu);
1136 if(le_world != NULL)
1144 cursor_x = (le_world->get_level()->width * 32) - 32;
1148 le_show_grid = !le_show_grid;
1154 case SDL_MOUSEBUTTONDOWN:
1155 if(event.button.button == SDL_BUTTON_LEFT)
1157 le_mouse_pressed[LEFT] = true;
1159 selection.x1 = event.motion.x + pos_x;
1160 selection.y1 = event.motion.y + pos_y;
1161 selection.x2 = event.motion.x + pos_x;
1162 selection.y2 = event.motion.y + pos_y;
1164 else if(event.button.button == SDL_BUTTON_RIGHT)
1166 le_mouse_pressed[RIGHT] = true;
1169 case SDL_MOUSEBUTTONUP:
1170 if(event.button.button == SDL_BUTTON_LEFT)
1172 le_mouse_pressed[LEFT] = false;
1173 le_mouse_clicked[LEFT] = true;
1175 else if(event.button.button == SDL_BUTTON_RIGHT)
1177 le_mouse_pressed[RIGHT] = false;
1178 le_mouse_clicked[RIGHT] = true;
1181 case SDL_MOUSEMOTION:
1183 if(!Menu::current())
1188 if(le_current.IsTile())
1190 cursor_x = ((int)(pos_x + x) / 32) * 32;
1191 cursor_y = ((int)(pos_y + y) / 32) * 32;
1199 if(le_mouse_pressed[LEFT])
1201 selection.x2 = x + pos_x;
1202 selection.y2 = y + pos_y;
1205 if(le_mouse_pressed[RIGHT])
1207 pos_x += -1 * event.motion.xrel;
1208 pos_y += -1 * event.motion.yrel;
1216 else if(event.type == SDL_QUIT) /* window closing */
1222 if(le_world != NULL)
1224 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 &&
1225 event.motion.y > 0 && event.motion.y < screen->h)))
1227 le_mouse_pressed[LEFT] = false;
1228 le_mouse_pressed[RIGHT] = false;
1230 if(!Menu::current())
1232 /* Check for button events */
1233 le_test_level_bt->event(event);
1234 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1236 le_save_level_bt->event(event);
1237 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1238 le_world->get_level()->save(le_level_subset->name.c_str(),le_level,
1240 le_exit_bt->event(event);
1241 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1243 Menu::set_current(leveleditor_menu);
1245 le_next_level_bt->event(event);
1246 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1248 if(le_level < le_level_subset->levels)
1250 le_goto_level(le_level+1);
1256 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1257 if(confirm_dialog(str))
1259 new_lev.init_defaults();
1260 new_lev.save(le_level_subset->name.c_str(),le_level+1, le_world);
1261 le_level_subset->levels = le_level;
1262 le_goto_level(le_level);
1266 le_previous_level_bt->event(event);
1267 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1270 le_goto_level(le_level -1);
1272 le_rubber_bt->event(event);
1273 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1276 if(!cur_objects.empty())
1278 le_object_select_bt->event(event);
1279 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1281 MouseCursor::set_current(mouse_select_object);
1284 le_object_properties_bt->event(event);
1285 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1287 le_change_object_properties(selected_game_object);
1292 if(le_selection_mode == SQUARE)
1294 le_select_mode_one_bt->event(event);
1295 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1296 le_selection_mode = CURSOR;
1300 le_select_mode_two_bt->event(event);
1301 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1302 le_selection_mode = SQUARE;
1304 ButtonPanelMap::iterator it;
1305 le_tilegroup_bt->event(event);
1306 switch (le_tilegroup_bt->get_state())
1308 case BUTTON_CLICKED:
1309 Menu::set_current(select_tilegroup_menu);
1310 select_tilegroup_menu_effect.start(200);
1311 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1313 case BUTTON_WHEELUP:
1314 if(cur_tilegroup.empty())
1316 cur_tilegroup = tilegroups_map.begin()->first;
1320 it = tilegroups_map.find(cur_tilegroup);
1321 if((++it) == tilegroups_map.end())
1323 cur_tilegroup = tilegroups_map.begin()->first;
1327 cur_tilegroup = (*it).first;
1333 case BUTTON_WHEELDOWN:
1334 it = tilegroups_map.find(cur_tilegroup);
1335 if(it == tilegroups_map.begin())
1337 cur_tilegroup = tilegroups_map.rbegin()->first;
1341 if(--it != --tilegroups_map.begin())
1342 cur_tilegroup = (*it).first;
1344 cur_tilegroup = tilegroups_map.rbegin()->first;
1352 le_objects_bt->event(event);
1353 switch (le_objects_bt->get_state())
1355 case BUTTON_CLICKED:
1356 Menu::set_current(select_objects_menu);
1357 select_objects_menu_effect.start(200);
1358 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1360 case BUTTON_WHEELUP:
1361 it = objects_map.find(cur_objects);
1362 if(it == objects_map.end())
1364 cur_objects = objects_map.begin()->first;
1368 if(++it != objects_map.end())
1369 cur_objects = (*it).first;
1371 cur_objects = objects_map.begin()->first;
1375 case BUTTON_WHEELDOWN:
1376 it = objects_map.find(cur_objects);
1377 if(it == objects_map.begin())
1379 cur_objects = objects_map.rbegin()->first;
1383 if(--it != --objects_map.begin())
1384 cur_objects = (*it).first;
1386 cur_objects = objects_map.rbegin()->first;
1395 le_settings_bt->event(event);
1396 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1398 update_level_settings_menu();
1399 Menu::set_current(level_settings_menu);
1401 if(!cur_tilegroup.empty())
1403 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1405 if(pbutton->get_state() == BUTTON_CLICKED)
1407 le_current.Tile(pbutton->get_tag());
1411 else if(!cur_objects.empty())
1413 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1415 if(pbutton->get_state() == BUTTON_CLICKED)
1417 #if 0 // TODO fixme!!
1418 le_current.Object(pbutton->get_drawable());
1424 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1426 if(pbutton->get_state() == BUTTON_CLICKED)
1428 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1434 le_settings_bt->event(event);
1435 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1437 Menu::set_current(0);
1439 le_tilegroup_bt->event(event);
1440 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1442 Menu::set_current(0);
1444 le_objects_bt->event(event);
1445 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1447 Menu::set_current(0);
1452 if(!Menu::current() && !show_minimap)
1454 if(le_mouse_pressed[LEFT])
1456 if(MouseCursor::current() != mouse_select_object)
1458 if(le_current.IsTile())
1459 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1462 else if(le_mouse_clicked[LEFT])
1464 if(MouseCursor::current() == mouse_select_object)
1466 bool object_got_hit = false;
1467 base_type cursor_base;
1468 if(le_current.IsTile())
1470 cursor_base.x = cursor_x;
1471 cursor_base.y = cursor_y;
1473 else if(le_current.IsObject())
1475 cursor_base.x = cursor_x + pos_x;
1476 cursor_base.y = cursor_y + pos_y;
1478 cursor_base.width = 32;
1479 cursor_base.height = 32;
1481 for(std::vector<GameObject*>::iterator it =
1482 le_world->gameobjects.begin();
1483 it != le_world->gameobjects.end(); ++it) {
1484 MovingObject* mobj = dynamic_cast<MovingObject*> (*it);
1488 if(rectcollision(cursor_base, mobj->base))
1490 selected_game_object = mobj;
1491 object_got_hit = true;
1498 selected_game_object = NULL;
1499 le_object_properties_bt->set_active(false);
1502 le_object_properties_bt->set_active(true);
1504 MouseCursor::set_current(mouse_cursor);
1510 if(le_current.IsObject())
1512 le_level_changed = true;
1513 std::string type = le_current.obj->type();
1514 if(type == "BadGuy")
1516 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1518 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1519 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1525 le_mouse_clicked[LEFT] = false;
1531 if(!Menu::current())
1533 show_minimap = false;
1535 le_move_left_bt->event(event);
1536 le_move_right_bt->event(event);
1537 le_move_up_bt->event(event);
1538 le_move_down_bt->event(event);
1539 switch(le_move_left_bt->get_state())
1541 case BUTTON_PRESSED:
1542 pos_x -= KEYBOARD_SPEED;
1543 show_minimap = true;
1546 pos_x -= MOUSE_SPEED;
1547 show_minimap = true;
1549 case BUTTON_CLICKED:
1550 show_minimap = true;
1556 switch(le_move_right_bt->get_state())
1558 case BUTTON_PRESSED:
1559 pos_x += KEYBOARD_SPEED;
1560 show_minimap = true;
1563 pos_x += MOUSE_SPEED;
1564 show_minimap = true;
1566 case BUTTON_CLICKED:
1567 show_minimap = true;
1573 switch(le_move_up_bt->get_state())
1575 case BUTTON_PRESSED:
1576 pos_y -= KEYBOARD_SPEED;
1577 show_minimap = true;
1580 pos_y -= MOUSE_SPEED;
1581 show_minimap = true;
1583 case BUTTON_CLICKED:
1584 show_minimap = true;
1590 switch(le_move_down_bt->get_state())
1592 case BUTTON_PRESSED:
1593 pos_y += KEYBOARD_SPEED;
1594 show_minimap = true;
1597 pos_y += MOUSE_SPEED;
1598 show_minimap = true;
1600 case BUTTON_CLICKED:
1601 show_minimap = true;
1607 /* checking if pos_x and pos_y is within the limits... */
1608 if(pos_x > (le_world->get_level()->width * 32 + 32*2) - screen->w)
1609 pos_x = (le_world->get_level()->width * 32 + 32*2) - screen->w;
1613 if(pos_y > (le_world->get_level()->height * 32) - screen->h)
1614 pos_y = (le_world->get_level()->height * 32) - screen->h;
1622 void le_highlight_selection()
1626 if(selection.x1 < selection.x2)
1636 if(selection.y1 < selection.y2)
1652 fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1655 void le_change(float x, float y, int tm, unsigned int c)
1657 if(le_world != NULL)
1662 le_level_changed = true;
1664 switch(le_selection_mode)
1667 le_world->get_level()->change(x,y,tm,c);
1669 base_type cursor_base;
1672 cursor_base.width = 32;
1673 cursor_base.height = 32;
1675 /* if there is a bad guy over there, remove it */
1678 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1679 if(rectcollision(cursor_base,(*it)->base))
1682 le_world->bad_guys.erase(it);
1683 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1690 if(selection.x1 < selection.x2)
1700 if(selection.y1 < selection.y2)
1716 /* if there is a bad guy over there, remove it */
1719 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1720 it != le_world->bad_guys.end(); /* will be at end of loop */)
1722 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1723 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1726 it = le_world->bad_guys.erase(it);
1727 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1738 for(xx = x1; xx <= x2; xx++)
1739 for(yy = y1; yy <= y2; yy++)
1741 le_world->get_level()->change(xx*32, yy*32, tm, c);
1753 //Make sure a time value is set when testing the level
1754 if(le_world->get_level()->time_left == 0)
1755 le_world->get_level()->time_left = 250;
1757 le_world->get_level()->save("test", le_level, le_world);
1759 GameSession session("test",le_level, ST_GL_TEST);
1761 player_status.reset();
1763 music_manager->halt_music();
1765 Menu::set_current(NULL);
1766 World::set_current(le_world);
1771 bool tmp_show_grid = le_show_grid;
1772 SelectionMode temp_le_selection_mode = le_selection_mode;
1773 le_selection_mode = NONE;
1774 show_selections = true;
1775 le_show_grid = false;
1776 le_help_shown = true;
1778 drawgradient(Color(0,0,0), Color(255,255,255));
1782 unsigned int i, done_;
1785 " - Supertux level editor tutorial - ",
1787 "To make your map, click the ",
1788 "tilegroup button and choose a ",
1790 "Pick a tile and simply hold down ",
1791 "the left mouse button over the map",
1792 "to \"paint\" your selection over",
1795 "There are three layers for painting",
1796 "tiles upon, Background layer,",
1797 "the Interactive layer, and the",
1798 "Foreground layer, which can be",
1799 "toggled by the BkGrd, IntAct and",
1800 "FrGrd buttons. The Foreground and",
1801 "Background layers do not effect",
1802 "Tux in the gameplay, but lie in",
1803 "front of him or lie behind him in",
1809 " - Supertux level editor tutorial - ",
1811 "The tiles placed on",
1812 "the Interactive layer are those",
1813 "which actually effect Tux in the",
1816 "Click the objects menu to put ",
1817 "bad guys and other objects in the",
1818 "game. Unlike placing tiles, you",
1819 "cannot \"paint\" enemies. Click",
1820 "them onto the screen one at a time.",
1822 "To change the settings of your",
1823 "level, click the button with the",
1824 "screwdriver and wrench. From here",
1825 "you can change the background,",
1826 "music, length of the level,",
1832 " - Supertux level editor tutorial - ",
1834 "You may have more than one level.",
1835 "Pressing the up and down buttons",
1836 "above the button bar lets you",
1837 "choose which one you are working on.",
1839 "If you would like to speed up your",
1840 "level editing, a useful trick is",
1841 "to learn the keyboard shortcuts.",
1842 "They are easy to learn, just right-",
1843 "click on the buttons.",
1845 "Have fun making levels! If you make",
1846 "some good ones, send them to us on",
1847 "the SuperTux mailing list!",
1853 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1855 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1856 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1858 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1866 done_ = wait_for_event(event);
1870 drawgradient(Color(0,0,0), Color(255,255,255));
1874 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1876 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1877 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1879 gold_text->drawf("Press Anything to Continue - Page 2/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(text3)/sizeof(char *); i++)
1898 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1900 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1908 done_ = wait_for_event(event);
1912 show_selections = true;
1913 le_show_grid = tmp_show_grid;
1914 le_selection_mode = temp_le_selection_mode;
1915 le_help_shown = false;