0bb891e11b4722aecb9ba68b9626488c9e41a89f
[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_object_types.h"
33 #include "DNA_space_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_screen_types.h"
36 #include "DNA_view3d_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_arithb.h"
42 #include "BLI_rand.h"
43
44 #include "BKE_context.h"
45 #include "BKE_global.h"
46 #include "BKE_screen.h"
47 #include "BKE_utildefines.h"
48
49 #include "ED_space_api.h"
50 #include "ED_screen.h"
51
52 #include "BIF_gl.h"
53
54 #include "WM_api.h"
55 #include "WM_types.h"
56
57 #include "UI_interface.h"
58 #include "UI_resources.h"
59 #include "UI_view2d.h"
60
61 #include "view3d_intern.h"      // own include
62
63 /* ******************** default callbacks for view3d space ***************** */
64
65 static SpaceLink *view3d_new(const bContext *C)
66 {
67         Scene *scene= CTX_data_scene(C);
68         ARegion *ar;
69         View3D *v3d;
70         RegionView3D *rv3d;
71         
72         v3d= MEM_callocN(sizeof(View3D), "initview3d");
73         v3d->spacetype= SPACE_VIEW3D;
74         v3d->blockscale= 0.7f;
75         v3d->lay= v3d->layact= 1;
76         if(scene) {
77                 v3d->lay= v3d->layact= scene->lay;
78                 v3d->camera= scene->camera;
79         }
80         v3d->scenelock= 1;
81         v3d->grid= 1.0f;
82         v3d->gridlines= 16;
83         v3d->gridsubdiv = 10;
84         v3d->drawtype= OB_WIRE;
85         
86         v3d->gridflag |= V3D_SHOW_X;
87         v3d->gridflag |= V3D_SHOW_Y;
88         v3d->gridflag |= V3D_SHOW_FLOOR;
89         v3d->gridflag &= ~V3D_SHOW_Z;
90         
91         v3d->lens= 35.0f;
92         v3d->near= 0.01f;
93         v3d->far= 500.0f;
94         
95         /* header */
96         ar= MEM_callocN(sizeof(ARegion), "header for view3d");
97         
98         BLI_addtail(&v3d->regionbase, ar);
99         ar->regiontype= RGN_TYPE_HEADER;
100         ar->alignment= RGN_ALIGN_BOTTOM;
101         
102         /* main area */
103         ar= MEM_callocN(sizeof(ARegion), "main area for view3d");
104         
105         BLI_addtail(&v3d->regionbase, ar);
106         ar->regiontype= RGN_TYPE_WINDOW;
107         
108         ar->regiondata= MEM_callocN(sizeof(RegionView3D), "region view3d");
109         rv3d= ar->regiondata;
110         rv3d->viewquat[0]= 1.0f;
111         rv3d->persp= 1;
112         rv3d->view= 7;
113         rv3d->dist= 10.0;
114         Mat4One(rv3d->twmat);
115         
116         return (SpaceLink *)v3d;
117 }
118
119 /* not spacelink itself */
120 static void view3d_free(SpaceLink *sl)
121 {
122         View3D *vd= (View3D *) sl;
123         
124         if(vd->bgpic) {
125                 if(vd->bgpic->ima) vd->bgpic->ima->id.us--;
126                 MEM_freeN(vd->bgpic);
127         }
128         
129         if(vd->localvd) MEM_freeN(vd->localvd);
130         
131         if(vd->properties_storage) MEM_freeN(vd->properties_storage);
132         
133 }
134
135
136 /* spacetype; init callback */
137 static void view3d_init(struct wmWindowManager *wm, ScrArea *sa)
138 {
139
140 }
141
142 static SpaceLink *view3d_duplicate(SpaceLink *sl)
143 {
144         View3D *v3do= (View3D *)sl;
145         View3D *v3dn= MEM_dupallocN(sl);
146         
147         /* clear or remove stuff from old */
148         
149 // XXX  BIF_view3d_previewrender_free(v3do);
150         
151         if(v3do->localvd) {
152 // XXX          restore_localviewdata(v3do);
153                 v3do->localvd= NULL;
154                 v3do->properties_storage= NULL;
155                 v3do->localview= 0;
156                 v3do->lay &= 0xFFFFFF;
157         }
158         
159         /* copy or clear inside new stuff */
160
161         if(v3dn->bgpic) {
162                 v3dn->bgpic= MEM_dupallocN(v3dn->bgpic);
163                 if(v3dn->bgpic->ima) v3dn->bgpic->ima->id.us++;
164         }
165         v3dn->properties_storage= NULL;
166         
167         return (SpaceLink *)v3dn;
168 }
169
170 /* add handlers, stuff you only do once or on area/region changes */
171 static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
172 {
173         ListBase *keymap;
174         
175         /* own keymap */
176         keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0);
177         WM_event_add_keymap_handler(&ar->handlers, keymap);
178         
179         /* object ops. */
180         keymap= WM_keymap_listbase(wm, "Object Non-modal", 0, 0);
181         WM_event_add_keymap_handler(&ar->handlers, keymap);
182         
183         /* object modal ops default */
184         keymap= WM_keymap_listbase(wm, "Object Mode", 0, 0);
185         WM_event_add_keymap_handler(&ar->handlers, keymap);
186         
187 }
188
189 /* type callback, not region itself */
190 static void view3d_main_area_free(ARegion *ar)
191 {
192         RegionView3D *rv3d= ar->regiondata;
193         
194         if(rv3d) {
195                 if(rv3d->localvd) MEM_freeN(rv3d->localvd);
196                 if(rv3d->clipbb) MEM_freeN(rv3d->clipbb);
197
198                 // XXX  retopo_free_view_data(rv3d);
199                 if(rv3d->ri) { 
200                         // XXX          BIF_view3d_previewrender_free(rv3d);
201                 }
202                 
203                 if(rv3d->depths) {
204                         if(rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
205                         MEM_freeN(rv3d->depths);
206                 }
207                 MEM_freeN(rv3d);
208                 ar->regiondata= NULL;
209         }
210 }
211
212 /* copy regiondata */
213 static void *view3d_main_area_duplicate(void *poin)
214 {
215         if(poin) {
216                 RegionView3D *rv3d= poin, *new;
217         
218                 new= MEM_dupallocN(rv3d);
219                 if(rv3d->localvd) 
220                         new->localvd= MEM_dupallocN(rv3d->localvd);
221                 if(rv3d->clipbb) 
222                         new->clipbb= MEM_dupallocN(rv3d->clipbb);
223                 
224                 new->depths= NULL;
225                 new->retopo_view_data= NULL;
226                 new->ri= NULL;
227                 new->gpd= NULL;
228                 new->sms= NULL;
229                 new->smooth_timer= NULL;
230                 
231                 return new;
232         }
233         return NULL;
234 }
235
236
237 static void view3d_modal_keymaps(wmWindowManager *wm, ARegion *ar, int stype)
238 {
239         ListBase *keymap;
240         
241         keymap= WM_keymap_listbase(wm, "Object Mode", 0, 0);
242         if(stype==NS_MODE_OBJECT)
243                 WM_event_add_keymap_handler(&ar->handlers, keymap);
244         else
245                 WM_event_remove_keymap_handler(&ar->handlers, keymap);
246         
247         
248         keymap= WM_keymap_listbase(wm, "EditMesh", 0, 0);
249         if(stype==NS_EDITMODE_MESH)
250                 WM_event_add_keymap_handler(&ar->handlers, keymap);
251         else
252                 WM_event_remove_keymap_handler(&ar->handlers, keymap);
253         
254 }
255
256 static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
257 {
258         /* context changes */
259         switch(wmn->category) {
260                 case NC_SCENE:
261                         switch(wmn->data) {
262                                 case ND_FRAME:
263                                 case ND_OB_ACTIVE:
264                                 case ND_OB_SELECT:
265                                         ED_region_tag_redraw(ar);
266                                         break;
267                                 case ND_MODE:
268                                         view3d_modal_keymaps(wmn->wm, ar, wmn->subtype);
269                                         ED_region_tag_redraw(ar);
270                                         break;
271                         }
272                         break;
273                 case NC_OBJECT:
274                         switch(wmn->data) {
275                                 case ND_BONE_ACTIVE:
276                                 case ND_BONE_SELECT:
277                                 case ND_TRANSFORM:
278                                 case ND_GEOM_SELECT:
279                                 case ND_DRAW:
280                                 case ND_MODIFIER:
281                                         ED_region_tag_redraw(ar);
282                                         break;
283                         }
284                 case NC_MATERIAL:
285                         switch(wmn->data) {
286                                 case ND_SHADING_DRAW:
287                                         ED_region_tag_redraw(ar);
288                                         break;
289                         }
290                 case NC_LAMP:
291                         switch(wmn->data) {
292                                 case ND_LIGHTING_DRAW:
293                                         ED_region_tag_redraw(ar);
294                                         break;
295                         }
296         }
297 }
298
299 /* concept is to retrieve cursor type context-less */
300 static void view3d_main_area_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
301 {
302         Scene *scene= win->screen->scene;
303
304         if(scene->obedit) {
305                 WM_cursor_set(win, CURSOR_EDIT);
306         }
307         else {
308                 WM_cursor_set(win, CURSOR_STD);
309         }
310 }
311
312 /* add handlers, stuff you only do once or on area/region changes */
313 static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar)
314 {
315         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
316 }
317
318 static void view3d_header_area_draw(const bContext *C, ARegion *ar)
319 {
320         float col[3];
321         
322         /* clear */
323         if(ED_screen_area_active(C))
324                 UI_GetThemeColor3fv(TH_HEADER, col);
325         else
326                 UI_GetThemeColor3fv(TH_HEADERDESEL, col);
327         
328         glClearColor(col[0], col[1], col[2], 0.0);
329         glClear(GL_COLOR_BUFFER_BIT);
330         
331         /* set view2d view matrix for scrolling (without scrollers) */
332         UI_view2d_view_ortho(C, &ar->v2d);
333         
334         view3d_header_buttons(C, ar);
335         
336         /* restore view matrix? */
337         UI_view2d_view_restore(C);
338 }
339
340 static void view3d_header_area_listener(ARegion *ar, wmNotifier *wmn)
341 {
342         /* context changes */
343         switch(wmn->category) {
344                 case NC_SCENE:
345                         switch(wmn->data) {
346                                 case ND_FRAME:
347                                 case ND_OB_ACTIVE:
348                                 case ND_OB_SELECT:
349                                 case ND_MODE:
350                                         ED_region_tag_redraw(ar);
351                                         break;
352                         }
353                         break;
354         }
355 }
356
357 /*
358  * Returns true if the Object is a from an external blend file (libdata)
359  */
360 static int object_is_libdata(Object *ob)
361 {
362         if (!ob) return 0;
363         if (ob->proxy) return 0;
364         if (ob->id.lib) return 1;
365         return 0;
366 }
367
368 static int view3d_context(const bContext *C, const bContextDataMember *member, bContextDataResult *result)
369 {
370         View3D *v3d= CTX_wm_view3d(C);
371         Scene *scene= CTX_data_scene(C);
372         Base *base;
373
374         if(v3d==NULL) return 0;
375         
376         if(ELEM(member, CTX_data_selected_objects, CTX_data_selected_bases)) {
377                 for(base=scene->base.first; base; base=base->next) {
378                         if((base->flag & SELECT) && (base->lay & v3d->lay)) {
379                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
380                                         if(member == CTX_data_selected_objects)
381                                                 CTX_data_list_add(result, base->object);
382                                         else
383                                                 CTX_data_list_add(result, base);
384                                 }
385                         }
386                 }
387
388                 return 1;
389         }
390         else if(ELEM(member, CTX_data_selected_editable_objects, CTX_data_selected_editable_bases)) {
391                 for(base=scene->base.first; base; base=base->next) {
392                         if((base->flag & SELECT) && (base->lay & v3d->lay)) {
393                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
394                                         if(0==object_is_libdata(base->object)) {
395                                                 if(member == CTX_data_selected_editable_objects)
396                                                         CTX_data_list_add(result, base->object);
397                                                 else
398                                                         CTX_data_list_add(result, base);
399                                         }
400                                 }
401                         }
402                 }
403                 
404                 return 1;
405         }
406         else if(ELEM(member, CTX_data_visible_objects, CTX_data_visible_bases)) {
407                 for(base=scene->base.first; base; base=base->next) {
408                         if(base->lay & v3d->lay) {
409                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
410                                         if(member == CTX_data_visible_objects)
411                                                 CTX_data_list_add(result, base->object);
412                                         else
413                                                 CTX_data_list_add(result, base);
414                                 }
415                         }
416                 }
417                 
418                 return 1;
419         }
420         else if(member == CTX_data_active_base) {
421                 if(scene->basact && (scene->basact->lay & v3d->lay))
422                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
423                                 CTX_data_pointer_set(result, scene->basact);
424
425                 return 1;
426         }
427         else if(member == CTX_data_active_object) {
428                 if(scene->basact && (scene->basact->lay & v3d->lay))
429                         if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
430                                 CTX_data_pointer_set(result, scene->basact->object);
431
432                 return 1;
433         }
434
435         return 0;
436 }
437
438 /* only called once, from space/spacetypes.c */
439 void ED_spacetype_view3d(void)
440 {
441         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype view3d");
442         ARegionType *art;
443         
444         st->spaceid= SPACE_VIEW3D;
445         
446         st->new= view3d_new;
447         st->free= view3d_free;
448         st->init= view3d_init;
449         st->duplicate= view3d_duplicate;
450         st->operatortypes= view3d_operatortypes;
451         st->keymap= view3d_keymap;
452         st->context= view3d_context;
453         
454         /* regions: main window */
455         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
456         art->regionid = RGN_TYPE_WINDOW;
457         art->draw= view3d_main_area_draw;
458         art->init= view3d_main_area_init;
459         art->free= view3d_main_area_free;
460         art->duplicate= view3d_main_area_duplicate;
461         art->listener= view3d_main_area_listener;
462         art->cursor= view3d_main_area_cursor;
463         BLI_addhead(&st->regiontypes, art);
464         
465         /* regions: header */
466         art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
467         art->regionid = RGN_TYPE_HEADER;
468         art->minsizey= HEADERY;
469         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
470         art->listener= view3d_header_area_listener;
471         
472         art->init= view3d_header_area_init;
473         art->draw= view3d_header_area_draw;
474         
475         BLI_addhead(&st->regiontypes, art);
476         
477         BKE_spacetype_register(st);
478 }
479