7e209bc8693dc2e6a36a0795c83ecc986ac85181
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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_arithb.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
52 #include "ED_armature.h"
53 #include "ED_space_api.h"
54 #include "ED_screen.h"
55
56 #include "BIF_gl.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 #include "UI_interface.h"
62 #include "UI_resources.h"
63 #include "UI_view2d.h"
64
65 #include "view3d_intern.h"      // own include
66
67 /* ******************** default callbacks for view3d space ***************** */
68
69 static SpaceLink *view3d_new(const bContext *C)
70 {
71         Scene *scene= CTX_data_scene(C);
72         ARegion *ar;
73         View3D *v3d;
74         RegionView3D *rv3d;
75         
76         v3d= MEM_callocN(sizeof(View3D), "initview3d");
77         v3d->spacetype= SPACE_VIEW3D;
78         v3d->blockscale= 0.7f;
79         v3d->lay= v3d->layact= 1;
80         if(scene) {
81                 v3d->lay= v3d->layact= scene->lay;
82                 v3d->camera= scene->camera;
83         }
84         v3d->scenelock= 1;
85         v3d->grid= 1.0f;
86         v3d->gridlines= 16;
87         v3d->gridsubdiv = 10;
88         v3d->drawtype= OB_WIRE;
89         
90         v3d->gridflag |= V3D_SHOW_X;
91         v3d->gridflag |= V3D_SHOW_Y;
92         v3d->gridflag |= V3D_SHOW_FLOOR;
93         v3d->gridflag &= ~V3D_SHOW_Z;
94         
95         v3d->lens= 35.0f;
96         v3d->near= 0.01f;
97         v3d->far= 500.0f;
98         
99         /* header */
100         ar= MEM_callocN(sizeof(ARegion), "header for view3d");
101         
102         BLI_addtail(&v3d->regionbase, ar);
103         ar->regiontype= RGN_TYPE_HEADER;
104         ar->alignment= RGN_ALIGN_BOTTOM;
105         
106         /* main area */
107         ar= MEM_callocN(sizeof(ARegion), "main area for view3d");
108         
109         BLI_addtail(&v3d->regionbase, ar);
110         ar->regiontype= RGN_TYPE_WINDOW;
111         
112         ar->regiondata= MEM_callocN(sizeof(RegionView3D), "region view3d");
113         rv3d= ar->regiondata;
114         rv3d->viewquat[0]= 1.0f;
115         rv3d->persp= 1;
116         rv3d->view= 7;
117         rv3d->dist= 10.0;
118         Mat4One(rv3d->twmat);
119         
120         return (SpaceLink *)v3d;
121 }
122
123 /* not spacelink itself */
124 static void view3d_free(SpaceLink *sl)
125 {
126         View3D *vd= (View3D *) sl;
127         
128         if(vd->bgpic) {
129                 if(vd->bgpic->ima) vd->bgpic->ima->id.us--;
130                 MEM_freeN(vd->bgpic);
131         }
132         
133         if(vd->localvd) MEM_freeN(vd->localvd);
134         
135         if(vd->properties_storage) MEM_freeN(vd->properties_storage);
136         
137 }
138
139
140 /* spacetype; init callback */
141 static void view3d_init(struct wmWindowManager *wm, ScrArea *sa)
142 {
143
144 }
145
146 static SpaceLink *view3d_duplicate(SpaceLink *sl)
147 {
148         View3D *v3do= (View3D *)sl;
149         View3D *v3dn= MEM_dupallocN(sl);
150         
151         /* clear or remove stuff from old */
152         
153 // XXX  BIF_view3d_previewrender_free(v3do);
154         
155         if(v3do->localvd) {
156 // XXX          restore_localviewdata(v3do);
157                 v3do->localvd= NULL;
158                 v3do->properties_storage= NULL;
159                 v3do->localview= 0;
160                 v3do->lay &= 0xFFFFFF;
161         }
162         
163         /* copy or clear inside new stuff */
164
165         if(v3dn->bgpic) {
166                 v3dn->bgpic= MEM_dupallocN(v3dn->bgpic);
167                 if(v3dn->bgpic->ima) v3dn->bgpic->ima->id.us++;
168         }
169         v3dn->properties_storage= NULL;
170         
171         return (SpaceLink *)v3dn;
172 }
173
174 /* add handlers, stuff you only do once or on area/region changes */
175 static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
176 {
177         ListBase *keymap;
178         
179         /* own keymap */
180         keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0);
181         WM_event_add_keymap_handler(&ar->handlers, keymap);
182         
183         /* object ops. */
184         keymap= WM_keymap_listbase(wm, "Object Non-modal", 0, 0);
185         WM_event_add_keymap_handler(&ar->handlers, keymap);
186         
187         /* pose is not modal, operator poll checks for this */
188         keymap= WM_keymap_listbase(wm, "Pose", 0, 0);
189         WM_event_add_keymap_handler(&ar->handlers, keymap);
190         
191         /* object modal ops default */
192         keymap= WM_keymap_listbase(wm, "Object Mode", 0, 0);
193         WM_event_add_keymap_handler(&ar->handlers, keymap);
194         
195 }
196
197 /* type callback, not region itself */
198 static void view3d_main_area_free(ARegion *ar)
199 {
200         RegionView3D *rv3d= ar->regiondata;
201         
202         if(rv3d) {
203                 if(rv3d->localvd) MEM_freeN(rv3d->localvd);
204                 if(rv3d->clipbb) MEM_freeN(rv3d->clipbb);
205
206                 // XXX  retopo_free_view_data(rv3d);
207                 if(rv3d->ri) { 
208                         // XXX          BIF_view3d_previewrender_free(rv3d);
209                 }
210                 
211                 if(rv3d->depths) {
212                         if(rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
213                         MEM_freeN(rv3d->depths);
214                 }
215                 MEM_freeN(rv3d);
216                 ar->regiondata= NULL;
217         }
218 }
219
220 /* copy regiondata */
221 static void *view3d_main_area_duplicate(void *poin)
222 {
223         if(poin) {
224                 RegionView3D *rv3d= poin, *new;
225         
226                 new= MEM_dupallocN(rv3d);
227                 if(rv3d->localvd) 
228                         new->localvd= MEM_dupallocN(rv3d->localvd);
229                 if(rv3d->clipbb) 
230                         new->clipbb= MEM_dupallocN(rv3d->clipbb);
231                 
232                 new->depths= NULL;
233                 new->retopo_view_data= NULL;
234                 new->ri= NULL;
235                 new->gpd= NULL;
236                 new->sms= NULL;
237                 new->smooth_timer= NULL;
238                 
239                 return new;
240         }
241         return NULL;
242 }
243
244
245 static void view3d_modal_keymaps(wmWindowManager *wm, ARegion *ar, int stype)
246 {
247         ListBase *keymap;
248         
249         keymap= WM_keymap_listbase(wm, "Object Mode", 0, 0);
250         if(stype==NS_MODE_OBJECT)
251                 WM_event_add_keymap_handler(&ar->handlers, keymap);
252         else
253                 WM_event_remove_keymap_handler(&ar->handlers, keymap);
254         
255         keymap= WM_keymap_listbase(wm, "EditMesh", 0, 0);
256         if(stype==NS_EDITMODE_MESH)
257                 WM_event_add_keymap_handler(&ar->handlers, keymap);
258         else
259                 WM_event_remove_keymap_handler(&ar->handlers, keymap);
260
261         keymap= WM_keymap_listbase(wm, "Curve", 0, 0);
262         if(stype==NS_EDITMODE_CURVE)
263                 WM_event_add_keymap_handler(&ar->handlers, keymap);
264         else
265                 WM_event_remove_keymap_handler(&ar->handlers, keymap);
266         
267         keymap= WM_keymap_listbase(wm, "Armature", 0, 0);
268         if(stype==NS_EDITMODE_ARMATURE)
269                 WM_event_add_keymap_handler(&ar->handlers, keymap);
270         else
271                 WM_event_remove_keymap_handler(&ar->handlers, keymap);
272         
273         /* editfont keymap swallows all... */
274         keymap= WM_keymap_listbase(wm, "Font", 0, 0);
275         if(stype==NS_EDITMODE_TEXT)
276                 WM_event_add_keymap_handler_priority(&ar->handlers, keymap, 10);
277         else
278                 WM_event_remove_keymap_handler(&ar->handlers, keymap);
279         
280 }
281
282 static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
283 {
284         /* context changes */
285         switch(wmn->category) {
286                 case NC_SCENE:
287                         switch(wmn->data) {
288                                 case ND_FRAME:
289                                 case ND_OB_ACTIVE:
290                                 case ND_OB_SELECT:
291                                         ED_region_tag_redraw(ar);
292                                         break;
293                                 case ND_MODE:
294                                         view3d_modal_keymaps(wmn->wm, ar, wmn->subtype);
295                                         ED_region_tag_redraw(ar);
296                                         break;
297                         }
298                         break;
299                 case NC_OBJECT:
300                         switch(wmn->data) {
301                                 case ND_BONE_ACTIVE:
302                                 case ND_BONE_SELECT:
303                                 case ND_TRANSFORM:
304                                 case ND_GEOM_SELECT:
305                                 case ND_GEOM_DATA:
306                                 case ND_DRAW:
307                                 case ND_MODIFIER:
308                                 case ND_KEYS:
309                                         ED_region_tag_redraw(ar);
310                                         break;
311                         }
312                 case NC_GROUP:
313                         /* all group ops for now */
314                         ED_region_tag_redraw(ar);
315                         break;
316                 case NC_MATERIAL:
317                         switch(wmn->data) {
318                                 case ND_SHADING_DRAW:
319                                         ED_region_tag_redraw(ar);
320                                         break;
321                         }
322                 case NC_LAMP:
323                         switch(wmn->data) {
324                                 case ND_LIGHTING_DRAW:
325                                         ED_region_tag_redraw(ar);
326                                         break;
327                         }
328         }
329 }
330
331 /* concept is to retrieve cursor type context-less */
332 static void view3d_main_area_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
333 {
334         Scene *scene= win->screen->scene;
335
336         if(scene->obedit) {
337                 WM_cursor_set(win, CURSOR_EDIT);
338         }
339         else {
340                 WM_cursor_set(win, CURSOR_STD);
341         }
342 }
343
344 /* add handlers, stuff you only do once or on area/region changes */
345 static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar)
346 {
347         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
348 }
349
350 static void view3d_header_area_draw(const bContext *C, ARegion *ar)
351 {
352         float col[3];
353         
354         /* clear */
355         if(ED_screen_area_active(C))
356                 UI_GetThemeColor3fv(TH_HEADER, col);
357         else
358                 UI_GetThemeColor3fv(TH_HEADERDESEL, col);
359         
360         glClearColor(col[0], col[1], col[2], 0.0);
361         glClear(GL_COLOR_BUFFER_BIT);
362         
363         /* set view2d view matrix for scrolling (without scrollers) */
364         UI_view2d_view_ortho(C, &ar->v2d);
365         
366         view3d_header_buttons(C, ar);
367         
368         /* restore view matrix? */
369         UI_view2d_view_restore(C);
370 }
371
372 static void view3d_header_area_listener(ARegion *ar, wmNotifier *wmn)
373 {
374         /* context changes */
375         switch(wmn->category) {
376                 case NC_SCENE:
377                         switch(wmn->data) {
378                                 case ND_FRAME:
379                                 case ND_OB_ACTIVE:
380                                 case ND_OB_SELECT:
381                                 case ND_MODE:
382                                         ED_region_tag_redraw(ar);
383                                         break;
384                         }
385                         break;
386         }
387 }
388
389 /*
390  * Returns true if the Object is a from an external blend file (libdata)
391  */
392 static int object_is_libdata(Object *ob)
393 {
394         if (!ob) return 0;
395         if (ob->proxy) return 0;
396         if (ob->id.lib) return 1;
397         return 0;
398 }
399
400 static int view3d_context(const bContext *C, bContextDataMember member, bContextDataResult *result)
401 {
402         View3D *v3d= CTX_wm_view3d(C);
403         Scene *scene= CTX_data_scene(C);
404         Base *base;
405
406         if(v3d==NULL) return 0;
407
408         if(ELEM(member, CTX_DATA_SELECTED_OBJECTS, CTX_DATA_SELECTED_BASES)) {
409                 for(base=scene->base.first; base; base=base->next) {
410                         if((base->flag & SELECT) && (base->lay & v3d->lay)) {
411                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
412                                         if(member == CTX_DATA_SELECTED_OBJECTS)
413                                                 CTX_data_list_add(result, base->object);
414                                         else
415                                                 CTX_data_list_add(result, base);
416                                 }
417                         }
418                 }
419
420                 return 1;
421         }
422         else if(ELEM(member, CTX_DATA_SELECTED_EDITABLE_OBJECTS, CTX_DATA_SELECTED_EDITABLE_BASES)) {
423                 for(base=scene->base.first; base; base=base->next) {
424                         if((base->flag & SELECT) && (base->lay & v3d->lay)) {
425                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
426                                         if(0==object_is_libdata(base->object)) {
427                                                 if(member == CTX_DATA_SELECTED_EDITABLE_OBJECTS)
428                                                         CTX_data_list_add(result, base->object);
429                                                 else
430                                                         CTX_data_list_add(result, base);
431                                         }
432                                 }
433                         }
434                 }
435                 
436                 return 1;
437         }
438         else if(ELEM(member, CTX_DATA_VISIBLE_OBJECTS, CTX_DATA_VISIBLE_BASES)) {
439                 for(base=scene->base.first; base; base=base->next) {
440                         if(base->lay & v3d->lay) {
441                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
442                                         if(member == CTX_DATA_VISIBLE_OBJECTS)
443                                                 CTX_data_list_add(result, base->object);
444                                         else
445                                                 CTX_data_list_add(result, base);
446                                 }
447                         }
448                 }
449                 
450                 return 1;
451         }
452         else if(member == CTX_DATA_ACTIVE_BASE) {
453                 if(scene->basact && (scene->basact->lay & v3d->lay))
454                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
455                                 CTX_data_pointer_set(result, scene->basact);
456
457                 return 1;
458         }
459         else if(member == CTX_DATA_ACTIVE_OBJECT) {
460                 if(scene->basact && (scene->basact->lay & v3d->lay))
461                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
462                                 CTX_data_pointer_set(result, scene->basact->object);
463
464                 return 1;
465         }
466         else if(ELEM(member, CTX_DATA_SELECTED_BONES, CTX_DATA_SELECTED_EDITABLE_BONES)) {
467                 Object *obedit= scene->obedit; // XXX get from context?
468                 bArmature *arm= (obedit) ? obedit->data : NULL;
469                 EditBone *ebone, *flipbone=NULL;
470                 
471                 if (arm && arm->edbo) {
472                         /* Attention: X-Axis Mirroring is also handled here... */
473                         for (ebone= arm->edbo->first; ebone; ebone= ebone->next) {
474                                 /* first and foremost, bone must be visible and selected */
475                                 if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_SELECTED)) {
476                                         /* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
477                                          * so that most users of this data don't need to explicitly check for it themselves.
478                                          * 
479                                          * We need to make sure that these mirrored copies are not selected, otherwise some
480                                          * bones will be operated on twice.
481                                          */
482                                         if (arm->flag & ARM_MIRROR_EDIT)
483                                                 flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
484                                         
485                                         /* if we're filtering for editable too, use the check for that instead, as it has selection check too */
486                                         if (member == CTX_DATA_SELECTED_EDITABLE_BONES) {
487                                                 /* only selected + editable */
488                                                 if (EBONE_EDITABLE(ebone)) {
489                                                         CTX_data_list_add(result, ebone);
490                                                 
491                                                         if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
492                                                                 CTX_data_list_add(result, flipbone);
493                                                 }
494                                         }
495                                         else {
496                                                 /* only include bones if selected */
497                                                 CTX_data_list_add(result, ebone);
498                                                 
499                                                 if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
500                                                         CTX_data_list_add(result, flipbone);
501                                         }
502                                 }
503                         }       
504                         
505                         return 1;
506                 }
507         }
508         else if(member == CTX_DATA_SELECTED_PCHANS) {
509                 Object *obact= OBACT;
510                 bArmature *arm= (obact) ? obact->data : NULL;
511                 bPoseChannel *pchan;
512                 
513                 if (obact && arm) {
514                         for (pchan= obact->pose->chanbase.first; pchan; pchan= pchan->next) {
515                                 /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
516                                 if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
517                                         if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) 
518                                                 CTX_data_list_add(result, pchan);
519                                 }
520                         }
521                         
522                         return 1;
523                 }
524         }
525         else if(member == CTX_DATA_ACTIVE_BONE) {
526                 Object *obedit= scene->obedit; // XXX get from context?
527                 bArmature *arm= (obedit) ? obedit->data : NULL;
528                 EditBone *ebone;
529                 
530                 if (arm && arm->edbo) {
531                         for (ebone= arm->edbo->first; ebone; ebone= ebone->next) {
532                                 if (EBONE_VISIBLE(arm, ebone)) {
533                                         if (ebone->flag & BONE_ACTIVE) {
534                                                 CTX_data_pointer_set(result, ebone);
535                                                 
536                                                 return 1;
537                                         }
538                                 }
539                         }
540                 }
541                 
542         }
543         else if(member == CTX_DATA_ACTIVE_PCHAN) {
544                 Object *obact= OBACT;
545                 bArmature *arm= (obact) ? obact->data : NULL;
546                 bPoseChannel *pchan;
547                 
548                 pchan= get_active_posechannel(obact);
549                 if (pchan) {
550                         CTX_data_pointer_set(result, pchan);
551                         return 1;
552                 }
553         }
554
555         return 0;
556 }
557
558 /* only called once, from space/spacetypes.c */
559 void ED_spacetype_view3d(void)
560 {
561         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype view3d");
562         ARegionType *art;
563         
564         st->spaceid= SPACE_VIEW3D;
565         
566         st->new= view3d_new;
567         st->free= view3d_free;
568         st->init= view3d_init;
569         st->duplicate= view3d_duplicate;
570         st->operatortypes= view3d_operatortypes;
571         st->keymap= view3d_keymap;
572         st->context= view3d_context;
573         
574         /* regions: main window */
575         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
576         art->regionid = RGN_TYPE_WINDOW;
577         art->keymapflag= ED_KEYMAP_FRAMES;
578         art->draw= view3d_main_area_draw;
579         art->init= view3d_main_area_init;
580         art->free= view3d_main_area_free;
581         art->duplicate= view3d_main_area_duplicate;
582         art->listener= view3d_main_area_listener;
583         art->cursor= view3d_main_area_cursor;
584         BLI_addhead(&st->regiontypes, art);
585         
586         /* regions: header */
587         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
588         art->regionid = RGN_TYPE_HEADER;
589         art->minsizey= HEADERY;
590         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
591         art->listener= view3d_header_area_listener;
592         
593         art->init= view3d_header_area_init;
594         art->draw= view3d_header_area_draw;
595         
596         BLI_addhead(&st->regiontypes, art);
597         
598         BKE_spacetype_register(st);
599 }
600