1 /**************************************************************************/ 2 /* Copyright 2012 Tim Day */ 3 /* */ 4 /* This file is part of Evolvotron */ 5 /* */ 6 /* Evolvotron is free software: you can redistribute it and/or modify */ 7 /* it under the terms of the GNU General Public License as published by */ 8 /* the Free Software Foundation, either version 3 of the License, or */ 9 /* (at your option) any later version. */ 10 /* */ 11 /* Evolvotron is distributed in the hope that it will be useful, */ 12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 14 /* GNU General Public License for more details. */ 15 /* */ 16 /* You should have received a copy of the GNU General Public License */ 17 /* along with Evolvotron. If not, see <http://www.gnu.org/licenses/>. */ 18 /**************************************************************************/ 19 20 /*! \file 21 \brief Interface for class EvolvotronMain. 22 */ 23 24 #ifndef _evolvotron_main_h_ 25 #define _evolvotron_main_h_ 26 27 #include "common.h" 28 29 #include "function_registry.h" 30 #include "transform_factory.h" 31 32 #include "mutatable_image.h" 33 #include "mutatable_image_display.h" 34 #include "mutatable_image_computer_farm.h" 35 #include "mutation_parameters_qobject.h" 36 #include "render_parameters.h" 37 38 class DialogAbout; 39 class DialogHelp; 40 class DialogMutationParameters; 41 class DialogRenderParameters; 42 class DialogFunctions; 43 class DialogFavourite; 44 45 //! Utility class to expand "restart with" menu picks 46 /*! A boost::bind kind of thing 47 */ 48 class SignalExpanderRestartWith : public QObject 49 { 50 private: 51 Q_OBJECT 52 53 const FunctionRegistration*const _fn; 54 public: SignalExpanderRestartWith(QObject * parent,const FunctionRegistration * fn)55 SignalExpanderRestartWith(QObject* parent,const FunctionRegistration* fn) 56 :QObject(parent) 57 ,_fn(fn) 58 {} 59 public slots: restart_with()60 void restart_with() 61 { 62 emit restart_with(_fn); 63 } 64 signals: 65 void restart_with(const FunctionRegistration*); 66 }; 67 68 //! Top level GUI component for evolvotron application 69 class EvolvotronMain : public QMainWindow 70 { 71 private: 72 Q_OBJECT 73 74 protected: 75 76 //! Class encapsulating everything needed for undo functionality. 77 /*! \todo This is too big to be a nested class. 78 */ 79 class History 80 { 81 protected: 82 //! Pointer to main app. 83 EvolvotronMain*const _main; 84 85 typedef std::map<MutatableImageDisplay*,boost::shared_ptr<const MutatableImage> > ArchiveRecordEntries; 86 typedef std::pair<std::string,ArchiveRecordEntries> ArchiveRecord; 87 typedef std::deque<ArchiveRecord> Archive; 88 89 //! Each deque slot contains the collection of display-image pairs replaced by an single action (and a string naming that action). 90 /*! We use a deque rather than a stack because we want to clean up the tail end (limited number of Undos). 91 */ 92 Archive _archive; 93 94 //! Number of slots retained for history. 95 const uint max_slots; 96 97 //! Clean up the last slot in the queue. 98 void purge(); 99 100 //! Write some info to std::clog. 101 void log_status() const; 102 103 public: 104 105 //! Constructor. 106 History(EvolvotronMain*); 107 108 //! Destructor. 109 ~History(); 110 111 //! Eliminate any references to the display (and clean up any undo actions which are empty as a result). 112 void goodbye(MutatableImageDisplay*); 113 114 //! Record that we are overwriting the given display. 115 void replacing(MutatableImageDisplay* display); 116 117 //! Starts a new action slot 118 void begin_action(const std::string& action_name); 119 120 //! Ends an action slot and updates the undoable state. 121 void end_action(); 122 123 //! Returns true if there is stuff to undo 124 bool undoable(); 125 126 //! Implements an undo. 127 void undo(); 128 }; 129 130 protected: 131 //! Convenience typedef for pointer to member function implementing a kind of spawn. 132 typedef void (EvolvotronMain::* SpawnMemberFn)(const boost::shared_ptr<const MutatableImage>& image,MutatableImageDisplay* display,bool one_of_many); 133 134 //! Instance of History object to track activity. 135 std::unique_ptr<History> _history; 136 137 //! Sweep z linearly through animations 138 /*! \todo Move to mutation or render paraemeters ? 139 */ 140 const bool _linear_zsweep; 141 142 //! Generate spheremaps 143 /*! \todo Move to mutation or render paraemeters ? 144 */ 145 const bool _spheremap; 146 147 //! Name of files to load on a reset. 148 std::vector<std::string> _startup_filenames; 149 150 //! Whether to shuffle startup files (if any). 151 const bool _startup_shuffle; 152 153 //! Instance of mutation parameters for the app 154 /*! This used to be held by DialogMutationParameters, but now we want to share it around a bit 155 (although modifications should always be via the dialog slots, to keep the dialogs up to date) 156 */ 157 MutationParametersQObject _mutation_parameters; 158 159 //! Instance of render parameters for the app 160 RenderParameters _render_parameters; 161 162 //! Somewhere to report what's going on 163 QStatusBar* _statusbar; 164 165 //! Label for displaying number of tasks running (more permanent than StatusBar's message method). 166 QLabel* _statusbar_tasks_label; 167 168 //! Number of main tasks the statusbar is currently reporting as active 169 /*! Cached to avoid unnecessarily regenerating message 170 */ 171 uint _statusbar_tasks_main; 172 173 //! Number of enlargement tasks the statusbar is currently reporting as active 174 /*! Cached to avoid unnecessarily regenerating message 175 */ 176 uint _statusbar_tasks_enlargement; 177 178 //! The "About" dialog widget. 179 DialogAbout* _dialog_about; 180 181 //! The "Help" dialog widget (quick reference text) 182 DialogHelp* _dialog_help_short; 183 184 //! The "Help" dialog widget (full manual text) 185 DialogHelp* _dialog_help_long; 186 187 //! The dialog for adjusting MutationParameters. 188 DialogMutationParameters* _dialog_mutation_parameters; 189 190 //! The dialog for adjusting RenderParameters. 191 DialogRenderParameters* _dialog_render_parameters; 192 193 //! Dialog for controlling which functions are in use. 194 DialogFunctions* _dialog_functions; 195 196 //! Dialog for selecting a favourite function (also holds the state for favourite stuff) 197 DialogFavourite* _dialog_favourite; 198 199 //! The file menu. 200 QMenu* _popupmenu_file; 201 202 //! The edit menu. 203 QMenu* _popupmenu_edit; 204 205 //! ID for the undo item (so we can disable it). 206 QAction* _popupmenu_edit_undo_action; 207 208 //! The settings menu 209 QMenu* _popupmenu_settings; 210 211 //! Action for setting fullscreen 212 QAction* _menu_action_fullscreen; 213 214 //! Action for hiding menubar 215 QAction* _menu_action_hide_menu; 216 217 //! The help menu. 218 QMenu* _popupmenu_help; 219 220 //! Select autocooling (also serves to reset the generation count). 221 QCheckBox* _checkbox_autocool_enable; 222 223 //! Report number of generations. 224 QLabel* _label_autocool_enable; 225 226 //! Button to reheat 227 QPushButton* _button_autocool_reheat; 228 229 //! Grid for image display areas 230 QWidget* _grid; 231 232 //! Timer to drive tick() slot 233 QTimer* _timer; 234 235 //! Two farms of compute threads. One for the main display, one for enlargements. 236 std::unique_ptr<MutatableImageComputerFarm> _farm[2]; 237 238 //! All the displays in the grid. 239 std::vector<MutatableImageDisplay*> _displays; 240 241 //! Keeps track of which displays are still available for display (they might have been destroyed while an image was computing). 242 /*! Non-const because we might need to notify them about various things 243 */ 244 std::set<MutatableImageDisplay*> _known_displays; 245 246 //! Keeps track of which displays are still resizing 247 std::set<const MutatableImageDisplay*> _resizing; 248 249 //! The last image spawned (used to regenerate single displays). 250 boost::shared_ptr<const MutatableImage> _last_spawned_image; 251 252 //! Pointer to member function used for last spawn. 253 SpawnMemberFn _last_spawn_method; 254 255 //! An owned pointer to the current transform factory (needed for Respawn). 256 std::unique_ptr<TransformFactory> _transform_factory; 257 258 //! Accessor. last_spawned_image()259 const boost::shared_ptr<const MutatableImage> last_spawned_image() const 260 { 261 return _last_spawned_image; 262 } 263 264 //! Accessor. last_spawn_method()265 SpawnMemberFn last_spawn_method() const 266 { 267 return _last_spawn_method; 268 } 269 270 //! Not just an accessor. Takes ownership of a deepclone of the image 271 void last_spawned_image(const boost::shared_ptr<const MutatableImage>& image,SpawnMemberFn method); 272 273 //! Accessor transform_factory()274 const TransformFactory& transform_factory() const 275 { 276 // We shouldn't be here unless transform_factory has been set to something. 277 assert(_transform_factory.get()!=0); 278 279 return *_transform_factory; 280 } 281 282 //! Not just an accessor. Takes ownership of a deepclone of the argument. transform_factory(const TransformFactory & tfactory)283 void transform_factory(const TransformFactory& tfactory) 284 { 285 _transform_factory=tfactory.clone(); 286 } 287 288 //@{ 289 //! Perform a particular type of spawn from an individiual image to an individual display. (Locking not checked). 290 void spawn_normal(const boost::shared_ptr<const MutatableImage>& image,MutatableImageDisplay* display,bool one_of_many); 291 void spawn_recoloured(const boost::shared_ptr<const MutatableImage>& image,MutatableImageDisplay* display,bool one_of_many); 292 void spawn_warped(const boost::shared_ptr<const MutatableImage>& image,MutatableImageDisplay* display,bool one_of_many); 293 //@} 294 295 //! Spawn the specified display using the specified method. 296 void spawn_all(MutatableImageDisplay* display,SpawnMemberFn method,const std::string& action_name); 297 298 public: 299 //! Constructor. 300 EvolvotronMain 301 ( 302 QWidget* parent, 303 const QSize& grid_size, 304 uint frames, 305 uint framerate, 306 uint n_threads, 307 bool separate_farm_for_enlargements, 308 int niceness_grid, 309 int niceness_enlargements, 310 bool start_fullscreen, 311 bool start_menuhidden, 312 bool autocool, 313 bool jitter, 314 uint multisample_level, 315 bool function_debug_mode, 316 bool linear_zsweep, 317 bool spheremap, 318 const std::vector<std::string>& startup_filenames, 319 bool startup_shuffle 320 ); 321 322 //! Destructor. 323 ~EvolvotronMain(); 324 325 //! Accessor. Returns true if function name recognised. Forwards to DialogFavourite. 326 bool favourite_function(const std::string& f); 327 328 //! Accessor. Forwards to DialogFavourite. 329 void favourite_function_unwrapped(bool v); 330 331 //! Accessor. displays()332 std::vector<MutatableImageDisplay*>& displays() 333 { 334 return _displays; 335 } 336 337 //! Accessor. 338 /*! NB Only const version made available publicly as modifications should be through an appropriate dialog slot. 339 */ mutation_parameters()340 const MutationParameters& mutation_parameters() const 341 { 342 return _mutation_parameters; 343 } 344 345 //! Accessor. 346 /*! NB Only const version made available publicly as modifications should be through an appropriate dialog slot. 347 */ render_parameters()348 const RenderParameters& render_parameters() const 349 { 350 return _render_parameters; 351 } 352 353 //! Returns which farm to use for purpose. farm(bool enlargement)354 MutatableImageComputerFarm& farm(bool enlargement) 355 { 356 return *_farm[enlargement && _farm[1].get()]; 357 } 358 359 //! Accessor. history()360 History& history() 361 { 362 return *_history; 363 } 364 365 //! Called by History when performing undo. 366 void restore(MutatableImageDisplay* display,const boost::shared_ptr<const MutatableImage>&,bool one_of_many); 367 368 //! Called by History to change undo menu status. 369 void set_undoable(bool v,const std::string& name); 370 371 //! Regenerates a single display using last spawn method and source. 372 void respawn(MutatableImageDisplay* display); 373 374 //! Mutates the image held by the given display to all the other displays owned. 375 void spawn_normal(MutatableImageDisplay* spawning_display); 376 377 //! Similar to spawn except just changes the colouration of the image. 378 void spawn_recoloured(MutatableImageDisplay* spawning_display); 379 380 //! Similar to spawn except just changes the input co-ordinates to the image. 381 void spawn_warped(MutatableImageDisplay* spawning_display,const TransformFactory& tfactory); 382 383 //! Called from display constructor to indicate the display is available for the disposal of its completed tasks. 384 void hello(MutatableImageDisplay*); 385 386 //! Called from display destructor to indicate the display is no longer available for the disposal of its completed tasks. 387 void goodbye(MutatableImageDisplay*); 388 389 //! Returns true if the display is known. 390 bool is_known(MutatableImageDisplay* disp) const; 391 392 //! Write a list of known displays (for debugging) 393 void list_known(std::ostream& out) const; 394 395 protected: 396 //! Handle key-presses 397 void keyPressEvent(QKeyEvent* e); 398 399 //! Reset the specified display. 400 void reset(MutatableImageDisplay* display); 401 402 protected slots: 403 //! Signalled by timer. 404 void tick(); 405 406 //! Signalled by menu item. Forwards to History object. 407 void undo(); 408 409 //! Signalled by menu item. Simplifies all functions. 410 void simplify_constants(); 411 public slots: 412 413 //! Signalled by menu item. 414 void toggle_hide_menu(); 415 416 //! Signalled by menu item 417 void toggle_fullscreen(); 418 419 //! Signalled by menu item. Public because called from evolvotron app wrapper. 420 void reset(bool reset_mutation_parameters,bool reset_locks); 421 422 //! Forwards to reset(false) 423 void reset_warm(); 424 425 //! Forwards to reset(true) 426 void reset_cold(); 427 428 //! Resets and randomizes function weightings 429 void reset_randomized(); 430 431 //! So we can update any exposed mutation parameters (e.g autocool enable, generation count) 432 void mutation_parameters_changed(); 433 434 //! So we can re-render when render parameters change 435 void render_parameters_changed(); 436 }; 437 438 #endif 439 440