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