1 /* 2 * Copyright (C) 2002-2020 by the Widelands Development Team 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 */ 19 20 #ifndef WL_WUI_INTERACTIVE_BASE_H 21 #define WL_WUI_INTERACTIVE_BASE_H 22 23 #include <memory> 24 25 #include "graphic/toolbar_imageset.h" 26 #include "io/profile.h" 27 #include "logic/editor_game_base.h" 28 #include "logic/map.h" 29 #include "logic/path.h" 30 #include "sound/note_sound.h" 31 #include "ui_basic/box.h" 32 #include "ui_basic/dropdown.h" 33 #include "ui_basic/unique_window.h" 34 #include "wui/chat_overlay.h" 35 #include "wui/debugconsole.h" 36 #include "wui/mapview.h" 37 #include "wui/minimap.h" 38 #include "wui/quicknavigation.h" 39 40 class UniqueWindowHandler; 41 42 struct WorkareaPreview { 43 Widelands::Coords coords; 44 const WorkareaInfo* info; 45 std::map<Widelands::TCoords<>, uint32_t> data; 46 }; 47 48 enum class RoadBuildingType { kRoad, kWaterway }; 49 50 /** 51 * This is used to represent the code that InteractivePlayer and 52 * EditorInteractive share. 53 */ 54 class InteractiveBase : public UI::Panel, public DebugConsole::Handler { 55 public: 56 enum { 57 dfShowCensus = 1, ///< show census report on buildings 58 dfShowStatistics = 2, ///< show statistics report on buildings 59 dfShowSoldierLevels = 4, ///< show level information above soldiers 60 dfShowWorkareaOverlap = 61 8, ///< highlight overlapping workareas when placing a constructionsite 62 dfDebug = 16 ///< general debugging info 63 }; 64 65 /// A build help overlay, i.e. small, big, mine, port ... 66 struct BuildhelpOverlay { 67 const Image* pic = nullptr; 68 Vector2i hotspot = Vector2i::zero(); 69 }; 70 71 // Manages all UniqueWindows. 72 UniqueWindowHandler& unique_windows(); 73 74 InteractiveBase(Widelands::EditorGameBase&, Section& global_s); 75 ~InteractiveBase() override; 76 egbase()77 Widelands::EditorGameBase& egbase() const { 78 return egbase_; 79 } 80 81 void show_workarea(const WorkareaInfo& workarea_info, Widelands::Coords coords); 82 void show_workarea(const WorkareaInfo& workarea_info, 83 Widelands::Coords coords, 84 std::map<Widelands::TCoords<>, uint32_t>& extra_data); 85 void hide_workarea(const Widelands::Coords& coords, bool is_additional); 86 87 bool has_expedition_port_space(const Widelands::Coords&) const; get_expedition_port_spaces()88 std::map<Widelands::Ship*, Widelands::Coords>& get_expedition_port_spaces() { 89 return expedition_port_spaces_; 90 } 91 92 // point of view for drawing 93 virtual Widelands::Player* get_player() const = 0; 94 95 void think() override; 96 double average_fps() const; 97 bool handle_key(bool down, SDL_Keysym code) override; 98 virtual void postload(); 99 get_sel_pos()100 const Widelands::NodeAndTriangle<>& get_sel_pos() const { 101 return sel_.pos; 102 } 103 104 // Returns true if the buildhelp is currently displayed. 105 bool buildhelp() const; 106 107 // Sets if the buildhelp should be displayed and then calls rebuild_showhide_menu 108 void show_buildhelp(bool t); 109 110 /** 111 * sel_triangles determines whether the mouse pointer selects triangles. 112 * (False meas that it selects nodes.) 113 */ get_sel_triangles()114 bool get_sel_triangles() const { 115 return sel_.triangles; 116 } set_sel_triangles(const bool yes)117 void set_sel_triangles(const bool yes) { 118 sel_.triangles = yes; 119 } 120 get_sel_radius()121 uint32_t get_sel_radius() const { 122 return sel_.radius; 123 } 124 virtual void set_sel_pos(Widelands::NodeAndTriangle<>); set_sel_freeze(const bool yes)125 void set_sel_freeze(const bool yes) { 126 sel_.freeze = yes; 127 } 128 void set_sel_radius(uint32_t); 129 130 // display flags 131 uint32_t get_display_flags() const; 132 void set_display_flags(uint32_t flags); 133 bool get_display_flag(uint32_t flag); 134 void set_display_flag(uint32_t flag, bool on); 135 136 // road building in_road_building_mode()137 bool in_road_building_mode() const { 138 return road_building_mode_ != nullptr; 139 } in_road_building_mode(RoadBuildingType t)140 bool in_road_building_mode(RoadBuildingType t) const { 141 return road_building_mode_ && (road_building_mode_->type == t); 142 } 143 void start_build_road(Widelands::Coords start, Widelands::PlayerNumber player, RoadBuildingType); 144 void abort_build_road(); 145 void finish_build_road(); 146 bool append_build_road(Widelands::Coords field); 147 Widelands::Coords get_build_road_start() const; 148 Widelands::Coords get_build_road_end() const; 149 Widelands::CoordPath get_build_road_path() const; 150 cleanup_for_load()151 virtual void cleanup_for_load() { 152 } 153 154 /** 155 * Log a message to be displayed on screen 156 */ 157 void log_message(const std::string& message) const; log_message(const char * message)158 void log_message(const char* message) const { 159 log_message(std::string(message)); 160 } 161 162 void toggle_minimap(); 163 // Toggles the buildhelp and calls rebuild_showhide_menu 164 void toggle_buildhelp(); 165 166 // Returns the list of landmarks that have been mapped to the keys 0-9 167 const QuickNavigation::Landmark* landmarks(); 168 169 // Sets the landmark for the keyboard 'key' to 'point' 170 void set_landmark(size_t key, const MapView::View& view); 171 map_view()172 MapView* map_view() { 173 return &map_view_; 174 } 175 176 protected: 177 // For referencing the items in mapviewmenu_ 178 enum class MapviewMenuEntry { kMinimap, kIncreaseZoom, kDecreaseZoom, kResetZoom }; 179 180 // Adds the mapviewmenu_ to the toolbar 181 void add_mapview_menu(MiniMapType minimap_type); 182 // Rebuilds the mapviewmenu_ according to current view settings 183 void rebuild_mapview_menu(); 184 // Takes the appropriate action when an item in the mapviewmenu_ is selected 185 void mapview_menu_selected(MapviewMenuEntry entry); 186 187 /// Adds a toolbar button to the toolbar 188 /// \param image_basename: File path for button image starting from 'images' and without 189 /// file extension 190 /// \param name: Internal name of the button 191 /// \param tooltip: The button tooltip 192 /// \param window: The window that's associated with this button. 193 /// \param bind_default_toggle: If true, the button will toggle with its 'window'. 194 UI::Button* add_toolbar_button(const std::string& image_basename, 195 const std::string& name, 196 const std::string& tooltip_text, 197 UI::UniqueWindow::Registry* window = nullptr, 198 bool bind_default_toggle = false); 199 200 void hide_minimap(); 201 202 void mainview_move(); 203 204 void draw_overlay(RenderTarget&) override; 205 /** 206 * Will blit the 'image' on the given 'pos', offset by 'hotspot' and scaled according to the 207 * given zoom 'scale'. 208 * */ 209 void blit_overlay(RenderTarget* dst, 210 const Vector2i& pos, 211 const Image* image, 212 const Vector2i& hotspot, 213 float scale); 214 /** 215 * Will blit the 'image' on the given 'field', offset by 'hotspot' and scaled according to the 216 * given zoom 'scale'. 217 * */ 218 void blit_field_overlay(RenderTarget* dst, 219 const FieldsToDraw::Field& field, 220 const Image* image, 221 const Vector2i& hotspot, 222 float scale); 223 224 void draw_bridges(RenderTarget* dst, 225 const FieldsToDraw::Field* f, 226 uint32_t gametime, 227 float scale) const; 228 void draw_road_building(FieldsToDraw::Field&); 229 230 void unset_sel_picture(); 231 void set_sel_picture(const Image* image); get_sel_picture()232 const Image* get_sel_picture() { 233 return sel_.pic; 234 } 235 236 // Sets the toolbar's position to the bottom middle and configures its background images 237 void finalize_toolbar(); 238 chat_overlay()239 ChatOverlay* chat_overlay() { 240 return chat_overlay_; 241 } 242 toolbar()243 UI::Box* toolbar() { 244 return &toolbar_.box; 245 } 246 247 // Returns the information which overlay text should currently be drawn. 248 // Returns InfoToDraw::kNone if not 'show' 249 InfoToDraw get_info_to_draw(bool show) const; 250 251 // Returns the current overlays for the work area previews. 252 Workareas get_workarea_overlays(const Widelands::Map& map); 253 static WorkareasEntry get_workarea_overlay(const Widelands::Map&, const WorkareaPreview&); 254 255 // Returns the 'BuildhelpOverlay' for 'caps' or nullptr if there is no help 256 // to be displayed on this field. 257 const BuildhelpOverlay* get_buildhelp_overlay(Widelands::NodeCaps caps) const; 258 259 // Overlays displayed while a road or waterway is under construction. 260 struct RoadBuildingMode { RoadBuildingModeRoadBuildingMode261 RoadBuildingMode(Widelands::PlayerNumber p, Widelands::Coords s, RoadBuildingType t) 262 : player(p), path(s), type(t), work_area(nullptr) { 263 } 264 const Widelands::PlayerNumber player; 265 Widelands::CoordPath path; 266 const RoadBuildingType type; 267 std::unique_ptr<WorkareaInfo> work_area; 268 std::map<Widelands::Coords, std::vector<uint8_t>> overlay_road_previews; 269 std::map<Widelands::Coords, const Image*> overlay_steepness_indicators; 270 }; 271 std::map<Widelands::Coords, std::vector<uint8_t>> road_building_preview_overlays() const; 272 std::map<Widelands::Coords, const Image*> road_building_steepness_overlays() const; 273 274 /// Returns true if there is a workarea preview being shown at the given coordinates. 275 /// If 'map' is 0, checks only if the given coords are the center of a workarea; 276 /// otherwise checks if the coords are within any workarea. 277 bool has_workarea_preview(const Widelands::Coords& coords, 278 const Widelands::Map* map = nullptr) const; 279 280 /// Returns true if the current player is allowed to hear sounds from map objects on this field 281 virtual bool player_hears_field(const Widelands::Coords& coords) const = 0; 282 283 void set_toolbar_imageset(const ToolbarImageset& imageset); 284 285 #ifndef NDEBUG // only in debug builds 286 UI::UniqueWindow::Registry debugconsole_; 287 #endif 288 289 private: 290 void play_sound_effect(const NoteSound& note) const; 291 void resize_chat_overlay(); 292 void road_building_add_overlay(); 293 void road_building_remove_overlay(); 294 void cmd_map_object(const std::vector<std::string>& args); 295 void cmd_lua(const std::vector<std::string>& args); 296 297 // Rebuilds the subclass' showhidemenu_ according to current map settings 298 virtual void rebuild_showhide_menu() = 0; 299 300 struct SelData { 301 SelData(const bool Freeze = false, 302 const bool Triangles = false, 303 const Widelands::NodeAndTriangle<>& Pos = 304 Widelands::NodeAndTriangle<>{ 305 Widelands::Coords(0, 0), 306 Widelands::TCoords<>(Widelands::Coords(0, 0), Widelands::TriangleIndex::D)}, 307 const uint32_t Radius = 0, 308 const Image* Pic = nullptr) freezeSelData309 : freeze(Freeze), triangles(Triangles), pos(Pos), radius(Radius), pic(Pic) { 310 } 311 bool freeze; // don't change sel, even if mouse moves 312 bool triangles; // otherwise nodes 313 Widelands::NodeAndTriangle<> pos; 314 uint32_t radius; 315 const Image* pic; 316 } sel_; 317 318 bool buildhelp_; 319 MapView map_view_; 320 ChatOverlay* chat_overlay_; 321 322 /// A horizontal menu bar embellished with background graphics 323 struct Toolbar : UI::Panel { 324 Toolbar(UI::Panel* parent); 325 326 /// Sets the actual size and position of the toolbar 327 void finalize(); 328 void draw(RenderTarget& dst) override; 329 void change_imageset(const ToolbarImageset& images); 330 331 /// A row of buttons and dropdown menus 332 UI::Box box; 333 334 private: 335 /// The set of background images 336 ToolbarImageset imageset; 337 /// How often the left and right images get repeated, calculated from the width of the box 338 int repeat; 339 } toolbar_; 340 341 // Map View menu on the toolbar 342 UI::Dropdown<MapviewMenuEntry> mapviewmenu_; 343 // No unique_ptr on purpose: 'minimap_' is a UniqueWindow, its parent will 344 // delete it. 345 MiniMap* minimap_; 346 MiniMap::Registry minimap_registry_; 347 QuickNavigation quick_navigation_; 348 349 // The currently enabled work area previews 350 std::unordered_set<std::unique_ptr<WorkareaPreview>> workarea_previews_; 351 std::unique_ptr<Workareas> workareas_cache_; 352 353 std::map<Widelands::Ship*, Widelands::Coords> expedition_port_spaces_; 354 355 std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>> 356 graphic_resolution_changed_subscriber_; 357 std::unique_ptr<Notifications::Subscriber<NoteSound>> sound_subscriber_; 358 std::unique_ptr<Notifications::Subscriber<Widelands::NoteShip>> shipnotes_subscriber_; 359 Widelands::EditorGameBase& egbase_; 360 uint32_t display_flags_; 361 uint32_t lastframe_; // system time (milliseconds) 362 uint32_t frametime_; // in millseconds 363 uint32_t avg_usframetime_; // in microseconds! 364 365 std::unique_ptr<RoadBuildingMode> road_building_mode_; 366 367 std::unique_ptr<UniqueWindowHandler> unique_window_handler_; 368 BuildhelpOverlay buildhelp_overlays_[Widelands::Field::Buildhelp_None]; 369 }; 370 371 #endif // end of include guard: WL_WUI_INTERACTIVE_BASE_H 372