1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup spview3d
22  */
23 
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include "DNA_defaults.h"
28 #include "DNA_gpencil_types.h"
29 #include "DNA_lightprobe_types.h"
30 #include "DNA_material_types.h"
31 #include "DNA_object_types.h"
32 #include "DNA_scene_types.h"
33 
34 #include "MEM_guardedalloc.h"
35 
36 #include "BLI_blenlib.h"
37 #include "BLI_math.h"
38 #include "BLI_utildefines.h"
39 
40 #include "BLT_translation.h"
41 
42 #include "BKE_context.h"
43 #include "BKE_curve.h"
44 #include "BKE_global.h"
45 #include "BKE_icons.h"
46 #include "BKE_idprop.h"
47 #include "BKE_lattice.h"
48 #include "BKE_main.h"
49 #include "BKE_mball.h"
50 #include "BKE_mesh.h"
51 #include "BKE_object.h"
52 #include "BKE_scene.h"
53 #include "BKE_screen.h"
54 #include "BKE_workspace.h"
55 
56 #include "ED_screen.h"
57 #include "ED_space_api.h"
58 #include "ED_transform.h"
59 
60 #include "GPU_matrix.h"
61 
62 #include "DRW_engine.h"
63 
64 #include "WM_api.h"
65 #include "WM_message.h"
66 #include "WM_toolsystem.h"
67 #include "WM_types.h"
68 
69 #include "RE_engine.h"
70 #include "RE_pipeline.h"
71 
72 #include "RNA_access.h"
73 
74 #include "UI_interface.h"
75 #include "UI_resources.h"
76 
77 #ifdef WITH_PYTHON
78 #  include "BPY_extern.h"
79 #endif
80 
81 #include "DEG_depsgraph.h"
82 
83 #include "view3d_intern.h" /* own include */
84 
85 /* ******************** manage regions ********************* */
86 
87 /* function to always find a regionview3d context inside 3D window */
ED_view3d_context_rv3d(bContext * C)88 RegionView3D *ED_view3d_context_rv3d(bContext *C)
89 {
90   RegionView3D *rv3d = CTX_wm_region_view3d(C);
91 
92   if (rv3d == NULL) {
93     ScrArea *area = CTX_wm_area(C);
94     if (area && area->spacetype == SPACE_VIEW3D) {
95       ARegion *region = BKE_area_find_region_active_win(area);
96       if (region) {
97         rv3d = region->regiondata;
98       }
99     }
100   }
101   return rv3d;
102 }
103 
104 /* ideally would return an rv3d but in some cases the region is needed too
105  * so return that, the caller can then access the region->regiondata */
ED_view3d_context_user_region(bContext * C,View3D ** r_v3d,ARegion ** r_region)106 bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_region)
107 {
108   ScrArea *area = CTX_wm_area(C);
109 
110   *r_v3d = NULL;
111   *r_region = NULL;
112 
113   if (area && area->spacetype == SPACE_VIEW3D) {
114     ARegion *region = CTX_wm_region(C);
115     View3D *v3d = (View3D *)area->spacedata.first;
116 
117     if (region) {
118       RegionView3D *rv3d;
119       if ((region->regiontype == RGN_TYPE_WINDOW) && (rv3d = region->regiondata) &&
120           (rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) {
121         *r_v3d = v3d;
122         *r_region = region;
123         return true;
124       }
125 
126       if (ED_view3d_area_user_region(area, v3d, r_region)) {
127         *r_v3d = v3d;
128         return true;
129       }
130     }
131   }
132 
133   return false;
134 }
135 
136 /**
137  * Similar to #ED_view3d_context_user_region() but does not use context. Always performs a lookup.
138  * Also works if \a v3d is not the active space.
139  */
ED_view3d_area_user_region(const ScrArea * area,const View3D * v3d,ARegion ** r_region)140 bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion **r_region)
141 {
142   RegionView3D *rv3d = NULL;
143   ARegion *region_unlock_user = NULL;
144   ARegion *region_unlock = NULL;
145   const ListBase *region_list = (v3d == area->spacedata.first) ? &area->regionbase :
146                                                                  &v3d->regionbase;
147 
148   BLI_assert(v3d->spacetype == SPACE_VIEW3D);
149 
150   LISTBASE_FOREACH (ARegion *, region, region_list) {
151     /* find the first unlocked rv3d */
152     if (region->regiondata && region->regiontype == RGN_TYPE_WINDOW) {
153       rv3d = region->regiondata;
154       if ((rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) {
155         region_unlock = region;
156         if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) {
157           region_unlock_user = region;
158           break;
159         }
160       }
161     }
162   }
163 
164   /* camera/perspective view get priority when the active region is locked */
165   if (region_unlock_user) {
166     *r_region = region_unlock_user;
167     return true;
168   }
169 
170   if (region_unlock) {
171     *r_region = region_unlock;
172     return true;
173   }
174 
175   return false;
176 }
177 
178 /* Most of the time this isn't needed since you could assume the view matrix was
179  * set while drawing, however when functions like mesh_foreachScreenVert are
180  * called by selection tools, we can't be sure this object was the last.
181  *
182  * for example, transparent objects are drawn after editmode and will cause
183  * the rv3d mat's to change and break selection.
184  *
185  * 'ED_view3d_init_mats_rv3d' should be called before
186  * view3d_project_short_clip and view3d_project_short_noclip in cases where
187  * these functions are not used during draw_object
188  */
ED_view3d_init_mats_rv3d(struct Object * ob,struct RegionView3D * rv3d)189 void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
190 {
191   /* local viewmat and persmat, to calculate projections */
192   mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
193   mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
194 
195   /* initializes object space clipping, speeds up clip tests */
196   ED_view3d_clipping_local(rv3d, ob->obmat);
197 }
198 
ED_view3d_init_mats_rv3d_gl(struct Object * ob,struct RegionView3D * rv3d)199 void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
200 {
201   ED_view3d_init_mats_rv3d(ob, rv3d);
202 
203   /* we have to multiply instead of loading viewmatob to make
204    * it work with duplis using displists, otherwise it will
205    * override the dupli-matrix */
206   GPU_matrix_mul(ob->obmat);
207 }
208 
209 #ifdef DEBUG
210 /* ensure we correctly initialize */
ED_view3d_clear_mats_rv3d(struct RegionView3D * rv3d)211 void ED_view3d_clear_mats_rv3d(struct RegionView3D *rv3d)
212 {
213   zero_m4(rv3d->viewmatob);
214   zero_m4(rv3d->persmatob);
215 }
216 
ED_view3d_check_mats_rv3d(struct RegionView3D * rv3d)217 void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
218 {
219   BLI_ASSERT_ZERO_M4(rv3d->viewmatob);
220   BLI_ASSERT_ZERO_M4(rv3d->persmatob);
221 }
222 #endif
223 
ED_view3d_stop_render_preview(wmWindowManager * wm,ARegion * region)224 void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *region)
225 {
226   RegionView3D *rv3d = region->regiondata;
227 
228   if (rv3d->render_engine) {
229 #ifdef WITH_PYTHON
230     BPy_BEGIN_ALLOW_THREADS;
231 #endif
232 
233     WM_jobs_kill_type(wm, region, WM_JOB_TYPE_RENDER_PREVIEW);
234 
235 #ifdef WITH_PYTHON
236     BPy_END_ALLOW_THREADS;
237 #endif
238 
239     RE_engine_free(rv3d->render_engine);
240     rv3d->render_engine = NULL;
241   }
242 
243   /* A bit overkill but this make sure the viewport is reset completely. (fclem) */
244   WM_draw_region_free(region, false);
245 }
246 
ED_view3d_shade_update(Main * bmain,View3D * v3d,ScrArea * area)247 void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *area)
248 {
249   wmWindowManager *wm = bmain->wm.first;
250 
251   if (v3d->shading.type != OB_RENDER) {
252     ARegion *region;
253 
254     for (region = area->regionbase.first; region; region = region->next) {
255       if ((region->regiontype == RGN_TYPE_WINDOW) && region->regiondata) {
256         ED_view3d_stop_render_preview(wm, region);
257         break;
258       }
259     }
260   }
261 }
262 
263 /* ******************** default callbacks for view3d space ***************** */
264 
view3d_create(const ScrArea * UNUSED (area),const Scene * scene)265 static SpaceLink *view3d_create(const ScrArea *UNUSED(area), const Scene *scene)
266 {
267   ARegion *region;
268   View3D *v3d;
269   RegionView3D *rv3d;
270 
271   v3d = DNA_struct_default_alloc(View3D);
272 
273   if (scene) {
274     v3d->camera = scene->camera;
275   }
276 
277   /* tool header */
278   region = MEM_callocN(sizeof(ARegion), "tool header for view3d");
279 
280   BLI_addtail(&v3d->regionbase, region);
281   region->regiontype = RGN_TYPE_TOOL_HEADER;
282   region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
283   region->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
284 
285   /* header */
286   region = MEM_callocN(sizeof(ARegion), "header for view3d");
287 
288   BLI_addtail(&v3d->regionbase, region);
289   region->regiontype = RGN_TYPE_HEADER;
290   region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
291 
292   /* tool shelf */
293   region = MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
294 
295   BLI_addtail(&v3d->regionbase, region);
296   region->regiontype = RGN_TYPE_TOOLS;
297   region->alignment = RGN_ALIGN_LEFT;
298   region->flag = RGN_FLAG_HIDDEN;
299 
300   /* buttons/list view */
301   region = MEM_callocN(sizeof(ARegion), "buttons for view3d");
302 
303   BLI_addtail(&v3d->regionbase, region);
304   region->regiontype = RGN_TYPE_UI;
305   region->alignment = RGN_ALIGN_RIGHT;
306   region->flag = RGN_FLAG_HIDDEN;
307 
308   /* main region */
309   region = MEM_callocN(sizeof(ARegion), "main region for view3d");
310 
311   BLI_addtail(&v3d->regionbase, region);
312   region->regiontype = RGN_TYPE_WINDOW;
313 
314   region->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d");
315   rv3d = region->regiondata;
316   rv3d->viewquat[0] = 1.0f;
317   rv3d->persp = RV3D_PERSP;
318   rv3d->view = RV3D_VIEW_USER;
319   rv3d->dist = 10.0;
320 
321   return (SpaceLink *)v3d;
322 }
323 
324 /* not spacelink itself */
view3d_free(SpaceLink * sl)325 static void view3d_free(SpaceLink *sl)
326 {
327   View3D *vd = (View3D *)sl;
328 
329   if (vd->localvd) {
330     MEM_freeN(vd->localvd);
331   }
332 
333   if (vd->runtime.properties_storage) {
334     MEM_freeN(vd->runtime.properties_storage);
335   }
336 
337   if (vd->shading.prop) {
338     IDP_FreeProperty(vd->shading.prop);
339     vd->shading.prop = NULL;
340   }
341 }
342 
343 /* spacetype; init callback */
view3d_init(wmWindowManager * UNUSED (wm),ScrArea * UNUSED (area))344 static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
345 {
346 }
347 
view3d_duplicate(SpaceLink * sl)348 static SpaceLink *view3d_duplicate(SpaceLink *sl)
349 {
350   View3D *v3do = (View3D *)sl;
351   View3D *v3dn = MEM_dupallocN(sl);
352 
353   /* clear or remove stuff from old */
354 
355   if (v3dn->localvd) {
356     v3dn->localvd = NULL;
357     v3dn->runtime.properties_storage = NULL;
358   }
359   /* Only one View3D is allowed to have this flag! */
360   v3dn->runtime.flag &= ~V3D_RUNTIME_XR_SESSION_ROOT;
361 
362   v3dn->local_collections_uuid = 0;
363   v3dn->flag &= ~(V3D_LOCAL_COLLECTIONS | V3D_XR_SESSION_MIRROR);
364 
365   if (v3dn->shading.type == OB_RENDER) {
366     v3dn->shading.type = OB_SOLID;
367   }
368 
369   if (v3dn->shading.prop) {
370     v3dn->shading.prop = IDP_CopyProperty(v3do->shading.prop);
371   }
372 
373   /* copy or clear inside new stuff */
374 
375   v3dn->runtime.properties_storage = NULL;
376 
377   return (SpaceLink *)v3dn;
378 }
379 
380 /* add handlers, stuff you only do once or on area/region changes */
view3d_main_region_init(wmWindowManager * wm,ARegion * region)381 static void view3d_main_region_init(wmWindowManager *wm, ARegion *region)
382 {
383   ListBase *lb;
384   wmKeyMap *keymap;
385 
386   /* object ops. */
387 
388   /* important to be before Pose keymap since they can both be enabled at once */
389   keymap = WM_keymap_ensure(wm->defaultconf, "Paint Face Mask (Weight, Vertex, Texture)", 0, 0);
390   WM_event_add_keymap_handler(&region->handlers, keymap);
391 
392   keymap = WM_keymap_ensure(wm->defaultconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0);
393   WM_event_add_keymap_handler(&region->handlers, keymap);
394 
395   /* Before 'Pose' so weight paint menus aren't overridden by pose menus. */
396   keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint", 0, 0);
397   WM_event_add_keymap_handler(&region->handlers, keymap);
398 
399   keymap = WM_keymap_ensure(wm->defaultconf, "Vertex Paint", 0, 0);
400   WM_event_add_keymap_handler(&region->handlers, keymap);
401 
402   /* pose is not modal, operator poll checks for this */
403   keymap = WM_keymap_ensure(wm->defaultconf, "Pose", 0, 0);
404   WM_event_add_keymap_handler(&region->handlers, keymap);
405 
406   keymap = WM_keymap_ensure(wm->defaultconf, "Object Mode", 0, 0);
407   WM_event_add_keymap_handler(&region->handlers, keymap);
408 
409   keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0);
410   WM_event_add_keymap_handler(&region->handlers, keymap);
411 
412   keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
413   WM_event_add_keymap_handler(&region->handlers, keymap);
414 
415   keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0);
416   WM_event_add_keymap_handler(&region->handlers, keymap);
417 
418   keymap = WM_keymap_ensure(wm->defaultconf, "Sculpt", 0, 0);
419   WM_event_add_keymap_handler(&region->handlers, keymap);
420 
421   keymap = WM_keymap_ensure(wm->defaultconf, "Mesh", 0, 0);
422   WM_event_add_keymap_handler(&region->handlers, keymap);
423 
424   keymap = WM_keymap_ensure(wm->defaultconf, "Armature", 0, 0);
425   WM_event_add_keymap_handler(&region->handlers, keymap);
426 
427   keymap = WM_keymap_ensure(wm->defaultconf, "Metaball", 0, 0);
428   WM_event_add_keymap_handler(&region->handlers, keymap);
429 
430   keymap = WM_keymap_ensure(wm->defaultconf, "Lattice", 0, 0);
431   WM_event_add_keymap_handler(&region->handlers, keymap);
432 
433   keymap = WM_keymap_ensure(wm->defaultconf, "Particle", 0, 0);
434   WM_event_add_keymap_handler(&region->handlers, keymap);
435 
436   /* editfont keymap swallows all... */
437   keymap = WM_keymap_ensure(wm->defaultconf, "Font", 0, 0);
438   WM_event_add_keymap_handler(&region->handlers, keymap);
439 
440   keymap = WM_keymap_ensure(wm->defaultconf, "Object Non-modal", 0, 0);
441   WM_event_add_keymap_handler(&region->handlers, keymap);
442 
443   keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0);
444   WM_event_add_keymap_handler(&region->handlers, keymap);
445 
446   /* own keymap, last so modes can override it */
447   keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
448   WM_event_add_keymap_handler(&region->handlers, keymap);
449 
450   keymap = WM_keymap_ensure(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
451   WM_event_add_keymap_handler(&region->handlers, keymap);
452 
453   /* add drop boxes */
454   lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
455 
456   WM_event_add_dropbox_handler(&region->handlers, lb);
457 }
458 
view3d_main_region_exit(wmWindowManager * wm,ARegion * region)459 static void view3d_main_region_exit(wmWindowManager *wm, ARegion *region)
460 {
461   ED_view3d_stop_render_preview(wm, region);
462 }
463 
view3d_drop_id_in_main_region_poll_id(bContext * C,wmDrag * drag,const wmEvent * event,ID_Type id_type)464 static ID *view3d_drop_id_in_main_region_poll_id(bContext *C,
465                                                  wmDrag *drag,
466                                                  const wmEvent *event,
467                                                  ID_Type id_type)
468 {
469   ScrArea *area = CTX_wm_area(C);
470   if (ED_region_overlap_isect_any_xy(area, &event->x)) {
471     return false;
472   }
473   return WM_drag_ID(drag, id_type);
474 }
475 
view3d_drop_id_in_main_region_poll(bContext * C,wmDrag * drag,const wmEvent * event,ID_Type id_type)476 static bool view3d_drop_id_in_main_region_poll(bContext *C,
477                                                wmDrag *drag,
478                                                const wmEvent *event,
479                                                ID_Type id_type)
480 {
481   return (view3d_drop_id_in_main_region_poll_id(C, drag, event, id_type) != NULL);
482 }
483 
view3d_ob_drop_poll(bContext * C,wmDrag * drag,const wmEvent * event,const char ** UNUSED (r_tooltip))484 static bool view3d_ob_drop_poll(bContext *C,
485                                 wmDrag *drag,
486                                 const wmEvent *event,
487                                 const char **UNUSED(r_tooltip))
488 {
489   return view3d_drop_id_in_main_region_poll(C, drag, event, ID_OB);
490 }
491 
view3d_collection_drop_poll(bContext * C,wmDrag * drag,const wmEvent * event,const char ** UNUSED (r_tooltip))492 static bool view3d_collection_drop_poll(bContext *C,
493                                         wmDrag *drag,
494                                         const wmEvent *event,
495                                         const char **UNUSED(r_tooltip))
496 {
497   return view3d_drop_id_in_main_region_poll(C, drag, event, ID_GR);
498 }
499 
view3d_mat_drop_poll(bContext * C,wmDrag * drag,const wmEvent * event,const char ** UNUSED (r_tooltip))500 static bool view3d_mat_drop_poll(bContext *C,
501                                  wmDrag *drag,
502                                  const wmEvent *event,
503                                  const char **UNUSED(r_tooltip))
504 {
505   return view3d_drop_id_in_main_region_poll(C, drag, event, ID_MA);
506 }
507 
view3d_object_data_drop_poll(bContext * C,wmDrag * drag,const wmEvent * event,const char ** r_tooltip)508 static bool view3d_object_data_drop_poll(bContext *C,
509                                          wmDrag *drag,
510                                          const wmEvent *event,
511                                          const char **r_tooltip)
512 {
513   ID *id = view3d_drop_id_in_main_region_poll_id(C, drag, event, 0);
514   if (id != NULL) {
515     if (BKE_object_obdata_to_type(id) != -1) {
516       *r_tooltip = TIP_("Create object instance from object-data");
517       return true;
518     }
519   }
520   return false;
521 }
522 
view3d_ima_drop_poll(bContext * C,wmDrag * drag,const wmEvent * event,const char ** UNUSED (r_tooltip))523 static bool view3d_ima_drop_poll(bContext *C,
524                                  wmDrag *drag,
525                                  const wmEvent *event,
526                                  const char **UNUSED(r_tooltip))
527 {
528   if (ED_region_overlap_isect_any_xy(CTX_wm_area(C), &event->x)) {
529     return false;
530   }
531   if (drag->type == WM_DRAG_PATH) {
532     /* rule might not work? */
533     return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
534   }
535 
536   return WM_drag_ID(drag, ID_IM) != NULL;
537 }
538 
view3d_ima_bg_is_camera_view(bContext * C)539 static bool view3d_ima_bg_is_camera_view(bContext *C)
540 {
541   RegionView3D *rv3d = CTX_wm_region_view3d(C);
542   if ((rv3d && (rv3d->persp == RV3D_CAMOB))) {
543     View3D *v3d = CTX_wm_view3d(C);
544     if (v3d && v3d->camera && v3d->camera->type == OB_CAMERA) {
545       return true;
546     }
547   }
548   return false;
549 }
550 
view3d_ima_bg_drop_poll(bContext * C,wmDrag * drag,const wmEvent * event,const char ** r_tooltip)551 static bool view3d_ima_bg_drop_poll(bContext *C,
552                                     wmDrag *drag,
553                                     const wmEvent *event,
554                                     const char **r_tooltip)
555 {
556   if (!view3d_ima_drop_poll(C, drag, event, r_tooltip)) {
557     return false;
558   }
559 
560   if (ED_view3d_is_object_under_cursor(C, event->mval)) {
561     return false;
562   }
563 
564   return view3d_ima_bg_is_camera_view(C);
565 }
566 
view3d_ima_empty_drop_poll(bContext * C,wmDrag * drag,const wmEvent * event,const char ** r_tooltip)567 static bool view3d_ima_empty_drop_poll(bContext *C,
568                                        wmDrag *drag,
569                                        const wmEvent *event,
570                                        const char **r_tooltip)
571 {
572   if (!view3d_ima_drop_poll(C, drag, event, r_tooltip)) {
573     return false;
574   }
575 
576   Object *ob = ED_view3d_give_object_under_cursor(C, event->mval);
577 
578   if (ob == NULL) {
579     return true;
580   }
581 
582   if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
583     return true;
584   }
585 
586   return false;
587 }
588 
view3d_volume_drop_poll(bContext * UNUSED (C),wmDrag * drag,const wmEvent * UNUSED (event),const char ** UNUSED (r_tooltip))589 static bool view3d_volume_drop_poll(bContext *UNUSED(C),
590                                     wmDrag *drag,
591                                     const wmEvent *UNUSED(event),
592                                     const char **UNUSED(r_tooltip))
593 {
594   return (drag->type == WM_DRAG_PATH) && (drag->icon == ICON_FILE_VOLUME);
595 }
596 
view3d_ob_drop_copy(wmDrag * drag,wmDropBox * drop)597 static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
598 {
599   ID *id = WM_drag_ID(drag, ID_OB);
600 
601   RNA_string_set(drop->ptr, "name", id->name + 2);
602 }
603 
view3d_collection_drop_copy(wmDrag * drag,wmDropBox * drop)604 static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
605 {
606   ID *id = WM_drag_ID(drag, ID_GR);
607 
608   drop->opcontext = WM_OP_EXEC_DEFAULT;
609   RNA_string_set(drop->ptr, "name", id->name + 2);
610 }
611 
view3d_id_drop_copy(wmDrag * drag,wmDropBox * drop)612 static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
613 {
614   ID *id = WM_drag_ID(drag, 0);
615 
616   RNA_string_set(drop->ptr, "name", id->name + 2);
617 }
618 
view3d_id_drop_copy_with_type(wmDrag * drag,wmDropBox * drop)619 static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop)
620 {
621   ID *id = WM_drag_ID(drag, 0);
622 
623   RNA_string_set(drop->ptr, "name", id->name + 2);
624   RNA_enum_set(drop->ptr, "type", GS(id->name));
625 }
626 
view3d_id_path_drop_copy(wmDrag * drag,wmDropBox * drop)627 static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
628 {
629   ID *id = WM_drag_ID(drag, 0);
630 
631   if (id) {
632     RNA_string_set(drop->ptr, "name", id->name + 2);
633     RNA_struct_property_unset(drop->ptr, "filepath");
634   }
635   else if (drag->path[0]) {
636     RNA_string_set(drop->ptr, "filepath", drag->path);
637     RNA_struct_property_unset(drop->ptr, "image");
638   }
639 }
640 
view3d_lightcache_update(bContext * C)641 static void view3d_lightcache_update(bContext *C)
642 {
643   PointerRNA op_ptr;
644 
645   Scene *scene = CTX_data_scene(C);
646 
647   if (!BKE_scene_uses_blender_eevee(scene)) {
648     /* Only do auto bake if eevee is the active engine */
649     return;
650   }
651 
652   wmOperatorType *ot = WM_operatortype_find("SCENE_OT_light_cache_bake", true);
653   WM_operator_properties_create_ptr(&op_ptr, ot);
654   RNA_int_set(&op_ptr, "delay", 200);
655   RNA_enum_set_identifier(C, &op_ptr, "subset", "DIRTY");
656 
657   WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr);
658 
659   WM_operator_properties_free(&op_ptr);
660 }
661 
662 /* region dropbox definition */
view3d_dropboxes(void)663 static void view3d_dropboxes(void)
664 {
665   ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
666 
667   WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy);
668   WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
669   WM_dropbox_add(
670       lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
671   WM_dropbox_add(
672       lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
673   WM_dropbox_add(lb, "OBJECT_OT_volume_import", view3d_volume_drop_poll, view3d_id_path_drop_copy);
674   WM_dropbox_add(lb,
675                  "OBJECT_OT_collection_instance_add",
676                  view3d_collection_drop_poll,
677                  view3d_collection_drop_copy);
678   WM_dropbox_add(lb,
679                  "OBJECT_OT_data_instance_add",
680                  view3d_object_data_drop_poll,
681                  view3d_id_drop_copy_with_type);
682 }
683 
view3d_widgets(void)684 static void view3d_widgets(void)
685 {
686   wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
687       &(const struct wmGizmoMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW});
688 
689   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_xform_gizmo_context);
690   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_spot);
691   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_area);
692   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_target);
693   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_force_field);
694   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera);
695   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera_view);
696   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_empty_image);
697   /* TODO(campbell): Not working well enough, disable for now. */
698 #if 0
699   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_armature_spline);
700 #endif
701 
702   WM_gizmogrouptype_append(VIEW3D_GGT_xform_gizmo);
703   WM_gizmogrouptype_append(VIEW3D_GGT_xform_cage);
704   WM_gizmogrouptype_append(VIEW3D_GGT_xform_shear);
705   WM_gizmogrouptype_append(VIEW3D_GGT_xform_extrude);
706   WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_elem);
707   WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_edgering);
708   WM_gizmogrouptype_append(VIEW3D_GGT_tool_generic_handle_normal);
709   WM_gizmogrouptype_append(VIEW3D_GGT_tool_generic_handle_free);
710 
711   WM_gizmogrouptype_append(VIEW3D_GGT_ruler);
712   WM_gizmotype_append(VIEW3D_GT_ruler_item);
713 
714   WM_gizmogrouptype_append(VIEW3D_GGT_placement);
715 
716   WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_navigate);
717   WM_gizmotype_append(VIEW3D_GT_navigate_rotate);
718 }
719 
720 /* type callback, not region itself */
view3d_main_region_free(ARegion * region)721 static void view3d_main_region_free(ARegion *region)
722 {
723   RegionView3D *rv3d = region->regiondata;
724 
725   if (rv3d) {
726     if (rv3d->localvd) {
727       MEM_freeN(rv3d->localvd);
728     }
729     if (rv3d->clipbb) {
730       MEM_freeN(rv3d->clipbb);
731     }
732 
733     if (rv3d->render_engine) {
734       RE_engine_free(rv3d->render_engine);
735     }
736 
737     if (rv3d->depths) {
738       if (rv3d->depths->depths) {
739         MEM_freeN(rv3d->depths->depths);
740       }
741       MEM_freeN(rv3d->depths);
742     }
743     if (rv3d->sms) {
744       MEM_freeN(rv3d->sms);
745     }
746 
747     MEM_freeN(rv3d);
748     region->regiondata = NULL;
749   }
750 }
751 
752 /* copy regiondata */
view3d_main_region_duplicate(void * poin)753 static void *view3d_main_region_duplicate(void *poin)
754 {
755   if (poin) {
756     RegionView3D *rv3d = poin, *new;
757 
758     new = MEM_dupallocN(rv3d);
759     if (rv3d->localvd) {
760       new->localvd = MEM_dupallocN(rv3d->localvd);
761     }
762     if (rv3d->clipbb) {
763       new->clipbb = MEM_dupallocN(rv3d->clipbb);
764     }
765 
766     new->depths = NULL;
767     new->render_engine = NULL;
768     new->sms = NULL;
769     new->smooth_timer = NULL;
770 
771     return new;
772   }
773   return NULL;
774 }
775 
view3d_main_region_listener(wmWindow * UNUSED (win),ScrArea * area,ARegion * region,wmNotifier * wmn,const Scene * scene)776 static void view3d_main_region_listener(
777     wmWindow *UNUSED(win), ScrArea *area, ARegion *region, wmNotifier *wmn, const Scene *scene)
778 {
779   View3D *v3d = area->spacedata.first;
780   RegionView3D *rv3d = region->regiondata;
781   wmGizmoMap *gzmap = region->gizmo_map;
782 
783   /* context changes */
784   switch (wmn->category) {
785     case NC_WM:
786       if (ELEM(wmn->data, ND_UNDO)) {
787         WM_gizmomap_tag_refresh(gzmap);
788       }
789       else if (ELEM(wmn->data, ND_XR_DATA_CHANGED)) {
790         /* Only cause a redraw if this a VR session mirror. Should more features be added that
791          * require redraws, we could pass something to wmn->reference, e.g. the flag value. */
792         if (v3d->flag & V3D_XR_SESSION_MIRROR) {
793           ED_region_tag_redraw(region);
794         }
795       }
796       break;
797     case NC_ANIMATION:
798       switch (wmn->data) {
799         case ND_KEYFRAME_PROP:
800         case ND_NLA_ACTCHANGE:
801           ED_region_tag_redraw(region);
802           break;
803         case ND_NLA:
804         case ND_KEYFRAME:
805           if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
806             ED_region_tag_redraw(region);
807           }
808           break;
809         case ND_ANIMCHAN:
810           if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED, NA_SELECTED)) {
811             ED_region_tag_redraw(region);
812           }
813           break;
814       }
815       break;
816     case NC_SCENE:
817       switch (wmn->data) {
818         case ND_SCENEBROWSE:
819         case ND_LAYER_CONTENT:
820           ED_region_tag_redraw(region);
821           WM_gizmomap_tag_refresh(gzmap);
822           break;
823         case ND_LAYER:
824           if (wmn->reference) {
825             BKE_screen_view3d_sync(v3d, wmn->reference);
826           }
827           ED_region_tag_redraw(region);
828           WM_gizmomap_tag_refresh(gzmap);
829           break;
830         case ND_OB_ACTIVE:
831         case ND_OB_SELECT:
832           ATTR_FALLTHROUGH;
833         case ND_FRAME:
834         case ND_TRANSFORM:
835         case ND_OB_VISIBLE:
836         case ND_RENDER_OPTIONS:
837         case ND_MARKERS:
838         case ND_MODE:
839           ED_region_tag_redraw(region);
840           WM_gizmomap_tag_refresh(gzmap);
841           break;
842         case ND_WORLD:
843           /* handled by space_view3d_listener() for v3d access */
844           break;
845         case ND_DRAW_RENDER_VIEWPORT: {
846           if (v3d->camera && (scene == wmn->reference)) {
847             if (rv3d->persp == RV3D_CAMOB) {
848               ED_region_tag_redraw(region);
849             }
850           }
851           break;
852         }
853       }
854       if (wmn->action == NA_EDITED) {
855         ED_region_tag_redraw(region);
856       }
857       break;
858     case NC_OBJECT:
859       switch (wmn->data) {
860         case ND_BONE_ACTIVE:
861         case ND_BONE_SELECT:
862         case ND_TRANSFORM:
863         case ND_POSE:
864         case ND_DRAW:
865         case ND_MODIFIER:
866         case ND_SHADERFX:
867         case ND_CONSTRAINT:
868         case ND_KEYS:
869         case ND_PARTICLE:
870         case ND_POINTCACHE:
871         case ND_LOD:
872           ED_region_tag_redraw(region);
873           WM_gizmomap_tag_refresh(gzmap);
874           break;
875       }
876       switch (wmn->action) {
877         case NA_ADDED:
878           ED_region_tag_redraw(region);
879           break;
880       }
881       break;
882     case NC_GEOM:
883       switch (wmn->data) {
884         case ND_SELECT: {
885           WM_gizmomap_tag_refresh(gzmap);
886           ATTR_FALLTHROUGH;
887         }
888         case ND_DATA:
889           ED_region_tag_redraw(region);
890           WM_gizmomap_tag_refresh(gzmap);
891           break;
892         case ND_VERTEX_GROUP:
893           ED_region_tag_redraw(region);
894           break;
895       }
896       switch (wmn->action) {
897         case NA_EDITED:
898           ED_region_tag_redraw(region);
899           break;
900       }
901       break;
902     case NC_CAMERA:
903       switch (wmn->data) {
904         case ND_DRAW_RENDER_VIEWPORT: {
905           if (v3d->camera && (v3d->camera->data == wmn->reference)) {
906             if (rv3d->persp == RV3D_CAMOB) {
907               ED_region_tag_redraw(region);
908             }
909           }
910           break;
911         }
912       }
913       break;
914     case NC_GROUP:
915       /* all group ops for now */
916       ED_region_tag_redraw(region);
917       break;
918     case NC_BRUSH:
919       switch (wmn->action) {
920         case NA_EDITED:
921           ED_region_tag_redraw_cursor(region);
922           break;
923         case NA_SELECTED:
924           /* used on brush changes - needed because 3d cursor
925            * has to be drawn if clone brush is selected */
926           ED_region_tag_redraw(region);
927           break;
928       }
929       break;
930     case NC_MATERIAL:
931       switch (wmn->data) {
932         case ND_SHADING:
933         case ND_NODES:
934           /* TODO(sergey): This is a bit too much updates, but needed to
935            * have proper material drivers update in the viewport.
936            *
937            * How to solve?
938            */
939           ED_region_tag_redraw(region);
940           break;
941         case ND_SHADING_DRAW:
942         case ND_SHADING_LINKS:
943           ED_region_tag_redraw(region);
944           break;
945       }
946       break;
947     case NC_WORLD:
948       switch (wmn->data) {
949         case ND_WORLD_DRAW:
950           /* handled by space_view3d_listener() for v3d access */
951           break;
952         case ND_WORLD:
953           /* Needed for updating world materials */
954           ED_region_tag_redraw(region);
955           break;
956       }
957       break;
958     case NC_LAMP:
959       switch (wmn->data) {
960         case ND_LIGHTING:
961           /* TODO(sergey): This is a bit too much, but needed to
962            * handle updates from new depsgraph.
963            */
964           ED_region_tag_redraw(region);
965           break;
966         case ND_LIGHTING_DRAW:
967           ED_region_tag_redraw(region);
968           WM_gizmomap_tag_refresh(gzmap);
969           break;
970       }
971       break;
972     case NC_LIGHTPROBE:
973       ED_area_tag_refresh(area);
974       break;
975     case NC_IMAGE:
976       /* this could be more fine grained checks if we had
977        * more context than just the region */
978       ED_region_tag_redraw(region);
979       break;
980     case NC_TEXTURE:
981       /* same as above */
982       ED_region_tag_redraw(region);
983       break;
984     case NC_MOVIECLIP:
985       if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED) {
986         ED_region_tag_redraw(region);
987       }
988       break;
989     case NC_SPACE:
990       if (wmn->data == ND_SPACE_VIEW3D) {
991         if (wmn->subtype == NS_VIEW3D_GPU) {
992           rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
993         }
994 #ifdef WITH_XR_OPENXR
995         else if (wmn->subtype == NS_VIEW3D_SHADING) {
996           ED_view3d_xr_shading_update(G_MAIN->wm.first, v3d, scene);
997         }
998 #endif
999         ED_region_tag_redraw(region);
1000         WM_gizmomap_tag_refresh(gzmap);
1001       }
1002       break;
1003     case NC_ID:
1004       if (wmn->action == NA_RENAME) {
1005         ED_region_tag_redraw(region);
1006       }
1007       break;
1008     case NC_SCREEN:
1009       switch (wmn->data) {
1010         case ND_ANIMPLAY:
1011         case ND_SKETCH:
1012           ED_region_tag_redraw(region);
1013           break;
1014         case ND_LAYOUTBROWSE:
1015         case ND_LAYOUTDELETE:
1016         case ND_LAYOUTSET:
1017           WM_gizmomap_tag_refresh(gzmap);
1018           ED_region_tag_redraw(region);
1019           break;
1020         case ND_LAYER:
1021           ED_region_tag_redraw(region);
1022           break;
1023       }
1024 
1025       break;
1026     case NC_GPENCIL:
1027       if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
1028         ED_region_tag_redraw(region);
1029       }
1030       break;
1031   }
1032 }
1033 
view3d_main_region_message_subscribe(const struct bContext * C,struct WorkSpace * UNUSED (workspace),struct Scene * UNUSED (scene),struct bScreen * UNUSED (screen),struct ScrArea * area,struct ARegion * region,struct wmMsgBus * mbus)1034 static void view3d_main_region_message_subscribe(const struct bContext *C,
1035                                                  struct WorkSpace *UNUSED(workspace),
1036                                                  struct Scene *UNUSED(scene),
1037                                                  struct bScreen *UNUSED(screen),
1038                                                  struct ScrArea *area,
1039                                                  struct ARegion *region,
1040                                                  struct wmMsgBus *mbus)
1041 {
1042   /* Developer note: there are many properties that impact 3D view drawing,
1043    * so instead of subscribing to individual properties, just subscribe to types
1044    * accepting some redundant redraws.
1045    *
1046    * For other space types we might try avoid this, keep the 3D view as an exceptional case! */
1047   wmMsgParams_RNA msg_key_params = {{0}};
1048 
1049   /* Only subscribe to types. */
1050   StructRNA *type_array[] = {
1051       &RNA_Window,
1052 
1053       /* These object have properties that impact drawing. */
1054       &RNA_AreaLight,
1055       &RNA_Camera,
1056       &RNA_Light,
1057       &RNA_Speaker,
1058       &RNA_SunLight,
1059 
1060       /* General types the 3D view depends on. */
1061       &RNA_Object,
1062       &RNA_UnitSettings, /* grid-floor */
1063 
1064       &RNA_View3DOverlay,
1065       &RNA_View3DShading,
1066       &RNA_World,
1067   };
1068 
1069   wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
1070       .owner = region,
1071       .user_data = region,
1072       .notify = ED_region_do_msg_notify_tag_redraw,
1073   };
1074 
1075   for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
1076     msg_key_params.ptr.type = type_array[i];
1077     WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
1078   }
1079 
1080   /* Subscribe to a handful of other properties. */
1081   RegionView3D *rv3d = region->regiondata;
1082 
1083   WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw);
1084   WM_msg_subscribe_rna_anon_prop(
1085       mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw);
1086   WM_msg_subscribe_rna_anon_prop(
1087       mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw);
1088   WM_msg_subscribe_rna_anon_prop(
1089       mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw);
1090   WM_msg_subscribe_rna_anon_prop(
1091       mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw);
1092   if (rv3d->persp == RV3D_CAMOB) {
1093     WM_msg_subscribe_rna_anon_prop(
1094         mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
1095   }
1096 
1097   WM_msg_subscribe_rna_anon_type(mbus, SceneEEVEE, &msg_sub_value_region_tag_redraw);
1098   WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw);
1099   WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw);
1100 
1101   ViewLayer *view_layer = CTX_data_view_layer(C);
1102   Object *obact = OBACT(view_layer);
1103   if (obact != NULL) {
1104     switch (obact->mode) {
1105       case OB_MODE_PARTICLE_EDIT:
1106         WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw);
1107         break;
1108       default:
1109         break;
1110     }
1111   }
1112 
1113   {
1114     wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
1115         .owner = region,
1116         .user_data = area,
1117         .notify = WM_toolsystem_do_msg_notify_tag_refresh,
1118     };
1119     WM_msg_subscribe_rna_anon_prop(mbus, Object, mode, &msg_sub_value_region_tag_refresh);
1120     WM_msg_subscribe_rna_anon_prop(mbus, LayerObjects, active, &msg_sub_value_region_tag_refresh);
1121   }
1122 }
1123 
1124 /* concept is to retrieve cursor type context-less */
view3d_main_region_cursor(wmWindow * win,ScrArea * area,ARegion * region)1125 static void view3d_main_region_cursor(wmWindow *win, ScrArea *area, ARegion *region)
1126 {
1127   if (WM_cursor_set_from_tool(win, area, region)) {
1128     return;
1129   }
1130 
1131   ViewLayer *view_layer = WM_window_get_active_view_layer(win);
1132   Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
1133   if (obedit) {
1134     WM_cursor_set(win, WM_CURSOR_EDIT);
1135   }
1136   else {
1137     WM_cursor_set(win, WM_CURSOR_DEFAULT);
1138   }
1139 }
1140 
1141 /* add handlers, stuff you only do once or on area/region changes */
view3d_header_region_init(wmWindowManager * wm,ARegion * region)1142 static void view3d_header_region_init(wmWindowManager *wm, ARegion *region)
1143 {
1144   wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
1145 
1146   WM_event_add_keymap_handler(&region->handlers, keymap);
1147 
1148   ED_region_header_init(region);
1149 }
1150 
view3d_header_region_draw(const bContext * C,ARegion * region)1151 static void view3d_header_region_draw(const bContext *C, ARegion *region)
1152 {
1153   ED_region_header(C, region);
1154 }
1155 
view3d_header_region_listener(wmWindow * UNUSED (win),ScrArea * UNUSED (area),ARegion * region,wmNotifier * wmn,const Scene * UNUSED (scene))1156 static void view3d_header_region_listener(wmWindow *UNUSED(win),
1157                                           ScrArea *UNUSED(area),
1158                                           ARegion *region,
1159                                           wmNotifier *wmn,
1160                                           const Scene *UNUSED(scene))
1161 {
1162   /* context changes */
1163   switch (wmn->category) {
1164     case NC_SCENE:
1165       switch (wmn->data) {
1166         case ND_FRAME:
1167         case ND_OB_ACTIVE:
1168         case ND_OB_SELECT:
1169         case ND_OB_VISIBLE:
1170         case ND_MODE:
1171         case ND_LAYER:
1172         case ND_TOOLSETTINGS:
1173         case ND_LAYER_CONTENT:
1174         case ND_RENDER_OPTIONS:
1175           ED_region_tag_redraw(region);
1176           break;
1177       }
1178       break;
1179     case NC_SPACE:
1180       if (wmn->data == ND_SPACE_VIEW3D) {
1181         ED_region_tag_redraw(region);
1182       }
1183       break;
1184     case NC_GPENCIL:
1185       if (wmn->data & ND_GPENCIL_EDITMODE) {
1186         ED_region_tag_redraw(region);
1187       }
1188       else if (wmn->action == NA_EDITED) {
1189         ED_region_tag_redraw(region);
1190       }
1191       break;
1192     case NC_BRUSH:
1193       ED_region_tag_redraw(region);
1194       break;
1195   }
1196 
1197     /* From topbar, which ones are needed? split per header? */
1198     /* Disable for now, re-enable if needed, or remove - campbell. */
1199 #if 0
1200   /* context changes */
1201   switch (wmn->category) {
1202     case NC_WM:
1203       if (wmn->data == ND_HISTORY) {
1204         ED_region_tag_redraw(region);
1205       }
1206       break;
1207     case NC_SCENE:
1208       if (wmn->data == ND_MODE) {
1209         ED_region_tag_redraw(region);
1210       }
1211       break;
1212     case NC_SPACE:
1213       if (wmn->data == ND_SPACE_VIEW3D) {
1214         ED_region_tag_redraw(region);
1215       }
1216       break;
1217     case NC_GPENCIL:
1218       if (wmn->data == ND_DATA) {
1219         ED_region_tag_redraw(region);
1220       }
1221       break;
1222   }
1223 #endif
1224 }
1225 
view3d_header_region_message_subscribe(const struct bContext * UNUSED (C),struct WorkSpace * UNUSED (workspace),struct Scene * UNUSED (scene),struct bScreen * UNUSED (screen),struct ScrArea * UNUSED (area),struct ARegion * region,struct wmMsgBus * mbus)1226 static void view3d_header_region_message_subscribe(const struct bContext *UNUSED(C),
1227                                                    struct WorkSpace *UNUSED(workspace),
1228                                                    struct Scene *UNUSED(scene),
1229                                                    struct bScreen *UNUSED(screen),
1230                                                    struct ScrArea *UNUSED(area),
1231                                                    struct ARegion *region,
1232                                                    struct wmMsgBus *mbus)
1233 {
1234   wmMsgParams_RNA msg_key_params = {{0}};
1235 
1236   /* Only subscribe to types. */
1237   StructRNA *type_array[] = {
1238       &RNA_View3DShading,
1239   };
1240 
1241   wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
1242       .owner = region,
1243       .user_data = region,
1244       .notify = ED_region_do_msg_notify_tag_redraw,
1245   };
1246 
1247   for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
1248     msg_key_params.ptr.type = type_array[i];
1249     WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
1250   }
1251 }
1252 
1253 /* add handlers, stuff you only do once or on area/region changes */
view3d_buttons_region_init(wmWindowManager * wm,ARegion * region)1254 static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *region)
1255 {
1256   wmKeyMap *keymap;
1257 
1258   ED_region_panels_init(wm, region);
1259 
1260   keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
1261   WM_event_add_keymap_handler(&region->handlers, keymap);
1262 }
1263 
ED_view3d_buttons_region_layout_ex(const bContext * C,ARegion * region,const char * category_override)1264 void ED_view3d_buttons_region_layout_ex(const bContext *C,
1265                                         ARegion *region,
1266                                         const char *category_override)
1267 {
1268   const enum eContextObjectMode mode = CTX_data_mode_enum(C);
1269 
1270   const char *contexts_base[4] = {NULL};
1271   contexts_base[0] = CTX_data_mode_string(C);
1272 
1273   const char **contexts = &contexts_base[1];
1274 
1275   switch (mode) {
1276     case CTX_MODE_EDIT_MESH:
1277       ARRAY_SET_ITEMS(contexts, ".mesh_edit");
1278       break;
1279     case CTX_MODE_EDIT_CURVE:
1280       ARRAY_SET_ITEMS(contexts, ".curve_edit");
1281       break;
1282     case CTX_MODE_EDIT_SURFACE:
1283       ARRAY_SET_ITEMS(contexts, ".curve_edit");
1284       break;
1285     case CTX_MODE_EDIT_TEXT:
1286       ARRAY_SET_ITEMS(contexts, ".text_edit");
1287       break;
1288     case CTX_MODE_EDIT_ARMATURE:
1289       ARRAY_SET_ITEMS(contexts, ".armature_edit");
1290       break;
1291     case CTX_MODE_EDIT_METABALL:
1292       ARRAY_SET_ITEMS(contexts, ".mball_edit");
1293       break;
1294     case CTX_MODE_EDIT_LATTICE:
1295       ARRAY_SET_ITEMS(contexts, ".lattice_edit");
1296       break;
1297     case CTX_MODE_POSE:
1298       ARRAY_SET_ITEMS(contexts, ".posemode");
1299       break;
1300     case CTX_MODE_SCULPT:
1301       ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
1302       break;
1303     case CTX_MODE_PAINT_WEIGHT:
1304       ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
1305       break;
1306     case CTX_MODE_PAINT_VERTEX:
1307       ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint");
1308       break;
1309     case CTX_MODE_PAINT_TEXTURE:
1310       ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
1311       break;
1312     case CTX_MODE_PARTICLE:
1313       ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode");
1314       break;
1315     case CTX_MODE_OBJECT:
1316       ARRAY_SET_ITEMS(contexts, ".objectmode");
1317       break;
1318     case CTX_MODE_PAINT_GPENCIL:
1319       ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
1320       break;
1321     case CTX_MODE_SCULPT_GPENCIL:
1322       ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
1323       break;
1324     case CTX_MODE_WEIGHT_GPENCIL:
1325       ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
1326       break;
1327     case CTX_MODE_VERTEX_GPENCIL:
1328       ARRAY_SET_ITEMS(contexts, ".greasepencil_vertex");
1329       break;
1330     default:
1331       break;
1332   }
1333 
1334   switch (mode) {
1335     case CTX_MODE_PAINT_GPENCIL:
1336       ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
1337       break;
1338     case CTX_MODE_SCULPT_GPENCIL:
1339       ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
1340       break;
1341     case CTX_MODE_WEIGHT_GPENCIL:
1342       ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
1343       break;
1344     case CTX_MODE_EDIT_GPENCIL:
1345       ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
1346       break;
1347     case CTX_MODE_VERTEX_GPENCIL:
1348       ARRAY_SET_ITEMS(contexts, ".greasepencil_vertex");
1349       break;
1350     default:
1351       break;
1352   }
1353 
1354   ListBase *paneltypes = &region->type->paneltypes;
1355 
1356   /* Allow drawing 3D view toolbar from non 3D view space type. */
1357   if (category_override != NULL) {
1358     SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D);
1359     ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_UI);
1360     paneltypes = &art->paneltypes;
1361   }
1362 
1363   ED_region_panels_layout_ex(C, region, paneltypes, contexts_base, category_override);
1364 }
1365 
view3d_buttons_region_layout(const bContext * C,ARegion * region)1366 static void view3d_buttons_region_layout(const bContext *C, ARegion *region)
1367 {
1368   ED_view3d_buttons_region_layout_ex(C, region, NULL);
1369 }
1370 
view3d_buttons_region_listener(wmWindow * UNUSED (win),ScrArea * UNUSED (area),ARegion * region,wmNotifier * wmn,const Scene * UNUSED (scene))1371 static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
1372                                            ScrArea *UNUSED(area),
1373                                            ARegion *region,
1374                                            wmNotifier *wmn,
1375                                            const Scene *UNUSED(scene))
1376 {
1377   /* context changes */
1378   switch (wmn->category) {
1379     case NC_ANIMATION:
1380       switch (wmn->data) {
1381         case ND_KEYFRAME_PROP:
1382         case ND_NLA_ACTCHANGE:
1383           ED_region_tag_redraw(region);
1384           break;
1385         case ND_NLA:
1386         case ND_KEYFRAME:
1387           if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
1388             ED_region_tag_redraw(region);
1389           }
1390           break;
1391       }
1392       break;
1393     case NC_SCENE:
1394       switch (wmn->data) {
1395         case ND_FRAME:
1396         case ND_OB_ACTIVE:
1397         case ND_OB_SELECT:
1398         case ND_OB_VISIBLE:
1399         case ND_MODE:
1400         case ND_LAYER:
1401         case ND_LAYER_CONTENT:
1402         case ND_TOOLSETTINGS:
1403           ED_region_tag_redraw(region);
1404           break;
1405       }
1406       switch (wmn->action) {
1407         case NA_EDITED:
1408           ED_region_tag_redraw(region);
1409           break;
1410       }
1411       break;
1412     case NC_OBJECT:
1413       switch (wmn->data) {
1414         case ND_BONE_ACTIVE:
1415         case ND_BONE_SELECT:
1416         case ND_TRANSFORM:
1417         case ND_POSE:
1418         case ND_DRAW:
1419         case ND_KEYS:
1420         case ND_MODIFIER:
1421         case ND_SHADERFX:
1422           ED_region_tag_redraw(region);
1423           break;
1424       }
1425       break;
1426     case NC_GEOM:
1427       switch (wmn->data) {
1428         case ND_DATA:
1429         case ND_VERTEX_GROUP:
1430         case ND_SELECT:
1431           ED_region_tag_redraw(region);
1432           break;
1433       }
1434       if (wmn->action == NA_EDITED) {
1435         ED_region_tag_redraw(region);
1436       }
1437       break;
1438     case NC_TEXTURE:
1439     case NC_MATERIAL:
1440       /* for brush textures */
1441       ED_region_tag_redraw(region);
1442       break;
1443     case NC_BRUSH:
1444       /* NA_SELECTED is used on brush changes */
1445       if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
1446         ED_region_tag_redraw(region);
1447       }
1448       break;
1449     case NC_SPACE:
1450       if (wmn->data == ND_SPACE_VIEW3D) {
1451         ED_region_tag_redraw(region);
1452       }
1453       break;
1454     case NC_ID:
1455       if (wmn->action == NA_RENAME) {
1456         ED_region_tag_redraw(region);
1457       }
1458       break;
1459     case NC_GPENCIL:
1460       if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED)) {
1461         ED_region_tag_redraw(region);
1462       }
1463       break;
1464     case NC_IMAGE:
1465       /* Update for the image layers in texture paint. */
1466       if (wmn->action == NA_EDITED) {
1467         ED_region_tag_redraw(region);
1468       }
1469       break;
1470     case NC_WM:
1471       if (wmn->data == ND_XR_DATA_CHANGED) {
1472         ED_region_tag_redraw(region);
1473       }
1474       break;
1475   }
1476 }
1477 
1478 /* add handlers, stuff you only do once or on area/region changes */
view3d_tools_region_init(wmWindowManager * wm,ARegion * region)1479 static void view3d_tools_region_init(wmWindowManager *wm, ARegion *region)
1480 {
1481   wmKeyMap *keymap;
1482 
1483   ED_region_panels_init(wm, region);
1484 
1485   keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
1486   WM_event_add_keymap_handler(&region->handlers, keymap);
1487 }
1488 
view3d_tools_region_draw(const bContext * C,ARegion * region)1489 static void view3d_tools_region_draw(const bContext *C, ARegion *region)
1490 {
1491   ED_region_panels_ex(C, region, (const char *[]){CTX_data_mode_string(C), NULL});
1492 }
1493 
1494 /* area (not region) level listener */
space_view3d_listener(wmWindow * UNUSED (win),ScrArea * area,struct wmNotifier * wmn,Scene * UNUSED (scene))1495 static void space_view3d_listener(wmWindow *UNUSED(win),
1496                                   ScrArea *area,
1497                                   struct wmNotifier *wmn,
1498                                   Scene *UNUSED(scene))
1499 {
1500   View3D *v3d = area->spacedata.first;
1501 
1502   /* context changes */
1503   switch (wmn->category) {
1504     case NC_SCENE:
1505       switch (wmn->data) {
1506         case ND_WORLD:
1507           if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
1508             ED_area_tag_redraw_regiontype(area, RGN_TYPE_WINDOW);
1509           }
1510           break;
1511       }
1512       break;
1513     case NC_WORLD:
1514       switch (wmn->data) {
1515         case ND_WORLD_DRAW:
1516         case ND_WORLD:
1517           if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) {
1518             ED_area_tag_redraw_regiontype(area, RGN_TYPE_WINDOW);
1519           }
1520           break;
1521       }
1522       break;
1523     case NC_MATERIAL:
1524       switch (wmn->data) {
1525         case ND_NODES:
1526           if (v3d->shading.type == OB_TEXTURE) {
1527             ED_area_tag_redraw_regiontype(area, RGN_TYPE_WINDOW);
1528           }
1529           break;
1530       }
1531       break;
1532   }
1533 }
1534 
space_view3d_refresh(const bContext * C,ScrArea * UNUSED (area))1535 static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(area))
1536 {
1537   Scene *scene = CTX_data_scene(C);
1538   LightCache *lcache = scene->eevee.light_cache_data;
1539 
1540   if (lcache && (lcache->flag & LIGHTCACHE_UPDATE_AUTO) != 0) {
1541     lcache->flag &= ~LIGHTCACHE_UPDATE_AUTO;
1542     view3d_lightcache_update((bContext *)C);
1543   }
1544 }
1545 
1546 const char *view3d_context_dir[] = {
1547     "active_base",
1548     "active_object",
1549     NULL,
1550 };
1551 
view3d_context(const bContext * C,const char * member,bContextDataResult * result)1552 static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
1553 {
1554   /* fallback to the scene layer,
1555    * allows duplicate and other object operators to run outside the 3d view */
1556 
1557   if (CTX_data_dir(member)) {
1558     CTX_data_dir_set(result, view3d_context_dir);
1559   }
1560   else if (CTX_data_equals(member, "active_base")) {
1561     Scene *scene = CTX_data_scene(C);
1562     ViewLayer *view_layer = CTX_data_view_layer(C);
1563     if (view_layer->basact) {
1564       Object *ob = view_layer->basact->object;
1565       /* if hidden but in edit mode, we still display, can happen with animation */
1566       if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 || (ob->mode & OB_MODE_EDIT)) {
1567         CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
1568       }
1569     }
1570 
1571     return 1;
1572   }
1573   else if (CTX_data_equals(member, "active_object")) {
1574     ViewLayer *view_layer = CTX_data_view_layer(C);
1575     if (view_layer->basact) {
1576       Object *ob = view_layer->basact->object;
1577       /* if hidden but in edit mode, we still display, can happen with animation */
1578       if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 ||
1579           (ob->mode & OB_MODE_EDIT) != 0) {
1580         CTX_data_id_pointer_set(result, &ob->id);
1581       }
1582     }
1583 
1584     return 1;
1585   }
1586   else {
1587     return 0; /* not found */
1588   }
1589 
1590   return -1; /* found but not available */
1591 }
1592 
view3d_id_remap(ScrArea * area,SpaceLink * slink,ID * old_id,ID * new_id)1593 static void view3d_id_remap(ScrArea *area, SpaceLink *slink, ID *old_id, ID *new_id)
1594 {
1595   View3D *v3d;
1596   ARegion *region;
1597   bool is_local = false;
1598 
1599   if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) {
1600     return;
1601   }
1602 
1603   for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) {
1604     if ((ID *)v3d->camera == old_id) {
1605       v3d->camera = (Object *)new_id;
1606       if (!new_id) {
1607         /* 3D view might be inactive, in that case needs to use slink->regionbase */
1608         ListBase *regionbase = (slink == area->spacedata.first) ? &area->regionbase :
1609                                                                   &slink->regionbase;
1610         for (region = regionbase->first; region; region = region->next) {
1611           if (region->regiontype == RGN_TYPE_WINDOW) {
1612             RegionView3D *rv3d = is_local ? ((RegionView3D *)region->regiondata)->localvd :
1613                                             region->regiondata;
1614             if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
1615               rv3d->persp = RV3D_PERSP;
1616             }
1617           }
1618         }
1619       }
1620     }
1621 
1622     /* Values in local-view aren't used, see: T52663 */
1623     if (is_local == false) {
1624       if ((ID *)v3d->ob_center == old_id) {
1625         v3d->ob_center = (Object *)new_id;
1626         /* Otherwise, bonename may remain valid...
1627          * We could be smart and check this, too? */
1628         if (new_id == NULL) {
1629           v3d->ob_center_bone[0] = '\0';
1630         }
1631       }
1632     }
1633 
1634     if (is_local) {
1635       break;
1636     }
1637   }
1638 }
1639 
1640 /* only called once, from space/spacetypes.c */
ED_spacetype_view3d(void)1641 void ED_spacetype_view3d(void)
1642 {
1643   SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype view3d");
1644   ARegionType *art;
1645 
1646   st->spaceid = SPACE_VIEW3D;
1647   strncpy(st->name, "View3D", BKE_ST_MAXNAME);
1648 
1649   st->create = view3d_create;
1650   st->free = view3d_free;
1651   st->init = view3d_init;
1652   st->listener = space_view3d_listener;
1653   st->refresh = space_view3d_refresh;
1654   st->duplicate = view3d_duplicate;
1655   st->operatortypes = view3d_operatortypes;
1656   st->keymap = view3d_keymap;
1657   st->dropboxes = view3d_dropboxes;
1658   st->gizmos = view3d_widgets;
1659   st->context = view3d_context;
1660   st->id_remap = view3d_id_remap;
1661 
1662   /* regions: main window */
1663   art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
1664   art->regionid = RGN_TYPE_WINDOW;
1665   art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_GPENCIL;
1666   art->draw = view3d_main_region_draw;
1667   art->init = view3d_main_region_init;
1668   art->exit = view3d_main_region_exit;
1669   art->free = view3d_main_region_free;
1670   art->duplicate = view3d_main_region_duplicate;
1671   art->listener = view3d_main_region_listener;
1672   art->message_subscribe = view3d_main_region_message_subscribe;
1673   art->cursor = view3d_main_region_cursor;
1674   art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
1675   BLI_addhead(&st->regiontypes, art);
1676 
1677   /* regions: listview/buttons */
1678   art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
1679   art->regionid = RGN_TYPE_UI;
1680   art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
1681   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1682   art->listener = view3d_buttons_region_listener;
1683   art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
1684   art->init = view3d_buttons_region_init;
1685   art->layout = view3d_buttons_region_layout;
1686   art->draw = ED_region_panels_draw;
1687   BLI_addhead(&st->regiontypes, art);
1688 
1689   view3d_buttons_register(art);
1690 
1691   /* regions: tool(bar) */
1692   art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
1693   art->regionid = RGN_TYPE_TOOLS;
1694   art->prefsizex = 58; /* XXX */
1695   art->prefsizey = 50; /* XXX */
1696   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1697   art->listener = view3d_buttons_region_listener;
1698   art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
1699   art->snap_size = ED_region_generic_tools_region_snap_size;
1700   art->init = view3d_tools_region_init;
1701   art->draw = view3d_tools_region_draw;
1702   BLI_addhead(&st->regiontypes, art);
1703 
1704   /* regions: tool header */
1705   art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tool header region");
1706   art->regionid = RGN_TYPE_TOOL_HEADER;
1707   art->prefsizey = HEADERY;
1708   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
1709   art->listener = view3d_header_region_listener;
1710   art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header;
1711   art->init = view3d_header_region_init;
1712   art->draw = view3d_header_region_draw;
1713   BLI_addhead(&st->regiontypes, art);
1714 
1715   /* regions: header */
1716   art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
1717   art->regionid = RGN_TYPE_HEADER;
1718   art->prefsizey = HEADERY;
1719   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
1720   art->listener = view3d_header_region_listener;
1721   art->message_subscribe = view3d_header_region_message_subscribe;
1722   art->init = view3d_header_region_init;
1723   art->draw = view3d_header_region_draw;
1724   BLI_addhead(&st->regiontypes, art);
1725 
1726   /* regions: hud */
1727   art = ED_area_type_hud(st->spaceid);
1728   BLI_addhead(&st->regiontypes, art);
1729 
1730   BKE_spacetype_register(st);
1731 }
1732