1 /* 2 * Copyright (c) 2008 prissi 3 * 4 * This file is part of the Simutrans project under the artistic license. 5 * 6 * New configurable OOP tool system 7 */ 8 9 #ifndef simmenu_h 10 #define simmenu_h 11 12 #include <string> 13 #include "descriptor/sound_desc.h" 14 15 #include "dataobj/koord3d.h" 16 #include "dataobj/translator.h" 17 18 #include "simtypes.h" 19 #include "display/simimg.h" 20 21 22 template<class T> class vector_tpl; 23 template<class T> class slist_tpl; 24 25 class scr_coord; 26 class tool_selector_t; 27 class player_t; 28 class toolbar_t; 29 class memory_rw_t; 30 class karte_ptr_t; 31 class zeiger_t; 32 33 enum { 34 // general tools 35 TOOL_QUERY=0, 36 TOOL_REMOVER, 37 TOOL_RAISE_LAND, 38 TOOL_LOWER_LAND, 39 TOOL_SETSLOPE, 40 TOOL_RESTORESLOPE, 41 TOOL_MARKER, 42 TOOL_CLEAR_RESERVATION, 43 TOOL_TRANSFORMER, 44 TOOL_ADD_CITY, 45 TOOL_CHANGE_CITY_SIZE, 46 TOOL_PLANT_TREE, 47 TOOL_SCHEDULE_ADD, 48 TOOL_SCHEDULE_INS, 49 TOOL_BUILD_WAY, 50 TOOL_BUILD_BRIDGE, 51 TOOL_BUILD_TUNNEL, 52 TOOL_WAYREMOVER, 53 TOOL_BUILD_WAYOBJ, 54 TOOL_BUILD_STATION, 55 TOOL_BUILD_ROADSIGN, 56 TOOL_BUILD_DEPOT, 57 TOOL_BUILD_HOUSE, 58 TOOL_BUILD_LAND_CHAIN, 59 TOOL_CITY_CHAIN, 60 TOOL_BUILD_FACTORY, 61 TOOL_LINK_FACTORY, 62 TOOL_HEADQUARTER, 63 TOOL_LOCK_GAME, 64 TOOL_ADD_CITYCAR, 65 TOOL_FOREST, 66 TOOL_STOP_MOVER, 67 TOOL_MAKE_STOP_PUBLIC, 68 TOOL_REMOVE_WAYOBJ, 69 TOOL_SLICED_AND_UNDERGROUND_VIEW, 70 TOOL_BUY_HOUSE, 71 TOOL_BUILD_CITYROAD, 72 TOOL_ERROR_MESSAGE, 73 TOOL_CHANGE_WATER_HEIGHT, 74 TOOL_SET_CLIMATE, 75 TOOL_ROTATE_BUILDING, 76 TOOL_MERGE_STOP, 77 GENERAL_TOOL_COUNT, 78 GENERAL_TOOL = 0x1000 79 }; 80 81 enum { 82 // simple one click tools 83 TOOL_PAUSE = 0, 84 TOOL_FASTFORWARD, 85 TOOL_SCREENSHOT, 86 TOOL_INCREASE_INDUSTRY, 87 TOOL_UNDO, 88 TOOL_SWITCH_PLAYER, 89 TOOL_STEP_YEAR, 90 TOOL_CHANGE_GAME_SPEED, 91 TOOL_ZOOM_IN, 92 TOOL_ZOOM_OUT, 93 TOOL_SHOW_COVERAGE, 94 TOOL_SHOW_NAME, 95 TOOL_SHOW_GRID, 96 TOOL_SHOW_TREES, 97 TOOL_SHOW_HOUSES, 98 TOOL_SHOW_UNDERGROUND, 99 TOOL_ROTATE90, 100 TOOL_QUIT, 101 TOOL_FILL_TREES, 102 TOOL_DAYNIGHT_LEVEL, 103 TOOL_VEHICLE_TOOLTIPS, 104 TOOL_TOOGLE_PAX, 105 TOOL_TOOGLE_PEDESTRIANS, 106 TOOL_TRAFFIC_LEVEL, 107 TOOL_CHANGE_CONVOI, 108 TOOL_CHANGE_LINE, 109 TOOL_CHANGE_DEPOT, 110 UNUSED_WKZ_PWDHASH_TOOL, 111 TOOL_CHANGE_PLAYER, 112 TOOL_CHANGE_TRAFFIC_LIGHT, 113 TOOL_CHANGE_CITY, 114 TOOL_RENAME, 115 TOOL_ADD_MESSAGE, 116 TOOL_TOGGLE_RESERVATION, 117 TOOL_VIEW_OWNER, 118 TOOL_HIDE_UNDER_CURSOR, 119 SIMPLE_TOOL_COUNT, 120 SIMPLE_TOOL = 0x2000 121 }; 122 123 enum { 124 // dialogue tools 125 DIALOG_HELP = 0, 126 DIALOG_OPTIONS, 127 DIALOG_MINIMAP, 128 DIALOG_LINEOVERVIEW, 129 DIALOG_MESSAGES, 130 DIALOG_FINANCES, 131 DIALOG_PLAYERS, 132 DIALOG_DISPLAYOPTIONS, 133 DIALOG_SOUND, 134 DIALOG_LANGUAGE, 135 DIALOG_PLAYERCOLOR, 136 DIALOG_JUMP, 137 DIALOG_LOAD, 138 DIALOG_SAVE, 139 DIALOG_LIST_HALT, 140 DIALOG_LIST_CONVOI, 141 DIALOG_LIST_TOWN, 142 DIALOG_LIST_GOODS, 143 DIALOG_LIST_FACTORY, 144 DIALOG_LIST_CURIOSITY, 145 DIALOG_EDIT_FACTORY, 146 DIALOG_EDIT_ATTRACTION, 147 DIALOG_EDIT_HOUSE, 148 DIALOG_EDIT_TREE, 149 DIALOG_ENLARGE_MAP, 150 DIALOG_LIST_LABEL, 151 DIALOG_CLIMATES, 152 DIALOG_SETTINGS, 153 DIALOG_GAMEINFO, 154 DIALOG_THEMES, 155 DIALOG_SCENARIO, 156 DIALOG_SCENARIO_INFO, 157 DIALOGE_TOOL_COUNT, 158 DIALOGE_TOOL = 0x4000 159 }; 160 161 enum { 162 // toolbars 163 TOOL_MAINMENU = 0, 164 TOOL_LAST_USED = 1022, 165 TOOLBAR_TOOL = 0x8000u 166 }; 167 168 class tool_t { 169 protected: 170 image_id icon; 171 private: 172 /* value to trigger this command (see documentation) */ 173 uint16 id; 174 175 protected: 176 static karte_ptr_t welt; 177 178 const char *default_param; 179 public: get_id()180 uint16 get_id() const { return id; } 181 182 static tool_t *dummy; 183 184 // for key lookup 185 static vector_tpl<tool_t *>char_to_tool; 186 187 /// cursor image 188 image_id cursor; 189 190 /// cursor marks this area 191 koord cursor_area; 192 193 /// cursor centered at marked area? default: false 194 bool cursor_centered; 195 196 /// cursor offset within marked area (only effective if cursor_centered != false) 197 koord cursor_offset; 198 199 /// z-offset of cursor, possible values: Z_PLAN and Z_GRID 200 sint8 offset; 201 202 sint16 ok_sound; 203 204 /// a script is waiting for a call-back 205 uint32 callback_id; 206 207 enum { 208 WFL_SHIFT = 1, ///< shift-key was pressed when mouse-click happened 209 WFL_CTRL = 2, ///< ctrl-key was pressed when mouse-click happened 210 WFL_LOCAL = 4, ///< tool call was issued by local client 211 WFL_SCRIPT = 8, ///< tool call was issued by script 212 WFL_NO_CHK = 16, ///< tool call needs no password or scenario checks 213 }; 214 uint8 flags; // flags are set before init/work/move is called 215 is_ctrl_pressed()216 bool is_ctrl_pressed() const { return flags & WFL_CTRL; } is_shift_pressed()217 bool is_shift_pressed() const { return flags & WFL_SHIFT; } is_local_execution()218 bool is_local_execution() const { return flags & WFL_LOCAL; } is_scripted()219 bool is_scripted() const { return flags & WFL_SCRIPT; } no_check()220 bool no_check() const { return flags & WFL_NO_CHK; } can_use_gui()221 bool can_use_gui() const { return is_local_execution() && !is_scripted(); } 222 223 uint16 command_key;// key to toggle action for this function 224 225 static vector_tpl<tool_t *> general_tool; 226 static vector_tpl<tool_t *> simple_tool; 227 static vector_tpl<tool_t *> dialog_tool; 228 static vector_tpl<toolbar_t *> toolbar_tool; 229 230 static void update_toolbars(); 231 232 // since only a single toolstr a time can be visible ... 233 static char toolstr[1024]; 234 235 static void init_menu(); 236 static void exit_menu(); 237 238 static void read_menu(const std::string &objfilename); 239 240 static uint16 const dummy_id = 0xFFFFU; 241 tool_t(uint16 const id)242 tool_t(uint16 const id) : id(id), cursor_area(1,1) 243 { 244 cursor = icon = IMG_EMPTY; 245 ok_sound = NO_SOUND; 246 offset = Z_PLAN; 247 default_param = NULL; 248 command_key = 0; 249 cursor_centered = false; 250 flags = 0; 251 callback_id = 0; 252 } 253 ~tool_t()254 virtual ~tool_t() {} 255 get_icon(player_t *)256 virtual image_id get_icon(player_t *) const { return icon; } set_icon(image_id i)257 void set_icon(image_id i) { icon = i; } 258 259 // returns default_param of this tool for player 260 // if player==NULL returns default_param that was used to create the tool 261 virtual const char* get_default_param(player_t* = NULL) const { return default_param; } set_default_param(const char * str)262 void set_default_param(const char* str) { default_param = str; } 263 264 // transfer additional information in networkgames rdwr_custom_data(memory_rw_t *)265 virtual void rdwr_custom_data(memory_rw_t*) { } 266 267 // this will draw the tool with some indication, if active 268 virtual bool is_selected() const; 269 270 // when true, local execution would do no harm is_init_network_save()271 virtual bool is_init_network_save() const { return false; } is_move_network_save(player_t *)272 virtual bool is_move_network_save(player_t *) const { return true; } 273 274 // if is_work_network_save()==false 275 // and is_work_here_network_save(...)==false 276 // then work-command is sent over network is_work_network_save()277 virtual bool is_work_network_save() const { return false; } is_work_here_network_save(player_t *,koord3d)278 virtual bool is_work_here_network_save(player_t *, koord3d) { return false; } 279 280 // will draw a dark frame, if selected 281 virtual void draw_after(scr_coord pos, bool dirty) const; 282 get_tooltip(const player_t *)283 virtual const char *get_tooltip(const player_t *) const { return NULL; } 284 285 /** 286 * @return true if this tool operates over the grid, not the map tiles. 287 */ is_grid_tool()288 virtual bool is_grid_tool() const {return false;} 289 290 /** 291 * Returning false on init will automatically invoke previous tool. 292 * Returning true will select tool and will make it possible to call work. 293 */ init(player_t *)294 virtual bool init( player_t * ) { return true; } 295 296 /// initializes cursor (icon, marked area) 297 void init_cursor( zeiger_t * ) const; 298 299 // returning true on exit will have tool_selector resets to query-tool on right-click exit(player_t *)300 virtual bool exit( player_t * ) { return true; } 301 302 /* the return string can have different meanings: 303 * NULL: ok 304 * "": unspecified error 305 * "blabla": errors message, will be handled and translated as appropriate 306 * check: called before work (and move too?) koord3d already valid coordinate, checks visibility 307 * work / move should depend on undergroundmode for not network safe tools 308 */ 309 virtual const char *check_pos( player_t *, koord3d ); work(player_t *,koord3d)310 virtual const char *work( player_t *, koord3d ) { return NULL; } move(player_t *,uint16,koord3d)311 virtual const char *move( player_t *, uint16 /* buttonstate */, koord3d ) { return ""; } 312 313 /** 314 * Should be overloaded if derived class implements move, 315 * move will only be called, if this function returns true. 316 */ move_has_effects()317 virtual bool move_has_effects() const { return false;} 318 319 /** 320 * Returns whether the 2d koordinate passed it's a valid position for this tool to highlight a tile, 321 * just takes into account is_grid_tool. It does not check if work is allowed there, that's check_pos() work. 322 * @see check_pos 323 * @return true is the coordinate it's found valid, false otherwise. 324 */ 325 bool check_valid_pos( koord k ) const; 326 327 /** 328 * Specifies if the cursor will need a position update after this tool takes effect (ie: changed the height of the tile) 329 * @note only used on lower_raise tools atm. 330 * @return true if the cursor has to be moved. 331 */ update_pos_after_use()332 virtual bool update_pos_after_use() const { return false; } 333 get_waytype()334 virtual waytype_t get_waytype() const { return invalid_wt; } 335 }; 336 337 /* 338 * Class for tools that work only on ground (kartenboden) 339 */ 340 class kartenboden_tool_t : public tool_t { 341 public: kartenboden_tool_t(uint16 const id)342 kartenboden_tool_t(uint16 const id) : tool_t(id) {} 343 344 char const* check_pos(player_t*, koord3d) OVERRIDE; 345 }; 346 347 /* 348 * Class for tools needing two clicks (e.g. building ways). 349 * Dragging is also possible. 350 * @author Gerd Wachsmuth 351 */ 352 class two_click_tool_t : public tool_t { 353 public: two_click_tool_t(uint16 const id)354 two_click_tool_t(uint16 const id) : tool_t(id) { 355 MEMZERO(start_marker); 356 first_click_var = true; 357 } 358 359 void rdwr_custom_data(memory_rw_t*) OVERRIDE; 360 bool init(player_t*) OVERRIDE; exit(player_t * const player)361 bool exit(player_t* const player) OVERRIDE { return init(player); } 362 363 char const* work(player_t*, koord3d) OVERRIDE; 364 char const* move(player_t*, uint16 /* buttonstate */, koord3d) OVERRIDE; move_has_effects()365 bool move_has_effects() const OVERRIDE { return true; } 366 367 bool is_work_here_network_save(player_t *, koord3d) OVERRIDE; 368 369 /** 370 * @returns true if cleanup() needs to be called before another tool can be executed 371 * necessary for all tools that create dummy tiles for preview 372 */ remove_preview_necessary()373 virtual bool remove_preview_necessary() const { return false; } 374 375 bool is_first_click() const; 376 377 /** 378 * Remove dummy grounds, remove start_marker. 379 */ cleanup()380 void cleanup() { cleanup(true); } 381 get_start_pos()382 const koord3d& get_start_pos() const { return start; } 383 384 private: 385 /** 386 * Remove dummy grounds, remove start_marker if @p delete_start_marker is true. 387 */ 388 void cleanup(bool delete_start_marker ); 389 390 /* 391 * This routine should fill marked_tiles. 392 */ 393 virtual void mark_tiles( player_t *, const koord3d &start, const koord3d &end ) = 0; 394 395 /* 396 * This routine is called, if the real work should be done. 397 * If the tool supports single clicks, end is sometimes == koord3d::invalid. 398 * Returned string is passed by work/move. 399 */ 400 virtual const char *do_work( player_t *, const koord3d &start, const koord3d &end ) = 0; 401 402 /* 403 * Can the tool start/end on pos? If it is the second click, start is the position of the first click 404 * 0 = no 405 * 1 = This tool can work on this tile (with single click) 406 * 2 = On this tile can dragging start/end 407 * 3 = Both (1 and 2) 408 * error will contain an error message (if this is != NULL, return value should be 0). 409 */ 410 virtual uint8 is_valid_pos( player_t *, const koord3d &pos, const char *&error, const koord3d &start ) = 0; 411 412 virtual image_id get_marker_image(); 413 414 bool first_click_var; 415 koord3d start; 416 417 zeiger_t *start_marker; 418 419 protected: 420 virtual void start_at( koord3d &new_start ); 421 422 slist_tpl< zeiger_t* > marked; 423 }; 424 425 /* toolbar are a new overclass */ 426 class toolbar_t : public tool_t { 427 protected: 428 const char *helpfile; 429 tool_selector_t *tool_selector; 430 slist_tpl<tool_t *>tools; 431 public: toolbar_t(uint16 const id,char const * const t,char const * const h)432 toolbar_t(uint16 const id, char const* const t, char const* const h) : tool_t(id) 433 { 434 default_param = t; 435 helpfile = h; 436 tool_selector = NULL; 437 } get_tooltip(player_t const *)438 char const* get_tooltip(player_t const*) const OVERRIDE { return translator::translate(default_param); } get_tool_selector()439 tool_selector_t *get_tool_selector() const { return tool_selector; } 440 image_id get_icon(player_t*) const OVERRIDE; 441 bool is_selected() const OVERRIDE; is_init_network_save()442 bool is_init_network_save() const OVERRIDE { return true; } is_work_network_save()443 bool is_work_network_save() const OVERRIDE { return true; } 444 // show this toolbar 445 bool init(player_t*) OVERRIDE; 446 // close this toolbar 447 bool exit(player_t*) OVERRIDE; 448 virtual void update(player_t *); // just refresh content append(tool_t * tool)449 void append(tool_t *tool) { tools.append(tool); } 450 }; 451 452 #define MAX_LAST_TOOLS (10) 453 454 class toolbar_last_used_t : public toolbar_t { 455 private: 456 slist_tpl<tool_t *>all_tools[MAX_PLAYER_COUNT]; 457 public: toolbar_last_used_t(uint16 const id,char const * const t,char const * const h)458 toolbar_last_used_t(uint16 const id, char const* const t, char const* const h) : toolbar_t(id,t,h) {} 459 static toolbar_last_used_t *last_used_tools; 460 void update(player_t *) OVERRIDE; // just refresh content 461 void append(tool_t *, player_t *); 462 void clear(); 463 }; 464 465 // create new instance of tool 466 tool_t *create_tool(int toolnr); 467 468 #endif 469