Blender  V2.59
space_image.c
Go to the documentation of this file.
00001 /*
00002  * $Id: space_image.c 38908 2011-08-02 04:28:05Z merwin $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2008 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * 
00024  * Contributor(s): Blender Foundation
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <string.h>
00035 #include <stdio.h>
00036 
00037 #include "DNA_meshdata_types.h"
00038 #include "DNA_object_types.h"
00039 #include "DNA_scene_types.h"
00040 
00041 #include "MEM_guardedalloc.h"
00042 
00043 #include "BLI_blenlib.h"
00044 #include "BLI_math.h"
00045 #include "BLI_editVert.h"
00046 #include "BLI_rand.h"
00047 #include "BLI_utildefines.h"
00048 
00049 #include "BKE_colortools.h"
00050 #include "BKE_context.h"
00051 #include "BKE_image.h"
00052 #include "BKE_mesh.h"
00053 #include "BKE_screen.h"
00054 
00055 #include "IMB_imbuf_types.h"
00056 
00057 #include "ED_image.h"
00058 #include "ED_mesh.h"
00059 #include "ED_space_api.h"
00060 #include "ED_screen.h"
00061 #include "ED_uvedit.h"
00062 
00063 #include "BIF_gl.h"
00064 
00065 #include "RNA_access.h"
00066 
00067 #include "WM_api.h"
00068 #include "WM_types.h"
00069 
00070 #include "UI_resources.h"
00071 #include "UI_view2d.h"
00072 
00073 #include "image_intern.h"
00074 
00075 /**************************** common state *****************************/
00076 
00077 /* note; image_panel_properties() uses pointer to sima->image directly */
00078 Image *ED_space_image(SpaceImage *sima)
00079 {
00080         return sima->image;
00081 }
00082 
00083 /* called to assign images to UV faces */
00084 void ED_space_image_set(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, Image *ima)
00085 {
00086         ED_uvedit_assign_image(scene, obedit, ima, sima->image);
00087         
00088         /* change the space ima after because uvedit_face_visible uses the space ima
00089          * to check if the face is displayed in UV-localview */
00090         sima->image= ima;
00091         
00092         if(ima == NULL || ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
00093                 sima->flag &= ~SI_DRAWTOOL;
00094         
00095         if(sima->image)
00096                 BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
00097         
00098         if(sima->image && sima->image->id.us==0)
00099                 sima->image->id.us= 1;
00100         
00101         if(C) {
00102                 if(obedit)
00103                         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
00104                 
00105                 ED_area_tag_redraw(CTX_wm_area(C));
00106                 
00107         }
00108 }
00109 
00110 ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r)
00111 {
00112         ImBuf *ibuf;
00113         
00114         if(sima && sima->image) {
00115 #if 0
00116                 if(sima->image->type==IMA_TYPE_R_RESULT && BIF_show_render_spare())
00117                         return BIF_render_spare_imbuf();
00118                 else
00119 #endif
00120                         ibuf= BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r);
00121                 
00122                 if(ibuf && (ibuf->rect || ibuf->rect_float))
00123                         return ibuf;
00124         }
00125         
00126         return NULL;
00127 }
00128 
00129 void ED_space_image_release_buffer(SpaceImage *sima, void *lock)
00130 {
00131         if(sima && sima->image)
00132                 BKE_image_release_ibuf(sima->image, lock);
00133 }
00134 
00135 int ED_space_image_has_buffer(SpaceImage *sima)
00136 {
00137         ImBuf *ibuf;
00138         void *lock;
00139         int has_buffer;
00140         
00141         ibuf= ED_space_image_acquire_buffer(sima, &lock);
00142         has_buffer= (ibuf != NULL);
00143         ED_space_image_release_buffer(sima, lock);
00144         
00145         return has_buffer;
00146 }
00147 
00148 void ED_image_size(Image *ima, int *width, int *height)
00149 {
00150         ImBuf *ibuf= NULL;
00151         void *lock;
00152         
00153         if(ima)
00154                 ibuf= BKE_image_acquire_ibuf(ima, NULL, &lock);
00155         
00156         if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
00157                 *width= ibuf->x;
00158                 *height= ibuf->y;
00159         }
00160         else {
00161                 *width= 256;
00162                 *height= 256;
00163         }
00164         
00165         if(ima)
00166                 BKE_image_release_ibuf(ima, lock);
00167 }
00168 
00169 void ED_space_image_size(SpaceImage *sima, int *width, int *height)
00170 {
00171         Scene *scene= sima->iuser.scene;
00172         ImBuf *ibuf;
00173         void *lock;
00174         
00175         ibuf= ED_space_image_acquire_buffer(sima, &lock);
00176         
00177         if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
00178                 *width= ibuf->x;
00179                 *height= ibuf->y;
00180         }
00181         else if(sima->image && sima->image->type==IMA_TYPE_R_RESULT && scene) {
00182                 /* not very important, just nice */
00183                 *width= (scene->r.xsch*scene->r.size)/100;
00184                 *height= (scene->r.ysch*scene->r.size)/100;
00185 
00186                 if((scene->r.mode & R_BORDER) && (scene->r.mode & R_CROP)) {
00187                         *width *= (scene->r.border.xmax - scene->r.border.xmin);
00188                         *height *= (scene->r.border.ymax - scene->r.border.ymin);
00189                 }
00190 
00191         }
00192         /* I know a bit weak... but preview uses not actual image size */
00193         // XXX else if(image_preview_active(sima, width, height));
00194         else {
00195                 *width= 256;
00196                 *height= 256;
00197         }
00198         
00199         ED_space_image_release_buffer(sima, lock);
00200 }
00201 
00202 void ED_image_aspect(Image *ima, float *aspx, float *aspy)
00203 {
00204         *aspx= *aspy= 1.0;
00205         
00206         if((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) ||
00207            (ima->aspx==0.0f || ima->aspy==0.0f))
00208                 return;
00209         
00210         /* x is always 1 */
00211         *aspy = ima->aspy/ima->aspx;
00212 }
00213 
00214 void ED_space_image_aspect(SpaceImage *sima, float *aspx, float *aspy)
00215 {
00216         ED_image_aspect(ED_space_image(sima), aspx, aspy);
00217 }
00218 
00219 void ED_space_image_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float *zoomy)
00220 {
00221         int width, height;
00222         
00223         ED_space_image_size(sima, &width, &height);
00224         
00225         *zoomx= (float)(ar->winrct.xmax - ar->winrct.xmin + 1)/(float)((ar->v2d.cur.xmax - ar->v2d.cur.xmin)*width);
00226         *zoomy= (float)(ar->winrct.ymax - ar->winrct.ymin + 1)/(float)((ar->v2d.cur.ymax - ar->v2d.cur.ymin)*height);
00227 }
00228 
00229 void ED_space_image_uv_aspect(SpaceImage *sima, float *aspx, float *aspy)
00230 {
00231         int w, h;
00232         
00233         ED_space_image_aspect(sima, aspx, aspy);
00234         ED_space_image_size(sima, &w, &h);
00235 
00236         *aspx *= (float)w;
00237         *aspy *= (float)h;
00238         
00239         if(*aspx < *aspy) {
00240                 *aspy= *aspy / *aspx;
00241                 *aspx= 1.0f;
00242         }
00243         else {
00244                 *aspx= *aspx / *aspy;
00245                 *aspy= 1.0f;            
00246         }
00247 }
00248 
00249 void ED_image_uv_aspect(Image *ima, float *aspx, float *aspy)
00250 {
00251         int w, h;
00252         
00253         ED_image_aspect(ima, aspx, aspy);
00254         ED_image_size(ima, &w, &h);
00255         
00256         *aspx *= (float)w;
00257         *aspy *= (float)h;
00258 }
00259 
00260 int ED_space_image_show_render(SpaceImage *sima)
00261 {
00262         return (sima->image && ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE));
00263 }
00264 
00265 int ED_space_image_show_paint(SpaceImage *sima)
00266 {
00267         if(ED_space_image_show_render(sima))
00268                 return 0;
00269         
00270         return (sima->flag & SI_DRAWTOOL);
00271 }
00272 
00273 int ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
00274 {
00275         if(sima && (ED_space_image_show_render(sima) || ED_space_image_show_paint(sima)))
00276                 return 0;
00277 
00278         if(obedit && obedit->type == OB_MESH) {
00279                 EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
00280                 int ret;
00281                 
00282                 ret = EM_texFaceCheck(em);
00283                 
00284                 BKE_mesh_end_editmesh(obedit->data, em);
00285                 return ret;
00286         }
00287         
00288         return 0;
00289 }
00290 
00291 int ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
00292 {
00293         if(ED_space_image_show_render(sima))
00294                 return 0;
00295         
00296         if(ED_space_image_show_paint(sima))
00297                 if(obedit && obedit->type == OB_MESH) {
00298                         EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
00299                         int ret;
00300                         
00301                         ret = EM_texFaceCheck(em);
00302                         
00303                         BKE_mesh_end_editmesh(obedit->data, em);
00304                         return ret;
00305                 }
00306         
00307         return 0;
00308 }
00309 
00310 
00311 static void image_scopes_tag_refresh(ScrArea *sa)
00312 {
00313         SpaceImage *sima= (SpaceImage *)sa->spacedata.first;
00314         ARegion *ar;
00315 
00316         /* only while histogram is visible */
00317         for (ar=sa->regionbase.first; ar; ar=ar->next) {
00318                 if (ar->regiontype == RGN_TYPE_PREVIEW && ar->flag & RGN_FLAG_HIDDEN)
00319                         return;
00320         }
00321 
00322         sima->scopes.ok=0;
00323 }
00324 
00325 
00326 /* ******************** manage regions ********************* */
00327 
00328 ARegion *image_has_buttons_region(ScrArea *sa)
00329 {
00330         ARegion *ar, *arnew;
00331 
00332         ar= BKE_area_find_region_type(sa, RGN_TYPE_UI);
00333         if(ar) return ar;
00334         
00335         /* add subdiv level; after header */
00336         ar= BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
00337 
00338         /* is error! */
00339         if(ar==NULL) return NULL;
00340         
00341         arnew= MEM_callocN(sizeof(ARegion), "buttons for image");
00342         
00343         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
00344         arnew->regiontype= RGN_TYPE_UI;
00345         arnew->alignment= RGN_ALIGN_LEFT;
00346         
00347         arnew->flag = RGN_FLAG_HIDDEN;
00348         
00349         return arnew;
00350 }
00351 
00352 ARegion *image_has_scope_region(ScrArea *sa)
00353 {
00354         ARegion *ar, *arnew;
00355 
00356         ar= BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
00357         if(ar) return ar;
00358 
00359         /* add subdiv level; after buttons */
00360         ar= BKE_area_find_region_type(sa, RGN_TYPE_UI);
00361 
00362         /* is error! */
00363         if(ar==NULL) return NULL;
00364         
00365         arnew= MEM_callocN(sizeof(ARegion), "scopes for image");
00366         
00367         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
00368         arnew->regiontype= RGN_TYPE_PREVIEW;
00369         arnew->alignment= RGN_ALIGN_RIGHT;
00370         
00371         arnew->flag = RGN_FLAG_HIDDEN;
00372 
00373         image_scopes_tag_refresh(sa);
00374         
00375         return arnew;
00376 }
00377 
00378 /* ******************** default callbacks for image space ***************** */
00379 
00380 static SpaceLink *image_new(const bContext *UNUSED(C))
00381 {
00382         ARegion *ar;
00383         SpaceImage *simage;
00384         
00385         simage= MEM_callocN(sizeof(SpaceImage), "initimage");
00386         simage->spacetype= SPACE_IMAGE;
00387         simage->zoom= 1;
00388         simage->lock= 1;
00389         
00390         simage->iuser.ok= 1;
00391         simage->iuser.fie_ima= 2;
00392         simage->iuser.frames= 100;
00393         
00394         scopes_new(&simage->scopes);
00395         simage->sample_line_hist.height= 100;
00396 
00397         /* header */
00398         ar= MEM_callocN(sizeof(ARegion), "header for image");
00399         
00400         BLI_addtail(&simage->regionbase, ar);
00401         ar->regiontype= RGN_TYPE_HEADER;
00402         ar->alignment= RGN_ALIGN_BOTTOM;
00403         
00404         /* buttons/list view */
00405         ar= MEM_callocN(sizeof(ARegion), "buttons for image");
00406         
00407         BLI_addtail(&simage->regionbase, ar);
00408         ar->regiontype= RGN_TYPE_UI;
00409         ar->alignment= RGN_ALIGN_LEFT;
00410         ar->flag = RGN_FLAG_HIDDEN;
00411         
00412         /* scopes */
00413         ar= MEM_callocN(sizeof(ARegion), "buttons for image");
00414         
00415         BLI_addtail(&simage->regionbase, ar);
00416         ar->regiontype= RGN_TYPE_PREVIEW;
00417         ar->alignment= RGN_ALIGN_RIGHT;
00418         ar->flag = RGN_FLAG_HIDDEN;
00419 
00420         /* main area */
00421         ar= MEM_callocN(sizeof(ARegion), "main area for image");
00422         
00423         BLI_addtail(&simage->regionbase, ar);
00424         ar->regiontype= RGN_TYPE_WINDOW;
00425         
00426         return (SpaceLink *)simage;
00427 }
00428 
00429 /* not spacelink itself */
00430 static void image_free(SpaceLink *sl)
00431 {       
00432         SpaceImage *simage= (SpaceImage*) sl;
00433         
00434         if(simage->cumap)
00435                 curvemapping_free(simage->cumap);
00436         scopes_free(&simage->scopes);
00437 }
00438 
00439 
00440 /* spacetype; init callback, add handlers */
00441 static void image_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
00442 {
00443         ListBase *lb= WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
00444 
00445         /* add drop boxes */
00446         WM_event_add_dropbox_handler(&sa->handlers, lb);
00447         
00448 }
00449 
00450 static SpaceLink *image_duplicate(SpaceLink *sl)
00451 {
00452         SpaceImage *simagen= MEM_dupallocN(sl);
00453         
00454         /* clear or remove stuff from old */
00455         if(simagen->cumap)
00456                 simagen->cumap= curvemapping_copy(simagen->cumap);
00457 
00458         scopes_new(&simagen->scopes);
00459 
00460         return (SpaceLink *)simagen;
00461 }
00462 
00463 static void image_operatortypes(void)
00464 {
00465         WM_operatortype_append(IMAGE_OT_view_all);
00466         WM_operatortype_append(IMAGE_OT_view_pan);
00467         WM_operatortype_append(IMAGE_OT_view_selected);
00468         WM_operatortype_append(IMAGE_OT_view_zoom);
00469         WM_operatortype_append(IMAGE_OT_view_zoom_in);
00470         WM_operatortype_append(IMAGE_OT_view_zoom_out);
00471         WM_operatortype_append(IMAGE_OT_view_zoom_ratio);
00472         WM_operatortype_append(IMAGE_OT_view_ndof);
00473 
00474         WM_operatortype_append(IMAGE_OT_new);
00475         WM_operatortype_append(IMAGE_OT_open);
00476         WM_operatortype_append(IMAGE_OT_replace);
00477         WM_operatortype_append(IMAGE_OT_reload);
00478         WM_operatortype_append(IMAGE_OT_save);
00479         WM_operatortype_append(IMAGE_OT_save_as);
00480         WM_operatortype_append(IMAGE_OT_save_sequence);
00481         WM_operatortype_append(IMAGE_OT_pack);
00482         WM_operatortype_append(IMAGE_OT_unpack);
00483         
00484         WM_operatortype_append(IMAGE_OT_invert);
00485 
00486         WM_operatortype_append(IMAGE_OT_cycle_render_slot);
00487 
00488         WM_operatortype_append(IMAGE_OT_sample);
00489         WM_operatortype_append(IMAGE_OT_sample_line);
00490         WM_operatortype_append(IMAGE_OT_curves_point_set);
00491 
00492         WM_operatortype_append(IMAGE_OT_record_composite);
00493 
00494         WM_operatortype_append(IMAGE_OT_properties);
00495         WM_operatortype_append(IMAGE_OT_scopes);
00496 }
00497 
00498 static void image_keymap(struct wmKeyConfig *keyconf)
00499 {
00500         wmKeyMap *keymap= WM_keymap_find(keyconf, "Image Generic", SPACE_IMAGE, 0);
00501         wmKeyMapItem *kmi;
00502         
00503         WM_keymap_add_item(keymap, "IMAGE_OT_new", NKEY, KM_PRESS, KM_ALT, 0);
00504         WM_keymap_add_item(keymap, "IMAGE_OT_open", OKEY, KM_PRESS, KM_ALT, 0);
00505         WM_keymap_add_item(keymap, "IMAGE_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
00506         WM_keymap_add_item(keymap, "IMAGE_OT_save", SKEY, KM_PRESS, KM_ALT, 0);
00507         WM_keymap_add_item(keymap, "IMAGE_OT_save_as", F3KEY, KM_PRESS, 0, 0);
00508         WM_keymap_add_item(keymap, "IMAGE_OT_properties", NKEY, KM_PRESS, 0, 0);
00509         WM_keymap_add_item(keymap, "IMAGE_OT_scopes", TKEY, KM_PRESS, 0, 0);
00510 
00511         WM_keymap_add_item(keymap, "IMAGE_OT_cycle_render_slot", JKEY, KM_PRESS, 0, 0);
00512         RNA_boolean_set(WM_keymap_add_item(keymap, "IMAGE_OT_cycle_render_slot", JKEY, KM_PRESS, KM_ALT, 0)->ptr, "reverse", TRUE);
00513         
00514         keymap= WM_keymap_find(keyconf, "Image", SPACE_IMAGE, 0);
00515         
00516         WM_keymap_add_item(keymap, "IMAGE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
00517         WM_keymap_add_item(keymap, "IMAGE_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
00518         WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
00519         WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
00520         WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MOUSEPAN, 0, 0, 0);
00521 
00522         WM_keymap_add_item(keymap, "IMAGE_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); // or view selected?
00523         WM_keymap_add_item(keymap, "IMAGE_OT_view_ndof", NDOF_MOTION, 0, 0, 0);
00524 
00525         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
00526         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0);
00527         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
00528         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", PADMINUS, KM_PRESS, 0, 0);
00529         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
00530         WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MOUSEZOOM, 0, 0, 0);
00531 
00532         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 8.0f);
00533         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 4.0f);
00534         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD2, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 2.0f);
00535         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD1, KM_PRESS, 0, 0)->ptr, "ratio", 1.0f);
00536         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD2, KM_PRESS, 0, 0)->ptr, "ratio", 0.5f);
00537         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, 0, 0)->ptr, "ratio", 0.25f);
00538         RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, 0, 0)->ptr, "ratio", 0.125f);
00539 
00540         WM_keymap_add_item(keymap, "IMAGE_OT_sample", ACTIONMOUSE, KM_PRESS, 0, 0);
00541         RNA_enum_set(WM_keymap_add_item(keymap, "IMAGE_OT_curves_point_set", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "point", 0);
00542         RNA_enum_set(WM_keymap_add_item(keymap, "IMAGE_OT_curves_point_set", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "point", 1);
00543 
00544         /* toggle editmode is handy to have while UV unwrapping */
00545         kmi= WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_PRESS, 0, 0);
00546         RNA_enum_set(kmi->ptr, "mode", OB_MODE_EDIT);
00547         RNA_boolean_set(kmi->ptr, "toggle", 1);
00548 }
00549 
00550 /* dropboxes */
00551 static int image_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
00552 {
00553         if(drag->type==WM_DRAG_PATH)
00554                 if(ELEM3(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK))      /* rule might not work? */
00555                         return 1;
00556         return 0;
00557 }
00558 
00559 static void image_drop_copy(wmDrag *drag, wmDropBox *drop)
00560 {
00561         /* copy drag path to properties */
00562         RNA_string_set(drop->ptr, "filepath", drag->path);
00563 }
00564 
00565 /* area+region dropbox definition */
00566 static void image_dropboxes(void)
00567 {
00568         ListBase *lb= WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
00569         
00570         WM_dropbox_add(lb, "IMAGE_OT_open", image_drop_poll, image_drop_copy);
00571 }
00572 
00573 
00574 
00575 static void image_refresh(const bContext *C, ScrArea *UNUSED(sa))
00576 {
00577         SpaceImage *sima= CTX_wm_space_image(C);
00578         Object *obedit= CTX_data_edit_object(C);
00579         Image *ima;
00580 
00581         ima= ED_space_image(sima);
00582 
00583         if(sima->iuser.flag & IMA_ANIM_ALWAYS)
00584                 BKE_image_user_calc_frame(&sima->iuser, CTX_data_scene(C)->r.cfra, 0);
00585         
00586         /* check if we have to set the image from the editmesh */
00587         if(ima && (ima->source==IMA_SRC_VIEWER || sima->pin));
00588         else if(obedit && obedit->type == OB_MESH) {
00589                 Mesh *me= (Mesh*)obedit->data;
00590                 EditMesh *em= BKE_mesh_get_editmesh(me);
00591                 MTFace *tf;
00592                 
00593                 if(em && EM_texFaceCheck(em)) {
00594                         sima->image= NULL;
00595                         
00596                         tf = EM_get_active_mtface(em, NULL, NULL, 1); /* partially selected face is ok */
00597                         
00598                         if(tf && (tf->mode & TF_TEX)) {
00599                                 /* don't need to check for pin here, see above */
00600                                 sima->image= tf->tpage;
00601                                 
00602                                 if(sima->flag & SI_EDITTILE);
00603                                 else sima->curtile= tf->tile;
00604                         }
00605                 }
00606 
00607                 BKE_mesh_end_editmesh(obedit->data, em);
00608         }
00609 }
00610 
00611 static void image_listener(ScrArea *sa, wmNotifier *wmn)
00612 {
00613         SpaceImage *sima= (SpaceImage *)sa->spacedata.first;
00614         
00615         /* context changes */
00616         switch(wmn->category) {
00617                 case NC_SCENE:
00618                         switch(wmn->data) {
00619                                 case ND_FRAME:
00620                                         image_scopes_tag_refresh(sa);
00621                                         ED_area_tag_refresh(sa);
00622                                         ED_area_tag_redraw(sa);                                 
00623                                         break;
00624                                 case ND_MODE:
00625                                 case ND_RENDER_RESULT:
00626                                 case ND_COMPO_RESULT:
00627                                         if (ED_space_image_show_render(sima))
00628                                                 image_scopes_tag_refresh(sa);
00629                                         ED_area_tag_refresh(sa);
00630                                         ED_area_tag_redraw(sa);                                 
00631                                         break;
00632                         }
00633                         break;
00634                 case NC_IMAGE:
00635                         if (wmn->reference == sima->image || !wmn->reference) {
00636                                 image_scopes_tag_refresh(sa);
00637                                 ED_area_tag_refresh(sa);
00638                                 ED_area_tag_redraw(sa);
00639                         }
00640                         break;
00641                 case NC_SPACE:  
00642                         if(wmn->data == ND_SPACE_IMAGE) {
00643                                 image_scopes_tag_refresh(sa);
00644                                 ED_area_tag_redraw(sa);
00645                         }
00646                         break;
00647                 case NC_GEOM:
00648                         switch(wmn->data) {
00649                                 case ND_DATA:
00650                                 case ND_SELECT:
00651                                         image_scopes_tag_refresh(sa);
00652                                         ED_area_tag_refresh(sa);
00653                                         ED_area_tag_redraw(sa);
00654                                         break;
00655                         }
00656                 case NC_OBJECT:
00657                 {
00658                         Object *ob= (Object *)wmn->reference;
00659                         switch(wmn->data) {
00660                                 case ND_TRANSFORM:
00661                                 case ND_MODIFIER:
00662                                         if(ob && (ob->mode & OB_MODE_EDIT) && sima->lock && (sima->flag & SI_DRAWSHADOW)) {
00663                                                 ED_area_tag_refresh(sa);
00664                                                 ED_area_tag_redraw(sa);
00665                                         }
00666                                         break;
00667                         }
00668                 }
00669         }
00670 }
00671 
00672 const char *image_context_dir[] = {"edit_image", NULL};
00673 
00674 static int image_context(const bContext *C, const char *member, bContextDataResult *result)
00675 {
00676         SpaceImage *sima= CTX_wm_space_image(C);
00677 
00678         if(CTX_data_dir(member)) {
00679                 CTX_data_dir_set(result, image_context_dir);
00680         }
00681         else if(CTX_data_equals(member, "edit_image")) {
00682                 CTX_data_id_pointer_set(result, (ID*)ED_space_image(sima));
00683                 return 1;
00684         }
00685 
00686         return 0;
00687 }
00688 
00689 /************************** main region ***************************/
00690 
00691 /* sets up the fields of the View2D from zoom and offset */
00692 static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar)
00693 {
00694         Image *ima= ED_space_image(sima);
00695         float x1, y1, w, h;
00696         int width, height, winx, winy;
00697         
00698 #if 0
00699         if(image_preview_active(curarea, &width, &height));
00700         else
00701 #endif
00702         ED_space_image_size(sima, &width, &height);
00703 
00704         w= width;
00705         h= height;
00706         
00707         if(ima)
00708                 h *= ima->aspy/ima->aspx;
00709 
00710         winx= ar->winrct.xmax - ar->winrct.xmin + 1;
00711         winy= ar->winrct.ymax - ar->winrct.ymin + 1;
00712                 
00713         ar->v2d.tot.xmin= 0;
00714         ar->v2d.tot.ymin= 0;
00715         ar->v2d.tot.xmax= w;
00716         ar->v2d.tot.ymax= h;
00717         
00718         ar->v2d.mask.xmin= ar->v2d.mask.ymin= 0;
00719         ar->v2d.mask.xmax= winx;
00720         ar->v2d.mask.ymax= winy;
00721 
00722         /* which part of the image space do we see? */
00723         x1= ar->winrct.xmin+(winx-sima->zoom*w)/2.0f;
00724         y1= ar->winrct.ymin+(winy-sima->zoom*h)/2.0f;
00725 
00726         x1-= sima->zoom*sima->xof;
00727         y1-= sima->zoom*sima->yof;
00728         
00729         /* relative display right */
00730         ar->v2d.cur.xmin= ((ar->winrct.xmin - (float)x1)/sima->zoom);
00731         ar->v2d.cur.xmax= ar->v2d.cur.xmin + ((float)winx/sima->zoom);
00732         
00733         /* relative display left */
00734         ar->v2d.cur.ymin= ((ar->winrct.ymin-(float)y1)/sima->zoom);
00735         ar->v2d.cur.ymax= ar->v2d.cur.ymin + ((float)winy/sima->zoom);
00736         
00737         /* normalize 0.0..1.0 */
00738         ar->v2d.cur.xmin /= w;
00739         ar->v2d.cur.xmax /= w;
00740         ar->v2d.cur.ymin /= h;
00741         ar->v2d.cur.ymax /= h;
00742 }
00743 
00744 /* add handlers, stuff you only do once or on area/region changes */
00745 static void image_main_area_init(wmWindowManager *wm, ARegion *ar)
00746 {
00747         wmKeyMap *keymap;
00748         
00749         // image space manages own v2d
00750         // UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
00751 
00752         /* image paint polls for mode */
00753         keymap= WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
00754         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00755 
00756         keymap= WM_keymap_find(wm->defaultconf, "UV Editor", 0, 0);
00757         WM_event_add_keymap_handler(&ar->handlers, keymap);
00758         
00759         /* own keymaps */
00760         keymap= WM_keymap_find(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
00761         WM_event_add_keymap_handler(&ar->handlers, keymap);
00762         keymap= WM_keymap_find(wm->defaultconf, "Image", SPACE_IMAGE, 0);
00763         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00764 
00765 }
00766 
00767 static void image_main_area_draw(const bContext *C, ARegion *ar)
00768 {
00769         /* draw entirely, view changes should be handled here */
00770         SpaceImage *sima= CTX_wm_space_image(C);
00771         Object *obedit= CTX_data_edit_object(C);
00772         Scene *scene= CTX_data_scene(C);
00773         View2D *v2d= &ar->v2d;
00774         //View2DScrollers *scrollers;
00775         float col[3];
00776         
00777         /* XXX not supported yet, disabling for now */
00778         scene->r.scemode &= ~R_COMP_CROP;
00779         
00780         /* clear and setup matrix */
00781         UI_GetThemeColor3fv(TH_BACK, col);
00782         glClearColor(col[0], col[1], col[2], 0.0);
00783         glClear(GL_COLOR_BUFFER_BIT);
00784 
00785         /* put scene context variable in iuser */
00786         sima->iuser.scene= scene;
00787 
00788         /* we set view2d from own zoom and offset each time */
00789         image_main_area_set_view2d(sima, ar);
00790         
00791         /* we draw image in pixelspace */
00792         draw_image_main(sima, ar, scene);
00793 
00794         /* and uvs in 0.0-1.0 space */
00795         UI_view2d_view_ortho(v2d);
00796         draw_uvedit_main(sima, ar, scene, obedit);
00797 
00798         ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
00799                 
00800         /* Grease Pencil too (in addition to UV's) */
00801         draw_image_grease_pencil((bContext *)C, 1); 
00802 
00803         UI_view2d_view_restore(C);
00804 
00805         /* draw Grease Pencil - screen space only */
00806         draw_image_grease_pencil((bContext *)C, 0);
00807         
00808         /* scrollers? */
00809         /*scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_UNIT_VALUES, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
00810         UI_view2d_scrollers_draw(C, v2d, scrollers);
00811         UI_view2d_scrollers_free(scrollers);*/
00812 }
00813 
00814 static void image_main_area_listener(ARegion *ar, wmNotifier *wmn)
00815 {
00816         /* context changes */
00817         switch(wmn->category) {
00818                 case NC_SCREEN:
00819                         if (wmn->data==ND_GPENCIL)
00820                                 ED_region_tag_redraw(ar);
00821                 break;
00822         }
00823 }
00824 
00825 /* *********************** buttons region ************************ */
00826 
00827 /* add handlers, stuff you only do once or on area/region changes */
00828 static void image_buttons_area_init(wmWindowManager *wm, ARegion *ar)
00829 {
00830         wmKeyMap *keymap;
00831 
00832         ED_region_panels_init(wm, ar);
00833         
00834         keymap= WM_keymap_find(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
00835         WM_event_add_keymap_handler(&ar->handlers, keymap);
00836 }
00837 
00838 static void image_buttons_area_draw(const bContext *C, ARegion *ar)
00839 {
00840         ED_region_panels(C, ar, 1, NULL, -1);
00841 }
00842 
00843 static void image_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
00844 {
00845         /* context changes */
00846         switch(wmn->category) {
00847                 case NC_SCREEN:
00848                         if (wmn->data==ND_GPENCIL)
00849                                 ED_region_tag_redraw(ar);
00850                         break;
00851                 case NC_BRUSH:
00852                         if(wmn->action==NA_EDITED)
00853                                 ED_region_tag_redraw(ar);
00854                         break;
00855         }
00856 }
00857 
00858 /* *********************** scopes region ************************ */
00859 
00860 /* add handlers, stuff you only do once or on area/region changes */
00861 static void image_scope_area_init(wmWindowManager *wm, ARegion *ar)
00862 {
00863         wmKeyMap *keymap;
00864         
00865         ED_region_panels_init(wm, ar);
00866         
00867         keymap= WM_keymap_find(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
00868         WM_event_add_keymap_handler(&ar->handlers, keymap);
00869 }
00870 
00871 static void image_scope_area_draw(const bContext *C, ARegion *ar)
00872 {
00873         SpaceImage *sima= CTX_wm_space_image(C);
00874         Scene *scene= CTX_data_scene(C);
00875         void *lock;
00876         ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock);
00877         if(ibuf) {
00878                 scopes_update(&sima->scopes, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT );
00879         }
00880         ED_space_image_release_buffer(sima, lock);
00881         
00882         ED_region_panels(C, ar, 1, NULL, -1);
00883 }
00884 
00885 static void image_scope_area_listener(ARegion *ar, wmNotifier *wmn)
00886 {
00887         /* context changes */
00888         switch(wmn->category) {
00889                 case NC_SCENE:
00890                         switch(wmn->data) {
00891                                 case ND_MODE:
00892                                 case ND_RENDER_RESULT:
00893                                 case ND_COMPO_RESULT:
00894                                         ED_region_tag_redraw(ar);
00895                                         break;
00896                         }
00897                         break;
00898                 case NC_IMAGE:
00899                         ED_region_tag_redraw(ar);
00900                         break;
00901                 case NC_NODE:
00902                         ED_region_tag_redraw(ar);
00903                         break;
00904                         
00905         }
00906 }
00907 
00908 /************************* header region **************************/
00909 
00910 /* add handlers, stuff you only do once or on area/region changes */
00911 static void image_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
00912 {
00913         ED_region_header_init(ar);
00914 }
00915 
00916 static void image_header_area_draw(const bContext *C, ARegion *ar)
00917 {
00918         ED_region_header(C, ar);
00919 }
00920 
00921 static void image_header_area_listener(ARegion *ar, wmNotifier *wmn)
00922 {
00923         /* context changes */
00924         switch(wmn->category) {
00925                 case NC_SCENE:
00926                         switch(wmn->data) {
00927                                 case ND_MODE:
00928                                 case ND_TOOLSETTINGS:
00929                                         ED_region_tag_redraw(ar);
00930                                         break;
00931                         }
00932                         break;
00933                 case NC_GEOM:
00934                         switch(wmn->data) {
00935                                 case ND_DATA:
00936                                 case ND_SELECT:
00937                                         ED_region_tag_redraw(ar);
00938                                         break;
00939                         }
00940                         
00941         }
00942 }
00943 
00944 /**************************** spacetype *****************************/
00945 
00946 /* only called once, from space/spacetypes.c */
00947 void ED_spacetype_image(void)
00948 {
00949         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype image");
00950         ARegionType *art;
00951         
00952         st->spaceid= SPACE_IMAGE;
00953         strncpy(st->name, "Image", BKE_ST_MAXNAME);
00954         
00955         st->new= image_new;
00956         st->free= image_free;
00957         st->init= image_init;
00958         st->duplicate= image_duplicate;
00959         st->operatortypes= image_operatortypes;
00960         st->keymap= image_keymap;
00961         st->dropboxes= image_dropboxes;
00962         st->refresh= image_refresh;
00963         st->listener= image_listener;
00964         st->context= image_context;
00965         
00966         /* regions: main window */
00967         art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
00968         art->regionid = RGN_TYPE_WINDOW;
00969         art->keymapflag= ED_KEYMAP_FRAMES|ED_KEYMAP_GPENCIL;
00970         art->init= image_main_area_init;
00971         art->draw= image_main_area_draw;
00972         art->listener= image_main_area_listener;
00973 
00974         BLI_addhead(&st->regiontypes, art);
00975         
00976         /* regions: listview/buttons */
00977         art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
00978         art->regionid = RGN_TYPE_UI;
00979         art->prefsizex= 220; // XXX
00980         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
00981         art->listener= image_buttons_area_listener;
00982         art->init= image_buttons_area_init;
00983         art->draw= image_buttons_area_draw;
00984         BLI_addhead(&st->regiontypes, art);
00985 
00986         image_buttons_register(art);
00987         ED_uvedit_buttons_register(art);
00988         
00989         /* regions: statistics/scope buttons */
00990         art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
00991         art->regionid = RGN_TYPE_PREVIEW;
00992         art->prefsizex= 220; // XXX
00993         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
00994         art->listener= image_scope_area_listener;
00995         art->init= image_scope_area_init;
00996         art->draw= image_scope_area_draw;
00997         BLI_addhead(&st->regiontypes, art);
00998 
00999         /* regions: header */
01000         art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
01001         art->regionid = RGN_TYPE_HEADER;
01002         art->prefsizey= HEADERY;
01003         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER;
01004         art->listener= image_header_area_listener;
01005         art->init= image_header_area_init;
01006         art->draw= image_header_area_draw;
01007         
01008         BLI_addhead(&st->regiontypes, art);
01009         
01010         BKE_spacetype_register(st);
01011 }
01012