4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program 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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2008 Blender Foundation.
21 * All rights reserved.
24 * ***** END GPL LICENSE BLOCK *****
27 /** \file blender/editors/render/render_view.c
34 #include "MEM_guardedalloc.h"
36 #include "BLI_blenlib.h"
37 #include "BLI_utildefines.h"
39 #include "DNA_scene_types.h"
41 #include "BKE_blender.h"
42 #include "BKE_context.h"
43 #include "BKE_image.h"
44 #include "BKE_global.h"
47 #include "BKE_report.h"
48 #include "BKE_screen.h"
53 #include "ED_screen.h"
55 #include "wm_window.h"
57 #include "render_intern.h"
59 /*********************** utilities for finding areas *************************/
61 /* returns biggest area that is not uv/image editor. Note that it uses buttons */
62 /* window as the last possible alternative. */
63 static ScrArea *biggest_non_image_area(bContext *C)
65 bScreen *sc= CTX_wm_screen(C);
66 ScrArea *sa, *big= NULL;
67 int size, maxsize= 0, bwmaxsize= 0;
70 for(sa= sc->areabase.first; sa; sa= sa->next) {
71 if(sa->winx > 30 && sa->winy > 30) {
72 size= sa->winx*sa->winy;
73 if(sa->spacetype == SPACE_BUTS) {
74 if(foundwin == 0 && size > bwmaxsize) {
79 else if(sa->spacetype != SPACE_IMAGE && size > maxsize) {
90 static ScrArea *biggest_area(bContext *C)
92 bScreen *sc= CTX_wm_screen(C);
93 ScrArea *sa, *big= NULL;
96 for(sa= sc->areabase.first; sa; sa= sa->next) {
97 size= sa->winx*sa->winy;
106 static ScrArea *find_area_showing_r_result(bContext *C, wmWindow **win)
108 wmWindowManager *wm= CTX_wm_manager(C);
112 /* find an imagewindow showing render result */
113 for(*win=wm->windows.first; *win; *win= (*win)->next) {
114 for(sa= (*win)->screen->areabase.first; sa; sa= sa->next) {
115 if(sa->spacetype==SPACE_IMAGE) {
116 sima= sa->spacedata.first;
117 if(sima->image && sima->image->type==IMA_TYPE_R_RESULT)
128 static ScrArea *find_area_image_empty(bContext *C)
130 bScreen *sc= CTX_wm_screen(C);
134 /* find an imagewindow showing render result */
135 for(sa=sc->areabase.first; sa; sa= sa->next) {
136 if(sa->spacetype==SPACE_IMAGE) {
137 sima= sa->spacedata.first;
146 /********************** open image editor for render *************************/
148 /* new window uses x,y to set position */
149 void render_view_open(bContext *C, int mx, int my)
151 wmWindow *win= CTX_wm_window(C);
152 Scene *scene= CTX_data_scene(C);
155 int area_was_image=0;
157 if(scene->r.displaymode==R_OUTPUT_NONE)
160 if(scene->r.displaymode==R_OUTPUT_WINDOW) {
164 sizex= 10 + (scene->r.xsch*scene->r.size)/100;
165 sizey= 40 + (scene->r.ysch*scene->r.size)/100;
167 /* arbitrary... miniature image window views don't make much sense */
168 if(sizex < 320) sizex= 320;
169 if(sizey < 256) sizey= 256;
171 /* XXX some magic to calculate postition */
172 rect.xmin= mx + win->posx - sizex/2;
173 rect.ymin= my + win->posy - sizey/2;
174 rect.xmax= rect.xmin + sizex;
175 rect.ymax= rect.ymin + sizey;
177 /* changes context! */
178 WM_window_open_temp(C, &rect, WM_WINDOW_RENDER);
182 else if(scene->r.displaymode==R_OUTPUT_SCREEN) {
183 if (CTX_wm_area(C) && CTX_wm_area(C)->spacetype == SPACE_IMAGE)
186 /* this function returns with changed context */
187 ED_screen_full_newspace(C, CTX_wm_area(C), SPACE_IMAGE);
192 sa= find_area_showing_r_result(C, &win);
194 sa= find_area_image_empty(C);
196 /* if area found in other window, we make that one show in front */
197 if(win && win!=CTX_wm_window(C))
198 wm_window_raise(win);
201 /* find largest open non-image area */
202 sa= biggest_non_image_area(C);
204 ED_area_newspace(C, sa, SPACE_IMAGE);
205 sima= sa->spacedata.first;
207 /* makes ESC go back to prev space */
208 sima->flag |= SI_PREVSPACE;
211 /* use any area of decent size */
213 if(sa->spacetype!=SPACE_IMAGE) {
214 // XXX newspace(sa, SPACE_IMAGE);
215 sima= sa->spacedata.first;
217 /* makes ESC go back to prev space */
218 sima->flag |= SI_PREVSPACE;
223 sima= sa->spacedata.first;
225 /* get the correct image, and scale it */
226 sima->image= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
229 /* if we're rendering to full screen, set appropriate hints on image editor
230 * so it can restore properly on pressing esc */
232 sima->flag |= SI_FULLWINDOW;
234 /* Tell the image editor to revert to previous space in space list on close
235 * _only_ if it wasn't already an image editor when the render was invoked */
236 if (area_was_image == 0)
237 sima->flag |= SI_PREVSPACE;
239 /* Leave it alone so the image editor will just go back from
240 * full screen to the original tiled setup */
246 /*************************** cancel render viewer **********************/
248 static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op))
250 wmWindow *win= CTX_wm_window(C);
251 ScrArea *sa= CTX_wm_area(C);
252 SpaceImage *sima= sa->spacedata.first;
254 /* test if we have a temp screen in front */
255 if(CTX_wm_window(C)->screen->temp) {
256 wm_window_lower(CTX_wm_window(C));
257 return OPERATOR_FINISHED;
259 /* determine if render already shows */
260 else if(sima->flag & SI_PREVSPACE) {
261 sima->flag &= ~SI_PREVSPACE;
263 if(sima->flag & SI_FULLWINDOW) {
264 sima->flag &= ~SI_FULLWINDOW;
265 ED_screen_full_prevspace(C, sa);
268 ED_area_prevspace(C, sa);
270 return OPERATOR_FINISHED;
272 else if(sima->flag & SI_FULLWINDOW) {
273 sima->flag &= ~SI_FULLWINDOW;
274 ED_screen_full_toggle(C, win, sa);
275 return OPERATOR_FINISHED;
278 return OPERATOR_PASS_THROUGH;
281 void RENDER_OT_view_cancel(struct wmOperatorType *ot)
284 ot->name= "Cancel Render View";
285 ot->description= "Cancel show render view";
286 ot->idname= "RENDER_OT_view_cancel";
289 ot->exec= render_view_cancel_exec;
290 ot->poll= ED_operator_image_active;
293 /************************* show render viewer *****************/
295 static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
297 wmWindow *wincur = CTX_wm_window(C);
299 /* test if we have currently a temp screen active */
300 if(wincur->screen->temp) {
301 wm_window_lower(wincur);
304 wmWindow *win, *winshow;
305 ScrArea *sa= find_area_showing_r_result(C, &winshow);
307 /* is there another window showing result? */
308 for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) {
309 if(win->screen->temp || (win==winshow && winshow!=wincur)) {
310 wm_window_raise(win);
311 return OPERATOR_FINISHED;
315 /* determine if render already shows */
317 /* but don't close it when rendering */
319 SpaceImage *sima= sa->spacedata.first;
321 if(sima->flag & SI_PREVSPACE) {
322 sima->flag &= ~SI_PREVSPACE;
324 if(sima->flag & SI_FULLWINDOW) {
325 sima->flag &= ~SI_FULLWINDOW;
326 ED_screen_full_prevspace(C, sa);
328 else if(sima->next) {
329 /* workaround for case of double prevspace, render window
330 with a file browser on top of it (same as in ED_area_prevspace) */
331 if(sima->next->spacetype == SPACE_FILE && sima->next->next)
332 ED_area_newspace(C, sa, sima->next->next->spacetype);
334 ED_area_newspace(C, sa, sima->next->spacetype);
335 ED_area_tag_redraw(sa);
341 render_view_open(C, event->x, event->y);
345 return OPERATOR_FINISHED;
348 void RENDER_OT_view_show(struct wmOperatorType *ot)
351 ot->name= "Show/Hide Render View";
352 ot->description= "Toggle show render view";
353 ot->idname= "RENDER_OT_view_show";
356 ot->invoke= render_view_show_invoke;
357 ot->poll= ED_operator_screenactive;