f726b771fb32d84c6f0a8100873147af4a798655
[blender-staging.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 #include <string.h>
30 #include <stdio.h>
31
32 #include "DNA_action_types.h"
33 #include "DNA_armature_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_space_types.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_screen_types.h"
38 #include "DNA_view3d_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
46 #include "BKE_action.h"
47 #include "BKE_context.h"
48 #include "BKE_global.h"
49 #include "BKE_screen.h"
50 #include "BKE_utildefines.h"
51 #include "BKE_image.h"
52
53 #include "ED_armature.h"
54 #include "ED_space_api.h"
55 #include "ED_screen.h"
56 #include "ED_object.h"
57
58 #include "BIF_gl.h"
59
60 #include "GPU_draw.h"
61
62 #include "WM_api.h"
63 #include "WM_types.h"
64
65 #include "UI_interface.h"
66 #include "UI_resources.h"
67 #include "UI_view2d.h"
68
69 #include "RNA_access.h"
70
71 #include "view3d_intern.h"      // own include
72
73 /* ******************** manage regions ********************* */
74
75 ARegion *view3d_has_buttons_region(ScrArea *sa)
76 {
77         ARegion *ar, *arnew;
78         
79         for(ar= sa->regionbase.first; ar; ar= ar->next)
80                 if(ar->regiontype==RGN_TYPE_UI)
81                         return ar;
82         
83         /* add subdiv level; after header */
84         for(ar= sa->regionbase.first; ar; ar= ar->next)
85                 if(ar->regiontype==RGN_TYPE_HEADER)
86                         break;
87         
88         /* is error! */
89         if(ar==NULL) return NULL;
90         
91         arnew= MEM_callocN(sizeof(ARegion), "buttons for view3d");
92         
93         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
94         arnew->regiontype= RGN_TYPE_UI;
95         arnew->alignment= RGN_ALIGN_RIGHT;
96         
97         arnew->flag = RGN_FLAG_HIDDEN;
98         
99         return arnew;
100 }
101
102 ARegion *view3d_has_tools_region(ScrArea *sa)
103 {
104         ARegion *ar, *artool=NULL, *arprops=NULL, *arhead;
105         
106         for(ar= sa->regionbase.first; ar; ar= ar->next) {
107                 if(ar->regiontype==RGN_TYPE_TOOLS)
108                         artool= ar;
109                 if(ar->regiontype==RGN_TYPE_TOOL_PROPS)
110                         arprops= ar;
111         }
112         
113         /* tool region hide/unhide also hides props */
114         if(arprops && artool) return artool;
115         
116         if(artool==NULL) {
117                 /* add subdiv level; after header */
118                 for(arhead= sa->regionbase.first; arhead; arhead= arhead->next)
119                         if(arhead->regiontype==RGN_TYPE_HEADER)
120                                 break;
121                 
122                 /* is error! */
123                 if(arhead==NULL) return NULL;
124                 
125                 artool= MEM_callocN(sizeof(ARegion), "tools for view3d");
126                 
127                 BLI_insertlinkafter(&sa->regionbase, arhead, artool);
128                 artool->regiontype= RGN_TYPE_TOOLS;
129                 artool->alignment= RGN_ALIGN_LEFT; //RGN_OVERLAP_LEFT;
130                 artool->flag = RGN_FLAG_HIDDEN;
131         }
132
133         if(arprops==NULL) {
134                 /* add extra subdivided region for tool properties */
135                 arprops= MEM_callocN(sizeof(ARegion), "tool props for view3d");
136                 
137                 BLI_insertlinkafter(&sa->regionbase, artool, arprops);
138                 arprops->regiontype= RGN_TYPE_TOOL_PROPS;
139                 arprops->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
140         }
141         
142         return artool;
143 }
144
145 /* ****************************************************** */
146
147 /* function to always find a regionview3d context inside 3D window */
148 RegionView3D *ED_view3d_context_rv3d(bContext *C)
149 {
150         RegionView3D *rv3d= CTX_wm_region_view3d(C);
151         
152         if(rv3d==NULL) {
153                 ScrArea *sa =CTX_wm_area(C);
154                 if(sa && sa->spacetype==SPACE_VIEW3D) {
155                         ARegion *ar;
156                         for(ar= sa->regionbase.first; ar; ar= ar->next)
157                                 if(ar->regiontype==RGN_TYPE_WINDOW)
158                                         return ar->regiondata;
159                 }
160         }
161         return rv3d;
162 }
163
164 /* Most of the time this isn't needed since you could assume the view matrix was
165  * set while drawing, however when functions like mesh_foreachScreenVert are
166  * called by selection tools, we can't be sure this object was the last.
167  *
168  * for example, transparent objects are drawn after editmode and will cause
169  * the rv3d mat's to change and break selection.
170  *
171  * 'ED_view3d_init_mats_rv3d' should be called before
172  * view3d_project_short_clip and view3d_project_short_noclip in cases where
173  * these functions are not used during draw_object
174  */
175 void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
176 {
177         /* local viewmat and persmat, to calculate projections */
178         mul_m4_m4m4(rv3d->viewmatob, ob->obmat, rv3d->viewmat);
179         mul_m4_m4m4(rv3d->persmatob, ob->obmat, rv3d->persmat);
180
181         /* we have to multiply instead of loading viewmatob to make
182            it work with duplis using displists, otherwise it will
183            override the dupli-matrix */
184         glMultMatrixf(ob->obmat);
185
186         /* initializes object space clipping, speeds up clip tests */
187         ED_view3d_local_clipping(rv3d, ob->obmat);
188 }
189
190 /* ******************** default callbacks for view3d space ***************** */
191
192 static SpaceLink *view3d_new(const bContext *C)
193 {
194         Scene *scene= CTX_data_scene(C);
195         ARegion *ar;
196         View3D *v3d;
197         RegionView3D *rv3d;
198         
199         v3d= MEM_callocN(sizeof(View3D), "initview3d");
200         v3d->spacetype= SPACE_VIEW3D;
201         v3d->blockscale= 0.7f;
202         v3d->lay= v3d->layact= 1;
203         if(scene) {
204                 v3d->lay= v3d->layact= scene->lay;
205                 v3d->camera= scene->camera;
206         }
207         v3d->scenelock= 1;
208         v3d->grid= 1.0f;
209         v3d->gridlines= 16;
210         v3d->gridsubdiv = 10;
211         v3d->drawtype= OB_WIRE;
212         
213         v3d->gridflag |= V3D_SHOW_X;
214         v3d->gridflag |= V3D_SHOW_Y;
215         v3d->gridflag |= V3D_SHOW_FLOOR;
216         v3d->gridflag &= ~V3D_SHOW_Z;
217         
218         v3d->lens= 35.0f;
219         v3d->near= 0.01f;
220         v3d->far= 500.0f;
221
222         v3d->twtype= V3D_MANIP_TRANSLATE;
223         
224         /* header */
225         ar= MEM_callocN(sizeof(ARegion), "header for view3d");
226         
227         BLI_addtail(&v3d->regionbase, ar);
228         ar->regiontype= RGN_TYPE_HEADER;
229         ar->alignment= RGN_ALIGN_BOTTOM;
230         
231         /* tool shelf */
232         ar= MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
233         
234         BLI_addtail(&v3d->regionbase, ar);
235         ar->regiontype= RGN_TYPE_TOOLS;
236         ar->alignment= RGN_ALIGN_LEFT;
237         ar->flag = RGN_FLAG_HIDDEN;
238         
239         /* tool properties */
240         ar= MEM_callocN(sizeof(ARegion), "tool properties for view3d");
241         
242         BLI_addtail(&v3d->regionbase, ar);
243         ar->regiontype= RGN_TYPE_TOOL_PROPS;
244         ar->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
245         ar->flag = RGN_FLAG_HIDDEN;
246         
247         /* buttons/list view */
248         ar= MEM_callocN(sizeof(ARegion), "buttons for view3d");
249         
250         BLI_addtail(&v3d->regionbase, ar);
251         ar->regiontype= RGN_TYPE_UI;
252         ar->alignment= RGN_ALIGN_RIGHT;
253         ar->flag = RGN_FLAG_HIDDEN;
254         
255         /* main area */
256         ar= MEM_callocN(sizeof(ARegion), "main area for view3d");
257         
258         BLI_addtail(&v3d->regionbase, ar);
259         ar->regiontype= RGN_TYPE_WINDOW;
260         
261         ar->regiondata= MEM_callocN(sizeof(RegionView3D), "region view3d");
262         rv3d= ar->regiondata;
263         rv3d->viewquat[0]= 1.0f;
264         rv3d->persp= 1;
265         rv3d->view= 7;
266         rv3d->dist= 10.0;
267         
268         return (SpaceLink *)v3d;
269 }
270
271 /* not spacelink itself */
272 static void view3d_free(SpaceLink *sl)
273 {
274         View3D *vd= (View3D *) sl;
275
276         BGpic *bgpic;
277         for(bgpic= vd->bgpicbase.first; bgpic; bgpic= bgpic->next) {
278                 if(bgpic->ima) bgpic->ima->id.us--;
279         }
280         BLI_freelistN(&vd->bgpicbase);
281
282         if(vd->localvd) MEM_freeN(vd->localvd);
283         
284         if(vd->properties_storage) MEM_freeN(vd->properties_storage);
285         
286 }
287
288
289 /* spacetype; init callback */
290 static void view3d_init(struct wmWindowManager *wm, ScrArea *sa)
291 {
292
293 }
294
295 static SpaceLink *view3d_duplicate(SpaceLink *sl)
296 {
297         View3D *v3do= (View3D *)sl;
298         View3D *v3dn= MEM_dupallocN(sl);
299         BGpic *bgpic;
300         
301         /* clear or remove stuff from old */
302         
303 // XXX  BIF_view3d_previewrender_free(v3do);
304         
305         if(v3do->localvd) {
306                 v3do->localvd= NULL;
307                 v3do->properties_storage= NULL;
308                 v3do->lay= v3dn->localvd->lay;
309                 v3do->lay &= 0xFFFFFF;
310         }
311         
312         /* copy or clear inside new stuff */
313
314         BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase);
315         for(bgpic= v3dn->bgpicbase.first; bgpic; bgpic= bgpic->next)
316                 if(bgpic->ima)
317                         bgpic->ima->id.us++;
318
319         v3dn->properties_storage= NULL;
320         
321         return (SpaceLink *)v3dn;
322 }
323
324 /* add handlers, stuff you only do once or on area/region changes */
325 static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
326 {
327         ListBase *lb;
328         wmKeyMap *keymap;
329
330         /* object ops. */
331         
332         /* pose is not modal, operator poll checks for this */
333         keymap= WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
334         WM_event_add_keymap_handler(&ar->handlers, keymap);
335         
336         keymap= WM_keymap_find(wm->defaultconf, "Object Mode", 0, 0);
337         WM_event_add_keymap_handler(&ar->handlers, keymap);
338
339         keymap= WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
340         WM_event_add_keymap_handler(&ar->handlers, keymap);
341
342         keymap= WM_keymap_find(wm->defaultconf, "Vertex Paint", 0, 0);
343         WM_event_add_keymap_handler(&ar->handlers, keymap);
344
345         keymap= WM_keymap_find(wm->defaultconf, "Weight Paint", 0, 0);
346         WM_event_add_keymap_handler(&ar->handlers, keymap);
347         
348         keymap= WM_keymap_find(wm->defaultconf, "Face Mask", 0, 0);
349         WM_event_add_keymap_handler(&ar->handlers, keymap);
350
351         keymap= WM_keymap_find(wm->defaultconf, "Sculpt", 0, 0);
352         WM_event_add_keymap_handler(&ar->handlers, keymap);
353         
354         keymap= WM_keymap_find(wm->defaultconf, "Mesh", 0, 0);
355         WM_event_add_keymap_handler(&ar->handlers, keymap);
356         
357         keymap= WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
358         WM_event_add_keymap_handler(&ar->handlers, keymap);
359         
360         keymap= WM_keymap_find(wm->defaultconf, "Armature", 0, 0);
361         WM_event_add_keymap_handler(&ar->handlers, keymap);
362
363         keymap= WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
364         WM_event_add_keymap_handler(&ar->handlers, keymap);
365
366         keymap= WM_keymap_find(wm->defaultconf, "Metaball", 0, 0);
367         WM_event_add_keymap_handler(&ar->handlers, keymap);
368         
369         keymap= WM_keymap_find(wm->defaultconf, "Lattice", 0, 0);
370         WM_event_add_keymap_handler(&ar->handlers, keymap);
371
372         /* armature sketching needs to take over mouse */
373         keymap= WM_keymap_find(wm->defaultconf, "Armature Sketch", 0, 0);
374         WM_event_add_keymap_handler(&ar->handlers, keymap);
375
376         keymap= WM_keymap_find(wm->defaultconf, "Particle", 0, 0);
377         WM_event_add_keymap_handler(&ar->handlers, keymap);
378
379         /* editfont keymap swallows all... */
380         keymap= WM_keymap_find(wm->defaultconf, "Font", 0, 0);
381         WM_event_add_keymap_handler(&ar->handlers, keymap);
382
383         keymap= WM_keymap_find(wm->defaultconf, "Object Non-modal", 0, 0);
384         WM_event_add_keymap_handler(&ar->handlers, keymap);
385
386         keymap= WM_keymap_find(wm->defaultconf, "Frames", 0, 0);
387         WM_event_add_keymap_handler(&ar->handlers, keymap);
388
389         /* own keymap, last so modes can override it */
390         keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
391         WM_event_add_keymap_handler(&ar->handlers, keymap);
392
393         keymap= WM_keymap_find(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
394         WM_event_add_keymap_handler(&ar->handlers, keymap);
395         
396         /* add drop boxes */
397         lb= WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
398         
399         WM_event_add_dropbox_handler(&ar->handlers, lb);
400         
401 }
402
403 static int view3d_ob_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
404 {
405         if(drag->type==WM_DRAG_ID) {
406                 ID *id= (ID *)drag->poin;
407                 if( GS(id->name)==ID_OB )
408                         return 1;
409         }
410         return 0;
411 }
412
413 static int view3d_mat_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
414 {
415         if(drag->type==WM_DRAG_ID) {
416                 ID *id= (ID *)drag->poin;
417                 if( GS(id->name)==ID_MA )
418                         return 1;
419         }
420         return 0;
421 }
422
423 static int view3d_ima_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
424 {
425         if(drag->type==WM_DRAG_ID) {
426                 ID *id= (ID *)drag->poin;
427                 if( GS(id->name)==ID_IM )
428                         return 1;
429         }
430         return 0;
431 }
432
433 static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
434 {
435         ID *id= (ID *)drag->poin;
436         PointerRNA ptr;
437
438         /* need to put name in sub-operator in macro */
439         ptr= RNA_pointer_get(drop->ptr, "OBJECT_OT_add_named");
440         if(ptr.data)
441                 RNA_string_set(&ptr, "name", id->name+2);
442         else
443                 RNA_string_set(drop->ptr, "name", id->name+2);
444 }
445
446 static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
447 {
448         ID *id= (ID *)drag->poin;
449
450         RNA_string_set(drop->ptr, "name", id->name+2);
451 }
452
453
454 /* region dropbox definition */
455 static void view3d_dropboxes(void)
456 {
457         ListBase *lb= WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
458         
459         WM_dropbox_add(lb, "OBJECT_OT_add_named_cursor", view3d_ob_drop_poll, view3d_ob_drop_copy);
460         WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
461         WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_drop_poll, view3d_id_drop_copy);
462 }
463
464
465
466 /* type callback, not region itself */
467 static void view3d_main_area_free(ARegion *ar)
468 {
469         RegionView3D *rv3d= ar->regiondata;
470         
471         if(rv3d) {
472                 if(rv3d->localvd) MEM_freeN(rv3d->localvd);
473                 if(rv3d->clipbb) MEM_freeN(rv3d->clipbb);
474
475                 // XXX  retopo_free_view_data(rv3d);
476                 if(rv3d->ri) { 
477                         // XXX          BIF_view3d_previewrender_free(rv3d);
478                 }
479                 
480                 if(rv3d->depths) {
481                         if(rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
482                         MEM_freeN(rv3d->depths);
483                 }
484                 MEM_freeN(rv3d);
485                 ar->regiondata= NULL;
486         }
487 }
488
489 /* copy regiondata */
490 static void *view3d_main_area_duplicate(void *poin)
491 {
492         if(poin) {
493                 RegionView3D *rv3d= poin, *new;
494         
495                 new= MEM_dupallocN(rv3d);
496                 if(rv3d->localvd) 
497                         new->localvd= MEM_dupallocN(rv3d->localvd);
498                 if(rv3d->clipbb) 
499                         new->clipbb= MEM_dupallocN(rv3d->clipbb);
500                 
501                 new->depths= NULL;
502                 new->retopo_view_data= NULL;
503                 new->ri= NULL;
504                 new->gpd= NULL;
505                 new->sms= NULL;
506                 new->smooth_timer= NULL;
507                 
508                 return new;
509         }
510         return NULL;
511 }
512
513 static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
514 {
515         /* context changes */
516         switch(wmn->category) {
517                 case NC_ANIMATION:
518                         switch(wmn->data) {
519                                 case ND_KEYFRAME_EDIT:
520                                 case ND_KEYFRAME_PROP:
521                                 case ND_NLA_EDIT:
522                                 case ND_NLA_ACTCHANGE:
523                                 case ND_ANIMCHAN_SELECT:
524                                         ED_region_tag_redraw(ar);
525                                         break;
526                         }
527                         break;
528                 case NC_SCENE:
529                         switch(wmn->data) {
530                                 case ND_FRAME:
531                                 case ND_TRANSFORM:
532                                 case ND_OB_ACTIVE:
533                                 case ND_OB_SELECT:
534                                 case ND_LAYER:
535                                 case ND_RENDER_OPTIONS:
536                                 case ND_MODE:
537                                         ED_region_tag_redraw(ar);
538                                         break;
539                         }
540                         if (wmn->action == NA_EDITED)
541                                 ED_region_tag_redraw(ar);
542                         break;
543                 case NC_OBJECT:
544                         switch(wmn->data) {
545                                 case ND_BONE_ACTIVE:
546                                 case ND_BONE_SELECT:
547                                 case ND_TRANSFORM:
548                                 case ND_POSE:
549                                 case ND_DRAW:
550                                 case ND_MODIFIER:
551                                 case ND_CONSTRAINT:
552                                 case ND_KEYS:
553                                 case ND_PARTICLE_SELECT:
554                                 case ND_PARTICLE_DATA:
555                                         ED_region_tag_redraw(ar);
556                                         break;
557                         }
558                         break;
559                 case NC_GEOM:
560                         switch(wmn->data) {
561                                 case ND_DATA:
562                                 case ND_SELECT:
563                                         ED_region_tag_redraw(ar);
564                                         break;
565                         }
566                         switch(wmn->action) {
567                                 case NA_EDITED:
568                                         ED_region_tag_redraw(ar);
569                                         break;
570                         }
571                         break;
572                 case NC_GROUP:
573                         /* all group ops for now */
574                         ED_region_tag_redraw(ar);
575                         break;
576                 case NC_BRUSH:
577                         if(wmn->action == NA_EDITED)
578                                 ED_region_tag_redraw(ar);
579                         break;                  
580                 case NC_MATERIAL:
581                         switch(wmn->data) {
582                                 case ND_SHADING_DRAW:
583                                         ED_region_tag_redraw(ar);
584                                         break;
585                         }
586                         break;
587                 case NC_WORLD:
588                         switch(wmn->data) {
589                                 case ND_WORLD_DRAW:
590                                         ED_region_tag_redraw(ar);
591                                         break;
592                         }
593                         break;
594                 case NC_LAMP:
595                         switch(wmn->data) {
596                                 case ND_LIGHTING_DRAW:
597                                         ED_region_tag_redraw(ar);
598                                         break;
599                         }
600                         break;
601                 case NC_IMAGE:  
602                         /* this could be more fine grained checks if we had
603                          * more context than just the region */
604                         ED_region_tag_redraw(ar);
605                         break;
606                 case NC_SPACE:
607                         if(wmn->data == ND_SPACE_VIEW3D) {
608                                 if (wmn->subtype == NS_VIEW3D_GPU) {
609                                         RegionView3D *rv3d= ar->regiondata;
610                                         rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
611                                 }
612                                 ED_region_tag_redraw(ar);
613                         }
614                         break;
615                 case NC_ID:
616                         if(wmn->action == NA_RENAME)
617                                 ED_region_tag_redraw(ar);
618                         break;
619                 case NC_SCREEN:
620                         if(wmn->data == ND_GPENCIL)     
621                                 ED_region_tag_redraw(ar);
622                         else if(wmn->data==ND_ANIMPLAY)
623                                 ED_region_tag_redraw(ar);
624                         break;
625         }
626 }
627
628 /* concept is to retrieve cursor type context-less */
629 static void view3d_main_area_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
630 {
631         Scene *scene= win->screen->scene;
632
633         if(scene->obedit) {
634                 WM_cursor_set(win, CURSOR_EDIT);
635         }
636         else {
637                 WM_cursor_set(win, CURSOR_STD);
638         }
639 }
640
641 /* add handlers, stuff you only do once or on area/region changes */
642 static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar)
643 {
644         wmKeyMap *keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
645         
646         WM_event_add_keymap_handler(&ar->handlers, keymap);
647
648         ED_region_header_init(ar);
649 }
650
651 static void view3d_header_area_draw(const bContext *C, ARegion *ar)
652 {
653         ED_region_header(C, ar);
654 }
655
656 static void view3d_header_area_listener(ARegion *ar, wmNotifier *wmn)
657 {
658         /* context changes */
659         switch(wmn->category) {
660                 case NC_SCENE:
661                         switch(wmn->data) {
662                                 case ND_FRAME:
663                                 case ND_OB_ACTIVE:
664                                 case ND_OB_SELECT:
665                                 case ND_MODE:
666                                 case ND_LAYER:
667                                 case ND_TOOLSETTINGS:
668                                         ED_region_tag_redraw(ar);
669                                         break;
670                         }
671                         break;
672                 case NC_SPACE:
673                         if(wmn->data == ND_SPACE_VIEW3D)
674                                 ED_region_tag_redraw(ar);
675                         break;
676         }
677 }
678
679 /* add handlers, stuff you only do once or on area/region changes */
680 static void view3d_buttons_area_init(wmWindowManager *wm, ARegion *ar)
681 {
682         wmKeyMap *keymap;
683
684         ED_region_panels_init(wm, ar);
685         
686         keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
687         WM_event_add_keymap_handler(&ar->handlers, keymap);
688 }
689
690 static void view3d_buttons_area_draw(const bContext *C, ARegion *ar)
691 {
692         ED_region_panels(C, ar, 1, NULL, -1);
693 }
694
695 static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
696 {
697         /* context changes */
698         switch(wmn->category) {
699                 case NC_ANIMATION:
700                         switch(wmn->data) {
701                                 case ND_KEYFRAME_EDIT:
702                                 case ND_KEYFRAME_PROP:
703                                 case ND_NLA_EDIT:
704                                 case ND_NLA_ACTCHANGE:
705                                         ED_region_tag_redraw(ar);
706                                         break;
707                         }
708                         break;
709                 case NC_SCENE:
710                         switch(wmn->data) {
711                                 case ND_FRAME:
712                                 case ND_OB_ACTIVE:
713                                 case ND_OB_SELECT:
714                                 case ND_MODE:
715                                 case ND_LAYER:
716                                         ED_region_tag_redraw(ar);
717                                         break;
718                         }
719                         switch(wmn->action) {
720                                 case NA_EDITED:
721                                         ED_region_tag_redraw(ar);
722                                         break;
723                         }
724                         break;
725                 case NC_OBJECT:
726                         switch(wmn->data) {
727                                 case ND_BONE_ACTIVE:
728                                 case ND_BONE_SELECT:
729                                 case ND_TRANSFORM:
730                                 case ND_POSE:
731                                 case ND_DRAW:
732                                 case ND_KEYS:
733                                         ED_region_tag_redraw(ar);
734                                         break;
735                         }
736                         break;
737                 case NC_GEOM:
738                         switch(wmn->data) {
739                                 case ND_DATA:
740                                 case ND_SELECT:
741                                         ED_region_tag_redraw(ar);
742                                         break;
743                         }
744                         break;
745                 case NC_TEXTURE:
746                         /* for brush textures */
747                         ED_region_tag_redraw(ar);
748                         break;
749                 case NC_BRUSH:
750                         if(wmn->action==NA_EDITED)
751                                 ED_region_tag_redraw(ar);
752                         break;
753                 case NC_SPACE:
754                         if(wmn->data == ND_SPACE_VIEW3D)
755                                 ED_region_tag_redraw(ar);
756                         break;
757                 case NC_ID:
758                         if(wmn->action == NA_RENAME)
759                                 ED_region_tag_redraw(ar);
760                         break;
761                 case NC_SCREEN: 
762                         if(wmn->data == ND_GPENCIL)
763                                 ED_region_tag_redraw(ar);
764                         break;
765         }
766 }
767
768 /* add handlers, stuff you only do once or on area/region changes */
769 static void view3d_tools_area_init(wmWindowManager *wm, ARegion *ar)
770 {
771         wmKeyMap *keymap;
772         
773         ED_region_panels_init(wm, ar);
774
775         keymap= WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
776         WM_event_add_keymap_handler(&ar->handlers, keymap);
777 }
778
779 static void view3d_tools_area_draw(const bContext *C, ARegion *ar)
780 {
781         ED_region_panels(C, ar, 1, CTX_data_mode_string(C), -1);
782 }
783
784 static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
785 {
786         View3D *v3d= CTX_wm_view3d(C);
787         Scene *scene= CTX_data_scene(C);
788         Base *base;
789         int lay = v3d ? v3d->lay:scene->lay; /* fallback to the scene layer, allows duplicate and other oject operators to run outside the 3d view */
790
791         if(CTX_data_dir(member)) {
792                 static const char *dir[] = {
793                         "selected_objects", "selected_bases", "selected_editable_objects",
794                         "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
795                         "active_base", "active_object", NULL};
796
797                 CTX_data_dir_set(result, dir);
798         }
799         else if(CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
800                 int selected_objects= CTX_data_equals(member, "selected_objects");
801
802                 for(base=scene->base.first; base; base=base->next) {
803                         if((base->flag & SELECT) && (base->lay & lay)) {
804                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
805                                         if(selected_objects)
806                                                 CTX_data_id_list_add(result, &base->object->id);
807                                         else
808                                                 CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
809                                 }
810                         }
811                 }
812
813                 return 1;
814         }
815         else if(CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
816                 int selected_editable_objects= CTX_data_equals(member, "selected_editable_objects");
817
818                 for(base=scene->base.first; base; base=base->next) {
819                         if((base->flag & SELECT) && (base->lay & lay)) {
820                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
821                                         if(0==object_is_libdata(base->object)) {
822                                                 if(selected_editable_objects)
823                                                         CTX_data_id_list_add(result, &base->object->id);
824                                                 else
825                                                         CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
826                                         }
827                                 }
828                         }
829                 }
830                 
831                 return 1;
832         }
833         else if(CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
834                 int visible_objects= CTX_data_equals(member, "visible_objects");
835
836                 for(base=scene->base.first; base; base=base->next) {
837                         if(base->lay & lay) {
838                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
839                                         if(visible_objects)
840                                                 CTX_data_id_list_add(result, &base->object->id);
841                                         else
842                                                 CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
843                                 }
844                         }
845                 }
846                 
847                 return 1;
848         }
849         else if(CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
850                 int selectable_objects= CTX_data_equals(member, "selectable_objects");
851
852                 for(base=scene->base.first; base; base=base->next) {
853                         if(base->lay & lay) {
854                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0 && (base->object->restrictflag & OB_RESTRICT_SELECT)==0) {
855                                         if(selectable_objects)
856                                                 CTX_data_id_list_add(result, &base->object->id);
857                                         else
858                                                 CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
859                                 }
860                         }
861                 }
862                 
863                 return 1;
864         }
865         else if(CTX_data_equals(member, "active_base")) {
866                 if(scene->basact && (scene->basact->lay & lay))
867                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
868                                 CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact);
869                 
870                 return 1;
871         }
872         else if(CTX_data_equals(member, "active_object")) {
873                 if(scene->basact && (scene->basact->lay & lay))
874                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
875                                 CTX_data_id_pointer_set(result, &scene->basact->object->id);
876                 
877                 return 1;
878         }
879         else {
880                 return 0; /* not found */
881         }
882
883         return -1; /* found but not available */
884 }
885
886 /*area (not region) level listener*/
887 #if 0 // removed since BKE_image_user_calc_frame is now called in draw_bgpic because screen_ops doesnt call the notifier.
888 void space_view3d_listener(struct ScrArea *area, struct wmNotifier *wmn)
889 {
890         if (wmn->category == NC_SCENE && wmn->data == ND_FRAME) {
891                 View3D *v3d = area->spacedata.first;
892                 BGpic *bgpic = v3d->bgpicbase.first;
893
894                 for (; bgpic; bgpic = bgpic->next) {
895                         if (bgpic->ima) {
896                                 Scene *scene = wmn->reference;
897                                 BKE_image_user_calc_frame(&bgpic->iuser, scene->r.cfra, 0);
898                         }
899                 }
900         }
901 }
902 #endif
903
904 /* only called once, from space/spacetypes.c */
905 void ED_spacetype_view3d(void)
906 {
907         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype view3d");
908         ARegionType *art;
909         
910         st->spaceid= SPACE_VIEW3D;
911         strncpy(st->name, "View3D", BKE_ST_MAXNAME);
912         
913         st->new= view3d_new;
914         st->free= view3d_free;
915         st->init= view3d_init;
916 //      st->listener = space_view3d_listener;
917         st->duplicate= view3d_duplicate;
918         st->operatortypes= view3d_operatortypes;
919         st->keymap= view3d_keymap;
920         st->dropboxes= view3d_dropboxes;
921         st->context= view3d_context;
922         
923         /* regions: main window */
924         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
925         art->regionid = RGN_TYPE_WINDOW;
926         art->keymapflag= ED_KEYMAP_GPENCIL;
927         art->draw= view3d_main_area_draw;
928         art->init= view3d_main_area_init;
929         art->free= view3d_main_area_free;
930         art->duplicate= view3d_main_area_duplicate;
931         art->listener= view3d_main_area_listener;
932         art->cursor= view3d_main_area_cursor;
933         BLI_addhead(&st->regiontypes, art);
934         
935         /* regions: listview/buttons */
936         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
937         art->regionid = RGN_TYPE_UI;
938         art->prefsizex= 180; // XXX
939         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
940         art->listener= view3d_buttons_area_listener;
941         art->init= view3d_buttons_area_init;
942         art->draw= view3d_buttons_area_draw;
943         BLI_addhead(&st->regiontypes, art);
944
945         view3d_buttons_register(art);
946
947         /* regions: tool(bar) */
948         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
949         art->regionid = RGN_TYPE_TOOLS;
950         art->prefsizex= 160; // XXX
951         art->prefsizey= 50; // XXX
952         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
953         art->listener= view3d_buttons_area_listener;
954         art->init= view3d_tools_area_init;
955         art->draw= view3d_tools_area_draw;
956         BLI_addhead(&st->regiontypes, art);
957         
958         view3d_toolshelf_register(art);
959
960         /* regions: tool properties */
961         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
962         art->regionid = RGN_TYPE_TOOL_PROPS;
963         art->prefsizex= 0;
964         art->prefsizey= 120;
965         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
966         art->listener= view3d_buttons_area_listener;
967         art->init= view3d_tools_area_init;
968         art->draw= view3d_tools_area_draw;
969         BLI_addhead(&st->regiontypes, art);
970         
971         view3d_tool_props_register(art);
972         
973         
974         /* regions: header */
975         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
976         art->regionid = RGN_TYPE_HEADER;
977         art->prefsizey= HEADERY;
978         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER;
979         art->listener= view3d_header_area_listener;
980         art->init= view3d_header_area_init;
981         art->draw= view3d_header_area_draw;
982         BLI_addhead(&st->regiontypes, art);
983         
984         BKE_spacetype_register(st);
985 }
986