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 MutatableImageDisplay
22 */
23 
24 #ifndef _mutatable_image_display_h_
25 #define _mutatable_image_display_h_
26 
27 #include "common.h"
28 
29 #include "mutatable_image.h"
30 #include "mutatable_image_computer.h"
31 #include "dialog_mutatable_image_display.h"
32 
33 class EvolvotronMain;
34 class MutatableImageComputerTask;
35 
36 //! Widget responsible for displaying a MutatableImage.
37 /*! A MutatableImageDisplay is responsible for displaying the image computed from the MutatableImage it owns.
38   Computations are split off into separate threads to take advantage of multiprocessor machines.
39  */
40 class MutatableImageDisplay : public QWidget
41 {
42   Q_OBJECT
43 
44  protected:
45   //! Pointer back to the application object to access services.
46   EvolvotronMain* _main;
47 
48   //! Flag for whether context menu should display all options.
49   /*! false also implies a standalone window
50    */
51   const bool _full_functionality;
52 
53   //! Flag for whether the offscreen buffer has fixed size
54   const bool _fixed_size;
55 
56   //! Size of offscreen buffer
57   QSize _image_size;
58 
59   //! Number of frames in image
60   uint _frames;
61 
62   //! Framerate for animation.
63   uint _framerate;
64 
65   //! Currently displaying frame.
66   uint _current_frame;
67 
68   //! Direction to play
69   bool _animate_reverse;
70 
71   //! Timer for animating frames
72   QTimer* _timer;
73 
74   //! Flag indicating resize is in progress (between resizeEvent and subsequent paintEvent).
75   /*! Used to supress unnecessary task spawning.
76    */
77   bool _resize_in_progress;
78 
79   //! The resolution level currently displaying (0=1-for-1 pixels, 1=half resolution etc).
80   /*! Needed to handle possible out of order task returns from multiple compute threads.
81    */
82   uint _current_display_level;
83 
84   //! Similar to _current_display_level, but for tracking multisample grids within a resolution level.
85   uint _current_display_multisample_grid;
86 
87   //! An image suitable for setting as an icon.
88   std::unique_ptr<QPixmap> _icon;
89 
90   //! Track which image the icon is actually of.
91   unsigned long long int _icon_serial;
92 
93   //! Offscreen image buffer.
94   std::vector<QPixmap> _offscreen_pixmaps;
95 
96   //! Offscreen image buffer in sensible image format (used for save, as pixmap is in display format which might be less bits).
97   std::vector<QImage> _offscreen_images;
98 
99   //! Type for staging area for incoming fragments.
100   /*! Key is level and multisampling, mapped type is also itself a map from fragment number to tasks.
101    */
102   typedef std::map<std::pair<uint,uint>,std::map<uint,boost::shared_ptr<const MutatableImageComputerTask> > > OffscreenImageInbox;
103 
104   //! Staging area for incoming fragments.
105   /*! Fragments are accumulated for each (level,multisample) key, and completed levels passed on for display
106    */
107   OffscreenImageInbox _offscreen_images_inbox;
108 
109   //! The image function being displayed (its root node).
110   /*! The held image is const because references to it could be held by history archive, compute tasks etc,
111     so it should be completely replaced rather than manipulated.
112    */
113   boost::shared_ptr<const MutatableImage> _image_function;
114 
115   //! Properties dialog.
116   DialogMutatableImageDisplay* _properties;
117 
118   //! Context (right-click) menu.
119   QMenu* _menu;
120 
121   //! Submenu for spawn warped options.
122   QMenu* _menu_warped;
123 
124   //! Submenu for Big image options.
125   QMenu* _menu_big;
126 
127   //! Position of item in menu.
128   /*! This is the only menu item we need to retain this information for becuase we need it to set the lock check-mark.
129    */
130   QAction* _menu_item_action_lock;
131 
132   //! Coordinate of mouse event which started mid-button adjustment
133   QPoint _mid_button_adjust_start_pos;
134 
135   //! Coordinate of last mouse event when mid-button adjusting
136   QPoint _mid_button_adjust_last_pos;
137 
138   //! Serial number to kill some rare problems with out-of-order tasks being returned
139   unsigned long long int _serial;
140 
141  public:
142   //! Constructor.
143   MutatableImageDisplay(EvolvotronMain* mn,bool full_functionality,bool fixed_size,const QSize& image_size,uint f,uint fr);
144 
145   //! Destructor.
146   virtual ~MutatableImageDisplay();
147 
148   //! Accessor.
image_function()149   const boost::shared_ptr<const MutatableImage>& image_function()
150     {
151       return _image_function;
152     }
153 
154   //! Accessor.
locked()155   bool locked() const
156     {
157       return (_image_function.get()!=0 ? _image_function->locked() : false);
158     }
159 
160   //! Accessor.
main()161   EvolvotronMain& main() const
162     {
163       assert(_main!=0);
164       return *_main;
165     }
166 
167   //! Accessor.
main(EvolvotronMain * m)168   void main(EvolvotronMain* m)
169     {
170       _main=m;
171     }
172 
173   //! Accessor.
image_size()174   const QSize& image_size() const
175     {
176       return _image_size;
177     }
178 
179   //! Load a new image (clears up old image, starts new compute tasks).
180   /*! When the one_of_many parameter is true, it implies many other images are also being updated
181     (affects fragmentation strategy for multithreading).
182    */
183   void image_function(const boost::shared_ptr<const MutatableImage>& image_fn,bool one_of_many);
184 
185   //! Evolvotron main calls this with completed (but possibly aborted) tasks.
186   void deliver(const boost::shared_ptr<const MutatableImageComputerTask>& task);
187 
188   //! Set the lock state.
189   void lock(bool l,bool record_in_history);
190 
191  protected:
192 
193   //! Which farm this display should use.
194   MutatableImageComputerFarm& farm() const;
195 
196   //! Usual handler for repaint events.
197   virtual void paintEvent(QPaintEvent* event);
198 
199   //! Usual handler for resize events.
200   virtual void resizeEvent(QResizeEvent* event);
201 
202   //! Handler for mouse events.
203   virtual void mousePressEvent(QMouseEvent* event);
204 
205   //! Handler for mouse events.
206   virtual void mouseMoveEvent(QMouseEvent* event);
207 
208   public slots:
209 
210   //! Simplify the held image, return the number of nodes eliminated
211   uint simplify_constants(bool single);
212 
213   //! Load a function from the given filename.
214   void load_function_file(const QString&);
215 
216   protected slots:
217 
218   //! Called by timer
219   void frame_advance();
220 
221   //! Called from context menu.
222   void menupick_respawn();
223 
224   //! Called from context menu and also by click event.
225   void menupick_spawn();
226 
227   //! Called from context menu.
228   void menupick_spawn_recoloured();
229 
230   //! Called from context menu.
231   void menupick_spawn_warped_random();
232 
233   //! Called from context menu.
234   void menupick_spawn_warped_zoom_in();
235 
236   //! Called from context menu.
237   void menupick_spawn_warped_zoom_out();
238 
239   //! Called from context menu.
240   void menupick_spawn_warped_rotate();
241 
242   //! Called from context menu.
243   void menupick_spawn_warped_pan_xy();
244 
245   //! Called from context menu.
246   void menupick_spawn_warped_pan_x();
247 
248   //! Called from context menu.
249   void menupick_spawn_warped_pan_y();
250 
251   //! Called from context menu.
252   void menupick_spawn_warped_pan_z();
253 
254   //! Called from context menu.
255   void menupick_lock();
256 
257   //! Trivial wrapper for simplify_constants
258   void menupick_simplify();
259 
260   //! Called from context menu.
261   void menupick_save_image();
262 
263   //! Called from context menu.
264   void menupick_save_function();
265 
266   //! Called from context menu.
267   void menupick_load_function();
268 
269   //! Called from "Big" submenu of context menu.
270   void menupick_big_resizable();
271 
272   //! Called from "Big" submenu of context menu.
273   void menupick_big_256x256();
274 
275   //! Called from "Big" submenu of context menu.
276   void menupick_big_512x512();
277 
278   //! Called from "Big" submenu of context menu.
279   void menupick_big_768x768();
280 
281   //! Called from "Big" submenu of context menu.
282   void menupick_big_1024x1024();
283 
284   //! Called from "Big" submenu of context menu.
285   void menupick_big_640x480();
286 
287   //! Called from "Big" submenu of context menu.
288   void menupick_big_1024x768();
289 
290   //! Called from "Big" submenu of context menu.
291   void menupick_big_1280x960();
292 
293   //! Called from "Big" submenu of context menu.
294   void menupick_big_1600x1200();
295 
296   //! Called from "Big" submenu of context menu.
297   void menupick_big_2048x2048();
298 
299   //! Called from "Big" submenu of context menu.
300   void menupick_big_4096x4096();
301 
302   //! Called from "Properties" on context menu
303   void menupick_properties();
304 
305  protected:
306   //! Common code for big slots.
307   void spawn_big(bool scrollable,const QSize& sz);
308 };
309 
310 #endif
311