Manipulator: Add b-bone spline editing
[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         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_armature_spline);
746 }
747
748
749 /* type callback, not region itself */
750 static void view3d_main_region_free(ARegion *ar)
751 {
752         RegionView3D *rv3d = ar->regiondata;
753         
754         if (rv3d) {
755                 if (rv3d->localvd) MEM_freeN(rv3d->localvd);
756                 if (rv3d->clipbb) MEM_freeN(rv3d->clipbb);
757
758                 if (rv3d->render_engine)
759                         RE_engine_free(rv3d->render_engine);
760                 
761                 if (rv3d->depths) {
762                         if (rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
763                         MEM_freeN(rv3d->depths);
764                 }
765                 if (rv3d->sms) {
766                         MEM_freeN(rv3d->sms);
767                 }
768                 if (rv3d->gpuoffscreen) {
769                         GPU_offscreen_free(rv3d->gpuoffscreen);
770                 }
771                 if (rv3d->compositor) {
772                         GPU_fx_compositor_destroy(rv3d->compositor);
773                 }
774                 if (rv3d->viewport) {
775                         GPU_viewport_free(rv3d->viewport);
776                         MEM_freeN(rv3d->viewport);
777                 }
778
779                 MEM_freeN(rv3d);
780                 ar->regiondata = NULL;
781         }
782 }
783
784 /* copy regiondata */
785 static void *view3d_main_region_duplicate(void *poin)
786 {
787         if (poin) {
788                 RegionView3D *rv3d = poin, *new;
789         
790                 new = MEM_dupallocN(rv3d);
791                 if (rv3d->localvd)
792                         new->localvd = MEM_dupallocN(rv3d->localvd);
793                 if (rv3d->clipbb)
794                         new->clipbb = MEM_dupallocN(rv3d->clipbb);
795                 
796                 new->depths = NULL;
797                 new->gpuoffscreen = NULL;
798                 new->render_engine = NULL;
799                 new->sms = NULL;
800                 new->smooth_timer = NULL;
801                 new->compositor = NULL;
802                 new->viewport = NULL;
803                 
804                 return new;
805         }
806         return NULL;
807 }
808
809 static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, const Scene *scene)
810 {
811         wmWindow *win = wmn->wm->winactive;
812         unsigned int lay_used = 0;
813         BaseLegacy *base;
814
815         if (!win) return;
816
817         base = scene->base.first;
818         while (base) {
819                 lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */
820
821                 if (lay_used == (1 << 20) - 1)
822                         break;
823
824                 base = base->next;
825         }
826
827         const bScreen *screen = WM_window_get_active_screen(win);
828         for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
829                 if (sa->spacetype == SPACE_VIEW3D) {
830                         if (BLI_findindex(&sa->regionbase, ar) != -1) {
831                                 View3D *v3d = sa->spacedata.first;
832                                 v3d->lay_used = lay_used;
833                                 break;
834                         }
835                 }
836         }
837 }
838
839 static void view3d_main_region_listener(
840         bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar,
841         wmNotifier *wmn, const Scene *scene)
842 {
843         View3D *v3d = sa->spacedata.first;
844         RegionView3D *rv3d = ar->regiondata;
845         wmManipulatorMap *mmap = ar->manipulator_map;
846
847         /* context changes */
848         switch (wmn->category) {
849                 case NC_WM:
850                         if (ELEM(wmn->data, ND_UNDO)) {
851                                 WM_manipulatormap_tag_refresh(mmap);
852                         }
853                         break;
854                 case NC_ANIMATION:
855                         switch (wmn->data) {
856                                 case ND_KEYFRAME_PROP:
857                                 case ND_NLA_ACTCHANGE:
858                                         ED_region_tag_redraw(ar);
859                                         break;
860                                 case ND_NLA:
861                                 case ND_KEYFRAME:
862                                         if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
863                                                 ED_region_tag_redraw(ar);
864                                         break;
865                                 case ND_ANIMCHAN:
866                                         if (wmn->action == NA_SELECTED)
867                                                 ED_region_tag_redraw(ar);
868                                         break;
869                         }
870                         break;
871                 case NC_SCENE:
872                         switch (wmn->data) {
873                                 case ND_SCENEBROWSE:
874                                 case ND_LAYER_CONTENT:
875                                         if (wmn->reference)
876                                                 view3d_recalc_used_layers(ar, wmn, wmn->reference);
877                                         ED_region_tag_redraw(ar);
878                                         WM_manipulatormap_tag_refresh(mmap);
879                                         break;
880                                 case ND_LAYER:
881                                         if (wmn->reference) {
882                                                 BKE_screen_view3d_sync(v3d, wmn->reference);
883                                         }
884                                         ED_region_tag_redraw(ar);
885                                         break;
886                                 case ND_OB_ACTIVE:
887                                 case ND_OB_SELECT:
888                                         DEG_id_tag_update((ID *)&scene->id, DEG_TAG_COPY_ON_WRITE);
889                                         ATTR_FALLTHROUGH;
890                                 case ND_FRAME:
891                                 case ND_TRANSFORM:
892                                 case ND_OB_VISIBLE:
893                                 case ND_RENDER_OPTIONS:
894                                 case ND_MARKERS:
895                                 case ND_MODE:
896                                         ED_region_tag_redraw(ar);
897                                         WM_manipulatormap_tag_refresh(mmap);
898                                         break;
899                                 case ND_WORLD:
900                                         /* handled by space_view3d_listener() for v3d access */
901                                         break;
902                                 case ND_DRAW_RENDER_VIEWPORT:
903                                 {
904                                         if (v3d->camera && (scene == wmn->reference)) {
905                                                 if (rv3d->persp == RV3D_CAMOB) {
906                                                         ED_region_tag_redraw(ar);
907                                                 }
908                                         }
909                                         break;
910                                 }
911                         }
912                         if (wmn->action == NA_EDITED)
913                                 ED_region_tag_redraw(ar);
914                         break;
915                 case NC_OBJECT:
916                         switch (wmn->data) {
917                                 case ND_BONE_ACTIVE:
918                                 case ND_BONE_SELECT:
919                                 case ND_TRANSFORM:
920                                 case ND_POSE:
921                                 case ND_DRAW:
922                                 case ND_MODIFIER:
923                                 case ND_CONSTRAINT:
924                                 case ND_KEYS:
925                                 case ND_PARTICLE:
926                                 case ND_POINTCACHE:
927                                 case ND_LOD:
928                                         ED_region_tag_redraw(ar);
929                                         WM_manipulatormap_tag_refresh(mmap);
930                                         break;
931                         }
932                         switch (wmn->action) {
933                                 case NA_ADDED:
934                                         ED_region_tag_redraw(ar);
935                                         break;
936                         }
937                         break;
938                 case NC_GEOM:
939                         switch (wmn->data) {
940                                 case ND_SELECT:
941                                 {
942                                         WM_manipulatormap_tag_refresh(mmap);
943
944                                         if (scene->obedit) {
945                                                 Object *ob = scene->obedit;
946                                                 switch (ob->type) {
947                                                         case OB_MESH:
948                                                                 BKE_mesh_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT);
949                                                                 break;
950                                                         // case OB_FONT:  /* handled by text_update_edited */
951                                                         case OB_CURVE:
952                                                         case OB_SURF:
953                                                                 BKE_curve_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT);
954                                                                 break;
955                                                         case OB_LATTICE:
956                                                                 BKE_lattice_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT);
957                                                                 break;
958                                                 }
959                                         }
960                                         ATTR_FALLTHROUGH;
961                                 }
962                                 case ND_DATA:
963                                 case ND_VERTEX_GROUP:
964                                         ED_region_tag_redraw(ar);
965                                         break;
966                         }
967                         switch (wmn->action) {
968                                 case NA_EDITED:
969                                         ED_region_tag_redraw(ar);
970                                         break;
971                         }
972                         break;
973                 case NC_CAMERA:
974                         switch (wmn->data) {
975                                 case ND_DRAW_RENDER_VIEWPORT:
976                                 {
977                                         if (v3d->camera && (v3d->camera->data == wmn->reference)) {
978                                                 if (rv3d->persp == RV3D_CAMOB) {
979                                                         ED_region_tag_redraw(ar);
980                                                 }
981                                         }
982                                         break;
983                                 }
984                         }
985                         break;
986                 case NC_GROUP:
987                         /* all group ops for now */
988                         ED_region_tag_redraw(ar);
989                         break;
990                 case NC_BRUSH:
991                         switch (wmn->action) {
992                                 case NA_EDITED:
993                                         ED_region_tag_redraw_overlay(ar);
994                                         break;
995                                 case NA_SELECTED:
996                                         /* used on brush changes - needed because 3d cursor
997                                          * has to be drawn if clone brush is selected */
998                                         ED_region_tag_redraw(ar);
999                                         break;
1000                         }
1001                         break;
1002                 case NC_MATERIAL:
1003                         switch (wmn->data) {
1004                                 case ND_SHADING:
1005                                 case ND_NODES:
1006                                         /* TODO(sergey) This is a bit too much updates, but needed to
1007                                          * have proper material drivers update in the viewport.
1008                                          *
1009                                          * How to solve?
1010                                          */
1011                                         ED_region_tag_redraw(ar);
1012                                         break;
1013                                 case ND_SHADING_DRAW:
1014                                 case ND_SHADING_LINKS:
1015                                         ED_region_tag_redraw(ar);
1016                                         break;
1017                         }
1018                         break;
1019                 case NC_WORLD:
1020                         switch (wmn->data) {
1021                                 case ND_WORLD_DRAW:
1022                                         /* handled by space_view3d_listener() for v3d access */
1023                                         break;
1024                                 case ND_WORLD:
1025                                         /* Needed for updating world materials */
1026                                         ED_region_tag_redraw(ar);
1027                                         break;
1028                         }
1029                         break;
1030                 case NC_LAMP:
1031                         switch (wmn->data) {
1032                                 case ND_LIGHTING:
1033                                         /* TODO(sergey): This is a bit too much, but needed to
1034                                          * handle updates from new depsgraph.
1035                                          */
1036                                         ED_region_tag_redraw(ar);
1037                                         break;
1038                                 case ND_LIGHTING_DRAW:
1039                                         ED_region_tag_redraw(ar);
1040                                         WM_manipulatormap_tag_refresh(mmap);
1041                                         break;
1042                         }
1043                         break;
1044                 case NC_IMAGE:
1045                         /* this could be more fine grained checks if we had
1046                          * more context than just the region */
1047                         ED_region_tag_redraw(ar);
1048                         break;
1049                 case NC_TEXTURE:
1050                         /* same as above */
1051                         ED_region_tag_redraw(ar);
1052                         break;
1053                 case NC_MOVIECLIP:
1054                         if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED)
1055                                 ED_region_tag_redraw(ar);
1056                         break;
1057                 case NC_SPACE:
1058                         if (wmn->data == ND_SPACE_VIEW3D) {
1059                                 if (wmn->subtype == NS_VIEW3D_GPU) {
1060                                         rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
1061                                 }
1062                                 ED_region_tag_redraw(ar);
1063                                 WM_manipulatormap_tag_refresh(mmap);
1064                         }
1065                         break;
1066                 case NC_ID:
1067                         if (wmn->action == NA_RENAME)
1068                                 ED_region_tag_redraw(ar);
1069                         break;
1070                 case NC_SCREEN:
1071                         switch (wmn->data) {
1072                                 case ND_ANIMPLAY:
1073                                 case ND_SKETCH:
1074                                         ED_region_tag_redraw(ar);
1075                                         break;
1076                                 case ND_LAYOUTBROWSE:
1077                                 case ND_LAYOUTDELETE:
1078                                 case ND_LAYOUTSET:
1079                                         WM_manipulatormap_tag_refresh(mmap);
1080                                         ED_region_tag_redraw(ar);
1081                                         break;
1082                                 case ND_LAYER:
1083                                         ED_region_tag_redraw(ar);
1084                                         break;
1085                         }
1086
1087                         break;
1088                 case NC_GPENCIL:
1089                         if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
1090                                 ED_region_tag_redraw(ar);
1091                         }
1092                         break;
1093         }
1094 }
1095
1096 /* concept is to retrieve cursor type context-less */
1097 static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
1098 {
1099         const Scene *scene = WM_window_get_active_scene(win);
1100
1101         if (scene->obedit) {
1102                 WM_cursor_set(win, CURSOR_EDIT);
1103         }
1104         else {
1105                 WM_cursor_set(win, CURSOR_STD);
1106         }
1107 }
1108
1109 /* add handlers, stuff you only do once or on area/region changes */
1110 static void view3d_header_region_init(wmWindowManager *wm, ARegion *ar)
1111 {
1112         wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
1113         
1114         WM_event_add_keymap_handler(&ar->handlers, keymap);
1115
1116         ED_region_header_init(ar);
1117 }
1118
1119 static void view3d_header_region_draw(const bContext *C, ARegion *ar)
1120 {
1121         ED_region_header(C, ar);
1122 }
1123
1124 static void view3d_header_region_listener(
1125         bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
1126         wmNotifier *wmn, const Scene *UNUSED(scene))
1127 {
1128         /* context changes */
1129         switch (wmn->category) {
1130                 case NC_SCENE:
1131                         switch (wmn->data) {
1132                                 case ND_FRAME:
1133                                 case ND_OB_ACTIVE:
1134                                 case ND_OB_SELECT:
1135                                 case ND_OB_VISIBLE:
1136                                 case ND_MODE:
1137                                 case ND_LAYER:
1138                                 case ND_TOOLSETTINGS:
1139                                 case ND_LAYER_CONTENT:
1140                                 case ND_RENDER_OPTIONS:
1141                                         ED_region_tag_redraw(ar);
1142                                         break;
1143                         }
1144                         break;
1145                 case NC_SPACE:
1146                         if (wmn->data == ND_SPACE_VIEW3D)
1147                                 ED_region_tag_redraw(ar);
1148                         break;
1149                 case NC_GPENCIL:
1150                         if (wmn->data & ND_GPENCIL_EDITMODE)
1151                                 ED_region_tag_redraw(ar);
1152                         break;
1153         }
1154 }
1155
1156 /* add handlers, stuff you only do once or on area/region changes */
1157 static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
1158 {
1159         wmKeyMap *keymap;
1160
1161         ED_region_panels_init(wm, ar);
1162         
1163         keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
1164         WM_event_add_keymap_handler(&ar->handlers, keymap);
1165 }
1166
1167 static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
1168 {
1169         ED_region_panels(C, ar, NULL, -1, true);
1170 }
1171
1172 static void view3d_buttons_region_listener(
1173         bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
1174         wmNotifier *wmn, const Scene *UNUSED(scene))
1175 {
1176         /* context changes */
1177         switch (wmn->category) {
1178                 case NC_ANIMATION:
1179                         switch (wmn->data) {
1180                                 case ND_KEYFRAME_PROP:
1181                                 case ND_NLA_ACTCHANGE:
1182                                         ED_region_tag_redraw(ar);
1183                                         break;
1184                                 case ND_NLA:
1185                                 case ND_KEYFRAME:
1186                                         if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
1187                                                 ED_region_tag_redraw(ar);
1188                                         break;
1189                         }
1190                         break;
1191                 case NC_SCENE:
1192                         switch (wmn->data) {
1193                                 case ND_FRAME:
1194                                 case ND_OB_ACTIVE:
1195                                 case ND_OB_SELECT:
1196                                 case ND_OB_VISIBLE:
1197                                 case ND_MODE:
1198                                 case ND_LAYER:
1199                                 case ND_LAYER_CONTENT:
1200                                 case ND_TOOLSETTINGS:
1201                                         ED_region_tag_redraw(ar);
1202                                         break;
1203                         }
1204                         switch (wmn->action) {
1205                                 case NA_EDITED:
1206                                         ED_region_tag_redraw(ar);
1207                                         break;
1208                         }
1209                         break;
1210                 case NC_OBJECT:
1211                         switch (wmn->data) {
1212                                 case ND_BONE_ACTIVE:
1213                                 case ND_BONE_SELECT:
1214                                 case ND_TRANSFORM:
1215                                 case ND_POSE:
1216                                 case ND_DRAW:
1217                                 case ND_KEYS:
1218                                 case ND_MODIFIER:
1219                                         ED_region_tag_redraw(ar);
1220                                         break;
1221                         }
1222                         break;
1223                 case NC_GEOM:
1224                         switch (wmn->data) {
1225                                 case ND_DATA:
1226                                 case ND_VERTEX_GROUP:
1227                                 case ND_SELECT:
1228                                         ED_region_tag_redraw(ar);
1229                                         break;
1230                         }
1231                         if (wmn->action == NA_EDITED)
1232                                 ED_region_tag_redraw(ar);
1233                         break;
1234                 case NC_TEXTURE:
1235                 case NC_MATERIAL:
1236                         /* for brush textures */
1237                         ED_region_tag_redraw(ar);
1238                         break;
1239                 case NC_BRUSH:
1240                         /* NA_SELECTED is used on brush changes */
1241                         if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
1242                                 ED_region_tag_redraw(ar);
1243                         break;
1244                 case NC_SPACE:
1245                         if (wmn->data == ND_SPACE_VIEW3D)
1246                                 ED_region_tag_redraw(ar);
1247                         break;
1248                 case NC_ID:
1249                         if (wmn->action == NA_RENAME)
1250                                 ED_region_tag_redraw(ar);
1251                         break;
1252                 case NC_GPENCIL:
1253                         if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED))
1254                                 ED_region_tag_redraw(ar);
1255                         break;
1256                 case NC_IMAGE:
1257                         /* Update for the image layers in texture paint. */
1258                         if (wmn->action == NA_EDITED)
1259                                 ED_region_tag_redraw(ar);
1260                         break;
1261         }
1262 }
1263
1264 /* add handlers, stuff you only do once or on area/region changes */
1265 static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
1266 {
1267         wmKeyMap *keymap;
1268         
1269         ED_region_panels_init(wm, ar);
1270
1271         keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
1272         WM_event_add_keymap_handler(&ar->handlers, keymap);
1273 }
1274
1275 static void view3d_tools_region_draw(const bContext *C, ARegion *ar)
1276 {
1277         ED_region_panels(C, ar, CTX_data_mode_string(C), -1, true);
1278 }
1279
1280 static void view3d_props_region_listener(
1281         bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
1282         wmNotifier *wmn, const Scene *UNUSED(scene))
1283 {
1284         /* context changes */
1285         switch (wmn->category) {
1286                 case NC_WM:
1287                         if (wmn->data == ND_HISTORY)
1288                                 ED_region_tag_redraw(ar);
1289                         break;
1290                 case NC_SCENE:
1291                         if (wmn->data == ND_MODE)
1292                                 ED_region_tag_redraw(ar);
1293                         break;
1294                 case NC_SPACE:
1295                         if (wmn->data == ND_SPACE_VIEW3D)
1296                                 ED_region_tag_redraw(ar);
1297                         break;
1298         }
1299 }
1300
1301 /* area (not region) level listener */
1302 static void space_view3d_listener(
1303         bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn, const Scene *UNUSED(scene))
1304 {
1305         View3D *v3d = sa->spacedata.first;
1306
1307         /* context changes */
1308         switch (wmn->category) {
1309                 case NC_SCENE:
1310                         switch (wmn->data) {
1311                                 case ND_WORLD:
1312                                         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1313                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
1314                                         break;
1315                         }
1316                         break;
1317                 case NC_WORLD:
1318                         switch (wmn->data) {
1319                                 case ND_WORLD_DRAW:
1320                                 case ND_WORLD:
1321                                         if (v3d->flag3 & V3D_SHOW_WORLD)
1322                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
1323                                         break;
1324                         }
1325                         break;
1326                 case NC_MATERIAL:
1327                         switch (wmn->data) {
1328                                 case ND_NODES:
1329                                         if (v3d->drawtype == OB_TEXTURE)
1330                                                 ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
1331                                         break;
1332                         }
1333                         break;
1334         }
1335 }
1336
1337 const char *view3d_context_dir[] = {
1338         "active_base", "active_object", NULL
1339 };
1340
1341 static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
1342 {
1343         /* fallback to the scene layer, allows duplicate and other object operators to run outside the 3d view */
1344
1345         if (CTX_data_dir(member)) {
1346                 CTX_data_dir_set(result, view3d_context_dir);
1347         }
1348         else if (CTX_data_equals(member, "active_base")) {
1349                 Scene *scene = CTX_data_scene(C);
1350                 SceneLayer *sl = CTX_data_scene_layer(C);
1351                 if (sl->basact) {
1352                         Object *ob = sl->basact->object;
1353                         /* if hidden but in edit mode, we still display, can happen with animation */
1354                         if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) {
1355                                 CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact);
1356                         }
1357                 }
1358                 
1359                 return 1;
1360         }
1361         else if (CTX_data_equals(member, "active_object")) {
1362                 SceneLayer *sl = CTX_data_scene_layer(C);
1363                 if (sl->basact) {
1364                         Object *ob = sl->basact->object;
1365                         /* if hidden but in edit mode, we still display, can happen with animation */
1366                         if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
1367                                 CTX_data_id_pointer_set(result, &ob->id);
1368                         }
1369                 }
1370                 
1371                 return 1;
1372         }
1373         else {
1374                 return 0; /* not found */
1375         }
1376
1377         return -1; /* found but not available */
1378 }
1379
1380 static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_id)
1381 {
1382         View3D *v3d;
1383         ARegion *ar;
1384         bool is_local = false;
1385
1386         if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) {
1387                 return;
1388         }
1389
1390         for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) {
1391                 if ((ID *)v3d->camera == old_id) {
1392                         v3d->camera = (Object *)new_id;
1393                         if (!new_id) {
1394                                 /* 3D view might be inactive, in that case needs to use slink->regionbase */
1395                                 ListBase *regionbase = (slink == sa->spacedata.first) ? &sa->regionbase : &slink->regionbase;
1396                                 for (ar = regionbase->first; ar; ar = ar->next) {
1397                                         if (ar->regiontype == RGN_TYPE_WINDOW) {
1398                                                 RegionView3D *rv3d = is_local ? ((RegionView3D *)ar->regiondata)->localvd : ar->regiondata;
1399                                                 if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
1400                                                         rv3d->persp = RV3D_PERSP;
1401                                                 }
1402                                         }
1403                                 }
1404                         }
1405                 }
1406                 if ((ID *)v3d->ob_centre == old_id) {
1407                         v3d->ob_centre = (Object *)new_id;
1408                         if (new_id == NULL) {  /* Otherwise, bonename may remain valid... We could be smart and check this, too? */
1409                                 v3d->ob_centre_bone[0] = '\0';
1410                         }
1411                 }
1412
1413                 if ((ID *)v3d->defmaterial == old_id) {
1414                         v3d->defmaterial = (Material *)new_id;
1415                 }
1416 #if 0  /* XXX Deprecated? */
1417                 if ((ID *)v3d->gpd == old_id) {
1418                         v3d->gpd = (bGPData *)new_id;
1419                 }
1420 #endif
1421
1422                 if (ELEM(GS(old_id->name), ID_IM, ID_MC)) {
1423                         for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
1424                                 if ((ID *)bgpic->ima == old_id) {
1425                                         bgpic->ima = (Image *)new_id;
1426                                         id_us_min(old_id);
1427                                         id_us_plus(new_id);
1428                                 }
1429                                 if ((ID *)bgpic->clip == old_id) {
1430                                         bgpic->clip = (MovieClip *)new_id;
1431                                         id_us_min(old_id);
1432                                         id_us_plus(new_id);
1433                                 }
1434                         }
1435                 }
1436
1437                 if (is_local) {
1438                         break;
1439                 }
1440         }
1441 }
1442
1443 /* only called once, from space/spacetypes.c */
1444 void ED_spacetype_view3d(void)
1445 {
1446         SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype view3d");
1447         ARegionType *art;
1448         
1449         st->spaceid = SPACE_VIEW3D;
1450         strncpy(st->name, "View3D", BKE_ST_MAXNAME);
1451         
1452         st->new = view3d_new;
1453         st->free = view3d_free;
1454         st->init = view3d_init;
1455         st->listener = space_view3d_listener;
1456         st->duplicate = view3d_duplicate;
1457         st->operatortypes = view3d_operatortypes;
1458         st->keymap = view3d_keymap;
1459         st->dropboxes = view3d_dropboxes;
1460         st->manipulators = view3d_widgets;
1461         st->context = view3d_context;
1462         st->id_remap = view3d_id_remap;
1463
1464         /* regions: main window */
1465         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
1466         art->regionid = RGN_TYPE_WINDOW;
1467         art->keymapflag = ED_KEYMAP_GPENCIL;
1468         art->draw = view3d_main_region_draw;
1469         art->init = view3d_main_region_init;
1470         art->exit = view3d_main_region_exit;
1471         art->free = view3d_main_region_free;
1472         art->duplicate = view3d_main_region_duplicate;
1473         art->listener = view3d_main_region_listener;
1474         art->cursor = view3d_main_region_cursor;
1475         art->lock = 1;   /* can become flag, see BKE_spacedata_draw_locks */
1476         BLI_addhead(&st->regiontypes, art);
1477         
1478         /* regions: listview/buttons */
1479         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
1480         art->regionid = RGN_TYPE_UI;
1481         art->prefsizex = 180; /* XXX */
1482         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1483         art->listener = view3d_buttons_region_listener;
1484         art->init = view3d_buttons_region_init;
1485         art->draw = view3d_buttons_region_draw;
1486         BLI_addhead(&st->regiontypes, art);
1487
1488         view3d_buttons_register(art);
1489
1490         /* regions: tool(bar) */
1491         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
1492         art->regionid = RGN_TYPE_TOOLS;
1493         art->prefsizex = 160; /* XXX */
1494         art->prefsizey = 50; /* XXX */
1495         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1496         art->listener = view3d_buttons_region_listener;
1497         art->init = view3d_tools_region_init;
1498         art->draw = view3d_tools_region_draw;
1499         BLI_addhead(&st->regiontypes, art);
1500         
1501 #if 0
1502         /* unfinished still */
1503         view3d_toolshelf_register(art);
1504 #endif
1505
1506         /* regions: tool properties */
1507         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tool properties region");
1508         art->regionid = RGN_TYPE_TOOL_PROPS;
1509         art->prefsizex = 0;
1510         art->prefsizey = 120;
1511         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1512         art->listener = view3d_props_region_listener;
1513         art->init = view3d_tools_region_init;
1514         art->draw = view3d_tools_region_draw;
1515         BLI_addhead(&st->regiontypes, art);
1516         
1517         view3d_tool_props_register(art);
1518         
1519         
1520         /* regions: header */
1521         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
1522         art->regionid = RGN_TYPE_HEADER;
1523         art->prefsizey = HEADERY;
1524         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
1525         art->listener = view3d_header_region_listener;
1526         art->init = view3d_header_region_init;
1527         art->draw = view3d_header_region_draw;
1528         BLI_addhead(&st->regiontypes, art);
1529         
1530         BKE_spacetype_register(st);
1531 }
1532