3d9d40deda1b7472f3ec0ec055a57079e34fbd85
[blender.git] / source / blender / editors / space_view3d / space_view3d.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_view3d/space_view3d.c
28  *  \ingroup spview3d
29  */
30
31
32 #include <string.h>
33 #include <stdio.h>
34
35 #include "DNA_material_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_scene_types.h"
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_math.h"
43 #include "BLI_utildefines.h"
44
45 #include "BKE_context.h"
46 #include "BKE_curve.h"
47 #include "BKE_icons.h"
48 #include "BKE_lattice.h"
49 #include "BKE_library.h"
50 #include "BKE_main.h"
51 #include "BKE_mesh.h"
52 #include "BKE_object.h"
53 #include "BKE_scene.h"
54 #include "BKE_screen.h"
55 #include "BKE_workspace.h"
56
57 #include "ED_space_api.h"
58 #include "ED_screen.h"
59 #include "ED_transform.h"
60
61 #include "GPU_compositing.h"
62 #include "GPU_framebuffer.h"
63 #include "GPU_material.h"
64 #include "GPU_viewport.h"
65 #include "GPU_matrix.h"
66
67 #include "WM_api.h"
68 #include "WM_types.h"
69
70 #include "RE_engine.h"
71 #include "RE_pipeline.h"
72
73 #include "RNA_access.h"
74
75 #include "UI_resources.h"
76
77 #ifdef WITH_PYTHON
78 #  include "BPY_extern.h"
79 #endif
80
81 #include "DEG_depsgraph.h"
82
83 #include "view3d_intern.h"  /* own include */
84
85 /* ******************** manage regions ********************* */
86
87 ARegion *view3d_has_buttons_region(ScrArea *sa)
88 {
89         ARegion *ar, *arnew;
90
91         ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
92         if (ar) return ar;
93         
94         /* add subdiv level; after header */
95         ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
96
97         /* is error! */
98         if (ar == NULL) return NULL;
99         
100         arnew = MEM_callocN(sizeof(ARegion), "buttons for view3d");
101         
102         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
103         arnew->regiontype = RGN_TYPE_UI;
104         arnew->alignment = RGN_ALIGN_RIGHT;
105         
106         arnew->flag = RGN_FLAG_HIDDEN;
107         
108         return arnew;
109 }
110
111 ARegion *view3d_has_tools_region(ScrArea *sa)
112 {
113         ARegion *ar, *artool = NULL, *arprops = NULL, *arhead;
114         
115         for (ar = sa->regionbase.first; ar; ar = ar->next) {
116                 if (ar->regiontype == RGN_TYPE_TOOLS)
117                         artool = ar;
118                 if (ar->regiontype == RGN_TYPE_TOOL_PROPS)
119                         arprops = ar;
120         }
121         
122         /* tool region hide/unhide also hides props */
123         if (arprops && artool) return artool;
124         
125         if (artool == NULL) {
126                 /* add subdiv level; after header */
127                 for (arhead = sa->regionbase.first; arhead; arhead = arhead->next)
128                         if (arhead->regiontype == RGN_TYPE_HEADER)
129                                 break;
130                 
131                 /* is error! */
132                 if (arhead == NULL) return NULL;
133                 
134                 artool = MEM_callocN(sizeof(ARegion), "tools for view3d");
135                 
136                 BLI_insertlinkafter(&sa->regionbase, arhead, artool);
137                 artool->regiontype = RGN_TYPE_TOOLS;
138                 artool->alignment = RGN_ALIGN_LEFT;
139                 artool->flag = RGN_FLAG_HIDDEN;
140         }
141
142         if (arprops == NULL) {
143                 /* add extra subdivided region for tool properties */
144                 arprops = MEM_callocN(sizeof(ARegion), "tool props for view3d");
145                 
146                 BLI_insertlinkafter(&sa->regionbase, artool, arprops);
147                 arprops->regiontype = RGN_TYPE_TOOL_PROPS;
148                 arprops->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
149         }
150         
151         return artool;
152 }
153
154 /* ****************************************************** */
155
156 /* function to always find a regionview3d context inside 3D window */
157 RegionView3D *ED_view3d_context_rv3d(bContext *C)
158 {
159         RegionView3D *rv3d = CTX_wm_region_view3d(C);
160         
161         if (rv3d == NULL) {
162                 ScrArea *sa = CTX_wm_area(C);
163                 if (sa && sa->spacetype == SPACE_VIEW3D) {
164                         ARegion *ar = BKE_area_find_region_active_win(sa);
165                         if (ar) {
166                                 rv3d = ar->regiondata;
167                         }
168                 }
169         }
170         return rv3d;
171 }
172
173 /* ideally would return an rv3d but in some cases the region is needed too
174  * so return that, the caller can then access the ar->regiondata */
175 bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
176 {
177         ScrArea *sa = CTX_wm_area(C);
178
179         *r_v3d = NULL;
180         *r_ar = NULL;
181
182         if (sa && sa->spacetype == SPACE_VIEW3D) {
183                 ARegion *ar = CTX_wm_region(C);
184                 View3D *v3d = (View3D *)sa->spacedata.first;
185
186                 if (ar) {
187                         RegionView3D *rv3d;
188                         if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) && (rv3d->viewlock & RV3D_LOCKED) == 0) {
189                                 *r_v3d = v3d;
190                                 *r_ar = ar;
191                                 return true;
192                         }
193                         else {
194                                 ARegion *ar_unlock_user = NULL;
195                                 ARegion *ar_unlock = NULL;
196                                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
197                                         /* find the first unlocked rv3d */
198                                         if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
199                                                 rv3d = ar->regiondata;
200                                                 if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
201                                                         ar_unlock = ar;
202                                                         if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) {
203                                                                 ar_unlock_user = ar;
204                                                                 break;
205                                                         }
206                                                 }
207                                         }
208                                 }
209
210                                 /* camera/perspective view get priority when the active region is locked */
211                                 if (ar_unlock_user) {
212                                         *r_v3d = v3d;
213                                         *r_ar = ar_unlock_user;
214                                         return true;
215                                 }
216
217                                 if (ar_unlock) {
218                                         *r_v3d = v3d;
219                                         *r_ar = ar_unlock;
220                                         return true;
221                                 }
222                         }
223                 }
224         }
225
226         return false;
227 }
228
229 /* Most of the time this isn't needed since you could assume the view matrix was
230  * set while drawing, however when functions like mesh_foreachScreenVert are
231  * called by selection tools, we can't be sure this object was the last.
232  *
233  * for example, transparent objects are drawn after editmode and will cause
234  * the rv3d mat's to change and break selection.
235  *
236  * 'ED_view3d_init_mats_rv3d' should be called before
237  * view3d_project_short_clip and view3d_project_short_noclip in cases where
238  * these functions are not used during draw_object
239  */
240 void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
241 {
242         /* local viewmat and persmat, to calculate projections */
243         mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
244         mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
245
246         /* initializes object space clipping, speeds up clip tests */
247         ED_view3d_clipping_local(rv3d, ob->obmat);
248 }
249
250 void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
251 {
252         ED_view3d_init_mats_rv3d(ob, rv3d);
253
254         /* we have to multiply instead of loading viewmatob to make
255          * it work with duplis using displists, otherwise it will
256          * override the dupli-matrix */
257         gpuMultMatrix(ob->obmat);
258 }
259
260 #ifdef DEBUG
261 /* ensure we correctly initialize */
262 void ED_view3d_clear_mats_rv3d(struct RegionView3D *rv3d)
263 {
264         zero_m4(rv3d->viewmatob);
265         zero_m4(rv3d->persmatob);
266 }
267
268 void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
269 {
270         BLI_ASSERT_ZERO_M4(rv3d->viewmatob);
271         BLI_ASSERT_ZERO_M4(rv3d->persmatob);
272 }
273 #endif
274
275 void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
276 {
277         RegionView3D *rv3d = ar->regiondata;
278
279         if (rv3d->render_engine) {
280 #ifdef WITH_PYTHON
281                 BPy_BEGIN_ALLOW_THREADS;
282 #endif
283
284                 WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
285
286 #ifdef WITH_PYTHON
287                 BPy_END_ALLOW_THREADS;
288 #endif
289
290                 if (rv3d->render_engine->re)
291                         RE_Database_Free(rv3d->render_engine->re);
292                 RE_engine_free(rv3d->render_engine);
293                 rv3d->render_engine = NULL;
294         }
295 }
296
297 void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa)
298 {
299         wmWindowManager *wm = bmain->wm.first;
300
301         if (v3d->drawtype != OB_RENDER) {
302                 ARegion *ar;
303
304                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
305                         if (ar->regiondata)
306                                 ED_view3d_stop_render_preview(wm, ar);
307                 }
308         }
309         else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) {
310                 /* Tag mesh to load edit data. */
311                 DEG_id_tag_update(scene->obedit->data, 0);
312         }
313 }
314
315 /* ******************** default callbacks for view3d space ***************** */
316
317 static SpaceLink *view3d_new(const bContext *C)
318 {
319         Scene *scene = CTX_data_scene(C);
320         ARegion *ar;
321         View3D *v3d;
322         RegionView3D *rv3d;
323         
324         v3d = MEM_callocN(sizeof(View3D), "initview3d");
325         v3d->spacetype = SPACE_VIEW3D;
326         v3d->blockscale = 0.7f;
327         v3d->lay = v3d->layact = 1;
328         if (scene) {
329                 v3d->lay = v3d->layact = scene->lay;
330                 v3d->camera = scene->camera;
331         }
332         v3d->scenelock = true;
333         v3d->grid = 1.0f;
334         v3d->gridlines = 16;
335         v3d->gridsubdiv = 10;
336         v3d->drawtype = OB_SOLID;
337
338         v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
339         
340         v3d->flag = V3D_SELECT_OUTLINE;
341         v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_GPENCIL;
342         
343         v3d->lens = 35.0f;
344         v3d->near = 0.01f;
345         v3d->far = 1000.0f;
346
347         v3d->twflag |= U.manipulator_flag & V3D_MANIPULATOR_DRAW;
348         v3d->twtype = V3D_MANIP_TRANSLATE;
349         v3d->around = V3D_AROUND_CENTER_MEAN;
350         
351         v3d->bundle_size = 0.2f;
352         v3d->bundle_drawtype = OB_PLAINAXES;
353
354         /* stereo */
355         v3d->stereo3d_camera = STEREO_3D_ID;
356         v3d->stereo3d_flag |= V3D_S3D_DISPPLANE;
357         v3d->stereo3d_convergence_alpha = 0.15f;
358         v3d->stereo3d_volume_alpha = 0.05f;
359
360         /* header */
361         ar = MEM_callocN(sizeof(ARegion), "header for view3d");
362         
363         BLI_addtail(&v3d->regionbase, ar);
364         ar->regiontype = RGN_TYPE_HEADER;
365         ar->alignment = RGN_ALIGN_BOTTOM;
366         
367         /* tool shelf */
368         ar = MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
369         
370         BLI_addtail(&v3d->regionbase, ar);
371         ar->regiontype = RGN_TYPE_TOOLS;
372         ar->alignment = RGN_ALIGN_LEFT;
373         ar->flag = RGN_FLAG_HIDDEN;
374         
375         /* tool properties */
376         ar = MEM_callocN(sizeof(ARegion), "tool properties for view3d");
377         
378         BLI_addtail(&v3d->regionbase, ar);
379         ar->regiontype = RGN_TYPE_TOOL_PROPS;
380         ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
381         ar->flag = RGN_FLAG_HIDDEN;
382         
383         /* buttons/list view */
384         ar = MEM_callocN(sizeof(ARegion), "buttons for view3d");
385         
386         BLI_addtail(&v3d->regionbase, ar);
387         ar->regiontype = RGN_TYPE_UI;
388         ar->alignment = RGN_ALIGN_RIGHT;
389         ar->flag = RGN_FLAG_HIDDEN;
390         
391         /* main region */
392         ar = MEM_callocN(sizeof(ARegion), "main region for view3d");
393         
394         BLI_addtail(&v3d->regionbase, ar);
395         ar->regiontype = RGN_TYPE_WINDOW;
396         
397         ar->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d");
398         rv3d = ar->regiondata;
399         rv3d->viewquat[0] = 1.0f;
400         rv3d->persp = RV3D_PERSP;
401         rv3d->view = RV3D_VIEW_USER;
402         rv3d->dist = 10.0;
403         
404         return (SpaceLink *)v3d;
405 }
406
407 /* not spacelink itself */
408 static void view3d_free(SpaceLink *sl)
409 {
410         View3D *vd = (View3D *) sl;
411         BGpic *bgpic;
412
413         for (bgpic = vd->bgpicbase.first; bgpic; bgpic = bgpic->next) {
414                 if (bgpic->source == V3D_BGPIC_IMAGE) {
415                         id_us_min((ID *)bgpic->ima);
416                 }
417                 else if (bgpic->source == V3D_BGPIC_MOVIE) {
418                         id_us_min((ID *)bgpic->clip);
419                 }
420         }
421         BLI_freelistN(&vd->bgpicbase);
422
423         if (vd->localvd) MEM_freeN(vd->localvd);
424         
425         if (vd->properties_storage) MEM_freeN(vd->properties_storage);
426         
427         /* matcap material, its preview rect gets freed via icons */
428         if (vd->defmaterial) {
429                 if (vd->defmaterial->gpumaterial.first)
430                         GPU_material_free(&vd->defmaterial->gpumaterial);
431                 BKE_previewimg_free(&vd->defmaterial->preview);
432                 MEM_freeN(vd->defmaterial);
433         }
434
435         if (vd->fx_settings.ssao)
436                 MEM_freeN(vd->fx_settings.ssao);
437         if (vd->fx_settings.dof)
438                 MEM_freeN(vd->fx_settings.dof);
439 }
440
441
442 /* spacetype; init callback */
443 static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
444 {
445
446 }
447
448 static SpaceLink *view3d_duplicate(SpaceLink *sl)
449 {
450         View3D *v3do = (View3D *)sl;
451         View3D *v3dn = MEM_dupallocN(sl);
452         BGpic *bgpic;
453         
454         /* clear or remove stuff from old */
455
456         if (v3dn->localvd) {
457                 v3dn->localvd = NULL;
458                 v3dn->properties_storage = NULL;
459                 v3dn->lay = v3do->localvd->lay & 0xFFFFFF;
460         }
461
462         if (v3dn->drawtype == OB_RENDER)
463                 v3dn->drawtype = OB_SOLID;
464         
465         /* copy or clear inside new stuff */
466
467         v3dn->defmaterial = NULL;
468
469         BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase);
470         for (bgpic = v3dn->bgpicbase.first; bgpic; bgpic = bgpic->next) {
471                 if (bgpic->source == V3D_BGPIC_IMAGE) {
472                         id_us_plus((ID *)bgpic->ima);
473                 }
474                 else if (bgpic->source == V3D_BGPIC_MOVIE) {
475                         id_us_plus((ID *)bgpic->clip);
476                 }
477         }
478
479         v3dn->properties_storage = NULL;
480         if (v3dn->fx_settings.dof)
481                 v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
482         if (v3dn->fx_settings.ssao)
483                 v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao);
484
485         return (SpaceLink *)v3dn;
486 }
487
488 /* add handlers, stuff you only do once or on area/region changes */
489 static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
490 {
491         ListBase *lb;
492         wmKeyMap *keymap;
493
494         if (ar->manipulator_map == NULL) {
495                 ar->manipulator_map = WM_manipulatormap_new_from_type(
496                         &(const struct wmManipulatorMapType_Params) {SPACE_VIEW3D, RGN_TYPE_WINDOW});
497         }
498
499         WM_manipulatormap_add_handlers(ar, ar->manipulator_map);
500
501         /* object ops. */
502         
503         /* important to be before Pose keymap since they can both be enabled at once */
504         keymap = WM_keymap_find(wm->defaultconf, "Face Mask", 0, 0);
505         WM_event_add_keymap_handler(&ar->handlers, keymap);
506         
507         
508         keymap = WM_keymap_find(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0);
509         WM_event_add_keymap_handler(&ar->handlers, keymap);
510
511         /* pose is not modal, operator poll checks for this */
512         keymap = WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
513         WM_event_add_keymap_handler(&ar->handlers, keymap);
514         
515         keymap = WM_keymap_find(wm->defaultconf, "Object Mode", 0, 0);
516         WM_event_add_keymap_handler(&ar->handlers, keymap);
517
518         keymap = WM_keymap_find(wm->defaultconf, "Paint Curve", 0, 0);
519         WM_event_add_keymap_handler(&ar->handlers, keymap);
520
521         keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
522         WM_event_add_keymap_handler(&ar->handlers, keymap);
523
524         keymap = WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
525         WM_event_add_keymap_handler(&ar->handlers, keymap);
526
527         keymap = WM_keymap_find(wm->defaultconf, "Vertex Paint", 0, 0);
528         WM_event_add_keymap_handler(&ar->handlers, keymap);
529
530         keymap = WM_keymap_find(wm->defaultconf, "Weight Paint", 0, 0);
531         WM_event_add_keymap_handler(&ar->handlers, keymap);
532
533         keymap = WM_keymap_find(wm->defaultconf, "Sculpt", 0, 0);
534         WM_event_add_keymap_handler(&ar->handlers, keymap);
535         
536         keymap = WM_keymap_find(wm->defaultconf, "Mesh", 0, 0);
537         WM_event_add_keymap_handler(&ar->handlers, keymap);
538         
539         keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
540         WM_event_add_keymap_handler(&ar->handlers, keymap);
541         
542         keymap = WM_keymap_find(wm->defaultconf, "Armature", 0, 0);
543         WM_event_add_keymap_handler(&ar->handlers, keymap);
544
545         keymap = WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
546         WM_event_add_keymap_handler(&ar->handlers, keymap);
547
548         keymap = WM_keymap_find(wm->defaultconf, "Metaball", 0, 0);
549         WM_event_add_keymap_handler(&ar->handlers, keymap);
550         
551         keymap = WM_keymap_find(wm->defaultconf, "Lattice", 0, 0);
552         WM_event_add_keymap_handler(&ar->handlers, keymap);
553
554         keymap = WM_keymap_find(wm->defaultconf, "Particle", 0, 0);
555         WM_event_add_keymap_handler(&ar->handlers, keymap);
556
557         /* editfont keymap swallows all... */
558         keymap = WM_keymap_find(wm->defaultconf, "Font", 0, 0);
559         WM_event_add_keymap_handler(&ar->handlers, keymap);
560
561         keymap = WM_keymap_find(wm->defaultconf, "Object Non-modal", 0, 0);
562         WM_event_add_keymap_handler(&ar->handlers, keymap);
563
564         keymap = WM_keymap_find(wm->defaultconf, "Frames", 0, 0);
565         WM_event_add_keymap_handler(&ar->handlers, keymap);
566
567         /* own keymap, last so modes can override it */
568         keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
569         WM_event_add_keymap_handler(&ar->handlers, keymap);
570
571         keymap = WM_keymap_find(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
572         WM_event_add_keymap_handler(&ar->handlers, keymap);
573         
574         /* add drop boxes */
575         lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
576         
577         WM_event_add_dropbox_handler(&ar->handlers, lb);
578         
579 }
580
581 static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
582 {
583         RegionView3D *rv3d = ar->regiondata;
584
585         ED_view3d_stop_render_preview(wm, ar);
586
587         if (rv3d->gpuoffscreen) {
588                 GPU_offscreen_free(rv3d->gpuoffscreen);
589                 rv3d->gpuoffscreen = NULL;
590         }
591         
592         if (rv3d->compositor) {
593                 GPU_fx_compositor_destroy(rv3d->compositor);
594                 rv3d->compositor = NULL;
595         }
596
597         if (rv3d->viewport) {
598                 GPU_viewport_free(rv3d->viewport);
599                 MEM_freeN(rv3d->viewport);
600                 rv3d->viewport = NULL;
601         }
602 }
603
604 static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
605 {
606         if (drag->type == WM_DRAG_ID) {
607                 ID *id = drag->poin;
608                 if (GS(id->name) == ID_OB)
609                         return 1;
610         }
611         return 0;
612 }
613
614 static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
615 {
616         if (drag->type == WM_DRAG_ID) {
617                 ID *id = drag->poin;
618                 if (GS(id->name) == ID_GR)
619                         return 1;
620         }
621         return 0;
622 }
623
624 static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
625 {
626         if (drag->type == WM_DRAG_ID) {
627                 ID *id = drag->poin;
628                 if (GS(id->name) == ID_MA)
629                         return 1;
630         }
631         return 0;
632 }
633
634 static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
635 {
636         if (drag->type == WM_DRAG_ID) {
637                 ID *id = drag->poin;
638                 if (GS(id->name) == ID_IM)
639                         return 1;
640         }
641         else if (drag->type == WM_DRAG_PATH) {
642                 if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE))   /* rule might not work? */
643                         return 1;
644         }
645         return 0;
646 }
647
648 static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
649 {
650         if (event->ctrl)
651                 return false;
652
653         if (!ED_view3d_give_base_under_cursor(C, event->mval)) {
654                 return view3d_ima_drop_poll(C, drag, event);
655         }
656         return 0;
657 }
658
659 static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
660 {
661         BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval);
662
663         /* either holding and ctrl and no object, or dropping to empty */
664         if (((base == NULL) && event->ctrl) ||
665             ((base != NULL) && base->object->type == OB_EMPTY))
666         {
667                 return view3d_ima_drop_poll(C, drag, event);
668         }
669
670         return 0;
671 }
672
673 static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
674 {
675         BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval);
676
677         if (base && base->object->type == OB_MESH)
678                 return view3d_ima_drop_poll(C, drag, event);
679         return 0;
680 }
681
682 static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
683 {
684         ID *id = drag->poin;
685
686         RNA_string_set(drop->ptr, "name", id->name + 2);
687 }
688
689 static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
690 {
691         ID *id = drag->poin;
692         
693         drop->opcontext = WM_OP_EXEC_DEFAULT;
694         RNA_string_set(drop->ptr, "name", id->name + 2);
695 }
696
697 static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
698 {
699         ID *id = drag->poin;
700         
701         RNA_string_set(drop->ptr, "name", id->name + 2);
702 }
703
704 static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
705 {
706         ID *id = drag->poin;
707         
708         if (id) {
709                 RNA_string_set(drop->ptr, "name", id->name + 2);
710                 RNA_struct_property_unset(drop->ptr, "filepath");
711         }
712         else if (drag->path[0]) {
713                 RNA_string_set(drop->ptr, "filepath", drag->path);
714                 RNA_struct_property_unset(drop->ptr, "image");
715         }
716 }
717
718
719 /* region dropbox definition */
720 static void view3d_dropboxes(void)
721 {
722         ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
723         
724         WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy);
725         WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
726         WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
727         WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
728         WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
729         WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);     
730 }
731
732 static void view3d_widgets(void)
733 {
734         wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(
735                 &(const struct wmManipulatorMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW});
736
737         WM_manipulatorgrouptype_append_and_link(mmap_type, TRANSFORM_WGT_manipulator);
738         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_spot);
739         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_area);
740         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_target);
741         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_force_field);
742         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera);
743         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera_view);
744         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_empty_image);
745 }
746
747
748 /* type callback, not region itself */
749 static void view3d_main_region_free(ARegion *ar)
750 {
751         RegionView3D *rv3d = ar->regiondata;
752         
753         if (rv3d) {
754                 if (rv3d->localvd) MEM_freeN(rv3d->localvd);
755                 if (rv3d->clipbb) MEM_freeN(rv3d->clipbb);
756
757                 if (rv3d->render_engine)
758                         RE_engine_free(rv3d->render_engine);
759                 
760                 if (rv3d->depths) {
761                         if (rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
762                         MEM_freeN(rv3d->depths);
763                 }
764                 if (rv3d->sms) {
765                         MEM_freeN(rv3d->sms);
766                 }
767                 if (rv3d->gpuoffscreen) {
768                         GPU_offscreen_free(rv3d->gpuoffscreen);
769                 }
770                 if (rv3d->compositor) {
771                         GPU_fx_compositor_destroy(rv3d->compositor);
772                 }
773                 if (rv3d->viewport) {
774                         GPU_viewport_free(rv3d->viewport);
775                         MEM_freeN(rv3d->viewport);
776                 }
777
778                 MEM_freeN(rv3d);
779                 ar->regiondata = NULL;
780         }
781 }
782
783 /* copy regiondata */
784 static void *view3d_main_region_duplicate(void *poin)
785 {
786         if (poin) {
787                 RegionView3D *rv3d = poin, *new;
788         
789                 new = MEM_dupallocN(rv3d);
790                 if (rv3d->localvd)
791                         new->localvd = MEM_dupallocN(rv3d->localvd);
792                 if (rv3d->clipbb)
793                         new->clipbb = MEM_dupallocN(rv3d->clipbb);
794                 
795                 new->depths = NULL;
796                 new->gpuoffscreen = NULL;
797                 new->render_engine = NULL;
798                 new->sms = NULL;
799                 new->smooth_timer = NULL;
800                 new->compositor = NULL;
801                 new->viewport = NULL;
802                 
803                 return new;
804         }
805         return NULL;
806 }
807
808 static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, const Scene *scene)
809 {
810         wmWindow *win = wmn->wm->winactive;
811         unsigned int lay_used = 0;
812         BaseLegacy *base;
813
814         if (!win) return;
815
816         base = scene->base.first;
817         while (base) {
818                 lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */
819
820                 if (lay_used == (1 << 20) - 1)
821                         break;
822
823                 base = base->next;
824         }
825
826         const bScreen *screen = WM_window_get_active_screen(win);
827         for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
828                 if (sa->spacetype == SPACE_VIEW3D) {
829                         if (BLI_findindex(&sa->regionbase, ar) != -1) {
830                                 View3D *v3d = sa->spacedata.first;
831                                 v3d->lay_used = lay_used;
832                                 break;
833                         }
834                 }
835         }
836 }
837
838 static void view3d_main_region_listener(
839         bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar,
840         wmNotifier *wmn, const Scene *scene)
841 {
842         View3D *v3d = sa->spacedata.first;
843         RegionView3D *rv3d = ar->regiondata;
844         wmManipulatorMap *mmap = ar->manipulator_map;
845
846         /* context changes */
847         switch (wmn->category) {
848                 case NC_WM:
849                         if (ELEM(wmn->data, ND_UNDO)) {
850                                 WM_manipulatormap_tag_refresh(mmap);
851                         }
852                         break;
853                 case NC_ANIMATION:
854                         switch (wmn->data) {
855                                 case ND_KEYFRAME_PROP:
856                                 case ND_NLA_ACTCHANGE:
857                                         ED_region_tag_redraw(ar);
858                                         break;
859                                 case ND_NLA:
860                                 case ND_KEYFRAME:
861                                         if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
862                                                 ED_region_tag_redraw(ar);
863                                         break;
864                                 case ND_ANIMCHAN:
865                                         if (wmn->action == NA_SELECTED)
866                                                 ED_region_tag_redraw(ar);
867                                         break;
868                         }
869                         break;
870                 case NC_SCENE:
871                         switch (wmn->data) {
872                                 case ND_SCENEBROWSE:
873                                 case ND_LAYER_CONTENT:
874                                         if (wmn->reference)
875                                                 view3d_recalc_used_layers(ar, wmn, wmn->reference);
876                                         ED_region_tag_redraw(ar);
877                                         WM_manipulatormap_tag_refresh(mmap);
878                                         break;
879                                 case ND_LAYER:
880                                         if (wmn->reference) {
881                                                 BKE_screen_view3d_sync(v3d, wmn->reference);
882                                         }
883                                         ED_region_tag_redraw(ar);
884                                         break;
885                                 case ND_OB_ACTIVE:
886                                 case ND_OB_SELECT:
887                                         DEG_id_tag_update((ID *)&scene->id, DEG_TAG_COPY_ON_WRITE);
888                                         ATTR_FALLTHROUGH;
889                                 case ND_FRAME:
890                                 case ND_TRANSFORM:
891                                 case ND_OB_VISIBLE:
892                                 case ND_RENDER_OPTIONS:
893                                 case ND_MARKERS:
894                                 case ND_MODE:
895                                         ED_region_tag_redraw(ar);
896                                         WM_manipulatormap_tag_refresh(mmap);
897                                         break;
898                                 case ND_WORLD:
899                                         /* handled by space_view3d_listener() for v3d access */
900                                         break;
901                                 case ND_DRAW_RENDER_VIEWPORT:
902                                 {
903                                         if (v3d->camera && (scene == wmn->reference)) {
904                                                 if (rv3d->persp == RV3D_CAMOB) {
905                                                         ED_region_tag_redraw(ar);
906                                                 }
907                                         }
908                                         break;
909                                 }
910                         }
911                         if (wmn->action == NA_EDITED)
912                                 ED_region_tag_redraw(ar);
913                         break;
914                 case NC_OBJECT:
915                         switch (wmn->data) {
916                                 case ND_BONE_ACTIVE:
917                                 case ND_BONE_SELECT:
918                                 case ND_TRANSFORM:
919                                 case ND_POSE:
920                                 case ND_DRAW:
921                                 case ND_MODIFIER:
922                                 case ND_CONSTRAINT:
923                                 case ND_KEYS:
924                                 case ND_PARTICLE:
925                                 case ND_POINTCACHE:
926                                 case ND_LOD:
927                                         ED_region_tag_redraw(ar);
928                                         WM_manipulatormap_tag_refresh(mmap);
929                                         break;
930                         }
931                         switch (wmn->action) {
932                                 case NA_ADDED:
933                                         ED_region_tag_redraw(ar);
934                                         break;
935                         }
936                         break;
937                 case NC_GEOM:
938                         switch (wmn->data) {
939                                 case ND_SELECT:
940                                 {
941                                         WM_manipulatormap_tag_refresh(mmap);
942
943                                         if (scene->obedit) {
944                                                 Object *ob = scene->obedit;
945                                                 switch (ob->type) {
946                                                         case OB_MESH:
947                                                                 BKE_mesh_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT);
948                                                                 break;
949                                                         // case OB_FONT:  /* handled by text_update_edited */
950                                                         case OB_CURVE:
951                                                         case OB_SURF:
952                                                                 BKE_curve_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT);
953                                                                 break;
954                                                         case OB_LATTICE:
955                                                                 BKE_lattice_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT);
956                                                                 break;
957                                                 }
958                                         }
959                                         ATTR_FALLTHROUGH;
960                                 }
961                                 case ND_DATA:
962                                 case ND_VERTEX_GROUP:
963                                         ED_region_tag_redraw(ar);
964                                         break;
965                         }
966                         switch (wmn->action) {
967                                 case NA_EDITED:
968                                         ED_region_tag_redraw(ar);
969                                         break;
970                         }
971                         break;
972                 case NC_CAMERA:
973                         switch (wmn->data) {
974                                 case ND_DRAW_RENDER_VIEWPORT:
975                                 {
976                                         if (v3d->camera && (v3d->camera->data == wmn->reference)) {
977                                                 if (rv3d->persp == RV3D_CAMOB) {
978                                                         ED_region_tag_redraw(ar);
979                                                 }
980                                         }
981                                         break;
982                                 }
983                         }
984                         break;
985                 case NC_GROUP:
986                         /* all group ops for now */
987                         ED_region_tag_redraw(ar);
988                         break;
989                 case NC_BRUSH:
990                         switch (wmn->action) {
991                                 case NA_EDITED:
992                                         ED_region_tag_redraw_overlay(ar);
993                                         break;
994                                 case NA_SELECTED:
995                                         /* used on brush changes - needed because 3d cursor
996                                          * has to be drawn if clone brush is selected */
997                                         ED_region_tag_redraw(ar);
998                                         break;
999                         }
1000                         break;
1001                 case NC_MATERIAL:
1002                         switch (wmn->data) {
1003                                 case ND_SHADING:
1004                                 case ND_NODES:
1005                                         /* TODO(sergey) This is a bit too much updates, but needed to
1006                                          * have proper material drivers update in the viewport.
1007                                          *
1008                                          * How to solve?
1009                                          */
1010                                         ED_region_tag_redraw(ar);
1011                                         break;
1012                                 case ND_SHADING_DRAW:
1013                                 case ND_SHADING_LINKS:
1014                                         ED_region_tag_redraw(ar);
1015                                         break;
1016                         }
1017                         break;
1018                 case NC_WORLD:
1019                         switch (wmn->data) {
1020                                 case ND_WORLD_DRAW:
1021                                         /* handled by space_view3d_listener() for v3d access */
1022                                         break;
1023                                 case ND_WORLD:
1024                                         /* Needed for updating world materials */
1025                                         ED_region_tag_redraw(ar);
1026                                         break;
1027                         }
1028                         break;
1029                 case NC_LAMP:
1030                         switch (wmn->data) {
1031                                 case ND_LIGHTING:
1032                                         /* TODO(sergey): This is a bit too much, but needed to
1033                                          * handle updates from new depsgraph.
1034                                          */
1035                                         ED_region_tag_redraw(ar);
1036                                         break;
1037                                 case ND_LIGHTING_DRAW:
1038                                         ED_region_tag_redraw(ar);
1039                                         WM_manipulatormap_tag_refresh(mmap);
1040                                         break;
1041                         }
1042                         break;
1043                 case NC_IMAGE:
1044                         /* this could be more fine grained checks if we had
1045                          * more context than just the region */
1046                         ED_region_tag_redraw(ar);
1047                         break;
1048                 case NC_TEXTURE:
1049                         /* same as above */
1050                         ED_region_tag_redraw(ar);
1051                         break;
1052                 case NC_MOVIECLIP:
1053                         if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED)
1054                                 ED_region_tag_redraw(ar);
1055                         break;
1056                 case NC_SPACE:
1057                         if (wmn->data == ND_SPACE_VIEW3D) {
1058                                 if (wmn->subtype == NS_VIEW3D_GPU) {
1059                                         rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
1060                                 }
1061                                 ED_region_tag_redraw(ar);
1062                                 WM_manipulatormap_tag_refresh(mmap);
1063                         }
1064                         break;
1065                 case NC_ID:
1066                         if (wmn->action == NA_RENAME)
1067                                 ED_region_tag_redraw(ar);
1068                         break;
1069                 case NC_SCREEN:
1070                         switch (wmn->data) {
1071                                 case ND_ANIMPLAY:
1072                                 case ND_SKETCH:
1073                                         ED_region_tag_redraw(ar);
1074                                         break;
1075                                 case ND_LAYOUTBROWSE:
1076                                 case ND_LAYOUTDELETE:
1077                                 case ND_LAYOUTSET:
1078                                         WM_manipulatormap_tag_refresh(mmap);
1079                                         ED_region_tag_redraw(ar);
1080                                         break;
1081                                 case ND_LAYER:
1082                                         ED_region_tag_redraw(ar);
1083                                         break;
1084                         }
1085
1086                         break;
1087                 case NC_GPENCIL:
1088                         if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
1089                                 ED_region_tag_redraw(ar);
1090                         }
1091                         break;
1092         }
1093 }
1094
1095 /* concept is to retrieve cursor type context-less */
1096 static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
1097 {
1098         const Scene *scene = WM_window_get_active_scene(win);
1099
1100         if (scene->obedit) {
1101                 WM_cursor_set(win, CURSOR_EDIT);
1102         }
1103         else {
1104                 WM_cursor_set(win, CURSOR_STD);
1105         }
1106 }
1107
1108 /* add handlers, stuff you only do once or on area/region changes */
1109 static void view3d_header_region_init(wmWindowManager *wm, ARegion *ar)
1110 {
1111         wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
1112         
1113         WM_event_add_keymap_handler(&ar->handlers, keymap);
1114
1115         ED_region_header_init(ar);
1116 }
1117
1118 static void view3d_header_region_draw(const bContext *C, ARegion *ar)
1119 {
1120         ED_region_header(C, ar);
1121 }
1122
1123 static void view3d_header_region_listener(
1124         bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
1125         wmNotifier *wmn, const Scene *UNUSED(scene))
1126 {
1127         /* context changes */
1128         switch (wmn->category) {
1129                 case NC_SCENE:
1130                         switch (wmn->data) {
1131                                 case ND_FRAME:
1132                                 case ND_OB_ACTIVE:
1133                                 case ND_OB_SELECT:
1134                                 case ND_OB_VISIBLE:
1135                                 case ND_MODE:
1136                                 case ND_LAYER:
1137                                 case ND_TOOLSETTINGS:
1138                                 case ND_LAYER_CONTENT:
1139                                 case ND_RENDER_OPTIONS:
1140                                         ED_region_tag_redraw(ar);
1141                                         break;
1142                         }
1143                         break;
1144                 case NC_SPACE:
1145                         if (wmn->data == ND_SPACE_VIEW3D)
1146                                 ED_region_tag_redraw(ar);
1147                         break;
1148                 case NC_GPENCIL:
1149                         if (wmn->data & ND_GPENCIL_EDITMODE)
1150                                 ED_region_tag_redraw(ar);
1151                         break;
1152         }
1153 }
1154
1155 /* add handlers, stuff you only do once or on area/region changes */
1156 static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
1157 {
1158         wmKeyMap *keymap;
1159
1160         ED_region_panels_init(wm, ar);
1161         
1162         keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
1163         WM_event_add_keymap_handler(&ar->handlers, keymap);
1164 }
1165
1166 static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
1167 {
1168         ED_region_panels(C, ar, NULL, -1, true);
1169 }
1170
1171 static void view3d_buttons_region_listener(
1172         bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
1173         wmNotifier *wmn, const Scene *UNUSED(scene))
1174 {
1175         /* context changes */
1176         switch (wmn->category) {
1177                 case NC_ANIMATION:
1178                         switch (wmn->data) {
1179                                 case ND_KEYFRAME_PROP:
1180                                 case ND_NLA_ACTCHANGE:
1181                                         ED_region_tag_redraw(ar);
1182                                         break;
1183                                 case ND_NLA:
1184                                 case ND_KEYFRAME:
1185                                         if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
1186                                                 ED_region_tag_redraw(ar);
1187                                         break;
1188                         }
1189                         break;
1190                 case NC_SCENE:
1191                         switch (wmn->data) {
1192                                 case ND_FRAME:
1193                                 case ND_OB_ACTIVE:
1194                                 case ND_OB_SELECT:
1195                                 case ND_OB_VISIBLE:
1196                                 case ND_MODE:
1197                                 case ND_LAYER:
1198                                 case ND_LAYER_CONTENT:
1199                                 case ND_TOOLSETTINGS:
1200                                         ED_region_tag_redraw(ar);
1201                                         break;
1202                         }
1203                         switch (wmn->action) {
1204                                 case NA_EDITED:
1205                                         ED_region_tag_redraw(ar);
1206                                         break;
1207                         }
1208                         break;
1209                 case NC_OBJECT:
1210                         switch (wmn->data) {
1211                                 case ND_BONE_ACTIVE:
1212                                 case ND_BONE_SELECT:
1213                                 case ND_TRANSFORM:
1214                                 case ND_POSE:
1215                                 case ND_DRAW:
1216                                 case ND_KEYS:
1217                                 case ND_MODIFIER:
1218                                         ED_region_tag_redraw(ar);
1219                                         break;
1220                         }
1221                         break;
1222                 case NC_GEOM:
1223                         switch (wmn->data) {
1224                                 case ND_DATA:
1225                                 case ND_VERTEX_GROUP:
1226                                 case ND_SELECT:
1227                                         ED_region_tag_redraw(ar);
1228                                         break;
1229                         }
1230                         if (wmn->action == NA_EDITED)
1231                                 ED_region_tag_redraw(ar);
1232                         break;
1233                 case NC_TEXTURE:
1234                 case NC_MATERIAL:
1235                         /* for brush textures */
1236                         ED_region_tag_redraw(ar);
1237                         break;
1238                 case NC_BRUSH:
1239                         /* NA_SELECTED is used on brush changes */
1240                         if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
1241                                 ED_region_tag_redraw(ar);
1242                         break;
1243                 case NC_SPACE:
1244                         if (wmn->data == ND_SPACE_VIEW3D)
1245                                 ED_region_tag_redraw(ar);
1246                         break;
1247                 case NC_ID:
1248                         if (wmn->action == NA_RENAME)
1249                                 ED_region_tag_redraw(ar);
1250                         break;
1251                 case NC_GPENCIL:
1252                         if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED))
1253                                 ED_region_tag_redraw(ar);
1254                         break;
1255                 case NC_IMAGE:
1256                         /* Update for the image layers in texture paint. */
1257                         if (wmn->action == NA_EDITED)
1258                                 ED_region_tag_redraw(ar);
1259                         break;
1260         }
1261 }
1262
1263 /* add handlers, stuff you only do once or on area/region changes */
1264 static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
1265 {
1266         wmKeyMap *keymap;
1267         
1268         ED_region_panels_init(wm, ar);
1269
1270         keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
1271         WM_event_add_keymap_handler(&ar->handlers, keymap);
1272 }
1273
1274 static void view3d_tools_region_draw(const bContext *C, ARegion *ar)
1275 {
1276         ED_region_panels(C, ar, CTX_data_mode_string(C), -1, true);
1277 }
1278
1279 static void view3d_props_region_listener(
1280         bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
1281         wmNotifier *wmn, const Scene *UNUSED(scene))
1282 {
1283         /* context changes */
1284         switch (wmn->category) {
1285                 case NC_WM:
1286                         if (wmn->data == ND_HISTORY)
1287                                 ED_region_tag_redraw(ar);
1288                         break;
1289                 case NC_SCENE:
1290                         if (wmn->data == ND_MODE)
1291                                 ED_region_tag_redraw(ar);
1292                         break;
1293                 case NC_SPACE:
1294                         if (wmn->data == ND_SPACE_VIEW3D)
1295                                 ED_region_tag_redraw(ar);
1296                         break;
1297         }
1298 }
1299
1300 /* area (not region) level listener */
1301 static void space_view3d_listener(
1302         bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn, const Scene *UNUSED(scene))
1303 {
1304         View3D *v3d = sa->spacedata.first;
1305
1306         /* context changes */
1307         switch (wmn->category) {
1308                 case NC_SCENE:
1309                         switch (wmn->data) {
1310                                 case ND_WORLD:
1311                                         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1312                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
1313                                         break;
1314                         }
1315                         break;
1316                 case NC_WORLD:
1317                         switch (wmn->data) {
1318                                 case ND_WORLD_DRAW:
1319                                 case ND_WORLD:
1320                                         if (v3d->flag3 & V3D_SHOW_WORLD)
1321                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
1322                                         break;
1323                         }
1324                         break;
1325                 case NC_MATERIAL:
1326                         switch (wmn->data) {
1327                                 case ND_NODES:
1328                                         if (v3d->drawtype == OB_TEXTURE)
1329                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
1330                                         break;
1331                         }
1332                         break;
1333         }
1334 }
1335
1336 const char *view3d_context_dir[] = {
1337         "active_base", "active_object", NULL
1338 };
1339
1340 static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
1341 {
1342         /* fallback to the scene layer, allows duplicate and other object operators to run outside the 3d view */
1343
1344         if (CTX_data_dir(member)) {
1345                 CTX_data_dir_set(result, view3d_context_dir);
1346         }
1347         else if (CTX_data_equals(member, "active_base")) {
1348                 Scene *scene = CTX_data_scene(C);
1349                 SceneLayer *sl = CTX_data_scene_layer(C);
1350                 if (sl->basact) {
1351                         Object *ob = sl->basact->object;
1352                         /* if hidden but in edit mode, we still display, can happen with animation */
1353                         if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) {
1354                                 CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact);
1355                         }
1356                 }
1357                 
1358                 return 1;
1359         }
1360         else if (CTX_data_equals(member, "active_object")) {
1361                 SceneLayer *sl = CTX_data_scene_layer(C);
1362                 if (sl->basact) {
1363                         Object *ob = sl->basact->object;
1364                         /* if hidden but in edit mode, we still display, can happen with animation */
1365                         if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
1366                                 CTX_data_id_pointer_set(result, &ob->id);
1367                         }
1368                 }
1369                 
1370                 return 1;
1371         }
1372         else {
1373                 return 0; /* not found */
1374         }
1375
1376         return -1; /* found but not available */
1377 }
1378
1379 static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_id)
1380 {
1381         View3D *v3d;
1382         ARegion *ar;
1383         bool is_local = false;
1384
1385         if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) {
1386                 return;
1387         }
1388
1389         for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) {
1390                 if ((ID *)v3d->camera == old_id) {
1391                         v3d->camera = (Object *)new_id;
1392                         if (!new_id) {
1393                                 /* 3D view might be inactive, in that case needs to use slink->regionbase */
1394                                 ListBase *regionbase = (slink == sa->spacedata.first) ? &sa->regionbase : &slink->regionbase;
1395                                 for (ar = regionbase->first; ar; ar = ar->next) {
1396                                         if (ar->regiontype == RGN_TYPE_WINDOW) {
1397                                                 RegionView3D *rv3d = is_local ? ((RegionView3D *)ar->regiondata)->localvd : ar->regiondata;
1398                                                 if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
1399                                                         rv3d->persp = RV3D_PERSP;
1400                                                 }
1401                                         }
1402                                 }
1403                         }
1404                 }
1405                 if ((ID *)v3d->ob_centre == old_id) {
1406                         v3d->ob_centre = (Object *)new_id;
1407                         if (new_id == NULL) {  /* Otherwise, bonename may remain valid... We could be smart and check this, too? */
1408                                 v3d->ob_centre_bone[0] = '\0';
1409                         }
1410                 }
1411
1412                 if ((ID *)v3d->defmaterial == old_id) {
1413                         v3d->defmaterial = (Material *)new_id;
1414                 }
1415 #if 0  /* XXX Deprecated? */
1416                 if ((ID *)v3d->gpd == old_id) {
1417                         v3d->gpd = (bGPData *)new_id;
1418                 }
1419 #endif
1420
1421                 if (ELEM(GS(old_id->name), ID_IM, ID_MC)) {
1422                         for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
1423                                 if ((ID *)bgpic->ima == old_id) {
1424                                         bgpic->ima = (Image *)new_id;
1425                                         id_us_min(old_id);
1426                                         id_us_plus(new_id);
1427                                 }
1428                                 if ((ID *)bgpic->clip == old_id) {
1429                                         bgpic->clip = (MovieClip *)new_id;
1430                                         id_us_min(old_id);
1431                                         id_us_plus(new_id);
1432                                 }
1433                         }
1434                 }
1435
1436                 if (is_local) {
1437                         break;
1438                 }
1439         }
1440 }
1441
1442 /* only called once, from space/spacetypes.c */
1443 void ED_spacetype_view3d(void)
1444 {
1445         SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype view3d");
1446         ARegionType *art;
1447         
1448         st->spaceid = SPACE_VIEW3D;
1449         strncpy(st->name, "View3D", BKE_ST_MAXNAME);
1450         
1451         st->new = view3d_new;
1452         st->free = view3d_free;
1453         st->init = view3d_init;
1454         st->listener = space_view3d_listener;
1455         st->duplicate = view3d_duplicate;
1456         st->operatortypes = view3d_operatortypes;
1457         st->keymap = view3d_keymap;
1458         st->dropboxes = view3d_dropboxes;
1459         st->manipulators = view3d_widgets;
1460         st->context = view3d_context;
1461         st->id_remap = view3d_id_remap;
1462
1463         /* regions: main window */
1464         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
1465         art->regionid = RGN_TYPE_WINDOW;
1466         art->keymapflag = ED_KEYMAP_GPENCIL;
1467         art->draw = view3d_main_region_draw;
1468         art->init = view3d_main_region_init;
1469         art->exit = view3d_main_region_exit;
1470         art->free = view3d_main_region_free;
1471         art->duplicate = view3d_main_region_duplicate;
1472         art->listener = view3d_main_region_listener;
1473         art->cursor = view3d_main_region_cursor;
1474         art->lock = 1;   /* can become flag, see BKE_spacedata_draw_locks */
1475         BLI_addhead(&st->regiontypes, art);
1476         
1477         /* regions: listview/buttons */
1478         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
1479         art->regionid = RGN_TYPE_UI;
1480         art->prefsizex = 180; /* XXX */
1481         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1482         art->listener = view3d_buttons_region_listener;
1483         art->init = view3d_buttons_region_init;
1484         art->draw = view3d_buttons_region_draw;
1485         BLI_addhead(&st->regiontypes, art);
1486
1487         view3d_buttons_register(art);
1488
1489         /* regions: tool(bar) */
1490         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
1491         art->regionid = RGN_TYPE_TOOLS;
1492         art->prefsizex = 160; /* XXX */
1493         art->prefsizey = 50; /* XXX */
1494         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1495         art->listener = view3d_buttons_region_listener;
1496         art->init = view3d_tools_region_init;
1497         art->draw = view3d_tools_region_draw;
1498         BLI_addhead(&st->regiontypes, art);
1499         
1500 #if 0
1501         /* unfinished still */
1502         view3d_toolshelf_register(art);
1503 #endif
1504
1505         /* regions: tool properties */
1506         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tool properties region");
1507         art->regionid = RGN_TYPE_TOOL_PROPS;
1508         art->prefsizex = 0;
1509         art->prefsizey = 120;
1510         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1511         art->listener = view3d_props_region_listener;
1512         art->init = view3d_tools_region_init;
1513         art->draw = view3d_tools_region_draw;
1514         BLI_addhead(&st->regiontypes, art);
1515         
1516         view3d_tool_props_register(art);
1517         
1518         
1519         /* regions: header */
1520         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
1521         art->regionid = RGN_TYPE_HEADER;
1522         art->prefsizey = HEADERY;
1523         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
1524         art->listener = view3d_header_region_listener;
1525         art->init = view3d_header_region_init;
1526         art->draw = view3d_header_region_draw;
1527         BLI_addhead(&st->regiontypes, art);
1528         
1529         BKE_spacetype_register(st);
1530 }
1531