3399ab4e2607604021ff242d717f0c1d6a45d578
[blender.git] / source / blender / editors / space_view3d / space_view3d.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/editors/space_view3d/space_view3d.c
30  *  \ingroup spview3d
31  */
32
33
34 #include <string.h>
35 #include <stdio.h>
36
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_blenlib.h"
43 #include "BLI_math.h"
44 #include "BLI_rand.h"
45 #include "BLI_utildefines.h"
46
47 #include "BKE_object.h"
48 #include "BKE_context.h"
49 #include "BKE_screen.h"
50
51 #include "ED_space_api.h"
52 #include "ED_screen.h"
53 #include "ED_object.h"
54
55 #include "BIF_gl.h"
56
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61
62 #include "RNA_access.h"
63
64 #include "UI_resources.h"
65
66 #include "view3d_intern.h"      // own include
67
68 /* ******************** manage regions ********************* */
69
70 ARegion *view3d_has_buttons_region(ScrArea *sa)
71 {
72         ARegion *ar, *arnew;
73
74         ar= BKE_area_find_region_type(sa, RGN_TYPE_UI);
75         if(ar) return ar;
76         
77         /* add subdiv level; after header */
78         ar= BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
79
80         /* is error! */
81         if(ar==NULL) return NULL;
82         
83         arnew= MEM_callocN(sizeof(ARegion), "buttons for view3d");
84         
85         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
86         arnew->regiontype= RGN_TYPE_UI;
87         arnew->alignment= RGN_ALIGN_RIGHT;
88         
89         arnew->flag = RGN_FLAG_HIDDEN;
90         
91         return arnew;
92 }
93
94 ARegion *view3d_has_tools_region(ScrArea *sa)
95 {
96         ARegion *ar, *artool=NULL, *arprops=NULL, *arhead;
97         
98         for(ar= sa->regionbase.first; ar; ar= ar->next) {
99                 if(ar->regiontype==RGN_TYPE_TOOLS)
100                         artool= ar;
101                 if(ar->regiontype==RGN_TYPE_TOOL_PROPS)
102                         arprops= ar;
103         }
104         
105         /* tool region hide/unhide also hides props */
106         if(arprops && artool) return artool;
107         
108         if(artool==NULL) {
109                 /* add subdiv level; after header */
110                 for(arhead= sa->regionbase.first; arhead; arhead= arhead->next)
111                         if(arhead->regiontype==RGN_TYPE_HEADER)
112                                 break;
113                 
114                 /* is error! */
115                 if(arhead==NULL) return NULL;
116                 
117                 artool= MEM_callocN(sizeof(ARegion), "tools for view3d");
118                 
119                 BLI_insertlinkafter(&sa->regionbase, arhead, artool);
120                 artool->regiontype= RGN_TYPE_TOOLS;
121                 artool->alignment= RGN_ALIGN_LEFT; //RGN_OVERLAP_LEFT;
122                 artool->flag = RGN_FLAG_HIDDEN;
123         }
124
125         if(arprops==NULL) {
126                 /* add extra subdivided region for tool properties */
127                 arprops= MEM_callocN(sizeof(ARegion), "tool props for view3d");
128                 
129                 BLI_insertlinkafter(&sa->regionbase, artool, arprops);
130                 arprops->regiontype= RGN_TYPE_TOOL_PROPS;
131                 arprops->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
132         }
133         
134         return artool;
135 }
136
137 /* ****************************************************** */
138
139 /* function to always find a regionview3d context inside 3D window */
140 RegionView3D *ED_view3d_context_rv3d(bContext *C)
141 {
142         RegionView3D *rv3d= CTX_wm_region_view3d(C);
143         
144         if(rv3d==NULL) {
145                 ScrArea *sa =CTX_wm_area(C);
146                 if(sa && sa->spacetype==SPACE_VIEW3D) {
147                         ARegion *ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
148                         if(ar) {
149                                 rv3d= ar->regiondata;
150                         }
151                 }
152         }
153         return rv3d;
154 }
155
156 /* ideally would return an rv3d but in some cases the region is needed too
157  * so return that, the caller can then access the ar->regiondata */
158 ARegion *ED_view3d_context_region_unlock(bContext *C)
159 {
160         ScrArea *sa= CTX_wm_area(C);
161         if(sa && sa->spacetype==SPACE_VIEW3D) {
162                 ARegion *ar= CTX_wm_region(C);
163                 if(ar) {
164                         RegionView3D *rv3d= ar->regiondata;
165                         if(rv3d && rv3d->viewlock == 0) {
166                                 return ar;
167                         }
168                         else {
169                                 ARegion *ar_unlock_user= NULL;
170                                 ARegion *ar_unlock= NULL;
171                                 for(ar= sa->regionbase.first; ar; ar= ar->next) {
172                                         /* find the first unlocked rv3d */
173                                         if(ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
174                                                 rv3d= ar->regiondata;
175                                                 if(rv3d->viewlock == 0) {
176                                                         ar_unlock= ar;
177                                                         if(rv3d->persp==RV3D_PERSP || rv3d->persp==RV3D_CAMOB) {
178                                                                 ar_unlock_user= ar;
179                                                                 break;
180                                                         }
181                                                 } 
182                                         }
183                                 }
184
185                                 /* camera/perspective view get priority when the active region is locked */
186                                 if(ar_unlock_user) return ar_unlock_user;
187                                 if(ar_unlock) return ar_unlock;
188                         }
189                 }
190         }
191         return NULL;
192 }
193
194 /* Most of the time this isn't needed since you could assume the view matrix was
195  * set while drawing, however when functions like mesh_foreachScreenVert are
196  * called by selection tools, we can't be sure this object was the last.
197  *
198  * for example, transparent objects are drawn after editmode and will cause
199  * the rv3d mat's to change and break selection.
200  *
201  * 'ED_view3d_init_mats_rv3d' should be called before
202  * view3d_project_short_clip and view3d_project_short_noclip in cases where
203  * these functions are not used during draw_object
204  */
205 void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
206 {
207         /* local viewmat and persmat, to calculate projections */
208         mul_m4_m4m4(rv3d->viewmatob, ob->obmat, rv3d->viewmat);
209         mul_m4_m4m4(rv3d->persmatob, ob->obmat, rv3d->persmat);
210
211         /* initializes object space clipping, speeds up clip tests */
212         ED_view3d_local_clipping(rv3d, ob->obmat);
213 }
214
215 void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
216 {
217         ED_view3d_init_mats_rv3d(ob, rv3d);
218
219         /* we have to multiply instead of loading viewmatob to make
220            it work with duplis using displists, otherwise it will
221            override the dupli-matrix */
222         glMultMatrixf(ob->obmat);
223 }
224
225 /* ******************** default callbacks for view3d space ***************** */
226
227 static SpaceLink *view3d_new(const bContext *C)
228 {
229         Scene *scene= CTX_data_scene(C);
230         ARegion *ar;
231         View3D *v3d;
232         RegionView3D *rv3d;
233         
234         v3d= MEM_callocN(sizeof(View3D), "initview3d");
235         v3d->spacetype= SPACE_VIEW3D;
236         v3d->blockscale= 0.7f;
237         v3d->lay= v3d->layact= 1;
238         if(scene) {
239                 v3d->lay= v3d->layact= scene->lay;
240                 v3d->camera= scene->camera;
241         }
242         v3d->scenelock= TRUE;
243         v3d->grid= 1.0f;
244         v3d->gridlines= 16;
245         v3d->gridsubdiv = 10;
246         v3d->drawtype= OB_SOLID;
247         
248         v3d->gridflag |= V3D_SHOW_X;
249         v3d->gridflag |= V3D_SHOW_Y;
250         v3d->gridflag |= V3D_SHOW_FLOOR;
251         v3d->gridflag &= ~V3D_SHOW_Z;
252         
253         v3d->flag |= V3D_SELECT_OUTLINE;
254         
255         v3d->lens= 35.0f;
256         v3d->near= 0.01f;
257         v3d->far= 1000.0f;
258
259         v3d->twflag |= U.tw_flag & V3D_USE_MANIPULATOR;
260         v3d->twtype= V3D_MANIP_TRANSLATE;
261         v3d->around= V3D_CENTROID;
262         
263         /* header */
264         ar= MEM_callocN(sizeof(ARegion), "header for view3d");
265         
266         BLI_addtail(&v3d->regionbase, ar);
267         ar->regiontype= RGN_TYPE_HEADER;
268         ar->alignment= RGN_ALIGN_BOTTOM;
269         
270         /* tool shelf */
271         ar= MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
272         
273         BLI_addtail(&v3d->regionbase, ar);
274         ar->regiontype= RGN_TYPE_TOOLS;
275         ar->alignment= RGN_ALIGN_LEFT;
276         ar->flag = RGN_FLAG_HIDDEN;
277         
278         /* tool properties */
279         ar= MEM_callocN(sizeof(ARegion), "tool properties for view3d");
280         
281         BLI_addtail(&v3d->regionbase, ar);
282         ar->regiontype= RGN_TYPE_TOOL_PROPS;
283         ar->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
284         ar->flag = RGN_FLAG_HIDDEN;
285         
286         /* buttons/list view */
287         ar= MEM_callocN(sizeof(ARegion), "buttons for view3d");
288         
289         BLI_addtail(&v3d->regionbase, ar);
290         ar->regiontype= RGN_TYPE_UI;
291         ar->alignment= RGN_ALIGN_RIGHT;
292         ar->flag = RGN_FLAG_HIDDEN;
293         
294         /* main area */
295         ar= MEM_callocN(sizeof(ARegion), "main area for view3d");
296         
297         BLI_addtail(&v3d->regionbase, ar);
298         ar->regiontype= RGN_TYPE_WINDOW;
299         
300         ar->regiondata= MEM_callocN(sizeof(RegionView3D), "region view3d");
301         rv3d= ar->regiondata;
302         rv3d->viewquat[0]= 1.0f;
303         rv3d->persp= RV3D_PERSP;
304         rv3d->view= RV3D_VIEW_PERSPORTHO;
305         rv3d->dist= 10.0;
306         
307         return (SpaceLink *)v3d;
308 }
309
310 /* not spacelink itself */
311 static void view3d_free(SpaceLink *sl)
312 {
313         View3D *vd= (View3D *) sl;
314
315         BGpic *bgpic;
316         for(bgpic= vd->bgpicbase.first; bgpic; bgpic= bgpic->next) {
317                 if(bgpic->ima) bgpic->ima->id.us--;
318         }
319         BLI_freelistN(&vd->bgpicbase);
320
321         if(vd->localvd) MEM_freeN(vd->localvd);
322         
323         if(vd->properties_storage) MEM_freeN(vd->properties_storage);
324 }
325
326
327 /* spacetype; init callback */
328 static void view3d_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
329 {
330
331 }
332
333 static SpaceLink *view3d_duplicate(SpaceLink *sl)
334 {
335         View3D *v3do= (View3D *)sl;
336         View3D *v3dn= MEM_dupallocN(sl);
337         BGpic *bgpic;
338         
339         /* clear or remove stuff from old */
340         
341 // XXX  BIF_view3d_previewrender_free(v3do);
342         
343         if(v3do->localvd) {
344                 v3do->localvd= NULL;
345                 v3do->properties_storage= NULL;
346                 v3do->lay= v3dn->localvd->lay;
347                 v3do->lay &= 0xFFFFFF;
348         }
349         
350         /* copy or clear inside new stuff */
351
352         BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase);
353         for(bgpic= v3dn->bgpicbase.first; bgpic; bgpic= bgpic->next)
354                 if(bgpic->ima)
355                         bgpic->ima->id.us++;
356
357         v3dn->properties_storage= NULL;
358         
359         return (SpaceLink *)v3dn;
360 }
361
362 /* add handlers, stuff you only do once or on area/region changes */
363 static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
364 {
365         ListBase *lb;
366         wmKeyMap *keymap;
367
368         /* object ops. */
369         
370         /* important to be before Pose keymap since they can both be enabled at once */
371         keymap= WM_keymap_find(wm->defaultconf, "Face Mask", 0, 0);
372         WM_event_add_keymap_handler(&ar->handlers, keymap);
373         
374         /* Radish */
375         keymap= WM_keymap_find(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0);
376         WM_event_add_keymap_handler(&ar->handlers, keymap);
377
378         /* pose is not modal, operator poll checks for this */
379         keymap= WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
380         WM_event_add_keymap_handler(&ar->handlers, keymap);
381         
382         keymap= WM_keymap_find(wm->defaultconf, "Object Mode", 0, 0);
383         WM_event_add_keymap_handler(&ar->handlers, keymap);
384
385         keymap= WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
386         WM_event_add_keymap_handler(&ar->handlers, keymap);
387
388         keymap= WM_keymap_find(wm->defaultconf, "Vertex Paint", 0, 0);
389         WM_event_add_keymap_handler(&ar->handlers, keymap);
390
391         keymap= WM_keymap_find(wm->defaultconf, "Weight Paint", 0, 0);
392         WM_event_add_keymap_handler(&ar->handlers, keymap);
393
394         keymap= WM_keymap_find(wm->defaultconf, "Sculpt", 0, 0);
395         WM_event_add_keymap_handler(&ar->handlers, keymap);
396         
397         keymap= WM_keymap_find(wm->defaultconf, "Mesh", 0, 0);
398         WM_event_add_keymap_handler(&ar->handlers, keymap);
399         
400         keymap= WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
401         WM_event_add_keymap_handler(&ar->handlers, keymap);
402         
403         keymap= WM_keymap_find(wm->defaultconf, "Armature", 0, 0);
404         WM_event_add_keymap_handler(&ar->handlers, keymap);
405
406         keymap= WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
407         WM_event_add_keymap_handler(&ar->handlers, keymap);
408
409         keymap= WM_keymap_find(wm->defaultconf, "Metaball", 0, 0);
410         WM_event_add_keymap_handler(&ar->handlers, keymap);
411         
412         keymap= WM_keymap_find(wm->defaultconf, "Lattice", 0, 0);
413         WM_event_add_keymap_handler(&ar->handlers, keymap);
414
415         /* armature sketching needs to take over mouse */
416         keymap= WM_keymap_find(wm->defaultconf, "Armature Sketch", 0, 0);
417         WM_event_add_keymap_handler(&ar->handlers, keymap);
418
419         keymap= WM_keymap_find(wm->defaultconf, "Particle", 0, 0);
420         WM_event_add_keymap_handler(&ar->handlers, keymap);
421
422         /* editfont keymap swallows all... */
423         keymap= WM_keymap_find(wm->defaultconf, "Font", 0, 0);
424         WM_event_add_keymap_handler(&ar->handlers, keymap);
425
426         keymap= WM_keymap_find(wm->defaultconf, "Object Non-modal", 0, 0);
427         WM_event_add_keymap_handler(&ar->handlers, keymap);
428
429         keymap= WM_keymap_find(wm->defaultconf, "Frames", 0, 0);
430         WM_event_add_keymap_handler(&ar->handlers, keymap);
431
432         /* own keymap, last so modes can override it */
433         keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
434         WM_event_add_keymap_handler(&ar->handlers, keymap);
435
436         keymap= WM_keymap_find(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
437         WM_event_add_keymap_handler(&ar->handlers, keymap);
438         
439         /* add drop boxes */
440         lb= WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
441         
442         WM_event_add_dropbox_handler(&ar->handlers, lb);
443         
444 }
445
446 static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
447 {
448         if(drag->type==WM_DRAG_ID) {
449                 ID *id= (ID *)drag->poin;
450                 if( GS(id->name)==ID_OB )
451                         return 1;
452         }
453         return 0;
454 }
455
456 static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
457 {
458         if(drag->type==WM_DRAG_ID) {
459                 ID *id= (ID *)drag->poin;
460                 if( GS(id->name)==ID_MA )
461                         return 1;
462         }
463         return 0;
464 }
465
466 static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
467 {
468         if(drag->type==WM_DRAG_ID) {
469                 ID *id= (ID *)drag->poin;
470                 if( GS(id->name)==ID_IM )
471                         return 1;
472         }
473         else if(drag->type==WM_DRAG_PATH){
474                 if(ELEM(drag->icon, 0, ICON_FILE_IMAGE))        /* rule might not work? */
475                         return 1;
476         }
477         return 0;
478 }
479
480
481 static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
482 {
483         if( ED_view3d_give_base_under_cursor(C, event->mval) ) {
484                 return 0;
485         }
486         return view3d_ima_drop_poll(C, drag, event);
487 }
488
489 static int view3d_ima_ob_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
490 {
491         if( ED_view3d_give_base_under_cursor(C, event->mval) ) {
492                 return view3d_ima_drop_poll(C, drag, event);
493         }
494         return 0;
495 }
496
497 static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
498 {
499         ID *id= (ID *)drag->poin;
500         PointerRNA ptr;
501
502         /* need to put name in sub-operator in macro */
503         ptr= RNA_pointer_get(drop->ptr, "OBJECT_OT_add_named");
504         if(ptr.data)
505                 RNA_string_set(&ptr, "name", id->name+2);
506         else
507                 RNA_string_set(drop->ptr, "name", id->name+2);
508 }
509
510 static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
511 {
512         ID *id= (ID *)drag->poin;
513         
514         RNA_string_set(drop->ptr, "name", id->name+2);
515 }
516
517 static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
518 {
519         ID *id= (ID *)drag->poin;
520         
521         if(id)
522                 RNA_string_set(drop->ptr, "name", id->name+2);
523         if(drag->path[0]) 
524                 RNA_string_set(drop->ptr, "filepath", drag->path);
525 }
526
527
528 /* region dropbox definition */
529 static void view3d_dropboxes(void)
530 {
531         ListBase *lb= WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
532         
533         WM_dropbox_add(lb, "OBJECT_OT_add_named_cursor", view3d_ob_drop_poll, view3d_ob_drop_copy);
534         WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
535         WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_ob_drop_poll, view3d_id_path_drop_copy);
536         WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
537 }
538
539
540
541 /* type callback, not region itself */
542 static void view3d_main_area_free(ARegion *ar)
543 {
544         RegionView3D *rv3d= ar->regiondata;
545         
546         if(rv3d) {
547                 if(rv3d->localvd) MEM_freeN(rv3d->localvd);
548                 if(rv3d->clipbb) MEM_freeN(rv3d->clipbb);
549
550                 // XXX  retopo_free_view_data(rv3d);
551                 if(rv3d->ri) { 
552                         // XXX          BIF_view3d_previewrender_free(rv3d);
553                 }
554                 
555                 if(rv3d->depths) {
556                         if(rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
557                         MEM_freeN(rv3d->depths);
558                 }
559                 MEM_freeN(rv3d);
560                 ar->regiondata= NULL;
561         }
562 }
563
564 /* copy regiondata */
565 static void *view3d_main_area_duplicate(void *poin)
566 {
567         if(poin) {
568                 RegionView3D *rv3d= poin, *new;
569         
570                 new= MEM_dupallocN(rv3d);
571                 if(rv3d->localvd) 
572                         new->localvd= MEM_dupallocN(rv3d->localvd);
573                 if(rv3d->clipbb) 
574                         new->clipbb= MEM_dupallocN(rv3d->clipbb);
575                 
576                 new->depths= NULL;
577                 new->ri= NULL;
578                 new->gpd= NULL;
579                 new->sms= NULL;
580                 new->smooth_timer= NULL;
581                 
582                 return new;
583         }
584         return NULL;
585 }
586
587 static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene)
588 {
589         wmWindow *win= wmn->wm->winactive;
590         ScrArea *sa;
591         unsigned int lay_used= 0;
592         Base *base;
593
594         if (!win) return;
595
596         base= scene->base.first;
597         while(base) {
598                 lay_used |= base->lay & ((1<<20)-1); /* ignore localview */
599
600                 if (lay_used == (1<<20)-1)
601                         break;
602
603                 base= base->next;
604         }
605
606         for(sa= win->screen->areabase.first; sa; sa= sa->next) {
607                 if(sa->spacetype == SPACE_VIEW3D) {
608                         if(BLI_findindex(&sa->regionbase, ar) != -1) {
609                                 View3D *v3d= sa->spacedata.first;
610                                 v3d->lay_used= lay_used;
611                                 break;
612                         }
613                 }
614         }
615 }
616
617 static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
618 {
619         bScreen *sc;
620
621         /* context changes */
622         switch(wmn->category) {
623                 case NC_ANIMATION:
624                         switch(wmn->data) {
625                                 case ND_KEYFRAME_PROP:
626                                 case ND_NLA_ACTCHANGE:
627                                         ED_region_tag_redraw(ar);
628                                         break;
629                                 case ND_NLA:
630                                 case ND_KEYFRAME:
631                                         if (wmn->action == NA_EDITED)
632                                                 ED_region_tag_redraw(ar);
633                                         break;
634                                 case ND_ANIMCHAN:
635                                         if (wmn->action == NA_SELECTED)
636                                                 ED_region_tag_redraw(ar);
637                                         break;
638                         }
639                         break;
640                 case NC_SCENE:
641                         switch(wmn->data) {
642                                 case ND_LAYER_CONTENT:
643                                         view3d_recalc_used_layers(ar, wmn, wmn->reference);
644                                         ED_region_tag_redraw(ar);
645                                         break;
646                                 case ND_FRAME:
647                                 case ND_TRANSFORM:
648                                 case ND_OB_ACTIVE:
649                                 case ND_OB_SELECT:
650                                 case ND_OB_VISIBLE:
651                                 case ND_LAYER:
652                                 case ND_RENDER_OPTIONS:
653                                 case ND_MODE:
654                                         ED_region_tag_redraw(ar);
655                                         break;
656                                 case ND_WORLD:
657                                         /* handled by space_view3d_listener() for v3d access */
658                                         break;
659                         }
660                         if (wmn->action == NA_EDITED)
661                                 ED_region_tag_redraw(ar);
662                         break;
663                 case NC_OBJECT:
664                         switch(wmn->data) {
665                                 case ND_BONE_ACTIVE:
666                                 case ND_BONE_SELECT:
667                                 case ND_TRANSFORM:
668                                 case ND_POSE:
669                                 case ND_DRAW:
670                                 case ND_MODIFIER:
671                                 case ND_CONSTRAINT:
672                                 case ND_KEYS:
673                                 case ND_PARTICLE:
674                                         ED_region_tag_redraw(ar);
675                                         break;
676                         }
677                         switch(wmn->action) {
678                                 case NA_ADDED:
679                                         ED_region_tag_redraw(ar);
680                                         break;
681                         }
682                         break;
683                 case NC_GEOM:
684                         switch(wmn->data) {
685                                 case ND_DATA:
686                                 case ND_SELECT:
687                                         ED_region_tag_redraw(ar);
688                                         break;
689                         }
690                         switch(wmn->action) {
691                                 case NA_EDITED:
692                                         ED_region_tag_redraw(ar);
693                                         break;
694                         }
695                         break;
696                 case NC_GROUP:
697                         /* all group ops for now */
698                         ED_region_tag_redraw(ar);
699                         break;
700                 case NC_BRUSH:
701                         if(wmn->action == NA_EDITED)
702                                 ED_region_tag_redraw_overlay(ar);
703                         break;                  
704                 case NC_MATERIAL:
705                         switch(wmn->data) {
706                                 case ND_SHADING_DRAW:
707                                         ED_region_tag_redraw(ar);
708                                         break;
709                         }
710                         break;
711                 case NC_WORLD:
712                         switch(wmn->data) {
713                                 case ND_WORLD_DRAW:
714                                         /* handled by space_view3d_listener() for v3d access */
715                                         break;
716                                 case ND_WORLD_STARS:
717                                 {
718                                         RegionView3D *rv3d= ar->regiondata;
719                                         if(rv3d->persp == RV3D_CAMOB) {
720                                                 ED_region_tag_redraw(ar);
721                                         }
722                                 }
723                         }
724                         break;
725                 case NC_LAMP:
726                         switch(wmn->data) {
727                                 case ND_LIGHTING_DRAW:
728                                         ED_region_tag_redraw(ar);
729                                         break;
730                         }
731                         break;
732                 case NC_IMAGE:  
733                         /* this could be more fine grained checks if we had
734                          * more context than just the region */
735                         ED_region_tag_redraw(ar);
736                         break;
737                 case NC_TEXTURE:        
738                         /* same as above */
739                         ED_region_tag_redraw(ar);
740                         break;
741                 case NC_SPACE:
742                         if(wmn->data == ND_SPACE_VIEW3D) {
743                                 if (wmn->subtype == NS_VIEW3D_GPU) {
744                                         RegionView3D *rv3d= ar->regiondata;
745                                         rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
746                                 }
747                                 ED_region_tag_redraw(ar);
748                         }
749                         break;
750                 case NC_ID:
751                         if(wmn->action == NA_RENAME)
752                                 ED_region_tag_redraw(ar);
753                         break;
754                 case NC_SCREEN:
755                         switch(wmn->data) {
756                                 case ND_GPENCIL:
757                                 case ND_ANIMPLAY:
758                                 case ND_SKETCH:
759                                         ED_region_tag_redraw(ar);
760                                         break;
761                                 case ND_SCREENBROWSE:
762                                 case ND_SCREENDELETE:
763                                 case ND_SCREENSET:
764                                         /* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */
765                                         /* updates used layers only for View3D in active screen */
766                                         sc= wmn->reference;
767                                         view3d_recalc_used_layers(ar, wmn, sc->scene);
768                                         ED_region_tag_redraw(ar);
769                                         break;
770                         }
771
772                         break;
773         }
774 }
775
776 /* concept is to retrieve cursor type context-less */
777 static void view3d_main_area_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
778 {
779         Scene *scene= win->screen->scene;
780
781         if(scene->obedit) {
782                 WM_cursor_set(win, CURSOR_EDIT);
783         }
784         else {
785                 WM_cursor_set(win, CURSOR_STD);
786         }
787 }
788
789 /* add handlers, stuff you only do once or on area/region changes */
790 static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar)
791 {
792         wmKeyMap *keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
793         
794         WM_event_add_keymap_handler(&ar->handlers, keymap);
795
796         ED_region_header_init(ar);
797 }
798
799 static void view3d_header_area_draw(const bContext *C, ARegion *ar)
800 {
801         ED_region_header(C, ar);
802 }
803
804 static void view3d_header_area_listener(ARegion *ar, wmNotifier *wmn)
805 {
806         /* context changes */
807         switch(wmn->category) {
808                 case NC_SCENE:
809                         switch(wmn->data) {
810                                 case ND_FRAME:
811                                 case ND_OB_ACTIVE:
812                                 case ND_OB_SELECT:
813                                 case ND_OB_VISIBLE:
814                                 case ND_MODE:
815                                 case ND_LAYER:
816                                 case ND_TOOLSETTINGS:
817                                 case ND_LAYER_CONTENT:
818                                         ED_region_tag_redraw(ar);
819                                         break;
820                         }
821                         break;
822                 case NC_SPACE:
823                         if(wmn->data == ND_SPACE_VIEW3D)
824                                 ED_region_tag_redraw(ar);
825                         break;
826         }
827 }
828
829 /* add handlers, stuff you only do once or on area/region changes */
830 static void view3d_buttons_area_init(wmWindowManager *wm, ARegion *ar)
831 {
832         wmKeyMap *keymap;
833
834         ED_region_panels_init(wm, ar);
835         
836         keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
837         WM_event_add_keymap_handler(&ar->handlers, keymap);
838 }
839
840 static void view3d_buttons_area_draw(const bContext *C, ARegion *ar)
841 {
842         ED_region_panels(C, ar, 1, NULL, -1);
843 }
844
845 static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
846 {
847         /* context changes */
848         switch(wmn->category) {
849                 case NC_ANIMATION:
850                         switch(wmn->data) {
851                                 case ND_KEYFRAME_PROP:
852                                 case ND_NLA_ACTCHANGE:
853                                         ED_region_tag_redraw(ar);
854                                         break;
855                                 case ND_NLA:
856                                 case ND_KEYFRAME:
857                                         if (wmn->action == NA_EDITED)
858                                                 ED_region_tag_redraw(ar);
859                                         break;  
860                         }
861                         break;
862                 case NC_SCENE:
863                         switch(wmn->data) {
864                                 case ND_FRAME:
865                                 case ND_OB_ACTIVE:
866                                 case ND_OB_SELECT:
867                                 case ND_OB_VISIBLE:
868                                 case ND_MODE:
869                                 case ND_LAYER:
870                                 case ND_LAYER_CONTENT:
871                                         ED_region_tag_redraw(ar);
872                                         break;
873                         }
874                         switch(wmn->action) {
875                                 case NA_EDITED:
876                                         ED_region_tag_redraw(ar);
877                                         break;
878                         }
879                         break;
880                 case NC_OBJECT:
881                         switch(wmn->data) {
882                                 case ND_BONE_ACTIVE:
883                                 case ND_BONE_SELECT:
884                                 case ND_TRANSFORM:
885                                 case ND_POSE:
886                                 case ND_DRAW:
887                                 case ND_KEYS:
888                                 case ND_MODIFIER:
889                                         ED_region_tag_redraw(ar);
890                                         break;
891                         }
892                         break;
893                 case NC_GEOM:
894                         switch(wmn->data) {
895                                 case ND_DATA:
896                                 case ND_SELECT:
897                                         ED_region_tag_redraw(ar);
898                                         break;
899                         }
900                         if (wmn->action == NA_EDITED)
901                                 ED_region_tag_redraw(ar);
902                         break;
903                 case NC_TEXTURE:
904                         /* for brush textures */
905                         ED_region_tag_redraw(ar);
906                         break;
907                 case NC_BRUSH:
908                         if(wmn->action==NA_EDITED)
909                                 ED_region_tag_redraw(ar);
910                         break;
911                 case NC_SPACE:
912                         if(wmn->data == ND_SPACE_VIEW3D)
913                                 ED_region_tag_redraw(ar);
914                         break;
915                 case NC_ID:
916                         if(wmn->action == NA_RENAME)
917                                 ED_region_tag_redraw(ar);
918                         break;
919                 case NC_SCREEN: 
920                         if(wmn->data == ND_GPENCIL)
921                                 ED_region_tag_redraw(ar);
922                         break;
923         }
924 }
925
926 /* add handlers, stuff you only do once or on area/region changes */
927 static void view3d_tools_area_init(wmWindowManager *wm, ARegion *ar)
928 {
929         wmKeyMap *keymap;
930         
931         ED_region_panels_init(wm, ar);
932
933         keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
934         WM_event_add_keymap_handler(&ar->handlers, keymap);
935 }
936
937 static void view3d_tools_area_draw(const bContext *C, ARegion *ar)
938 {
939         ED_region_panels(C, ar, 1, CTX_data_mode_string(C), -1);
940 }
941
942 static void view3d_props_area_listener(ARegion *ar, wmNotifier *wmn)
943 {
944         /* context changes */
945         switch(wmn->category) {
946                 case NC_WM:
947                         if(wmn->data == ND_HISTORY)
948                                 ED_region_tag_redraw(ar);
949                         break;
950                 case NC_SCENE:
951                         if(wmn->data == ND_MODE)
952                                 ED_region_tag_redraw(ar);
953                         break;
954                 case NC_SPACE:
955                         if(wmn->data == ND_SPACE_VIEW3D)
956                                 ED_region_tag_redraw(ar);
957                         break;
958         }
959 }
960
961 /*area (not region) level listener*/
962 static void space_view3d_listener(struct ScrArea *sa, struct wmNotifier *wmn)
963 {
964         View3D *v3d = sa->spacedata.first;
965
966         /* context changes */
967         switch(wmn->category) {
968                 case NC_SCENE:
969                         switch(wmn->data) {
970                                 case ND_WORLD:
971                                         if(v3d->flag2 & V3D_RENDER_OVERRIDE)
972                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
973                                         break;
974                         }
975                         break;
976                 case NC_WORLD:
977                         switch(wmn->data) {
978                                 case ND_WORLD_DRAW:
979                                         if(v3d->flag2 & V3D_RENDER_OVERRIDE)
980                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
981                                         break;
982                         }
983                         break;
984                 case NC_MATERIAL:
985                         switch(wmn->data) {
986                                 case ND_NODES:
987                                         if(v3d->drawtype == OB_TEXTURE)
988                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
989                                         break;
990                         }
991                         break;
992         }
993
994 #if 0 // removed since BKE_image_user_calc_frame is now called in draw_bgpic because screen_ops doesnt call the notifier.
995         if (wmn->category == NC_SCENE && wmn->data == ND_FRAME) {
996                 View3D *v3d = area->spacedata.first;
997                 BGpic *bgpic = v3d->bgpicbase.first;
998
999                 for (; bgpic; bgpic = bgpic->next) {
1000                         if (bgpic->ima) {
1001                                 Scene *scene = wmn->reference;
1002                                 BKE_image_user_calc_frame(&bgpic->iuser, scene->r.cfra, 0);
1003                         }
1004                 }
1005         }
1006 #endif
1007 }
1008
1009 const char *view3d_context_dir[] = {
1010         "selected_objects", "selected_bases", "selected_editable_objects",
1011         "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
1012         "active_base", "active_object", NULL};
1013
1014 static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
1015 {
1016         View3D *v3d= CTX_wm_view3d(C);
1017         Scene *scene= CTX_data_scene(C);
1018         Base *base;
1019         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 */
1020
1021         if(CTX_data_dir(member)) {
1022                 CTX_data_dir_set(result, view3d_context_dir);
1023         }
1024         else if(CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
1025                 int selected_objects= CTX_data_equals(member, "selected_objects");
1026
1027                 for(base=scene->base.first; base; base=base->next) {
1028                         if((base->flag & SELECT) && (base->lay & lay)) {
1029                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
1030                                         if(selected_objects)
1031                                                 CTX_data_id_list_add(result, &base->object->id);
1032                                         else
1033                                                 CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
1034                                 }
1035                         }
1036                 }
1037                 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
1038                 return 1;
1039         }
1040         else if(CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
1041                 int selected_editable_objects= CTX_data_equals(member, "selected_editable_objects");
1042
1043                 for(base=scene->base.first; base; base=base->next) {
1044                         if((base->flag & SELECT) && (base->lay & lay)) {
1045                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
1046                                         if(0==object_is_libdata(base->object)) {
1047                                                 if(selected_editable_objects)
1048                                                         CTX_data_id_list_add(result, &base->object->id);
1049                                                 else
1050                                                         CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
1051                                         }
1052                                 }
1053                         }
1054                 }
1055                 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
1056                 return 1;
1057         }
1058         else if(CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
1059                 int visible_objects= CTX_data_equals(member, "visible_objects");
1060
1061                 for(base=scene->base.first; base; base=base->next) {
1062                         if(base->lay & lay) {
1063                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
1064                                         if(visible_objects)
1065                                                 CTX_data_id_list_add(result, &base->object->id);
1066                                         else
1067                                                 CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
1068                                 }
1069                         }
1070                 }
1071                 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
1072                 return 1;
1073         }
1074         else if(CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
1075                 int selectable_objects= CTX_data_equals(member, "selectable_objects");
1076
1077                 for(base=scene->base.first; base; base=base->next) {
1078                         if(base->lay & lay) {
1079                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0 && (base->object->restrictflag & OB_RESTRICT_SELECT)==0) {
1080                                         if(selectable_objects)
1081                                                 CTX_data_id_list_add(result, &base->object->id);
1082                                         else
1083                                                 CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
1084                                 }
1085                         }
1086                 }
1087                 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
1088                 return 1;
1089         }
1090         else if(CTX_data_equals(member, "active_base")) {
1091                 if(scene->basact && (scene->basact->lay & lay))
1092                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
1093                                 CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact);
1094                 
1095                 return 1;
1096         }
1097         else if(CTX_data_equals(member, "active_object")) {
1098                 if(scene->basact && (scene->basact->lay & lay))
1099                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
1100                                 CTX_data_id_pointer_set(result, &scene->basact->object->id);
1101                 
1102                 return 1;
1103         }
1104         else {
1105                 return 0; /* not found */
1106         }
1107
1108         return -1; /* found but not available */
1109 }
1110
1111
1112 /* only called once, from space/spacetypes.c */
1113 void ED_spacetype_view3d(void)
1114 {
1115         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype view3d");
1116         ARegionType *art;
1117         
1118         st->spaceid= SPACE_VIEW3D;
1119         strncpy(st->name, "View3D", BKE_ST_MAXNAME);
1120         
1121         st->new= view3d_new;
1122         st->free= view3d_free;
1123         st->init= view3d_init;
1124         st->listener = space_view3d_listener;
1125         st->duplicate= view3d_duplicate;
1126         st->operatortypes= view3d_operatortypes;
1127         st->keymap= view3d_keymap;
1128         st->dropboxes= view3d_dropboxes;
1129         st->context= view3d_context;
1130         
1131         /* regions: main window */
1132         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
1133         art->regionid = RGN_TYPE_WINDOW;
1134         art->keymapflag= ED_KEYMAP_GPENCIL;
1135         art->draw= view3d_main_area_draw;
1136         art->init= view3d_main_area_init;
1137         art->free= view3d_main_area_free;
1138         art->duplicate= view3d_main_area_duplicate;
1139         art->listener= view3d_main_area_listener;
1140         art->cursor= view3d_main_area_cursor;
1141         art->lock= 1;   /* can become flag, see BKE_spacedata_draw_locks */
1142         BLI_addhead(&st->regiontypes, art);
1143         
1144         /* regions: listview/buttons */
1145         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
1146         art->regionid = RGN_TYPE_UI;
1147         art->prefsizex= 180; // XXX
1148         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
1149         art->listener= view3d_buttons_area_listener;
1150         art->init= view3d_buttons_area_init;
1151         art->draw= view3d_buttons_area_draw;
1152         BLI_addhead(&st->regiontypes, art);
1153
1154         view3d_buttons_register(art);
1155
1156         /* regions: tool(bar) */
1157         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
1158         art->regionid = RGN_TYPE_TOOLS;
1159         art->prefsizex= 160; // XXX
1160         art->prefsizey= 50; // XXX
1161         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
1162         art->listener= view3d_buttons_area_listener;
1163         art->init= view3d_tools_area_init;
1164         art->draw= view3d_tools_area_draw;
1165         BLI_addhead(&st->regiontypes, art);
1166         
1167 #if 0
1168         /* unfinished still */
1169         view3d_toolshelf_register(art);
1170 #endif
1171
1172         /* regions: tool properties */
1173         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d tool properties region");
1174         art->regionid = RGN_TYPE_TOOL_PROPS;
1175         art->prefsizex= 0;
1176         art->prefsizey= 120;
1177         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
1178         art->listener= view3d_props_area_listener;
1179         art->init= view3d_tools_area_init;
1180         art->draw= view3d_tools_area_draw;
1181         BLI_addhead(&st->regiontypes, art);
1182         
1183         view3d_tool_props_register(art);
1184         
1185         
1186         /* regions: header */
1187         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
1188         art->regionid = RGN_TYPE_HEADER;
1189         art->prefsizey= HEADERY;
1190         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER;
1191         art->listener= view3d_header_area_listener;
1192         art->init= view3d_header_area_init;
1193         art->draw= view3d_header_area_draw;
1194         BLI_addhead(&st->regiontypes, art);
1195         
1196         BKE_spacetype_register(st);
1197 }
1198