Blender  V2.59
space_view3d.c
Go to the documentation of this file.
00001 /*
00002  * $Id: space_view3d.c 37327 2011-06-09 03:56:32Z campbellbarton $
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_object_types.h"
00038 #include "DNA_scene_types.h"
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "BLI_blenlib.h"
00043 #include "BLI_math.h"
00044 #include "BLI_rand.h"
00045 #include "BLI_utildefines.h"
00046 
00047 #include "BKE_object.h"
00048 #include "BKE_context.h"
00049 #include "BKE_screen.h"
00050 
00051 #include "ED_space_api.h"
00052 #include "ED_screen.h"
00053 #include "ED_object.h"
00054 
00055 #include "BIF_gl.h"
00056 
00057 
00058 #include "WM_api.h"
00059 #include "WM_types.h"
00060 
00061 
00062 #include "RNA_access.h"
00063 
00064 #include "UI_resources.h"
00065 
00066 #include "view3d_intern.h"      // own include
00067 
00068 /* ******************** manage regions ********************* */
00069 
00070 ARegion *view3d_has_buttons_region(ScrArea *sa)
00071 {
00072         ARegion *ar, *arnew;
00073 
00074         ar= BKE_area_find_region_type(sa, RGN_TYPE_UI);
00075         if(ar) return ar;
00076         
00077         /* add subdiv level; after header */
00078         ar= BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
00079 
00080         /* is error! */
00081         if(ar==NULL) return NULL;
00082         
00083         arnew= MEM_callocN(sizeof(ARegion), "buttons for view3d");
00084         
00085         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
00086         arnew->regiontype= RGN_TYPE_UI;
00087         arnew->alignment= RGN_ALIGN_RIGHT;
00088         
00089         arnew->flag = RGN_FLAG_HIDDEN;
00090         
00091         return arnew;
00092 }
00093 
00094 ARegion *view3d_has_tools_region(ScrArea *sa)
00095 {
00096         ARegion *ar, *artool=NULL, *arprops=NULL, *arhead;
00097         
00098         for(ar= sa->regionbase.first; ar; ar= ar->next) {
00099                 if(ar->regiontype==RGN_TYPE_TOOLS)
00100                         artool= ar;
00101                 if(ar->regiontype==RGN_TYPE_TOOL_PROPS)
00102                         arprops= ar;
00103         }
00104         
00105         /* tool region hide/unhide also hides props */
00106         if(arprops && artool) return artool;
00107         
00108         if(artool==NULL) {
00109                 /* add subdiv level; after header */
00110                 for(arhead= sa->regionbase.first; arhead; arhead= arhead->next)
00111                         if(arhead->regiontype==RGN_TYPE_HEADER)
00112                                 break;
00113                 
00114                 /* is error! */
00115                 if(arhead==NULL) return NULL;
00116                 
00117                 artool= MEM_callocN(sizeof(ARegion), "tools for view3d");
00118                 
00119                 BLI_insertlinkafter(&sa->regionbase, arhead, artool);
00120                 artool->regiontype= RGN_TYPE_TOOLS;
00121                 artool->alignment= RGN_ALIGN_LEFT; //RGN_OVERLAP_LEFT;
00122                 artool->flag = RGN_FLAG_HIDDEN;
00123         }
00124 
00125         if(arprops==NULL) {
00126                 /* add extra subdivided region for tool properties */
00127                 arprops= MEM_callocN(sizeof(ARegion), "tool props for view3d");
00128                 
00129                 BLI_insertlinkafter(&sa->regionbase, artool, arprops);
00130                 arprops->regiontype= RGN_TYPE_TOOL_PROPS;
00131                 arprops->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
00132         }
00133         
00134         return artool;
00135 }
00136 
00137 /* ****************************************************** */
00138 
00139 /* function to always find a regionview3d context inside 3D window */
00140 RegionView3D *ED_view3d_context_rv3d(bContext *C)
00141 {
00142         RegionView3D *rv3d= CTX_wm_region_view3d(C);
00143         
00144         if(rv3d==NULL) {
00145                 ScrArea *sa =CTX_wm_area(C);
00146                 if(sa && sa->spacetype==SPACE_VIEW3D) {
00147                         ARegion *ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
00148                         if(ar) {
00149                                 rv3d= ar->regiondata;
00150                         }
00151                 }
00152         }
00153         return rv3d;
00154 }
00155 
00156 /* ideally would return an rv3d but in some cases the region is needed too
00157  * so return that, the caller can then access the ar->regiondata */
00158 ARegion *ED_view3d_context_region_unlock(bContext *C)
00159 {
00160         ScrArea *sa= CTX_wm_area(C);
00161         if(sa && sa->spacetype==SPACE_VIEW3D) {
00162                 ARegion *ar= CTX_wm_region(C);
00163                 if(ar) {
00164                         RegionView3D *rv3d= ar->regiondata;
00165                         if(rv3d && rv3d->viewlock == 0) {
00166                                 return ar;
00167                         }
00168                         else {
00169                                 ARegion *ar_unlock_user= NULL;
00170                                 ARegion *ar_unlock= NULL;
00171                                 for(ar= sa->regionbase.first; ar; ar= ar->next) {
00172                                         /* find the first unlocked rv3d */
00173                                         if(ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
00174                                                 rv3d= ar->regiondata;
00175                                                 if(rv3d->viewlock == 0) {
00176                                                         ar_unlock= ar;
00177                                                         if(rv3d->persp==RV3D_PERSP || rv3d->persp==RV3D_CAMOB) {
00178                                                                 ar_unlock_user= ar;
00179                                                                 break;
00180                                                         }
00181                                                 } 
00182                                         }
00183                                 }
00184 
00185                                 /* camera/perspective view get priority when the active region is locked */
00186                                 if(ar_unlock_user) return ar_unlock_user;
00187                                 if(ar_unlock) return ar_unlock;
00188                         }
00189                 }
00190         }
00191         return NULL;
00192 }
00193 
00194 /* Most of the time this isn't needed since you could assume the view matrix was
00195  * set while drawing, however when functions like mesh_foreachScreenVert are
00196  * called by selection tools, we can't be sure this object was the last.
00197  *
00198  * for example, transparent objects are drawn after editmode and will cause
00199  * the rv3d mat's to change and break selection.
00200  *
00201  * 'ED_view3d_init_mats_rv3d' should be called before
00202  * view3d_project_short_clip and view3d_project_short_noclip in cases where
00203  * these functions are not used during draw_object
00204  */
00205 void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
00206 {
00207         /* local viewmat and persmat, to calculate projections */
00208         mul_m4_m4m4(rv3d->viewmatob, ob->obmat, rv3d->viewmat);
00209         mul_m4_m4m4(rv3d->persmatob, ob->obmat, rv3d->persmat);
00210 
00211         /* initializes object space clipping, speeds up clip tests */
00212         ED_view3d_local_clipping(rv3d, ob->obmat);
00213 }
00214 
00215 void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
00216 {
00217         ED_view3d_init_mats_rv3d(ob, rv3d);
00218 
00219         /* we have to multiply instead of loading viewmatob to make
00220            it work with duplis using displists, otherwise it will
00221            override the dupli-matrix */
00222         glMultMatrixf(ob->obmat);
00223 }
00224 
00225 /* ******************** default callbacks for view3d space ***************** */
00226 
00227 static SpaceLink *view3d_new(const bContext *C)
00228 {
00229         Scene *scene= CTX_data_scene(C);
00230         ARegion *ar;
00231         View3D *v3d;
00232         RegionView3D *rv3d;
00233         
00234         v3d= MEM_callocN(sizeof(View3D), "initview3d");
00235         v3d->spacetype= SPACE_VIEW3D;
00236         v3d->blockscale= 0.7f;
00237         v3d->lay= v3d->layact= 1;
00238         if(scene) {
00239                 v3d->lay= v3d->layact= scene->lay;
00240                 v3d->camera= scene->camera;
00241         }
00242         v3d->scenelock= TRUE;
00243         v3d->grid= 1.0f;
00244         v3d->gridlines= 16;
00245         v3d->gridsubdiv = 10;
00246         v3d->drawtype= OB_SOLID;
00247         
00248         v3d->gridflag |= V3D_SHOW_X;
00249         v3d->gridflag |= V3D_SHOW_Y;
00250         v3d->gridflag |= V3D_SHOW_FLOOR;
00251         v3d->gridflag &= ~V3D_SHOW_Z;
00252         
00253         v3d->flag |= V3D_SELECT_OUTLINE;
00254         
00255         v3d->lens= 35.0f;
00256         v3d->near= 0.01f;
00257         v3d->far= 1000.0f;
00258 
00259         v3d->twflag |= U.tw_flag & V3D_USE_MANIPULATOR;
00260         v3d->twtype= V3D_MANIP_TRANSLATE;
00261         v3d->around= V3D_CENTROID;
00262         
00263         /* header */
00264         ar= MEM_callocN(sizeof(ARegion), "header for view3d");
00265         
00266         BLI_addtail(&v3d->regionbase, ar);
00267         ar->regiontype= RGN_TYPE_HEADER;
00268         ar->alignment= RGN_ALIGN_BOTTOM;
00269         
00270         /* tool shelf */
00271         ar= MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
00272         
00273         BLI_addtail(&v3d->regionbase, ar);
00274         ar->regiontype= RGN_TYPE_TOOLS;
00275         ar->alignment= RGN_ALIGN_LEFT;
00276         ar->flag = RGN_FLAG_HIDDEN;
00277         
00278         /* tool properties */
00279         ar= MEM_callocN(sizeof(ARegion), "tool properties for view3d");
00280         
00281         BLI_addtail(&v3d->regionbase, ar);
00282         ar->regiontype= RGN_TYPE_TOOL_PROPS;
00283         ar->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
00284         ar->flag = RGN_FLAG_HIDDEN;
00285         
00286         /* buttons/list view */
00287         ar= MEM_callocN(sizeof(ARegion), "buttons for view3d");
00288         
00289         BLI_addtail(&v3d->regionbase, ar);
00290         ar->regiontype= RGN_TYPE_UI;
00291         ar->alignment= RGN_ALIGN_RIGHT;
00292         ar->flag = RGN_FLAG_HIDDEN;
00293         
00294         /* main area */
00295         ar= MEM_callocN(sizeof(ARegion), "main area for view3d");
00296         
00297         BLI_addtail(&v3d->regionbase, ar);
00298         ar->regiontype= RGN_TYPE_WINDOW;
00299         
00300         ar->regiondata= MEM_callocN(sizeof(RegionView3D), "region view3d");
00301         rv3d= ar->regiondata;
00302         rv3d->viewquat[0]= 1.0f;
00303         rv3d->persp= RV3D_PERSP;
00304         rv3d->view= RV3D_VIEW_PERSPORTHO;
00305         rv3d->dist= 10.0;
00306         
00307         return (SpaceLink *)v3d;
00308 }
00309 
00310 /* not spacelink itself */
00311 static void view3d_free(SpaceLink *sl)
00312 {
00313         View3D *vd= (View3D *) sl;
00314 
00315         BGpic *bgpic;
00316         for(bgpic= vd->bgpicbase.first; bgpic; bgpic= bgpic->next) {
00317                 if(bgpic->ima) bgpic->ima->id.us--;
00318         }
00319         BLI_freelistN(&vd->bgpicbase);
00320 
00321         if(vd->localvd) MEM_freeN(vd->localvd);
00322         
00323         if(vd->properties_storage) MEM_freeN(vd->properties_storage);
00324 }
00325 
00326 
00327 /* spacetype; init callback */
00328 static void view3d_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
00329 {
00330 
00331 }
00332 
00333 static SpaceLink *view3d_duplicate(SpaceLink *sl)
00334 {
00335         View3D *v3do= (View3D *)sl;
00336         View3D *v3dn= MEM_dupallocN(sl);
00337         BGpic *bgpic;
00338         
00339         /* clear or remove stuff from old */
00340         
00341 // XXX  BIF_view3d_previewrender_free(v3do);
00342         
00343         if(v3do->localvd) {
00344                 v3do->localvd= NULL;
00345                 v3do->properties_storage= NULL;
00346                 v3do->lay= v3dn->localvd->lay;
00347                 v3do->lay &= 0xFFFFFF;
00348         }
00349         
00350         /* copy or clear inside new stuff */
00351 
00352         BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase);
00353         for(bgpic= v3dn->bgpicbase.first; bgpic; bgpic= bgpic->next)
00354                 if(bgpic->ima)
00355                         bgpic->ima->id.us++;
00356 
00357         v3dn->properties_storage= NULL;
00358         
00359         return (SpaceLink *)v3dn;
00360 }
00361 
00362 /* add handlers, stuff you only do once or on area/region changes */
00363 static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
00364 {
00365         ListBase *lb;
00366         wmKeyMap *keymap;
00367 
00368         /* object ops. */
00369         
00370         /* important to be before Pose keymap since they can both be enabled at once */
00371         keymap= WM_keymap_find(wm->defaultconf, "Face Mask", 0, 0);
00372         WM_event_add_keymap_handler(&ar->handlers, keymap);
00373         
00374         /* pose is not modal, operator poll checks for this */
00375         keymap= WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
00376         WM_event_add_keymap_handler(&ar->handlers, keymap);
00377         
00378         keymap= WM_keymap_find(wm->defaultconf, "Object Mode", 0, 0);
00379         WM_event_add_keymap_handler(&ar->handlers, keymap);
00380 
00381         keymap= WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
00382         WM_event_add_keymap_handler(&ar->handlers, keymap);
00383 
00384         keymap= WM_keymap_find(wm->defaultconf, "Vertex Paint", 0, 0);
00385         WM_event_add_keymap_handler(&ar->handlers, keymap);
00386 
00387         keymap= WM_keymap_find(wm->defaultconf, "Weight Paint", 0, 0);
00388         WM_event_add_keymap_handler(&ar->handlers, keymap);
00389 
00390         keymap= WM_keymap_find(wm->defaultconf, "Sculpt", 0, 0);
00391         WM_event_add_keymap_handler(&ar->handlers, keymap);
00392         
00393         keymap= WM_keymap_find(wm->defaultconf, "Mesh", 0, 0);
00394         WM_event_add_keymap_handler(&ar->handlers, keymap);
00395         
00396         keymap= WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
00397         WM_event_add_keymap_handler(&ar->handlers, keymap);
00398         
00399         keymap= WM_keymap_find(wm->defaultconf, "Armature", 0, 0);
00400         WM_event_add_keymap_handler(&ar->handlers, keymap);
00401 
00402         keymap= WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
00403         WM_event_add_keymap_handler(&ar->handlers, keymap);
00404 
00405         keymap= WM_keymap_find(wm->defaultconf, "Metaball", 0, 0);
00406         WM_event_add_keymap_handler(&ar->handlers, keymap);
00407         
00408         keymap= WM_keymap_find(wm->defaultconf, "Lattice", 0, 0);
00409         WM_event_add_keymap_handler(&ar->handlers, keymap);
00410 
00411         /* armature sketching needs to take over mouse */
00412         keymap= WM_keymap_find(wm->defaultconf, "Armature Sketch", 0, 0);
00413         WM_event_add_keymap_handler(&ar->handlers, keymap);
00414 
00415         keymap= WM_keymap_find(wm->defaultconf, "Particle", 0, 0);
00416         WM_event_add_keymap_handler(&ar->handlers, keymap);
00417 
00418         /* editfont keymap swallows all... */
00419         keymap= WM_keymap_find(wm->defaultconf, "Font", 0, 0);
00420         WM_event_add_keymap_handler(&ar->handlers, keymap);
00421 
00422         keymap= WM_keymap_find(wm->defaultconf, "Object Non-modal", 0, 0);
00423         WM_event_add_keymap_handler(&ar->handlers, keymap);
00424 
00425         keymap= WM_keymap_find(wm->defaultconf, "Frames", 0, 0);
00426         WM_event_add_keymap_handler(&ar->handlers, keymap);
00427 
00428         /* own keymap, last so modes can override it */
00429         keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
00430         WM_event_add_keymap_handler(&ar->handlers, keymap);
00431 
00432         keymap= WM_keymap_find(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
00433         WM_event_add_keymap_handler(&ar->handlers, keymap);
00434         
00435         /* add drop boxes */
00436         lb= WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
00437         
00438         WM_event_add_dropbox_handler(&ar->handlers, lb);
00439         
00440 }
00441 
00442 static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
00443 {
00444         if(drag->type==WM_DRAG_ID) {
00445                 ID *id= (ID *)drag->poin;
00446                 if( GS(id->name)==ID_OB )
00447                         return 1;
00448         }
00449         return 0;
00450 }
00451 
00452 static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
00453 {
00454         if(drag->type==WM_DRAG_ID) {
00455                 ID *id= (ID *)drag->poin;
00456                 if( GS(id->name)==ID_MA )
00457                         return 1;
00458         }
00459         return 0;
00460 }
00461 
00462 static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
00463 {
00464         if(drag->type==WM_DRAG_ID) {
00465                 ID *id= (ID *)drag->poin;
00466                 if( GS(id->name)==ID_IM )
00467                         return 1;
00468         }
00469         else if(drag->type==WM_DRAG_PATH){
00470                 if(ELEM(drag->icon, 0, ICON_FILE_IMAGE))        /* rule might not work? */
00471                         return 1;
00472         }
00473         return 0;
00474 }
00475 
00476 
00477 static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
00478 {
00479         if( ED_view3d_give_base_under_cursor(C, event->mval) ) {
00480                 return 0;
00481         }
00482         return view3d_ima_drop_poll(C, drag, event);
00483 }
00484 
00485 static int view3d_ima_ob_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
00486 {
00487         if( ED_view3d_give_base_under_cursor(C, event->mval) ) {
00488                 return view3d_ima_drop_poll(C, drag, event);
00489         }
00490         return 0;
00491 }
00492 
00493 static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
00494 {
00495         ID *id= (ID *)drag->poin;
00496         PointerRNA ptr;
00497 
00498         /* need to put name in sub-operator in macro */
00499         ptr= RNA_pointer_get(drop->ptr, "OBJECT_OT_add_named");
00500         if(ptr.data)
00501                 RNA_string_set(&ptr, "name", id->name+2);
00502         else
00503                 RNA_string_set(drop->ptr, "name", id->name+2);
00504 }
00505 
00506 static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
00507 {
00508         ID *id= (ID *)drag->poin;
00509         
00510         RNA_string_set(drop->ptr, "name", id->name+2);
00511 }
00512 
00513 static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
00514 {
00515         ID *id= (ID *)drag->poin;
00516         
00517         if(id)
00518                 RNA_string_set(drop->ptr, "name", id->name+2);
00519         if(drag->path[0]) 
00520                 RNA_string_set(drop->ptr, "filepath", drag->path);
00521 }
00522 
00523 
00524 /* region dropbox definition */
00525 static void view3d_dropboxes(void)
00526 {
00527         ListBase *lb= WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
00528         
00529         WM_dropbox_add(lb, "OBJECT_OT_add_named_cursor", view3d_ob_drop_poll, view3d_ob_drop_copy);
00530         WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
00531         WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_ob_drop_poll, view3d_id_path_drop_copy);
00532         WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
00533 }
00534 
00535 
00536 
00537 /* type callback, not region itself */
00538 static void view3d_main_area_free(ARegion *ar)
00539 {
00540         RegionView3D *rv3d= ar->regiondata;
00541         
00542         if(rv3d) {
00543                 if(rv3d->localvd) MEM_freeN(rv3d->localvd);
00544                 if(rv3d->clipbb) MEM_freeN(rv3d->clipbb);
00545 
00546                 // XXX  retopo_free_view_data(rv3d);
00547                 if(rv3d->ri) { 
00548                         // XXX          BIF_view3d_previewrender_free(rv3d);
00549                 }
00550                 
00551                 if(rv3d->depths) {
00552                         if(rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
00553                         MEM_freeN(rv3d->depths);
00554                 }
00555                 MEM_freeN(rv3d);
00556                 ar->regiondata= NULL;
00557         }
00558 }
00559 
00560 /* copy regiondata */
00561 static void *view3d_main_area_duplicate(void *poin)
00562 {
00563         if(poin) {
00564                 RegionView3D *rv3d= poin, *new;
00565         
00566                 new= MEM_dupallocN(rv3d);
00567                 if(rv3d->localvd) 
00568                         new->localvd= MEM_dupallocN(rv3d->localvd);
00569                 if(rv3d->clipbb) 
00570                         new->clipbb= MEM_dupallocN(rv3d->clipbb);
00571                 
00572                 new->depths= NULL;
00573                 new->ri= NULL;
00574                 new->gpd= NULL;
00575                 new->sms= NULL;
00576                 new->smooth_timer= NULL;
00577                 
00578                 return new;
00579         }
00580         return NULL;
00581 }
00582 
00583 static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene)
00584 {
00585         wmWindow *win= wmn->wm->winactive;
00586         ScrArea *sa;
00587         unsigned int lay_used= 0;
00588         Base *base;
00589 
00590         if (!win) return;
00591 
00592         base= scene->base.first;
00593         while(base) {
00594                 lay_used |= base->lay & ((1<<20)-1); /* ignore localview */
00595 
00596                 if (lay_used == (1<<20)-1)
00597                         break;
00598 
00599                 base= base->next;
00600         }
00601 
00602         for(sa= win->screen->areabase.first; sa; sa= sa->next) {
00603                 if(sa->spacetype == SPACE_VIEW3D) {
00604                         if(BLI_findindex(&sa->regionbase, ar) != -1) {
00605                                 View3D *v3d= sa->spacedata.first;
00606                                 v3d->lay_used= lay_used;
00607                                 break;
00608                         }
00609                 }
00610         }
00611 }
00612 
00613 static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
00614 {
00615         bScreen *sc;
00616 
00617         /* context changes */
00618         switch(wmn->category) {
00619                 case NC_ANIMATION:
00620                         switch(wmn->data) {
00621                                 case ND_KEYFRAME_PROP:
00622                                 case ND_NLA_ACTCHANGE:
00623                                         ED_region_tag_redraw(ar);
00624                                         break;
00625                                 case ND_NLA:
00626                                 case ND_KEYFRAME:
00627                                         if (wmn->action == NA_EDITED)
00628                                                 ED_region_tag_redraw(ar);
00629                                         break;
00630                                 case ND_ANIMCHAN:
00631                                         if (wmn->action == NA_SELECTED)
00632                                                 ED_region_tag_redraw(ar);
00633                                         break;
00634                         }
00635                         break;
00636                 case NC_SCENE:
00637                         switch(wmn->data) {
00638                                 case ND_LAYER_CONTENT:
00639                                         view3d_recalc_used_layers(ar, wmn, wmn->reference);
00640                                         ED_region_tag_redraw(ar);
00641                                         break;
00642                                 case ND_FRAME:
00643                                 case ND_TRANSFORM:
00644                                 case ND_OB_ACTIVE:
00645                                 case ND_OB_SELECT:
00646                                 case ND_OB_VISIBLE:
00647                                 case ND_LAYER:
00648                                 case ND_RENDER_OPTIONS:
00649                                 case ND_MODE:
00650                                         ED_region_tag_redraw(ar);
00651                                         break;
00652                                 case ND_WORLD:
00653                                         /* handled by space_view3d_listener() for v3d access */
00654                                         break;
00655                         }
00656                         if (wmn->action == NA_EDITED)
00657                                 ED_region_tag_redraw(ar);
00658                         break;
00659                 case NC_OBJECT:
00660                         switch(wmn->data) {
00661                                 case ND_BONE_ACTIVE:
00662                                 case ND_BONE_SELECT:
00663                                 case ND_TRANSFORM:
00664                                 case ND_POSE:
00665                                 case ND_DRAW:
00666                                 case ND_MODIFIER:
00667                                 case ND_CONSTRAINT:
00668                                 case ND_KEYS:
00669                                 case ND_PARTICLE:
00670                                         ED_region_tag_redraw(ar);
00671                                         break;
00672                         }
00673                         switch(wmn->action) {
00674                                 case NA_ADDED:
00675                                         ED_region_tag_redraw(ar);
00676                                         break;
00677                         }
00678                         break;
00679                 case NC_GEOM:
00680                         switch(wmn->data) {
00681                                 case ND_DATA:
00682                                 case ND_SELECT:
00683                                         ED_region_tag_redraw(ar);
00684                                         break;
00685                         }
00686                         switch(wmn->action) {
00687                                 case NA_EDITED:
00688                                         ED_region_tag_redraw(ar);
00689                                         break;
00690                         }
00691                         break;
00692                 case NC_GROUP:
00693                         /* all group ops for now */
00694                         ED_region_tag_redraw(ar);
00695                         break;
00696                 case NC_BRUSH:
00697                         if(wmn->action == NA_EDITED)
00698                                 ED_region_tag_redraw_overlay(ar);
00699                         break;                  
00700                 case NC_MATERIAL:
00701                         switch(wmn->data) {
00702                                 case ND_SHADING_DRAW:
00703                                         ED_region_tag_redraw(ar);
00704                                         break;
00705                         }
00706                         break;
00707                 case NC_WORLD:
00708                         switch(wmn->data) {
00709                                 case ND_WORLD_DRAW:
00710                                         /* handled by space_view3d_listener() for v3d access */
00711                                         break;
00712                                 case ND_WORLD_STARS:
00713                                 {
00714                                         RegionView3D *rv3d= ar->regiondata;
00715                                         if(rv3d->persp == RV3D_CAMOB) {
00716                                                 ED_region_tag_redraw(ar);
00717                                         }
00718                                 }
00719                         }
00720                         break;
00721                 case NC_LAMP:
00722                         switch(wmn->data) {
00723                                 case ND_LIGHTING_DRAW:
00724                                         ED_region_tag_redraw(ar);
00725                                         break;
00726                         }
00727                         break;
00728                 case NC_IMAGE:  
00729                         /* this could be more fine grained checks if we had
00730                          * more context than just the region */
00731                         ED_region_tag_redraw(ar);
00732                         break;
00733                 case NC_TEXTURE:        
00734                         /* same as above */
00735                         ED_region_tag_redraw(ar);
00736                         break;
00737                 case NC_SPACE:
00738                         if(wmn->data == ND_SPACE_VIEW3D) {
00739                                 if (wmn->subtype == NS_VIEW3D_GPU) {
00740                                         RegionView3D *rv3d= ar->regiondata;
00741                                         rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
00742                                 }
00743                                 ED_region_tag_redraw(ar);
00744                         }
00745                         break;
00746                 case NC_ID:
00747                         if(wmn->action == NA_RENAME)
00748                                 ED_region_tag_redraw(ar);
00749                         break;
00750                 case NC_SCREEN:
00751                         switch(wmn->data) {
00752                                 case ND_GPENCIL:
00753                                 case ND_ANIMPLAY:
00754                                 case ND_SKETCH:
00755                                         ED_region_tag_redraw(ar);
00756                                         break;
00757                                 case ND_SCREENBROWSE:
00758                                 case ND_SCREENDELETE:
00759                                 case ND_SCREENSET:
00760                                         /* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */
00761                                         /* updates used layers only for View3D in active screen */
00762                                         sc= wmn->reference;
00763                                         view3d_recalc_used_layers(ar, wmn, sc->scene);
00764                                         ED_region_tag_redraw(ar);
00765                                         break;
00766                         }
00767 
00768                         break;
00769         }
00770 }
00771 
00772 /* concept is to retrieve cursor type context-less */
00773 static void view3d_main_area_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
00774 {
00775         Scene *scene= win->screen->scene;
00776 
00777         if(scene->obedit) {
00778                 WM_cursor_set(win, CURSOR_EDIT);
00779         }
00780         else {
00781                 WM_cursor_set(win, CURSOR_STD);
00782         }
00783 }
00784 
00785 /* add handlers, stuff you only do once or on area/region changes */
00786 static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar)
00787 {
00788         wmKeyMap *keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
00789         
00790         WM_event_add_keymap_handler(&ar->handlers, keymap);
00791 
00792         ED_region_header_init(ar);
00793 }
00794 
00795 static void view3d_header_area_draw(const bContext *C, ARegion *ar)
00796 {
00797         ED_region_header(C, ar);
00798 }
00799 
00800 static void view3d_header_area_listener(ARegion *ar, wmNotifier *wmn)
00801 {
00802         /* context changes */
00803         switch(wmn->category) {
00804                 case NC_SCENE:
00805                         switch(wmn->data) {
00806                                 case ND_FRAME:
00807                                 case ND_OB_ACTIVE:
00808                                 case ND_OB_SELECT:
00809                                 case ND_OB_VISIBLE:
00810                                 case ND_MODE:
00811                                 case ND_LAYER:
00812                                 case ND_TOOLSETTINGS:
00813                                 case ND_LAYER_CONTENT:
00814                                         ED_region_tag_redraw(ar);
00815                                         break;
00816                         }
00817                         break;
00818                 case NC_SPACE:
00819                         if(wmn->data == ND_SPACE_VIEW3D)
00820                                 ED_region_tag_redraw(ar);
00821                         break;
00822         }
00823 }
00824 
00825 /* add handlers, stuff you only do once or on area/region changes */
00826 static void view3d_buttons_area_init(wmWindowManager *wm, ARegion *ar)
00827 {
00828         wmKeyMap *keymap;
00829 
00830         ED_region_panels_init(wm, ar);
00831         
00832         keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
00833         WM_event_add_keymap_handler(&ar->handlers, keymap);
00834 }
00835 
00836 static void view3d_buttons_area_draw(const bContext *C, ARegion *ar)
00837 {
00838         ED_region_panels(C, ar, 1, NULL, -1);
00839 }
00840 
00841 static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
00842 {
00843         /* context changes */
00844         switch(wmn->category) {
00845                 case NC_ANIMATION:
00846                         switch(wmn->data) {
00847                                 case ND_KEYFRAME_PROP:
00848                                 case ND_NLA_ACTCHANGE:
00849                                         ED_region_tag_redraw(ar);
00850                                         break;
00851                                 case ND_NLA:
00852                                 case ND_KEYFRAME:
00853                                         if (wmn->action == NA_EDITED)
00854                                                 ED_region_tag_redraw(ar);
00855                                         break;  
00856                         }
00857                         break;
00858                 case NC_SCENE:
00859                         switch(wmn->data) {
00860                                 case ND_FRAME:
00861                                 case ND_OB_ACTIVE:
00862                                 case ND_OB_SELECT:
00863                                 case ND_OB_VISIBLE:
00864                                 case ND_MODE:
00865                                 case ND_LAYER:
00866                                 case ND_LAYER_CONTENT:
00867                                         ED_region_tag_redraw(ar);
00868                                         break;
00869                         }
00870                         switch(wmn->action) {
00871                                 case NA_EDITED:
00872                                         ED_region_tag_redraw(ar);
00873                                         break;
00874                         }
00875                         break;
00876                 case NC_OBJECT:
00877                         switch(wmn->data) {
00878                                 case ND_BONE_ACTIVE:
00879                                 case ND_BONE_SELECT:
00880                                 case ND_TRANSFORM:
00881                                 case ND_POSE:
00882                                 case ND_DRAW:
00883                                 case ND_KEYS:
00884                                 case ND_MODIFIER:
00885                                         ED_region_tag_redraw(ar);
00886                                         break;
00887                         }
00888                         break;
00889                 case NC_GEOM:
00890                         switch(wmn->data) {
00891                                 case ND_DATA:
00892                                 case ND_SELECT:
00893                                         ED_region_tag_redraw(ar);
00894                                         break;
00895                         }
00896                         if (wmn->action == NA_EDITED)
00897                                 ED_region_tag_redraw(ar);
00898                         break;
00899                 case NC_TEXTURE:
00900                         /* for brush textures */
00901                         ED_region_tag_redraw(ar);
00902                         break;
00903                 case NC_BRUSH:
00904                         if(wmn->action==NA_EDITED)
00905                                 ED_region_tag_redraw(ar);
00906                         break;
00907                 case NC_SPACE:
00908                         if(wmn->data == ND_SPACE_VIEW3D)
00909                                 ED_region_tag_redraw(ar);
00910                         break;
00911                 case NC_ID:
00912                         if(wmn->action == NA_RENAME)
00913                                 ED_region_tag_redraw(ar);
00914                         break;
00915                 case NC_SCREEN: 
00916                         if(wmn->data == ND_GPENCIL)
00917                                 ED_region_tag_redraw(ar);
00918                         break;
00919         }
00920 }
00921 
00922 /* add handlers, stuff you only do once or on area/region changes */
00923 static void view3d_tools_area_init(wmWindowManager *wm, ARegion *ar)
00924 {
00925         wmKeyMap *keymap;
00926         
00927         ED_region_panels_init(wm, ar);
00928 
00929         keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
00930         WM_event_add_keymap_handler(&ar->handlers, keymap);
00931 }
00932 
00933 static void view3d_tools_area_draw(const bContext *C, ARegion *ar)
00934 {
00935         ED_region_panels(C, ar, 1, CTX_data_mode_string(C), -1);
00936 }
00937 
00938 static void view3d_props_area_listener(ARegion *ar, wmNotifier *wmn)
00939 {
00940         /* context changes */
00941         switch(wmn->category) {
00942                 case NC_WM:
00943                         if(wmn->data == ND_HISTORY)
00944                                 ED_region_tag_redraw(ar);
00945                         break;
00946                 case NC_SCENE:
00947                         if(wmn->data == ND_MODE)
00948                                 ED_region_tag_redraw(ar);
00949                         break;
00950                 case NC_SPACE:
00951                         if(wmn->data == ND_SPACE_VIEW3D)
00952                                 ED_region_tag_redraw(ar);
00953                         break;
00954         }
00955 }
00956 
00957 /*area (not region) level listener*/
00958 static void space_view3d_listener(struct ScrArea *sa, struct wmNotifier *wmn)
00959 {
00960         View3D *v3d = sa->spacedata.first;
00961 
00962         /* context changes */
00963         switch(wmn->category) {
00964                 case NC_SCENE:
00965                         switch(wmn->data) {
00966                                 case ND_WORLD:
00967                                         if(v3d->flag2 & V3D_RENDER_OVERRIDE)
00968                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
00969                                         break;
00970                         }
00971                         break;
00972                 case NC_WORLD:
00973                         switch(wmn->data) {
00974                                 case ND_WORLD_DRAW:
00975                                         if(v3d->flag2 & V3D_RENDER_OVERRIDE)
00976                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
00977                                         break;
00978                         }
00979                         break;
00980                 case NC_MATERIAL:
00981                         switch(wmn->data) {
00982                                 case ND_NODES:
00983                                         if(v3d->drawtype == OB_TEXTURE)
00984                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
00985                                         break;
00986                         }
00987                         break;
00988         }
00989 
00990 #if 0 // removed since BKE_image_user_calc_frame is now called in draw_bgpic because screen_ops doesnt call the notifier.
00991         if (wmn->category == NC_SCENE && wmn->data == ND_FRAME) {
00992                 View3D *v3d = area->spacedata.first;
00993                 BGpic *bgpic = v3d->bgpicbase.first;
00994 
00995                 for (; bgpic; bgpic = bgpic->next) {
00996                         if (bgpic->ima) {
00997                                 Scene *scene = wmn->reference;
00998                                 BKE_image_user_calc_frame(&bgpic->iuser, scene->r.cfra, 0);
00999                         }
01000                 }
01001         }
01002 #endif
01003 }
01004 
01005 const char *view3d_context_dir[] = {
01006         "selected_objects", "selected_bases", "selected_editable_objects",
01007         "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
01008         "active_base", "active_object", NULL};
01009 
01010 static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
01011 {
01012         View3D *v3d= CTX_wm_view3d(C);
01013         Scene *scene= CTX_data_scene(C);
01014         Base *base;
01015         unsigned int lay = v3d ? v3d->lay:scene->lay; /* fallback to the scene layer, allows duplicate and other oject operators to run outside the 3d view */
01016 
01017         if(CTX_data_dir(member)) {
01018                 CTX_data_dir_set(result, view3d_context_dir);
01019         }
01020         else if(CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
01021                 int selected_objects= CTX_data_equals(member, "selected_objects");
01022 
01023                 for(base=scene->base.first; base; base=base->next) {
01024                         if((base->flag & SELECT) && (base->lay & lay)) {
01025                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
01026                                         if(selected_objects)
01027                                                 CTX_data_id_list_add(result, &base->object->id);
01028                                         else
01029                                                 CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
01030                                 }
01031                         }
01032                 }
01033                 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
01034                 return 1;
01035         }
01036         else if(CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
01037                 int selected_editable_objects= CTX_data_equals(member, "selected_editable_objects");
01038 
01039                 for(base=scene->base.first; base; base=base->next) {
01040                         if((base->flag & SELECT) && (base->lay & lay)) {
01041                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
01042                                         if(0==object_is_libdata(base->object)) {
01043                                                 if(selected_editable_objects)
01044                                                         CTX_data_id_list_add(result, &base->object->id);
01045                                                 else
01046                                                         CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
01047                                         }
01048                                 }
01049                         }
01050                 }
01051                 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
01052                 return 1;
01053         }
01054         else if(CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
01055                 int visible_objects= CTX_data_equals(member, "visible_objects");
01056 
01057                 for(base=scene->base.first; base; base=base->next) {
01058                         if(base->lay & lay) {
01059                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
01060                                         if(visible_objects)
01061                                                 CTX_data_id_list_add(result, &base->object->id);
01062                                         else
01063                                                 CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
01064                                 }
01065                         }
01066                 }
01067                 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
01068                 return 1;
01069         }
01070         else if(CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
01071                 int selectable_objects= CTX_data_equals(member, "selectable_objects");
01072 
01073                 for(base=scene->base.first; base; base=base->next) {
01074                         if(base->lay & lay) {
01075                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0 && (base->object->restrictflag & OB_RESTRICT_SELECT)==0) {
01076                                         if(selectable_objects)
01077                                                 CTX_data_id_list_add(result, &base->object->id);
01078                                         else
01079                                                 CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
01080                                 }
01081                         }
01082                 }
01083                 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
01084                 return 1;
01085         }
01086         else if(CTX_data_equals(member, "active_base")) {
01087                 if(scene->basact && (scene->basact->lay & lay))
01088                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
01089                                 CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact);
01090                 
01091                 return 1;
01092         }
01093         else if(CTX_data_equals(member, "active_object")) {
01094                 if(scene->basact && (scene->basact->lay & lay))
01095                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
01096                                 CTX_data_id_pointer_set(result, &scene->basact->object->id);
01097                 
01098                 return 1;
01099         }
01100         else {
01101                 return 0; /* not found */
01102         }
01103 
01104         return -1; /* found but not available */
01105 }
01106 
01107 
01108 /* only called once, from space/spacetypes.c */
01109 void ED_spacetype_view3d(void)
01110 {
01111         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype view3d");
01112         ARegionType *art;
01113         
01114         st->spaceid= SPACE_VIEW3D;
01115         strncpy(st->name, "View3D", BKE_ST_MAXNAME);
01116         
01117         st->new= view3d_new;
01118         st->free= view3d_free;
01119         st->init= view3d_init;
01120         st->listener = space_view3d_listener;
01121         st->duplicate= view3d_duplicate;
01122         st->operatortypes= view3d_operatortypes;
01123         st->keymap= view3d_keymap;
01124         st->dropboxes= view3d_dropboxes;
01125         st->context= view3d_context;
01126         
01127         /* regions: main window */
01128         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
01129         art->regionid = RGN_TYPE_WINDOW;
01130         art->keymapflag= ED_KEYMAP_GPENCIL;
01131         art->draw= view3d_main_area_draw;
01132         art->init= view3d_main_area_init;
01133         art->free= view3d_main_area_free;
01134         art->duplicate= view3d_main_area_duplicate;
01135         art->listener= view3d_main_area_listener;
01136         art->cursor= view3d_main_area_cursor;
01137         art->lock= 1;   /* can become flag, see BKE_spacedata_draw_locks */
01138         BLI_addhead(&st->regiontypes, art);
01139         
01140         /* regions: listview/buttons */
01141         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
01142         art->regionid = RGN_TYPE_UI;
01143         art->prefsizex= 180; // XXX
01144         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
01145         art->listener= view3d_buttons_area_listener;
01146         art->init= view3d_buttons_area_init;
01147         art->draw= view3d_buttons_area_draw;
01148         BLI_addhead(&st->regiontypes, art);
01149 
01150         view3d_buttons_register(art);
01151 
01152         /* regions: tool(bar) */
01153         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
01154         art->regionid = RGN_TYPE_TOOLS;
01155         art->prefsizex= 160; // XXX
01156         art->prefsizey= 50; // XXX
01157         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
01158         art->listener= view3d_buttons_area_listener;
01159         art->init= view3d_tools_area_init;
01160         art->draw= view3d_tools_area_draw;
01161         BLI_addhead(&st->regiontypes, art);
01162         
01163 #if 0
01164         /* unfinished still */
01165         view3d_toolshelf_register(art);
01166 #endif
01167 
01168         /* regions: tool properties */
01169         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d tool properties region");
01170         art->regionid = RGN_TYPE_TOOL_PROPS;
01171         art->prefsizex= 0;
01172         art->prefsizey= 120;
01173         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
01174         art->listener= view3d_props_area_listener;
01175         art->init= view3d_tools_area_init;
01176         art->draw= view3d_tools_area_draw;
01177         BLI_addhead(&st->regiontypes, art);
01178         
01179         view3d_tool_props_register(art);
01180         
01181         
01182         /* regions: header */
01183         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
01184         art->regionid = RGN_TYPE_HEADER;
01185         art->prefsizey= HEADERY;
01186         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER;
01187         art->listener= view3d_header_area_listener;
01188         art->init= view3d_header_area_init;
01189         art->draw= view3d_header_area_draw;
01190         BLI_addhead(&st->regiontypes, art);
01191         
01192         BKE_spacetype_register(st);
01193 }
01194