Blender V2.61 - r43446

space_view3d.c

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