Workbench: Option to use Object color
[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_framebuffer.h"
63 #include "GPU_material.h"
64 #include "GPU_viewport.h"
65 #include "GPU_matrix.h"
66
67 #include "DRW_engine.h"
68
69 #include "WM_api.h"
70 #include "WM_types.h"
71 #include "WM_message.h"
72
73 #include "RE_engine.h"
74 #include "RE_pipeline.h"
75
76 #include "RNA_access.h"
77
78 #include "UI_resources.h"
79
80 #ifdef WITH_PYTHON
81 #  include "BPY_extern.h"
82 #endif
83
84 #include "DEG_depsgraph.h"
85
86 #include "view3d_intern.h"  /* own include */
87
88 /* ******************** manage regions ********************* */
89
90 ARegion *view3d_has_buttons_region(ScrArea *sa)
91 {
92         ARegion *ar, *arnew;
93
94         ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
95         if (ar) return ar;
96         
97         /* add subdiv level; after header */
98         ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
99
100         /* is error! */
101         if (ar == NULL) return NULL;
102         
103         arnew = MEM_callocN(sizeof(ARegion), "buttons for view3d");
104         
105         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
106         arnew->regiontype = RGN_TYPE_UI;
107         arnew->alignment = RGN_ALIGN_RIGHT;
108         
109         arnew->flag = RGN_FLAG_HIDDEN;
110         
111         return arnew;
112 }
113
114 ARegion *view3d_has_tools_region(ScrArea *sa)
115 {
116         ARegion *ar, *artool = NULL, *arprops = NULL, *arhead;
117         
118         for (ar = sa->regionbase.first; ar; ar = ar->next) {
119                 if (ar->regiontype == RGN_TYPE_TOOLS)
120                         artool = ar;
121                 if (ar->regiontype == RGN_TYPE_TOOL_PROPS)
122                         arprops = ar;
123         }
124         
125         /* tool region hide/unhide also hides props */
126         if (arprops && artool) return artool;
127         
128         if (artool == NULL) {
129                 /* add subdiv level; after header */
130                 for (arhead = sa->regionbase.first; arhead; arhead = arhead->next)
131                         if (arhead->regiontype == RGN_TYPE_HEADER)
132                                 break;
133                 
134                 /* is error! */
135                 if (arhead == NULL) return NULL;
136                 
137                 artool = MEM_callocN(sizeof(ARegion), "tools for view3d");
138                 
139                 BLI_insertlinkafter(&sa->regionbase, arhead, artool);
140                 artool->regiontype = RGN_TYPE_TOOLS;
141                 artool->alignment = RGN_ALIGN_LEFT;
142                 artool->flag = RGN_FLAG_HIDDEN;
143         }
144
145         if (arprops == NULL) {
146                 /* add extra subdivided region for tool properties */
147                 arprops = MEM_callocN(sizeof(ARegion), "tool props for view3d");
148                 
149                 BLI_insertlinkafter(&sa->regionbase, artool, arprops);
150                 arprops->regiontype = RGN_TYPE_TOOL_PROPS;
151                 arprops->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
152         }
153         
154         return artool;
155 }
156
157 /* ****************************************************** */
158
159 /* function to always find a regionview3d context inside 3D window */
160 RegionView3D *ED_view3d_context_rv3d(bContext *C)
161 {
162         RegionView3D *rv3d = CTX_wm_region_view3d(C);
163         
164         if (rv3d == NULL) {
165                 ScrArea *sa = CTX_wm_area(C);
166                 if (sa && sa->spacetype == SPACE_VIEW3D) {
167                         ARegion *ar = BKE_area_find_region_active_win(sa);
168                         if (ar) {
169                                 rv3d = ar->regiondata;
170                         }
171                 }
172         }
173         return rv3d;
174 }
175
176 /* ideally would return an rv3d but in some cases the region is needed too
177  * so return that, the caller can then access the ar->regiondata */
178 bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
179 {
180         ScrArea *sa = CTX_wm_area(C);
181
182         *r_v3d = NULL;
183         *r_ar = NULL;
184
185         if (sa && sa->spacetype == SPACE_VIEW3D) {
186                 ARegion *ar = CTX_wm_region(C);
187                 View3D *v3d = (View3D *)sa->spacedata.first;
188
189                 if (ar) {
190                         RegionView3D *rv3d;
191                         if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) && (rv3d->viewlock & RV3D_LOCKED) == 0) {
192                                 *r_v3d = v3d;
193                                 *r_ar = ar;
194                                 return true;
195                         }
196                         else {
197                                 ARegion *ar_unlock_user = NULL;
198                                 ARegion *ar_unlock = NULL;
199                                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
200                                         /* find the first unlocked rv3d */
201                                         if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
202                                                 rv3d = ar->regiondata;
203                                                 if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
204                                                         ar_unlock = ar;
205                                                         if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) {
206                                                                 ar_unlock_user = ar;
207                                                                 break;
208                                                         }
209                                                 }
210                                         }
211                                 }
212
213                                 /* camera/perspective view get priority when the active region is locked */
214                                 if (ar_unlock_user) {
215                                         *r_v3d = v3d;
216                                         *r_ar = ar_unlock_user;
217                                         return true;
218                                 }
219
220                                 if (ar_unlock) {
221                                         *r_v3d = v3d;
222                                         *r_ar = ar_unlock;
223                                         return true;
224                                 }
225                         }
226                 }
227         }
228
229         return false;
230 }
231
232 /* Most of the time this isn't needed since you could assume the view matrix was
233  * set while drawing, however when functions like mesh_foreachScreenVert are
234  * called by selection tools, we can't be sure this object was the last.
235  *
236  * for example, transparent objects are drawn after editmode and will cause
237  * the rv3d mat's to change and break selection.
238  *
239  * 'ED_view3d_init_mats_rv3d' should be called before
240  * view3d_project_short_clip and view3d_project_short_noclip in cases where
241  * these functions are not used during draw_object
242  */
243 void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
244 {
245         /* local viewmat and persmat, to calculate projections */
246         mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
247         mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
248
249         /* initializes object space clipping, speeds up clip tests */
250         ED_view3d_clipping_local(rv3d, ob->obmat);
251 }
252
253 void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
254 {
255         ED_view3d_init_mats_rv3d(ob, rv3d);
256
257         /* we have to multiply instead of loading viewmatob to make
258          * it work with duplis using displists, otherwise it will
259          * override the dupli-matrix */
260         gpuMultMatrix(ob->obmat);
261 }
262
263 #ifdef DEBUG
264 /* ensure we correctly initialize */
265 void ED_view3d_clear_mats_rv3d(struct RegionView3D *rv3d)
266 {
267         zero_m4(rv3d->viewmatob);
268         zero_m4(rv3d->persmatob);
269 }
270
271 void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
272 {
273         BLI_ASSERT_ZERO_M4(rv3d->viewmatob);
274         BLI_ASSERT_ZERO_M4(rv3d->persmatob);
275 }
276 #endif
277
278 void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
279 {
280         RegionView3D *rv3d = ar->regiondata;
281
282         if (rv3d->render_engine) {
283 #ifdef WITH_PYTHON
284                 BPy_BEGIN_ALLOW_THREADS;
285 #endif
286
287                 WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
288
289 #ifdef WITH_PYTHON
290                 BPy_END_ALLOW_THREADS;
291 #endif
292
293                 if (rv3d->render_engine->re)
294                         RE_Database_Free(rv3d->render_engine->re);
295                 RE_engine_free(rv3d->render_engine);
296                 rv3d->render_engine = NULL;
297         }
298 }
299
300 void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
301 {
302         wmWindowManager *wm = bmain->wm.first;
303
304         if (v3d->drawtype != OB_RENDER) {
305                 ARegion *ar;
306
307                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
308                         if (ar->regiondata)
309                                 ED_view3d_stop_render_preview(wm, ar);
310                 }
311         }
312 }
313
314 /* ******************** default callbacks for view3d space ***************** */
315
316 static SpaceLink *view3d_new(const bContext *C)
317 {
318         Scene *scene = CTX_data_scene(C);
319         ARegion *ar;
320         View3D *v3d;
321         RegionView3D *rv3d;
322         
323         v3d = MEM_callocN(sizeof(View3D), "initview3d");
324         v3d->spacetype = SPACE_VIEW3D;
325         v3d->blockscale = 0.7f;
326         v3d->lay = v3d->layact = 1;
327         if (scene) {
328                 v3d->lay = v3d->layact = scene->lay;
329                 v3d->camera = scene->camera;
330         }
331         v3d->scenelock = true;
332         v3d->grid = 1.0f;
333         v3d->gridlines = 16;
334         v3d->gridsubdiv = 10;
335         v3d->drawtype = OB_SOLID;
336         v3d->drawtype_solid = V3D_LIGHTING_STUDIO;
337         v3d->drawtype_texture = V3D_LIGHTING_STUDIO;
338
339         v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
340         
341         v3d->flag = V3D_SELECT_OUTLINE;
342         v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_GPENCIL;
343         
344         v3d->lens = 35.0f;
345         v3d->near = 0.01f;
346         v3d->far = 1000.0f;
347
348         v3d->twflag |= U.manipulator_flag & V3D_MANIPULATOR_DRAW;
349         v3d->twtype = V3D_MANIP_TRANSLATE;
350         v3d->around = V3D_AROUND_CENTER_MEAN;
351         scene->orientation_index_custom = -1;
352         
353         v3d->bundle_size = 0.2f;
354         v3d->bundle_drawtype = OB_PLAINAXES;
355
356         /* stereo */
357         v3d->stereo3d_camera = STEREO_3D_ID;
358         v3d->stereo3d_flag |= V3D_S3D_DISPPLANE;
359         v3d->stereo3d_convergence_alpha = 0.15f;
360         v3d->stereo3d_volume_alpha = 0.05f;
361
362         /* header */
363         ar = MEM_callocN(sizeof(ARegion), "header for view3d");
364         
365         BLI_addtail(&v3d->regionbase, ar);
366         ar->regiontype = RGN_TYPE_HEADER;
367         ar->alignment = RGN_ALIGN_BOTTOM;
368         
369         /* tool shelf */
370         ar = MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
371         
372         BLI_addtail(&v3d->regionbase, ar);
373         ar->regiontype = RGN_TYPE_TOOLS;
374         ar->alignment = RGN_ALIGN_LEFT;
375         ar->flag = RGN_FLAG_HIDDEN;
376         
377         /* tool properties */
378         ar = MEM_callocN(sizeof(ARegion), "tool properties for view3d");
379         
380         BLI_addtail(&v3d->regionbase, ar);
381         ar->regiontype = RGN_TYPE_TOOL_PROPS;
382         ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
383         ar->flag = RGN_FLAG_HIDDEN;
384         
385         /* buttons/list view */
386         ar = MEM_callocN(sizeof(ARegion), "buttons for view3d");
387         
388         BLI_addtail(&v3d->regionbase, ar);
389         ar->regiontype = RGN_TYPE_UI;
390         ar->alignment = RGN_ALIGN_RIGHT;
391         ar->flag = RGN_FLAG_HIDDEN;
392         
393         /* main region */
394         ar = MEM_callocN(sizeof(ARegion), "main region for view3d");
395         
396         BLI_addtail(&v3d->regionbase, ar);
397         ar->regiontype = RGN_TYPE_WINDOW;
398         
399         ar->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d");
400         rv3d = ar->regiondata;
401         rv3d->viewquat[0] = 1.0f;
402         rv3d->persp = RV3D_PERSP;
403         rv3d->view = RV3D_VIEW_USER;
404         rv3d->dist = 10.0;
405         
406         return (SpaceLink *)v3d;
407 }
408
409 /* not spacelink itself */
410 static void view3d_free(SpaceLink *sl)
411 {
412         View3D *vd = (View3D *) sl;
413
414         if (vd->localvd) MEM_freeN(vd->localvd);
415         
416         if (vd->properties_storage) MEM_freeN(vd->properties_storage);
417         
418         /* matcap material, its preview rect gets freed via icons */
419         if (vd->defmaterial) {
420                 if (vd->defmaterial->gpumaterial.first)
421                         GPU_material_free(&vd->defmaterial->gpumaterial);
422                 BKE_previewimg_free(&vd->defmaterial->preview);
423                 MEM_freeN(vd->defmaterial);
424         }
425
426         if (vd->fx_settings.ssao)
427                 MEM_freeN(vd->fx_settings.ssao);
428         if (vd->fx_settings.dof)
429                 MEM_freeN(vd->fx_settings.dof);
430 }
431
432
433 /* spacetype; init callback */
434 static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
435 {
436
437 }
438
439 static SpaceLink *view3d_duplicate(SpaceLink *sl)
440 {
441         View3D *v3do = (View3D *)sl;
442         View3D *v3dn = MEM_dupallocN(sl);
443         
444         /* clear or remove stuff from old */
445
446         if (v3dn->localvd) {
447                 v3dn->localvd = NULL;
448                 v3dn->properties_storage = NULL;
449                 v3dn->lay = v3do->localvd->lay & 0xFFFFFF;
450         }
451
452         if (v3dn->drawtype == OB_RENDER)
453                 v3dn->drawtype = OB_SOLID;
454         
455         /* copy or clear inside new stuff */
456
457         v3dn->defmaterial = NULL;
458
459         v3dn->properties_storage = NULL;
460         if (v3dn->fx_settings.dof)
461                 v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
462         if (v3dn->fx_settings.ssao)
463                 v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao);
464
465         return (SpaceLink *)v3dn;
466 }
467
468 /* add handlers, stuff you only do once or on area/region changes */
469 static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
470 {
471         ListBase *lb;
472         wmKeyMap *keymap;
473
474         if (ar->manipulator_map == NULL) {
475                 ar->manipulator_map = WM_manipulatormap_new_from_type(
476                         &(const struct wmManipulatorMapType_Params) {SPACE_VIEW3D, RGN_TYPE_WINDOW});
477         }
478
479         WM_manipulatormap_add_handlers(ar, ar->manipulator_map);
480
481         /* object ops. */
482         
483         /* important to be before Pose keymap since they can both be enabled at once */
484         keymap = WM_keymap_find(wm->defaultconf, "Face Mask", 0, 0);
485         WM_event_add_keymap_handler(&ar->handlers, keymap);
486         
487         
488         keymap = WM_keymap_find(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0);
489         WM_event_add_keymap_handler(&ar->handlers, keymap);
490
491         /* pose is not modal, operator poll checks for this */
492         keymap = WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
493         WM_event_add_keymap_handler(&ar->handlers, keymap);
494         
495         keymap = WM_keymap_find(wm->defaultconf, "Object Mode", 0, 0);
496         WM_event_add_keymap_handler(&ar->handlers, keymap);
497
498         keymap = WM_keymap_find(wm->defaultconf, "Paint Curve", 0, 0);
499         WM_event_add_keymap_handler(&ar->handlers, keymap);
500
501         keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
502         WM_event_add_keymap_handler(&ar->handlers, keymap);
503
504         keymap = WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
505         WM_event_add_keymap_handler(&ar->handlers, keymap);
506
507         keymap = WM_keymap_find(wm->defaultconf, "Vertex Paint", 0, 0);
508         WM_event_add_keymap_handler(&ar->handlers, keymap);
509
510         keymap = WM_keymap_find(wm->defaultconf, "Weight Paint", 0, 0);
511         WM_event_add_keymap_handler(&ar->handlers, keymap);
512
513         keymap = WM_keymap_find(wm->defaultconf, "Sculpt", 0, 0);
514         WM_event_add_keymap_handler(&ar->handlers, keymap);
515         
516         keymap = WM_keymap_find(wm->defaultconf, "Mesh", 0, 0);
517         WM_event_add_keymap_handler(&ar->handlers, keymap);
518         
519         keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
520         WM_event_add_keymap_handler(&ar->handlers, keymap);
521         
522         keymap = WM_keymap_find(wm->defaultconf, "Armature", 0, 0);
523         WM_event_add_keymap_handler(&ar->handlers, keymap);
524
525         keymap = WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
526         WM_event_add_keymap_handler(&ar->handlers, keymap);
527
528         keymap = WM_keymap_find(wm->defaultconf, "Metaball", 0, 0);
529         WM_event_add_keymap_handler(&ar->handlers, keymap);
530         
531         keymap = WM_keymap_find(wm->defaultconf, "Lattice", 0, 0);
532         WM_event_add_keymap_handler(&ar->handlers, keymap);
533
534         keymap = WM_keymap_find(wm->defaultconf, "Particle", 0, 0);
535         WM_event_add_keymap_handler(&ar->handlers, keymap);
536
537         /* editfont keymap swallows all... */
538         keymap = WM_keymap_find(wm->defaultconf, "Font", 0, 0);
539         WM_event_add_keymap_handler(&ar->handlers, keymap);
540
541         keymap = WM_keymap_find(wm->defaultconf, "Object Non-modal", 0, 0);
542         WM_event_add_keymap_handler(&ar->handlers, keymap);
543
544         keymap = WM_keymap_find(wm->defaultconf, "Frames", 0, 0);
545         WM_event_add_keymap_handler(&ar->handlers, keymap);
546
547         /* own keymap, last so modes can override it */
548         keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
549         WM_event_add_keymap_handler(&ar->handlers, keymap);
550
551         keymap = WM_keymap_find(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
552         WM_event_add_keymap_handler(&ar->handlers, keymap);
553         
554         /* add drop boxes */
555         lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
556         
557         WM_event_add_dropbox_handler(&ar->handlers, lb);
558         
559 }
560
561 static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
562 {
563         RegionView3D *rv3d = ar->regiondata;
564
565         ED_view3d_stop_render_preview(wm, ar);
566
567         if (rv3d->gpuoffscreen) {
568                 GPU_offscreen_free(rv3d->gpuoffscreen);
569                 rv3d->gpuoffscreen = NULL;
570         }
571         
572         if (rv3d->viewport) {
573                 DRW_opengl_context_enable();
574                 GPU_viewport_free(rv3d->viewport);
575                 DRW_opengl_context_disable();
576                 rv3d->viewport = NULL;
577         }
578 }
579
580 static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
581 {
582         if (drag->type == WM_DRAG_ID) {
583                 ID *id = drag->poin;
584                 if (GS(id->name) == ID_OB)
585                         return 1;
586         }
587         return 0;
588 }
589
590 static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
591 {
592         if (drag->type == WM_DRAG_ID) {
593                 ID *id = drag->poin;
594                 if (GS(id->name) == ID_GR)
595                         return 1;
596         }
597         return 0;
598 }
599
600 static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
601 {
602         if (drag->type == WM_DRAG_ID) {
603                 ID *id = drag->poin;
604                 if (GS(id->name) == ID_MA)
605                         return 1;
606         }
607         return 0;
608 }
609
610 static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
611 {
612         if (drag->type == WM_DRAG_ID) {
613                 ID *id = drag->poin;
614                 if (GS(id->name) == ID_IM)
615                         return 1;
616         }
617         else if (drag->type == WM_DRAG_PATH) {
618                 if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE))   /* rule might not work? */
619                         return 1;
620         }
621         return 0;
622 }
623
624 static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
625 {
626         if (event->ctrl)
627                 return false;
628
629         if (!ED_view3d_give_base_under_cursor(C, event->mval)) {
630                 return view3d_ima_drop_poll(C, drag, event);
631         }
632         return 0;
633 }
634
635 static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
636 {
637         Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
638
639         /* either holding and ctrl and no object, or dropping to empty */
640         if (((base == NULL) && event->ctrl) ||
641             ((base != NULL) && base->object->type == OB_EMPTY))
642         {
643                 return view3d_ima_drop_poll(C, drag, event);
644         }
645
646         return 0;
647 }
648
649 static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
650 {
651         Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
652
653         if (base && base->object->type == OB_MESH)
654                 return view3d_ima_drop_poll(C, drag, event);
655         return 0;
656 }
657
658 static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
659 {
660         ID *id = drag->poin;
661
662         RNA_string_set(drop->ptr, "name", id->name + 2);
663 }
664
665 static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
666 {
667         ID *id = drag->poin;
668         
669         drop->opcontext = WM_OP_EXEC_DEFAULT;
670         RNA_string_set(drop->ptr, "name", id->name + 2);
671 }
672
673 static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
674 {
675         ID *id = drag->poin;
676         
677         RNA_string_set(drop->ptr, "name", id->name + 2);
678 }
679
680 static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
681 {
682         ID *id = drag->poin;
683         
684         if (id) {
685                 RNA_string_set(drop->ptr, "name", id->name + 2);
686                 RNA_struct_property_unset(drop->ptr, "filepath");
687         }
688         else if (drag->path[0]) {
689                 RNA_string_set(drop->ptr, "filepath", drag->path);
690                 RNA_struct_property_unset(drop->ptr, "image");
691         }
692 }
693
694
695 /* region dropbox definition */
696 static void view3d_dropboxes(void)
697 {
698         ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
699         
700         WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy);
701         WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
702         WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
703         WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
704         WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
705         WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);     
706 }
707
708 static void view3d_widgets(void)
709 {
710         wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(
711                 &(const struct wmManipulatorMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW});
712
713         WM_manipulatorgrouptype_append_and_link(mmap_type, TRANSFORM_WGT_manipulator);
714         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_spot);
715         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_area);
716         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_target);
717         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_force_field);
718         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera);
719         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera_view);
720         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_empty_image);
721         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_armature_spline);
722
723         WM_manipulatorgrouptype_append(VIEW3D_WGT_xform_cage);
724
725         WM_manipulatorgrouptype_append(VIEW3D_WGT_ruler);
726         WM_manipulatortype_append(VIEW3D_WT_ruler_item);
727
728         WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_navigate);
729         WM_manipulatortype_append(VIEW3D_WT_navigate_rotate);
730 }
731
732
733 /* type callback, not region itself */
734 static void view3d_main_region_free(ARegion *ar)
735 {
736         RegionView3D *rv3d = ar->regiondata;
737         
738         if (rv3d) {
739                 if (rv3d->localvd) MEM_freeN(rv3d->localvd);
740                 if (rv3d->clipbb) MEM_freeN(rv3d->clipbb);
741
742                 if (rv3d->render_engine)
743                         RE_engine_free(rv3d->render_engine);
744                 
745                 if (rv3d->depths) {
746                         if (rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
747                         MEM_freeN(rv3d->depths);
748                 }
749                 if (rv3d->sms) {
750                         MEM_freeN(rv3d->sms);
751                 }
752                 if (rv3d->gpuoffscreen) {
753                         GPU_offscreen_free(rv3d->gpuoffscreen);
754                 }
755                 if (rv3d->viewport) {
756                         DRW_opengl_context_enable();
757                         GPU_viewport_free(rv3d->viewport);
758                         DRW_opengl_context_disable();
759                 }
760
761                 MEM_freeN(rv3d);
762                 ar->regiondata = NULL;
763         }
764 }
765
766 /* copy regiondata */
767 static void *view3d_main_region_duplicate(void *poin)
768 {
769         if (poin) {
770                 RegionView3D *rv3d = poin, *new;
771         
772                 new = MEM_dupallocN(rv3d);
773                 if (rv3d->localvd)
774                         new->localvd = MEM_dupallocN(rv3d->localvd);
775                 if (rv3d->clipbb)
776                         new->clipbb = MEM_dupallocN(rv3d->clipbb);
777                 
778                 new->depths = NULL;
779                 new->gpuoffscreen = NULL;
780                 new->render_engine = NULL;
781                 new->sms = NULL;
782                 new->smooth_timer = NULL;
783                 new->compositor = NULL;
784                 new->viewport = NULL;
785                 
786                 return new;
787         }
788         return NULL;
789 }
790
791 static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
792 {
793         wmWindow *win = wmn->wm->winactive;
794         unsigned int lay_used = 0;
795
796         if (!win) return;
797
798         const bScreen *screen = WM_window_get_active_screen(win);
799         for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
800                 if (sa->spacetype == SPACE_VIEW3D) {
801                         if (BLI_findindex(&sa->regionbase, ar) != -1) {
802                                 View3D *v3d = sa->spacedata.first;
803                                 v3d->lay_used = lay_used;
804                                 break;
805                         }
806                 }
807         }
808 }
809
810 static void view3d_main_region_listener(
811         bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar,
812         wmNotifier *wmn, const Scene *scene)
813 {
814         View3D *v3d = sa->spacedata.first;
815         RegionView3D *rv3d = ar->regiondata;
816         wmManipulatorMap *mmap = ar->manipulator_map;
817
818         /* context changes */
819         switch (wmn->category) {
820                 case NC_WM:
821                         if (ELEM(wmn->data, ND_UNDO)) {
822                                 WM_manipulatormap_tag_refresh(mmap);
823                         }
824                         break;
825                 case NC_ANIMATION:
826                         switch (wmn->data) {
827                                 case ND_KEYFRAME_PROP:
828                                 case ND_NLA_ACTCHANGE:
829                                         ED_region_tag_redraw(ar);
830                                         break;
831                                 case ND_NLA:
832                                 case ND_KEYFRAME:
833                                         if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
834                                                 ED_region_tag_redraw(ar);
835                                         break;
836                                 case ND_ANIMCHAN:
837                                         if (wmn->action == NA_SELECTED)
838                                                 ED_region_tag_redraw(ar);
839                                         break;
840                         }
841                         break;
842                 case NC_SCENE:
843                         switch (wmn->data) {
844                                 case ND_SCENEBROWSE:
845                                 case ND_LAYER_CONTENT:
846                                         if (wmn->reference)
847                                                 view3d_recalc_used_layers(ar, wmn, wmn->reference);
848                                         ED_region_tag_redraw(ar);
849                                         WM_manipulatormap_tag_refresh(mmap);
850                                         break;
851                                 case ND_LAYER:
852                                         if (wmn->reference) {
853                                                 BKE_screen_view3d_sync(v3d, wmn->reference);
854                                         }
855                                         ED_region_tag_redraw(ar);
856                                         WM_manipulatormap_tag_refresh(mmap);
857                                         break;
858                                 case ND_OB_ACTIVE:
859                                 case ND_OB_SELECT:
860                                         DEG_id_tag_update((ID *)&scene->id, DEG_TAG_SELECT_UPDATE);
861                                         ATTR_FALLTHROUGH;
862                                 case ND_FRAME:
863                                 case ND_TRANSFORM:
864                                 case ND_OB_VISIBLE:
865                                 case ND_RENDER_OPTIONS:
866                                 case ND_MARKERS:
867                                 case ND_MODE:
868                                         ED_region_tag_redraw(ar);
869                                         WM_manipulatormap_tag_refresh(mmap);
870                                         break;
871                                 case ND_WORLD:
872                                         /* handled by space_view3d_listener() for v3d access */
873                                         break;
874                                 case ND_DRAW_RENDER_VIEWPORT:
875                                 {
876                                         if (v3d->camera && (scene == wmn->reference)) {
877                                                 if (rv3d->persp == RV3D_CAMOB) {
878                                                         ED_region_tag_redraw(ar);
879                                                 }
880                                         }
881                                         break;
882                                 }
883                         }
884                         if (wmn->action == NA_EDITED)
885                                 ED_region_tag_redraw(ar);
886                         break;
887                 case NC_OBJECT:
888                         switch (wmn->data) {
889                                 case ND_BONE_ACTIVE:
890                                 case ND_BONE_SELECT:
891                                 case ND_TRANSFORM:
892                                 case ND_POSE:
893                                 case ND_DRAW:
894                                 case ND_MODIFIER:
895                                 case ND_CONSTRAINT:
896                                 case ND_KEYS:
897                                 case ND_PARTICLE:
898                                 case ND_POINTCACHE:
899                                 case ND_LOD:
900                                         ED_region_tag_redraw(ar);
901                                         WM_manipulatormap_tag_refresh(mmap);
902                                         break;
903                         }
904                         switch (wmn->action) {
905                                 case NA_ADDED:
906                                         ED_region_tag_redraw(ar);
907                                         break;
908                         }
909                         break;
910                 case NC_GEOM:
911                         switch (wmn->data) {
912                                 case ND_SELECT:
913                                 {
914                                         WM_manipulatormap_tag_refresh(mmap);
915
916                                         ID *ob_data = wmn->reference;
917                                         if (ob_data == NULL) {
918                                                 BLI_assert(wmn->window); // Use `WM_event_add_notifier` instead of `WM_main_add_notifier`
919                                                 ViewLayer *view_layer = WM_window_get_active_view_layer(wmn->window);
920                                                 ob_data = OBEDIT_FROM_VIEW_LAYER(view_layer)->data;
921                                         }
922                                         if (ob_data) {
923                                                 BLI_assert(OB_DATA_SUPPORT_ID(GS(ob_data->name)));
924                                                 /* TODO(sergey): Notifiers shouldn't really be doing DEG tags. */
925                                                 DEG_id_tag_update(ob_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 *UNUSED(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         wmMsgParams_RNA msg_key_params = {{{0}}};
1075
1076         /* Only subscribe to types. */
1077         StructRNA *type_array[] = {
1078                 &RNA_Window,
1079
1080                 /* These object have properties that impact drawing. */
1081                 &RNA_AreaLamp,
1082                 &RNA_Camera,
1083                 &RNA_Lamp,
1084                 &RNA_Speaker,
1085                 &RNA_SunLamp,
1086
1087                 /* General types the 3D view depends on. */
1088                 &RNA_Object,
1089                 &RNA_UnitSettings,  /* grid-floor */
1090
1091                 &RNA_World,
1092         };
1093
1094         wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
1095                 .owner = ar,
1096                 .user_data = ar,
1097                 .notify = ED_region_do_msg_notify_tag_redraw,
1098         };
1099
1100         for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
1101                 msg_key_params.ptr.type = type_array[i];
1102                 WM_msg_subscribe_rna_params(
1103                         mbus,
1104                         &msg_key_params,
1105                         &msg_sub_value_region_tag_redraw,
1106                         __func__);
1107         }
1108
1109         /* Subscribe to a handful of other properties. */
1110         RegionView3D *rv3d = ar->regiondata;
1111
1112         WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw);
1113         WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw);
1114         WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw);
1115         WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw);
1116         WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw);
1117         if (rv3d->persp == RV3D_CAMOB) {
1118                 WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
1119         }
1120
1121         /* Each engine could be responsible for its own engine data types.
1122          * For now this is simplest. */
1123         if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
1124                 extern StructRNA RNA_ViewLayerEngineSettingsEevee;
1125                 WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsEevee, &msg_sub_value_region_tag_redraw);
1126         }
1127 #ifdef WITH_CLAY_ENGINE
1128         else if (STREQ(scene->r.engine, RE_engine_id_BLENDER_CLAY)) {
1129                 extern StructRNA RNA_ViewLayerEngineSettingsClay;
1130                 WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsClay, &msg_sub_value_region_tag_redraw);
1131         }
1132 #endif
1133 }
1134
1135 /* concept is to retrieve cursor type context-less */
1136 static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
1137 {
1138         ViewLayer *view_layer = WM_window_get_active_view_layer(win);
1139         Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
1140         if (obedit) {
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                         Object *ob = view_layer->basact->object;
1393                         /* if hidden but in edit mode, we still display, can happen with animation */
1394                         if ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->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                         Object *ob = view_layer->basact->object;
1405                         /* if hidden but in edit mode, we still display, can happen with animation */
1406                         if ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
1407                                 CTX_data_id_pointer_set(result, &ob->id);
1408                         }
1409                 }
1410                 
1411                 return 1;
1412         }
1413         else {
1414                 return 0; /* not found */
1415         }
1416
1417         return -1; /* found but not available */
1418 }
1419
1420 static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_id)
1421 {
1422         View3D *v3d;
1423         ARegion *ar;
1424         bool is_local = false;
1425
1426         if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) {
1427                 return;
1428         }
1429
1430         for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) {
1431                 if ((ID *)v3d->camera == old_id) {
1432                         v3d->camera = (Object *)new_id;
1433                         if (!new_id) {
1434                                 /* 3D view might be inactive, in that case needs to use slink->regionbase */
1435                                 ListBase *regionbase = (slink == sa->spacedata.first) ? &sa->regionbase : &slink->regionbase;
1436                                 for (ar = regionbase->first; ar; ar = ar->next) {
1437                                         if (ar->regiontype == RGN_TYPE_WINDOW) {
1438                                                 RegionView3D *rv3d = is_local ? ((RegionView3D *)ar->regiondata)->localvd : ar->regiondata;
1439                                                 if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
1440                                                         rv3d->persp = RV3D_PERSP;
1441                                                 }
1442                                         }
1443                                 }
1444                         }
1445                 }
1446
1447                 /* Values in local-view aren't used, see: T52663 */
1448                 if (is_local == false) {
1449                         /* Skip 'v3d->defmaterial', it's not library data.  */
1450
1451                         if ((ID *)v3d->ob_centre == old_id) {
1452                                 v3d->ob_centre = (Object *)new_id;
1453                                 /* Otherwise, bonename may remain valid... We could be smart and check this, too? */
1454                                 if (new_id == NULL) {
1455                                         v3d->ob_centre_bone[0] = '\0';
1456                                 }
1457                         }
1458                 }
1459
1460                 if (is_local) {
1461                         break;
1462                 }
1463         }
1464 }
1465
1466 /* only called once, from space/spacetypes.c */
1467 void ED_spacetype_view3d(void)
1468 {
1469         SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype view3d");
1470         ARegionType *art;
1471         
1472         st->spaceid = SPACE_VIEW3D;
1473         strncpy(st->name, "View3D", BKE_ST_MAXNAME);
1474         
1475         st->new = view3d_new;
1476         st->free = view3d_free;
1477         st->init = view3d_init;
1478         st->listener = space_view3d_listener;
1479         st->duplicate = view3d_duplicate;
1480         st->operatortypes = view3d_operatortypes;
1481         st->keymap = view3d_keymap;
1482         st->dropboxes = view3d_dropboxes;
1483         st->manipulators = view3d_widgets;
1484         st->context = view3d_context;
1485         st->id_remap = view3d_id_remap;
1486
1487         /* regions: main window */
1488         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
1489         art->regionid = RGN_TYPE_WINDOW;
1490         art->keymapflag = ED_KEYMAP_GPENCIL;
1491         art->draw = view3d_main_region_draw;
1492         art->init = view3d_main_region_init;
1493         art->exit = view3d_main_region_exit;
1494         art->free = view3d_main_region_free;
1495         art->duplicate = view3d_main_region_duplicate;
1496         art->listener = view3d_main_region_listener;
1497         art->message_subscribe = view3d_main_region_message_subscribe;
1498         art->cursor = view3d_main_region_cursor;
1499         art->lock = 1;   /* can become flag, see BKE_spacedata_draw_locks */
1500         BLI_addhead(&st->regiontypes, art);
1501         
1502         /* regions: listview/buttons */
1503         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
1504         art->regionid = RGN_TYPE_UI;
1505         art->prefsizex = 180; /* XXX */
1506         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1507         art->listener = view3d_buttons_region_listener;
1508         art->init = view3d_buttons_region_init;
1509         art->draw = view3d_buttons_region_draw;
1510         BLI_addhead(&st->regiontypes, art);
1511
1512         view3d_buttons_register(art);
1513
1514         /* regions: tool(bar) */
1515         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
1516         art->regionid = RGN_TYPE_TOOLS;
1517         art->prefsizex = 160; /* XXX */
1518         art->prefsizey = 50; /* XXX */
1519         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1520         art->listener = view3d_buttons_region_listener;
1521         art->init = view3d_tools_region_init;
1522         art->draw = view3d_tools_region_draw;
1523         BLI_addhead(&st->regiontypes, art);
1524         
1525 #if 0
1526         /* unfinished still */
1527         view3d_toolshelf_register(art);
1528 #endif
1529
1530         /* regions: tool properties */
1531         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tool properties region");
1532         art->regionid = RGN_TYPE_TOOL_PROPS;
1533         art->prefsizex = 0;
1534         art->prefsizey = 120;
1535         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1536         art->listener = view3d_props_region_listener;
1537         art->init = view3d_tools_region_init;
1538         art->draw = view3d_tools_region_draw;
1539         BLI_addhead(&st->regiontypes, art);
1540         
1541         view3d_tool_props_register(art);
1542         
1543         
1544         /* regions: header */
1545         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
1546         art->regionid = RGN_TYPE_HEADER;
1547         art->prefsizey = HEADERY;
1548         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
1549         art->listener = view3d_header_region_listener;
1550         art->init = view3d_header_region_init;
1551         art->draw = view3d_header_region_draw;
1552         BLI_addhead(&st->regiontypes, art);
1553         
1554         BKE_spacetype_register(st);
1555 }
1556