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(®ion->handlers, keymap);
391
392 keymap = WM_keymap_ensure(wm->defaultconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0);
393 WM_event_add_keymap_handler(®ion->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(®ion->handlers, keymap);
398
399 keymap = WM_keymap_ensure(wm->defaultconf, "Vertex Paint", 0, 0);
400 WM_event_add_keymap_handler(®ion->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(®ion->handlers, keymap);
405
406 keymap = WM_keymap_ensure(wm->defaultconf, "Object Mode", 0, 0);
407 WM_event_add_keymap_handler(®ion->handlers, keymap);
408
409 keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0);
410 WM_event_add_keymap_handler(®ion->handlers, keymap);
411
412 keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
413 WM_event_add_keymap_handler(®ion->handlers, keymap);
414
415 keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0);
416 WM_event_add_keymap_handler(®ion->handlers, keymap);
417
418 keymap = WM_keymap_ensure(wm->defaultconf, "Sculpt", 0, 0);
419 WM_event_add_keymap_handler(®ion->handlers, keymap);
420
421 keymap = WM_keymap_ensure(wm->defaultconf, "Mesh", 0, 0);
422 WM_event_add_keymap_handler(®ion->handlers, keymap);
423
424 keymap = WM_keymap_ensure(wm->defaultconf, "Armature", 0, 0);
425 WM_event_add_keymap_handler(®ion->handlers, keymap);
426
427 keymap = WM_keymap_ensure(wm->defaultconf, "Metaball", 0, 0);
428 WM_event_add_keymap_handler(®ion->handlers, keymap);
429
430 keymap = WM_keymap_ensure(wm->defaultconf, "Lattice", 0, 0);
431 WM_event_add_keymap_handler(®ion->handlers, keymap);
432
433 keymap = WM_keymap_ensure(wm->defaultconf, "Particle", 0, 0);
434 WM_event_add_keymap_handler(®ion->handlers, keymap);
435
436 /* editfont keymap swallows all... */
437 keymap = WM_keymap_ensure(wm->defaultconf, "Font", 0, 0);
438 WM_event_add_keymap_handler(®ion->handlers, keymap);
439
440 keymap = WM_keymap_ensure(wm->defaultconf, "Object Non-modal", 0, 0);
441 WM_event_add_keymap_handler(®ion->handlers, keymap);
442
443 keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0);
444 WM_event_add_keymap_handler(®ion->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(®ion->handlers, keymap);
449
450 keymap = WM_keymap_ensure(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
451 WM_event_add_keymap_handler(®ion->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(®ion->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(®ion->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(®ion->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 = ®ion->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(®ion->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