2.5: Space Image ported back
[blender.git] / source / blender / editors / space_image / space_image.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
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. 
10  *
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.
15  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30 #include <stdio.h>
31
32 #include "DNA_image_types.h"
33 #include "DNA_mesh_types.h"
34 #include "DNA_meshdata_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_space_types.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_screen_types.h"
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_blenlib.h"
43 #include "BLI_arithb.h"
44 #include "BLI_editVert.h"
45 #include "BLI_rand.h"
46
47 #include "BKE_colortools.h"
48 #include "BKE_context.h"
49 #include "BKE_image.h"
50 #include "BKE_screen.h"
51 #include "BKE_utildefines.h"
52
53 #include "IMB_imbuf.h"
54 #include "IMB_imbuf_types.h"
55
56 #include "ED_mesh.h"
57 #include "ED_space_api.h"
58 #include "ED_screen.h"
59 #include "ED_uvedit.h"
60
61 #include "BIF_gl.h"
62 #include "BIF_glutil.h"
63
64 #include "RNA_access.h"
65
66 #include "WM_api.h"
67 #include "WM_types.h"
68
69 #include "UI_interface.h"
70 #include "UI_resources.h"
71 #include "UI_view2d.h"
72
73 #include "image_intern.h"
74
75 /* ******************** default callbacks for image space ***************** */
76
77 static SpaceLink *image_new(const bContext *C)
78 {
79         ARegion *ar;
80         SpaceImage *simage;
81         
82         simage= MEM_callocN(sizeof(SpaceImage), "initimage");
83         simage->spacetype= SPACE_IMAGE;
84         simage->zoom= 1;
85         
86         simage->iuser.ok= 1;
87         simage->iuser.fie_ima= 2;
88         simage->iuser.frames= 100;
89         
90         /* header */
91         ar= MEM_callocN(sizeof(ARegion), "header for image");
92         
93         BLI_addtail(&simage->regionbase, ar);
94         ar->regiontype= RGN_TYPE_HEADER;
95         ar->alignment= RGN_ALIGN_BOTTOM;
96         
97         /* main area */
98         ar= MEM_callocN(sizeof(ARegion), "main area for image");
99         
100         BLI_addtail(&simage->regionbase, ar);
101         ar->regiontype= RGN_TYPE_WINDOW;
102         
103         /* channel list region XXX */
104
105         
106         return (SpaceLink *)simage;
107 }
108
109 /* not spacelink itself */
110 static void image_free(SpaceLink *sl)
111 {       
112         SpaceImage *simage= (SpaceImage*) sl;
113         
114         if(simage->cumap)
115                 curvemapping_free(simage->cumap);
116 //      if(simage->gpd)
117 // XXX          free_gpencil_data(simage->gpd);
118         
119 }
120
121
122 /* spacetype; init callback */
123 static void image_init(struct wmWindowManager *wm, ScrArea *sa)
124 {
125
126 }
127
128 static SpaceLink *image_duplicate(SpaceLink *sl)
129 {
130         SpaceImage *simagen= MEM_dupallocN(sl);
131         
132         /* clear or remove stuff from old */
133         if(simagen->cumap)
134                 simagen->cumap= curvemapping_copy(simagen->cumap);
135         
136         return (SpaceLink *)simagen;
137 }
138
139 void image_operatortypes(void)
140 {
141         WM_operatortype_append(IMAGE_OT_view_all);
142         WM_operatortype_append(IMAGE_OT_view_pan);
143         WM_operatortype_append(IMAGE_OT_view_selected);
144         WM_operatortype_append(IMAGE_OT_view_zoom);
145         WM_operatortype_append(IMAGE_OT_view_zoom_in);
146         WM_operatortype_append(IMAGE_OT_view_zoom_out);
147         WM_operatortype_append(IMAGE_OT_view_zoom_ratio);
148 }
149
150 void image_keymap(struct wmWindowManager *wm)
151 {
152         ListBase *keymap= WM_keymap_listbase(wm, "Image", SPACE_IMAGE, 0);
153         
154         WM_keymap_add_item(keymap, "IMAGE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
155         WM_keymap_add_item(keymap, "IMAGE_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
156         WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
157
158         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
159         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0);
160         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
161         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", PADMINUS, KM_PRESS, 0, 0);
162         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
163
164         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 8.0f);
165         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 4.0f);
166         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD2, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 2.0f);
167         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD1, KM_PRESS, 0, 0)->ptr, "ratio", 1.0f);
168         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD2, KM_PRESS, 0, 0)->ptr, "ratio", 0.5f);
169         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, 0, 0)->ptr, "ratio", 0.25f);
170         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, 0, 0)->ptr, "ratio", 0.125f);
171 }
172
173 static void image_refresh(const bContext *C, ScrArea *sa)
174 {
175         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
176         Object *obedit= CTX_data_edit_object(C);
177         Image *ima;
178
179         ima= get_space_image(sima);
180
181         /* check if we have to set the image from the editmesh */
182         if(ima && (ima->source==IMA_SRC_VIEWER || sima->pin));
183         else if(obedit && obedit->type == OB_MESH) {
184                 Mesh *me= (Mesh*)obedit->data;
185                 EditMesh *em= me->edit_mesh;
186                 MTFace *tf;
187                 
188                 if(EM_texFaceCheck(em)) {
189                         sima->image= ima= NULL;
190                         
191                         tf = EM_get_active_mtface(em, NULL, NULL, 1); /* partially selected face is ok */
192                         
193                         if(tf && (tf->mode & TF_TEX)) {
194                                 /* don't need to check for pin here, see above */
195                                 sima->image= ima= tf->tpage;
196                                 
197                                 if(sima->flag & SI_EDITTILE);
198                                 else sima->curtile= tf->tile;
199                                 
200                                 if(ima) {
201                                         if(tf->mode & TF_TILES)
202                                                 ima->tpageflag |= IMA_TILES;
203                                         else
204                                                 ima->tpageflag &= ~IMA_TILES;
205                                 }
206                         }
207                 }
208         }
209 }
210
211 static void image_listener(ScrArea *sa, wmNotifier *wmn)
212 {
213         /* context changes */
214         switch(wmn->category) {
215                 case NC_SCENE:
216                         switch(wmn->data) {
217                                 case ND_MODE:
218                                         ED_area_tag_refresh(sa);
219                                         ED_area_tag_redraw(sa);
220                                         break;
221                         }
222                         break;
223         }
224 }
225
226 static int image_context(const bContext *C, const bContextDataMember *member, bContextDataResult *result)
227 {
228         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
229
230         if(member == CTX_data_edit_image) {
231                 CTX_data_pointer_set(result, get_space_image(sima));
232                 return 1;
233         }
234         else if(member == CTX_data_edit_image_buffer) {
235                 CTX_data_pointer_set(result, get_space_image_buffer(sima));
236                 return 1;
237         }
238
239         return 0;
240 }
241
242 /************************** main region ***************************/
243
244 /* sets up the fields of the View2D from zoom and offset */
245 static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar)
246 {
247         Image *ima= get_space_image(sima);
248         float x1, y1, w, h;
249         int width, height, winx, winy;
250         
251 #if 0
252         if(image_preview_active(curarea, &xim, &yim));
253         else if(sima->image) {
254                 ImBuf *ibuf= imagewindow_get_ibuf(sima);
255                 float xuser_asp, yuser_asp;
256                 
257                 image_pixel_aspect(sima->image, &xuser_asp, &yuser_asp);
258                 if(ibuf) {
259                         xim= ibuf->x * xuser_asp;
260                         yim= ibuf->y * yuser_asp;
261                 }
262                 else if( sima->image->type==IMA_TYPE_R_RESULT ) {
263                         /* not very important, just nice */
264                         xim= (G.scene->r.xsch*G.scene->r.size)/100;
265                         yim= (G.scene->r.ysch*G.scene->r.size)/100;
266                 }
267         }
268 #endif
269
270         get_space_image_size(sima, &width, &height);
271
272         w= width;
273         h= height;
274         
275         if(ima)
276                 h *= ima->aspy/ima->aspx;
277
278         winx= ar->winrct.xmax - ar->winrct.xmin + 1;
279         winy= ar->winrct.ymax - ar->winrct.ymin + 1;
280                 
281         ar->v2d.tot.xmin= 0;
282         ar->v2d.tot.ymin= 0;
283         ar->v2d.tot.xmax= w;
284         ar->v2d.tot.ymax= h;
285         
286         ar->v2d.mask.xmin= ar->v2d.mask.ymin= 0;
287         ar->v2d.mask.xmax= winx;
288         ar->v2d.mask.ymax= winy;
289
290         /* which part of the image space do we see? */
291         /* same calculation as in lrectwrite: area left and down*/
292         x1= ar->winrct.xmin+(winx-sima->zoom*w)/2;
293         y1= ar->winrct.ymin+(winy-sima->zoom*h)/2;
294
295         x1-= sima->zoom*sima->xof;
296         y1-= sima->zoom*sima->yof;
297         
298         /* relative display right */
299         ar->v2d.cur.xmin= ((ar->winrct.xmin - (float)x1)/sima->zoom);
300         ar->v2d.cur.xmax= ar->v2d.cur.xmin + ((float)winx/sima->zoom);
301         
302         /* relative display left */
303         ar->v2d.cur.ymin= ((ar->winrct.ymin-(float)y1)/sima->zoom);
304         ar->v2d.cur.ymax= ar->v2d.cur.ymin + ((float)winy/sima->zoom);
305         
306         /* normalize 0.0..1.0 */
307         ar->v2d.cur.xmin /= w;
308         ar->v2d.cur.xmax /= w;
309         ar->v2d.cur.ymin /= h;
310         ar->v2d.cur.ymax /= h;
311 }
312
313 /* add handlers, stuff you only do once or on area/region changes */
314 static void image_main_area_init(wmWindowManager *wm, ARegion *ar)
315 {
316         ListBase *keymap;
317         
318         // image space manages own v2d
319         // UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
320         
321         /* own keymap */
322         keymap= WM_keymap_listbase(wm, "Image", SPACE_IMAGE, 0);
323         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
324 }
325
326 static void image_main_area_draw(const bContext *C, ARegion *ar)
327 {
328         /* draw entirely, view changes should be handled here */
329         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
330         Object *obedit= CTX_data_edit_object(C);
331         Scene *scene= CTX_data_scene(C);
332         View2D *v2d= &ar->v2d;
333         //View2DScrollers *scrollers;
334         float col[3];
335         
336         /* clear and setup matrix */
337         UI_GetThemeColor3fv(TH_BACK, col);
338         glClearColor(col[0], col[1], col[2], 0.0);
339         glClear(GL_COLOR_BUFFER_BIT);
340         
341         /* we set view2d from own zoom and offset each time */
342         image_main_area_set_view2d(sima, ar);
343                 
344         /* we draw image in pixelspace */
345         draw_image_main(sima, ar, scene);
346
347         /* and uvs in 0.0-1.0 space */
348         UI_view2d_view_ortho(C, v2d);
349         draw_uvedit_main(sima, ar, scene, obedit);
350         UI_view2d_view_restore(C);
351         
352         /* scrollers? */
353         /*scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_UNIT_VALUES, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
354         UI_view2d_scrollers_draw(C, v2d, scrollers);
355         UI_view2d_scrollers_free(scrollers);*/
356 }
357
358 static void image_modal_keymaps(wmWindowManager *wm, ARegion *ar, int stype)
359 {
360         ListBase *keymap;
361         
362         keymap= WM_keymap_listbase(wm, "UVEdit", 0, 0);
363         if(stype==NS_EDITMODE_MESH)
364                 WM_event_add_keymap_handler(&ar->handlers, keymap);
365         else
366                 WM_event_remove_keymap_handler(&ar->handlers, keymap);
367 }
368
369 static void image_main_area_listener(ARegion *ar, wmNotifier *wmn)
370 {
371         /* context changes */
372         switch(wmn->category) {
373                 case NC_SCENE:
374                         switch(wmn->data) {
375                                 case ND_MODE:
376                                         image_modal_keymaps(wmn->wm, ar, wmn->subtype);
377                                         break;
378                         }
379                         break;
380                 case NC_OBJECT:
381                         switch(wmn->data) {
382                                 case ND_GEOM_SELECT:
383                                         ED_region_tag_redraw(ar);
384                                         break;
385                         }
386         }
387 }
388
389 /************************* header region **************************/
390
391 /* add handlers, stuff you only do once or on area/region changes */
392 static void image_header_area_init(wmWindowManager *wm, ARegion *ar)
393 {
394         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
395 }
396
397 static void image_header_area_draw(const bContext *C, ARegion *ar)
398 {
399         float col[3];
400         
401         /* clear */
402         if(ED_screen_area_active(C))
403                 UI_GetThemeColor3fv(TH_HEADER, col);
404         else
405                 UI_GetThemeColor3fv(TH_HEADERDESEL, col);
406         
407         glClearColor(col[0], col[1], col[2], 0.0);
408         glClear(GL_COLOR_BUFFER_BIT);
409         
410         /* set view2d view matrix for scrolling (without scrollers) */
411         UI_view2d_view_ortho(C, &ar->v2d);
412         
413         image_header_buttons(C, ar);
414         
415         /* restore view matrix? */
416         UI_view2d_view_restore(C);
417 }
418
419 /**************************** spacetype *****************************/
420
421 /* only called once, from space/spacetypes.c */
422 void ED_spacetype_image(void)
423 {
424         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype image");
425         ARegionType *art;
426         
427         st->spaceid= SPACE_IMAGE;
428         
429         st->new= image_new;
430         st->free= image_free;
431         st->init= image_init;
432         st->duplicate= image_duplicate;
433         st->operatortypes= image_operatortypes;
434         st->keymap= image_keymap;
435         st->refresh= image_refresh;
436         st->listener= image_listener;
437         st->context= image_context;
438         
439         /* regions: main window */
440         art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
441         art->regionid = RGN_TYPE_WINDOW;
442         art->init= image_main_area_init;
443         art->draw= image_main_area_draw;
444         art->listener= image_main_area_listener;
445         art->keymapflag= 0;
446
447         BLI_addhead(&st->regiontypes, art);
448         
449         /* regions: header */
450         art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
451         art->regionid = RGN_TYPE_HEADER;
452         art->minsizey= HEADERY;
453         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
454         
455         art->init= image_header_area_init;
456         art->draw= image_header_area_draw;
457         
458         BLI_addhead(&st->regiontypes, art);
459         
460         
461         BKE_spacetype_register(st);
462 }
463
464 /**************************** common state *****************************/
465
466 Image *get_space_image(SpaceImage *sima)
467 {
468         return sima->image;
469 }
470
471 /* called to assign images to UV faces */
472 void set_space_image(SpaceImage *sima, Scene *scene, Object *obedit, Image *ima)
473 {
474         ED_uvedit_assign_image(scene, obedit, ima, sima->image);
475
476         /* change the space ima after because uvedit_face_visible uses the space ima
477          * to check if the face is displayed in UV-localview */
478         sima->image= ima;
479
480         if(ima == NULL || ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
481                 sima->flag &= ~SI_DRAWTOOL;
482 }
483
484 ImBuf *get_space_image_buffer(SpaceImage *sima)
485 {
486         ImBuf *ibuf;
487
488         if(sima->image) {
489 #if 0
490                 if(sima->image->type==IMA_TYPE_R_RESULT && BIF_show_render_spare())
491                         return BIF_render_spare_imbuf();
492                 else
493 #endif
494                         ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
495
496                 if(ibuf->rect || ibuf->rect_float)
497                         return ibuf;
498         }
499
500         return NULL;
501 }
502
503 void get_space_image_size(SpaceImage *sima, int *width, int *height)
504 {
505         ImBuf *ibuf;
506
507         ibuf= get_space_image_buffer(sima);
508
509         if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
510                 *width= ibuf->x;
511                 *height= ibuf->y;
512         }
513         /* I know a bit weak... but preview uses not actual image size */
514         // XXX else if(image_preview_active(sima, width, height));
515         else {
516                 *width= 256;
517                 *height= 256;
518         }
519 }
520
521 void get_space_image_aspect(SpaceImage *sima, float *aspx, float *aspy)
522 {
523         Image *ima;
524
525         ima= get_space_image(sima);
526
527         *aspx= *aspy= 1.0;
528
529         if((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) ||
530            (ima->tpageflag & IMA_TILES) || (ima->aspx==0.0 || ima->aspy==0.0))
531                 return;
532
533         /* x is always 1 */
534         *aspy = ima->aspy/ima->aspx;
535 }
536
537 void get_space_image_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float *zoomy)
538 {
539         int width, height;
540
541         get_space_image_size(sima, &width, &height);
542
543         *zoomx= (float)(ar->winrct.xmax - ar->winrct.xmin)/(float)((ar->v2d.cur.xmax - ar->v2d.cur.xmin)*width);
544         *zoomy= (float)(ar->winrct.ymax - ar->winrct.ymin)/(float)((ar->v2d.cur.ymax - ar->v2d.cur.ymin)*height);
545 }
546
547 int get_space_image_show_render(SpaceImage *sima)
548 {
549         return (sima->image && ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE));
550 }
551
552 int get_space_image_show_paint(SpaceImage *sima)
553 {
554         if(get_space_image_show_render(sima))
555                 return 0;
556
557         return (sima->flag & SI_DRAWTOOL);
558 }
559
560 int get_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
561 {
562         if(get_space_image_show_render(sima))
563                 return 0;
564         if(get_space_image_show_paint(sima))
565                 return 0;
566
567         if(obedit && obedit->type == OB_MESH)
568                 return EM_texFaceCheck(((Mesh*)obedit->data)->edit_mesh);
569
570         return 0;
571 }
572
573 int get_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
574 {
575         if(get_space_image_show_render(sima))
576                 return 0;
577
578         if(get_space_image_show_paint(sima))
579                 if(obedit && obedit->type == OB_MESH)
580                         return EM_texFaceCheck(((Mesh*)obedit->data)->edit_mesh);
581
582         return 0;
583 }
584