Blender V4.3
view3d_view.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11#include "BLI_linklist.h"
12#include "BLI_listbase.h"
13#include "BLI_math_matrix.h"
14#include "BLI_math_rotation.h"
15#include "BLI_math_vector.h"
16#include "BLI_rect.h"
17
18#include "BKE_action.hh"
19#include "BKE_context.hh"
20#include "BKE_global.hh"
21#include "BKE_idprop.hh"
22#include "BKE_layer.hh"
23#include "BKE_lib_id.hh"
24#include "BKE_main.hh"
25#include "BKE_modifier.hh"
26#include "BKE_object.hh"
27#include "BKE_report.hh"
28#include "BKE_scene.hh"
29
31
32#include "UI_resources.hh"
33
34#include "GPU_matrix.hh"
35#include "GPU_platform.hh"
36#include "GPU_select.hh"
37#include "GPU_state.hh"
38
39#include "WM_api.hh"
40
41#include "ED_object.hh"
42#include "ED_screen.hh"
43
44#include "DRW_engine.hh"
45
46#include "RNA_access.hh"
47#include "RNA_define.hh"
48
49#include "view3d_intern.hh" /* own include */
50#include "view3d_navigate.hh"
51
52/* -------------------------------------------------------------------- */
55
57{
59 View3D *v3d;
60 ARegion *region;
61 RegionView3D *rv3d;
62
64
65 ED_view3d_context_user_region(C, &v3d, &region);
66 rv3d = static_cast<RegionView3D *>(region->regiondata);
67
69
71
72 ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
73
75
77 rv3d->persp = RV3D_CAMOB;
78
80
81 return OPERATOR_FINISHED;
82}
83
85{
86 View3D *v3d;
87 ARegion *region;
88
89 if (ED_view3d_context_user_region(C, &v3d, &region)) {
90 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
91 if (v3d && v3d->camera && BKE_id_is_editable(CTX_data_main(C), &v3d->camera->id)) {
92 if (rv3d && (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
93 if (rv3d->persp != RV3D_CAMOB) {
94 return true;
95 }
96 }
97 }
98 }
99
100 return false;
101}
102
104{
105 /* identifiers */
106 ot->name = "Align Camera to View";
107 ot->description = "Set camera view to active view";
108 ot->idname = "VIEW3D_OT_camera_to_view";
109
110 /* api callbacks */
113
114 /* flags */
116}
117
119
120/* -------------------------------------------------------------------- */
123
124/* unlike VIEW3D_OT_view_selected this is for framing a render and not
125 * meant to take into account vertex/bone selection for eg. */
127{
128 Main *bmain = CTX_data_main(C);
130 Scene *scene = CTX_data_scene(C);
131 View3D *v3d = CTX_wm_view3d(C); /* can be nullptr */
132 Object *camera_ob = v3d ? v3d->camera : scene->camera;
133
134 if (camera_ob == nullptr) {
135 BKE_report(op->reports, RPT_ERROR, "No active camera");
136 return OPERATOR_CANCELLED;
137 }
138
139 if (ED_view3d_camera_to_view_selected(bmain, depsgraph, scene, camera_ob)) {
141 return OPERATOR_FINISHED;
142 }
143 return OPERATOR_CANCELLED;
144}
145
147{
148 /* identifiers */
149 ot->name = "Camera Fit Frame to Selected";
150 ot->description = "Move the camera so selected objects are framed";
151 ot->idname = "VIEW3D_OT_camera_to_view_selected";
152
153 /* api callbacks */
156
157 /* flags */
159}
160
162
163/* -------------------------------------------------------------------- */
166
168 View3D *v3d,
169 Object *ob,
170 const int smooth_viewtx)
171{
172 Main *bmain = CTX_data_main(C);
173 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
174 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
175 LISTBASE_FOREACH (SpaceLink *, space_link, &area->spacedata) {
176 if (space_link->spacetype == SPACE_VIEW3D) {
177 View3D *other_v3d = reinterpret_cast<View3D *>(space_link);
178 if (other_v3d == v3d) {
179 continue;
180 }
181 if (other_v3d->camera == ob) {
182 continue;
183 }
184 /* Checking the other view is needed to prevent local cameras being modified. */
185 if (v3d->scenelock && other_v3d->scenelock) {
186 ListBase *lb = (space_link == area->spacedata.first) ? &area->regionbase :
187 &space_link->regionbase;
188 LISTBASE_FOREACH (ARegion *, other_region, lb) {
189 if (other_region->regiontype == RGN_TYPE_WINDOW) {
190 if (other_region->regiondata) {
191 RegionView3D *other_rv3d = static_cast<RegionView3D *>(other_region->regiondata);
192 if (other_rv3d->persp == RV3D_CAMOB) {
193 Object *other_camera_old = other_v3d->camera;
194 other_v3d->camera = ob;
195
196 V3D_SmoothParams sview_params = {};
197 sview_params.camera_old = other_camera_old;
198 sview_params.camera = other_v3d->camera;
199 sview_params.ofs = other_rv3d->ofs;
200 sview_params.quat = other_rv3d->viewquat;
201 sview_params.dist = &other_rv3d->dist;
202 sview_params.lens = &other_v3d->lens;
203 /* No undo because this switches cameras. */
204 sview_params.undo_str = nullptr;
205
206 ED_view3d_lastview_store(other_rv3d);
208 C, other_v3d, other_region, smooth_viewtx, &sview_params);
209 }
210 else {
211 other_v3d->camera = ob;
212 }
213 }
214 }
215 }
216 }
217 }
218 }
219 }
220 }
221}
222
224{
225 View3D *v3d;
226 ARegion *region;
227 RegionView3D *rv3d;
228
229 Scene *scene = CTX_data_scene(C);
231
232 const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
233
234 /* no nullptr check is needed, poll checks */
235 ED_view3d_context_user_region(C, &v3d, &region);
236 rv3d = static_cast<RegionView3D *>(region->regiondata);
237
238 if (ob) {
239 Object *camera_old = (rv3d->persp == RV3D_CAMOB) ? V3D_CAMERA_SCENE(scene, v3d) : nullptr;
240 rv3d->persp = RV3D_CAMOB;
241 v3d->camera = ob;
242 if (v3d->scenelock && scene->camera != ob) {
243 scene->camera = ob;
246 }
247
248 /* unlikely but looks like a glitch when set to the same */
249 if (camera_old != ob) {
250 V3D_SmoothParams sview_params = {};
251 sview_params.camera_old = camera_old;
252 sview_params.camera = v3d->camera;
253 sview_params.ofs = rv3d->ofs;
254 sview_params.quat = rv3d->viewquat;
255 sview_params.dist = &rv3d->dist;
256 sview_params.lens = &v3d->lens;
257 /* No undo because this switches cameras. */
258 sview_params.undo_str = nullptr;
259
261 ED_view3d_smooth_view(C, v3d, region, smooth_viewtx, &sview_params);
262 }
263
264 if (v3d->scenelock) {
265 sync_viewport_camera_smoothview(C, v3d, ob, smooth_viewtx);
267 }
269 }
270
271 return OPERATOR_FINISHED;
272}
273
275{
276 View3D *v3d_dummy;
277 ARegion *region_dummy;
278
279 return ED_view3d_context_user_region(C, &v3d_dummy, &region_dummy);
280}
281
283{
284 /* identifiers */
285 ot->name = "Set Active Object as Camera";
286 ot->description = "Set the active object as the active camera for this view or scene";
287 ot->idname = "VIEW3D_OT_object_as_camera";
288
289 /* api callbacks */
292
293 /* flags */
295}
296
298
299/* -------------------------------------------------------------------- */
302
303void view3d_winmatrix_set(const Depsgraph *depsgraph,
304 ARegion *region,
305 const View3D *v3d,
306 const rcti *rect)
307{
308 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
309 rctf full_viewplane;
310 float clipsta, clipend;
311 bool is_ortho;
312
314 v3d,
315 rv3d,
316 region->winx,
317 region->winy,
318 &full_viewplane,
319 &clipsta,
320 &clipend,
321 nullptr);
322 rv3d->is_persp = !is_ortho;
323
324#if 0
325 printf("%s: %d %d %f %f %f %f %f %f\n",
326 __func__,
327 winx,
328 winy,
329 full_viewplane.xmin,
330 full_viewplane.ymin,
331 full_viewplane.xmax,
332 full_viewplane.ymax,
333 clipsta,
334 clipend);
335#endif
336
337 /* Note the code here was tweaked to avoid an apparent compiler bug in clang 13 (see #91680). */
338 rctf viewplane;
339 if (rect) {
340 /* Smaller viewplane subset for selection picking. */
341 viewplane.xmin = full_viewplane.xmin +
342 (BLI_rctf_size_x(&full_viewplane) * (rect->xmin / float(region->winx)));
343 viewplane.ymin = full_viewplane.ymin +
344 (BLI_rctf_size_y(&full_viewplane) * (rect->ymin / float(region->winy)));
345 viewplane.xmax = full_viewplane.xmin +
346 (BLI_rctf_size_x(&full_viewplane) * (rect->xmax / float(region->winx)));
347 viewplane.ymax = full_viewplane.ymin +
348 (BLI_rctf_size_y(&full_viewplane) * (rect->ymax / float(region->winy)));
349 }
350 else {
351 viewplane = full_viewplane;
352 }
353
354 if (is_ortho) {
356 viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
357 }
358 else {
360 viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
361 }
362
363 /* update matrix in 3d view region */
365}
366
367static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
368{
369 float bmat[4][4];
370
371 rv3d->view = RV3D_VIEW_USER; /* don't show the grid */
372
373 normalize_m4_m4(bmat, ob->object_to_world().ptr());
374 invert_m4_m4(rv3d->viewmat, bmat);
375
376 /* view quat calculation, needed for add object */
378}
379
380void view3d_viewmatrix_set(const Depsgraph *depsgraph,
381 const Scene *scene,
382 const View3D *v3d,
383 RegionView3D *rv3d,
384 const float rect_scale[2])
385{
386 if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */
387 if (v3d->camera) {
388 Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
389 obmat_to_viewmat(rv3d, ob_camera_eval);
390 }
391 else {
392 quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
393 rv3d->viewmat[3][2] -= rv3d->dist;
394 }
395 }
396 else {
397 bool use_lock_ofs = false;
398
399 /* should be moved to better initialize later on XXX */
401 ED_view3d_lock(rv3d);
402 }
403
404 quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
405 if (rv3d->persp == RV3D_PERSP) {
406 rv3d->viewmat[3][2] -= rv3d->dist;
407 }
408 if (v3d->ob_center) {
410 float vec[3];
411
412 copy_v3_v3(vec, ob_eval->object_to_world().location());
413 if (ob_eval->type == OB_ARMATURE && v3d->ob_center_bone[0]) {
415 if (pchan) {
416 copy_v3_v3(vec, pchan->pose_mat[3]);
417 mul_m4_v3(ob_eval->object_to_world().ptr(), vec);
418 }
419 }
420 translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
421 use_lock_ofs = true;
422 }
423 else if (v3d->ob_center_cursor) {
424 float vec[3];
425 copy_v3_v3(vec, scene->cursor.location);
426 translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
427 use_lock_ofs = true;
428 }
429 else {
430 translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]);
431 }
432
433 /* lock offset */
434 if (use_lock_ofs) {
435 float persmat[4][4], persinv[4][4];
436 float vec[3];
437
438 /* we could calculate the real persmat/persinv here
439 * but it would be unreliable so better to later */
440 mul_m4_m4m4(persmat, rv3d->winmat, rv3d->viewmat);
441 invert_m4_m4(persinv, persmat);
442
443 mul_v2_v2fl(vec, rv3d->ofs_lock, rv3d->is_persp ? rv3d->dist : 1.0f);
444 vec[2] = 0.0f;
445
446 if (rect_scale) {
447 /* Since 'RegionView3D.winmat' has been calculated and this function doesn't take the
448 * 'ARegion' we don't know about the region size.
449 * Use 'rect_scale' when drawing a sub-region to apply 2D offset,
450 * scaled by the difference between the sub-region and the region size.
451 */
452 vec[0] /= rect_scale[0];
453 vec[1] /= rect_scale[1];
454 }
455
456 mul_mat3_m4_v3(persinv, vec);
457 translate_m4(rv3d->viewmat, vec[0], vec[1], vec[2]);
458 }
459 /* end lock offset */
460 }
461}
462
464
465/* -------------------------------------------------------------------- */
468
473
478
486
487static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
488{
489 bool continue_pass = false;
490 DrawSelectLoopUserData *data = static_cast<DrawSelectLoopUserData *>(user_data);
491 if (stage == DRW_SELECT_PASS_PRE) {
492 GPU_select_begin_next(data->buffer, data->rect, data->gpu_select_mode, data->hits);
493 /* always run POST after PRE. */
494 continue_pass = true;
495 }
496 else if (stage == DRW_SELECT_PASS_POST) {
497 int hits = GPU_select_end();
498 if (data->pass == 0) {
499 /* quirk of GPU_select_end, only take hits value from first call. */
500 data->hits = hits;
501 }
502 if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) {
503 data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS;
504 continue_pass = (hits > 0);
505 }
506 data->pass += 1;
507 }
508 else {
509 BLI_assert(0);
510 }
511 return continue_pass;
512}
513
526
528static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data)
529{
530 const Object *obact = static_cast<const Object *>(user_data);
531 return BKE_object_is_mode_compat(ob, eObjectMode(obact->mode));
532}
533
539{
540 LinkNode *ob_pose_list = static_cast<LinkNode *>(user_data);
541 return ob_pose_list && (BLI_linklist_index(ob_pose_list, DEG_get_original_object(ob)) != -1);
542}
543
545 GPUSelectBuffer *buffer,
546 const rcti *input,
547 eV3DSelectMode select_mode,
548 eV3DSelectObjectFilter select_filter,
549 const bool do_material_slot_selection)
550{
551 bThemeState theme_state;
552 const wmWindowManager *wm = CTX_wm_manager(vc->C);
553 Depsgraph *depsgraph = vc->depsgraph;
554 Scene *scene = vc->scene;
555 View3D *v3d = vc->v3d;
556 ARegion *region = vc->region;
557 rcti rect;
558 int hits = 0;
560 const bool use_obedit_skip = (BKE_view_layer_edit_object_get(vc->view_layer) != nullptr) &&
561 (vc->obedit == nullptr);
562 /* WORKAROUND: GPU depth picking is not working on AMD/NVIDIA official Vulkan drivers. */
563 const bool is_pick_select = (!GPU_type_matches_ex(GPU_DEVICE_ATI | GPU_DEVICE_NVIDIA,
567 (U.gpu_flag & USER_GPU_FLAG_NO_DEPT_PICK) == 0;
568 const bool do_passes = ((is_pick_select == false) &&
569 (select_mode == VIEW3D_SELECT_PICK_NEAREST));
570 const bool use_nearest = (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST);
571 bool draw_surface = true;
572
573 eGPUSelectMode gpu_select_mode;
574
575 /* case not a box select */
576 if (input->xmin == input->xmax) {
577 const int xy[2] = {input->xmin, input->ymin};
578 /* seems to be default value for bones only now */
579 BLI_rcti_init_pt_radius(&rect, xy, 12);
580 }
581 else {
582 rect = *input;
583 }
584
585 if (is_pick_select) {
586 if (select_mode == VIEW3D_SELECT_PICK_NEAREST) {
587 gpu_select_mode = GPU_SELECT_PICK_NEAREST;
588 }
589 else if (select_mode == VIEW3D_SELECT_PICK_ALL) {
590 gpu_select_mode = GPU_SELECT_PICK_ALL;
591 }
592 else {
593 gpu_select_mode = GPU_SELECT_ALL;
594 }
595 }
596 else {
597 if (do_passes) {
598 gpu_select_mode = GPU_SELECT_NEAREST_FIRST_PASS;
599 }
600 else {
601 gpu_select_mode = GPU_SELECT_ALL;
602 }
603 }
604
605 /* Important to use 'vc->obact', not 'BKE_view_layer_active_object_get(vc->view_layer)' below,
606 * so it will be nullptr when hidden. */
607 struct {
609 void *user_data;
610 } object_filter = {nullptr, nullptr};
611
612 /* Re-use cache (rect must be smaller than the cached)
613 * other context is assumed to be unchanged */
614 if (GPU_select_is_cached()) {
615 GPU_select_begin_next(buffer, &rect, gpu_select_mode, 0);
617 hits = GPU_select_end();
618 goto finally;
619 }
620
621 switch (select_filter) {
623 Object *obact = vc->obact;
624 if (obact && obact->mode != OB_MODE_OBJECT) {
625 object_filter.fn = drw_select_filter_object_mode_lock;
626 object_filter.user_data = obact;
627 }
628 break;
629 }
631 Object *obact = vc->obact;
632 BLI_assert(obact && (obact->mode & OB_MODE_ALL_WEIGHT_PAINT));
633 /* While this uses 'alloca' in a loop (which we typically avoid),
634 * the number of items is nearly always 1, maybe 2..3 in rare cases. */
635 LinkNode *ob_pose_list = nullptr;
636 VirtualModifierData virtual_modifier_data;
637 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(obact, &virtual_modifier_data);
638 for (; md; md = md->next) {
639 if (md->type == eModifierType_Armature) {
640 ArmatureModifierData *amd = reinterpret_cast<ArmatureModifierData *>(md);
641 if (amd->object && (amd->object->mode & OB_MODE_POSE)) {
642 BLI_linklist_prepend_alloca(&ob_pose_list, amd->object);
643 }
644 }
647 reinterpret_cast<GreasePencilArmatureModifierData *>(md);
648 if (amd->object && (amd->object->mode & OB_MODE_POSE)) {
649 BLI_linklist_prepend_alloca(&ob_pose_list, amd->object);
650 }
651 }
652 }
654 object_filter.user_data = ob_pose_list;
655 break;
656 }
658 break;
659 }
660
661 /* Tools may request depth outside of regular drawing code. */
662 UI_Theme_Store(&theme_state);
664
665 /* All of the queries need to be perform on the drawing context. */
667
668 G.f |= G_FLAG_PICKSEL;
669
670 /* Important we use the 'viewmat' and don't re-calculate since
671 * the object & bone view locking takes 'rect' into account, see: #51629. */
673 wm, vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, nullptr, &rect);
674
675 if (!XRAY_ACTIVE(v3d)) {
677 }
678
679 /* If in X-ray mode, we select the wires in priority. */
680 if (XRAY_ACTIVE(v3d) && use_nearest) {
681 /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
682 * because the OpenGL context created & destroyed inside this function. */
683 DrawSelectLoopUserData drw_select_loop_user_data = {};
684 drw_select_loop_user_data.pass = 0;
685 drw_select_loop_user_data.hits = 0;
686 drw_select_loop_user_data.buffer = buffer;
687 drw_select_loop_user_data.rect = &rect;
688 drw_select_loop_user_data.gpu_select_mode = gpu_select_mode;
689
690 draw_surface = false;
692 region,
693 v3d,
694 use_obedit_skip,
695 draw_surface,
696 use_nearest,
697 do_material_slot_selection,
698 &rect,
700 &drw_select_loop_user_data,
701 object_filter.fn,
702 object_filter.user_data);
703 hits = drw_select_loop_user_data.hits;
704 /* FIX: This cleanup the state before doing another selection pass.
705 * (see #56695) */
707 }
708
709 if (hits == 0) {
710 /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
711 * because the OpenGL context created & destroyed inside this function. */
712 DrawSelectLoopUserData drw_select_loop_user_data = {};
713 drw_select_loop_user_data.pass = 0;
714 drw_select_loop_user_data.hits = 0;
715 drw_select_loop_user_data.buffer = buffer;
716 drw_select_loop_user_data.rect = &rect;
717 drw_select_loop_user_data.gpu_select_mode = gpu_select_mode;
718
719 /* If are not in wireframe mode, we need to use the mesh surfaces to check for hits */
720 draw_surface = (v3d->shading.type > OB_WIRE) || !XRAY_ENABLED(v3d);
722 region,
723 v3d,
724 use_obedit_skip,
725 draw_surface,
726 use_nearest,
727 do_material_slot_selection,
728 &rect,
730 &drw_select_loop_user_data,
731 object_filter.fn,
732 object_filter.user_data);
733 hits = drw_select_loop_user_data.hits;
734 }
735
736 G.f &= ~G_FLAG_PICKSEL;
738 wm, vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, nullptr, nullptr);
739
740 if (!XRAY_ACTIVE(v3d)) {
742 }
743
745
746 UI_Theme_Restore(&theme_state);
747
748finally:
749 return hits;
750}
751
753 GPUSelectBuffer *buffer,
754 const rcti *input,
755 eV3DSelectMode select_mode,
756 eV3DSelectObjectFilter select_filter)
757{
758 return view3d_opengl_select_ex(vc, buffer, input, select_mode, select_filter, false);
759}
760
762 GPUSelectBuffer *buffer,
763 const rcti *input,
764 eV3DSelectMode select_mode,
765 eV3DSelectObjectFilter select_filter,
766 uint select_id)
767{
768 const int64_t start = buffer->storage.size();
769 int hits = view3d_opengl_select(vc, buffer, input, select_mode, select_filter);
770
771 /* Selection sometimes uses -1 for an invalid selection ID, remove these as they
772 * interfere with detection of actual number of hits in the selection. */
773 if (hits > 0) {
774 hits = GPU_select_buffer_remove_by_id(buffer->storage.as_mutable_span().slice(start, hits),
775 select_id);
776
777 /* Trim buffer to the exact size in case selections were removed. */
778 buffer->storage.resize(start + hits);
779 }
780 return hits;
781}
782
784
785/* -------------------------------------------------------------------- */
788
790{
791 ushort local_view_bits = 0;
792
793 /* Sometimes we lose a local-view: when an area is closed.
794 * Check all areas: which local-views are in use? */
795 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
796 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
797 SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
798 for (; sl; sl = sl->next) {
799 if (sl->spacetype == SPACE_VIEW3D) {
800 View3D *v3d = reinterpret_cast<View3D *>(sl);
801 if (v3d->localvd) {
802 local_view_bits |= v3d->local_view_uid;
803 }
804 }
805 }
806 }
807 }
808
809 for (int i = 0; i < 16; i++) {
810 if ((local_view_bits & (1 << i)) == 0) {
811 return (1 << i);
812 }
813 }
814
815 return 0;
816}
817
818static bool view3d_localview_init(const Depsgraph *depsgraph,
819 wmWindowManager *wm,
820 wmWindow *win,
821 Main *bmain,
822 const Scene *scene,
823 ViewLayer *view_layer,
824 ScrArea *area,
825 const bool frame_selected,
826 const int smooth_viewtx,
827 ReportList *reports)
828{
829 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
830 float min[3], max[3], box[3];
831 float size = 0.0f;
832 uint local_view_bit;
833 bool changed = false;
834
835 if (v3d->localvd) {
836 return changed;
837 }
838
840
841 local_view_bit = free_localview_bit(bmain);
842
843 if (local_view_bit == 0) {
844 /* TODO(dfelinto): We can kick one of the other 3D views out of local view
845 * specially if it is not being used. */
846 BKE_report(reports, RPT_ERROR, "No more than 16 local views");
847 changed = false;
848 }
849 else {
850 BKE_view_layer_synced_ensure(scene, view_layer);
851 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
852 if (obedit) {
853 BKE_view_layer_synced_ensure(scene, view_layer);
855 base->local_view_bits &= ~local_view_bit;
856 }
857 FOREACH_BASE_IN_EDIT_MODE_BEGIN (scene, view_layer, v3d, base_iter) {
858 Object *ob_eval = DEG_get_evaluated_object(depsgraph, base_iter->object);
859 BKE_object_minmax(ob_eval ? ob_eval : base_iter->object, min, max);
860 base_iter->local_view_bits |= local_view_bit;
861 changed = true;
862 }
864 }
865 else {
866 BKE_view_layer_synced_ensure(scene, view_layer);
868 if (BASE_SELECTED(v3d, base)) {
869 Object *ob_eval = DEG_get_evaluated_object(depsgraph, base->object);
870 BKE_object_minmax(ob_eval ? ob_eval : base->object, min, max);
871 base->local_view_bits |= local_view_bit;
872 changed = true;
873 }
874 else {
875 base->local_view_bits &= ~local_view_bit;
876 }
877 }
878 }
879
880 sub_v3_v3v3(box, max, min);
881 size = max_fff(box[0], box[1], box[2]);
882 }
883
884 if (changed == false) {
885 return false;
886 }
887
888 /* Apply any running smooth-view values before reading from the viewport. */
889 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
890 if (region->regiontype == RGN_TYPE_WINDOW) {
891 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
892 if (rv3d->sms) {
894 }
895 }
896 }
897
898 v3d->localvd = static_cast<View3D *>(MEM_mallocN(sizeof(View3D), "localview"));
899 *v3d->localvd = blender::dna::shallow_copy(*v3d);
900 v3d->local_view_uid = local_view_bit;
901
902 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
903 if (region->regiontype == RGN_TYPE_WINDOW) {
904 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
905 bool ok_dist = true;
906
907 /* New view values. */
908 Object *camera_old = nullptr;
909 float dist_new, ofs_new[3];
910
911 rv3d->localvd = static_cast<RegionView3D *>(
912 MEM_mallocN(sizeof(RegionView3D), "localview region"));
913 memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D));
914
915 if (frame_selected) {
916 float mid[3];
917 mid_v3_v3v3(mid, min, max);
918 negate_v3_v3(ofs_new, mid);
919
920 if (rv3d->persp == RV3D_CAMOB) {
921 rv3d->persp = RV3D_PERSP;
922 camera_old = v3d->camera;
923 }
924
925 if (rv3d->persp == RV3D_ORTHO) {
926 if (size < 0.0001f) {
927 ok_dist = false;
928 }
929 }
930
931 if (ok_dist) {
932 dist_new = ED_view3d_radius_to_dist(
933 v3d, region, depsgraph, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
934
935 if (rv3d->persp == RV3D_PERSP) {
936 /* Don't zoom closer than the near clipping plane. */
937 dist_new = max_ff(dist_new, v3d->clip_start * 1.5f);
938 }
939 }
940
941 V3D_SmoothParams sview_params = {};
942 sview_params.camera_old = camera_old;
943 sview_params.ofs = ofs_new;
944 sview_params.quat = rv3d->viewquat;
945 sview_params.dist = ok_dist ? &dist_new : nullptr;
946 sview_params.lens = &v3d->lens;
947 /* No undo because this doesn't move the camera. */
948 sview_params.undo_str = nullptr;
949
951 depsgraph, wm, win, area, v3d, region, smooth_viewtx, &sview_params);
952 }
953 }
954 }
955
956 return changed;
957}
958
959static bool view3d_localview_exit(const Depsgraph *depsgraph,
960 wmWindowManager *wm,
961 wmWindow *win,
962 const Scene *scene,
963 ViewLayer *view_layer,
964 ScrArea *area,
965 const bool frame_selected,
966 const int smooth_viewtx)
967{
968 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
969 bool changed = false;
970
971 if (v3d->localvd == nullptr) {
972 return changed;
973 }
974 BKE_view_layer_synced_ensure(scene, view_layer);
976 if (base->local_view_bits & v3d->local_view_uid) {
977 base->local_view_bits &= ~v3d->local_view_uid;
978 }
979 }
980
981 /* Apply any running smooth-view values before reading from the viewport. */
982 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
983 if (region->regiontype == RGN_TYPE_WINDOW) {
984 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
985 if (rv3d->localvd == nullptr) {
986 continue;
987 }
988 if (rv3d->sms) {
990 }
991 }
992 }
993
994 Object *camera_old = v3d->camera;
995 Object *camera_new = v3d->localvd->camera;
996
997 v3d->local_view_uid = 0;
998 v3d->camera = v3d->localvd->camera;
999
1000 MEM_freeN(v3d->localvd);
1001 v3d->localvd = nullptr;
1003
1004 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1005 if (region->regiontype == RGN_TYPE_WINDOW) {
1006 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
1007
1008 if (rv3d->localvd == nullptr) {
1009 continue;
1010 }
1011
1012 if (frame_selected && depsgraph) {
1013 Object *camera_old_rv3d, *camera_new_rv3d;
1014
1015 camera_old_rv3d = (rv3d->persp == RV3D_CAMOB) ? camera_old : nullptr;
1016 camera_new_rv3d = (rv3d->localvd->persp == RV3D_CAMOB) ? camera_new : nullptr;
1017
1018 rv3d->view = rv3d->localvd->view;
1019 rv3d->view_axis_roll = rv3d->localvd->view_axis_roll;
1020 rv3d->persp = rv3d->localvd->persp;
1021 rv3d->camzoom = rv3d->localvd->camzoom;
1022
1023 V3D_SmoothParams sview_params = {};
1024 sview_params.camera_old = camera_old_rv3d;
1025 sview_params.camera = camera_new_rv3d;
1026 sview_params.ofs = rv3d->localvd->ofs;
1027 sview_params.quat = rv3d->localvd->viewquat;
1028 sview_params.dist = &rv3d->localvd->dist;
1029 /* No undo because this doesn't move the camera. */
1030 sview_params.undo_str = nullptr;
1031
1033 depsgraph, wm, win, area, v3d, region, smooth_viewtx, &sview_params);
1034 }
1035
1036 MEM_freeN(rv3d->localvd);
1037 rv3d->localvd = nullptr;
1038 changed = true;
1039 }
1040 }
1041 return changed;
1042}
1043
1045 Scene *scene,
1046 ViewLayer *view_layer,
1047 wmWindowManager *wm,
1048 wmWindow *win,
1049 View3D *v3d,
1050 ScrArea *area,
1051 const bool frame_selected,
1052 const int smooth_viewtx)
1053{
1054 if (v3d->localvd == nullptr) {
1055 return false;
1056 }
1057
1059
1060 BKE_view_layer_synced_ensure(scene, view_layer);
1062 if (base->local_view_bits & v3d->local_view_uid) {
1063 return false;
1064 }
1065 }
1066
1067 return view3d_localview_exit(
1068 depsgraph, wm, win, scene, view_layer, area, frame_selected, smooth_viewtx);
1069}
1070
1072{
1074 const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
1076 wmWindow *win = CTX_wm_window(C);
1077 Main *bmain = CTX_data_main(C);
1078 Scene *scene = CTX_data_scene(C);
1079 ViewLayer *view_layer = CTX_data_view_layer(C);
1080 ScrArea *area = CTX_wm_area(C);
1081 View3D *v3d = CTX_wm_view3d(C);
1082 bool frame_selected = RNA_boolean_get(op->ptr, "frame_selected");
1083 bool changed;
1084
1085 if (v3d->localvd) {
1086 changed = view3d_localview_exit(
1087 depsgraph, wm, win, scene, view_layer, area, frame_selected, smooth_viewtx);
1088 }
1089 else {
1091 wm,
1092 win,
1093 bmain,
1094 scene,
1095 view_layer,
1096 area,
1097 frame_selected,
1098 smooth_viewtx,
1099 op->reports);
1100 }
1101
1102 if (changed) {
1103 DEG_id_type_tag(bmain, ID_OB);
1104 ED_area_tag_redraw(area);
1105
1106 /* Unselected objects become selected when exiting. */
1107 if (v3d->localvd == nullptr) {
1110 }
1111 else {
1113 }
1114
1115 return OPERATOR_FINISHED;
1116 }
1117 return OPERATOR_CANCELLED;
1118}
1119
1121{
1122 /* identifiers */
1123 ot->name = "Local View";
1124 ot->description = "Toggle display of selected object(s) separately and centered in view";
1125 ot->idname = "VIEW3D_OT_localview";
1126
1127 /* api callbacks */
1128 ot->exec = localview_exec;
1129 ot->flag = OPTYPE_UNDO; /* localview changes object layer bitflags */
1130
1132
1133 RNA_def_boolean(ot->srna,
1134 "frame_selected",
1135 true,
1136 "Frame Selected",
1137 "Move the view to frame the selected objects");
1138}
1139
1141{
1142 View3D *v3d = CTX_wm_view3d(C);
1143 Main *bmain = CTX_data_main(C);
1144 Scene *scene = CTX_data_scene(C);
1145 ViewLayer *view_layer = CTX_data_view_layer(C);
1146 bool changed = false;
1147 BKE_view_layer_synced_ensure(scene, view_layer);
1149 if (BASE_SELECTED(v3d, base)) {
1150 base->local_view_bits &= ~v3d->local_view_uid;
1152
1153 if (base == view_layer->basact) {
1154 view_layer->basact = nullptr;
1155 }
1156 changed = true;
1157 }
1158 }
1159
1160 /* If some object was removed from the local view, exit the local view if it is now empty. */
1161 if (changed) {
1163 scene,
1164 view_layer,
1167 v3d,
1168 CTX_wm_area(C),
1169 true,
1171 }
1172
1173 if (changed) {
1174 DEG_tag_on_visible_update(bmain, false);
1178 return OPERATOR_FINISHED;
1179 }
1180
1181 BKE_report(op->reports, RPT_ERROR, "No object selected");
1182 return OPERATOR_CANCELLED;
1183}
1184
1186{
1187 if (CTX_data_edit_object(C) != nullptr) {
1188 return false;
1189 }
1190
1191 View3D *v3d = CTX_wm_view3d(C);
1192 return v3d && v3d->localvd;
1193}
1194
1196{
1197 /* identifiers */
1198 ot->name = "Remove from Local View";
1199 ot->description = "Move selected objects out of local view";
1200 ot->idname = "VIEW3D_OT_localview_remove_from";
1201
1202 /* api callbacks */
1205 ot->flag = OPTYPE_UNDO;
1206}
1207
1209
1210/* -------------------------------------------------------------------- */
1213
1215 ushort local_collections_uid,
1216 bool *r_reset)
1217{
1218 ushort local_view_bits = 0;
1219
1220 /* Check all areas: which local-views are in use? */
1221 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
1222 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1223 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1224 if (sl->spacetype == SPACE_VIEW3D) {
1225 View3D *v3d = reinterpret_cast<View3D *>(sl);
1226 if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
1227 local_view_bits |= v3d->local_collections_uid;
1228 }
1229 }
1230 }
1231 }
1232 }
1233
1234 /* First try to keep the old uuid. */
1235 if (local_collections_uid && ((local_collections_uid & local_view_bits) == 0)) {
1236 return local_collections_uid;
1237 }
1238
1239 /* Otherwise get the first free available. */
1240 for (int i = 0; i < 16; i++) {
1241 if ((local_view_bits & (1 << i)) == 0) {
1242 *r_reset = true;
1243 return (1 << i);
1244 }
1245 }
1246
1247 return 0;
1248}
1249
1250static void local_collections_reset_uuid(LayerCollection *layer_collection,
1251 const ushort local_view_bit)
1252{
1253 if (layer_collection->flag & LAYER_COLLECTION_HIDE) {
1254 layer_collection->local_collections_bits &= ~local_view_bit;
1255 }
1256 else {
1257 layer_collection->local_collections_bits |= local_view_bit;
1258 }
1259
1260 LISTBASE_FOREACH (LayerCollection *, child, &layer_collection->layer_collections) {
1261 local_collections_reset_uuid(child, local_view_bit);
1262 }
1263}
1264
1265static void view3d_local_collections_reset(const Main *bmain, const uint local_view_bit)
1266{
1267 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1268 LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
1269 LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) {
1270 local_collections_reset_uuid(layer_collection, local_view_bit);
1271 }
1272 }
1273 }
1274}
1275
1277{
1278 if ((v3d->flag & V3D_LOCAL_COLLECTIONS) == 0) {
1279 return true;
1280 }
1281
1282 bool reset = false;
1284 uint local_view_bit = free_localcollection_bit(bmain, v3d->local_collections_uid, &reset);
1285
1286 if (local_view_bit == 0) {
1287 return false;
1288 }
1289
1290 v3d->local_collections_uid = local_view_bit;
1292
1293 if (reset) {
1294 view3d_local_collections_reset(bmain, local_view_bit);
1295 }
1296
1297 return true;
1298}
1299
1300void ED_view3d_local_collections_reset(const bContext *C, const bool reset_all)
1301{
1302 Main *bmain = CTX_data_main(C);
1303 uint local_view_bit = ~(0);
1304 bool do_reset = false;
1305
1306 /* Reset only the ones that are not in use. */
1307 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
1308 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1309 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1310 if (sl->spacetype == SPACE_VIEW3D) {
1311 View3D *v3d = reinterpret_cast<View3D *>(sl);
1312 if (v3d->local_collections_uid) {
1313 if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
1314 local_view_bit &= ~v3d->local_collections_uid;
1315 }
1316 else {
1317 do_reset = true;
1318 }
1319 }
1320 }
1321 }
1322 }
1323 }
1324
1325 if (do_reset) {
1326 view3d_local_collections_reset(bmain, local_view_bit);
1327 }
1328 else if (reset_all && (do_reset || (local_view_bit != ~(0)))) {
1329 view3d_local_collections_reset(bmain, ~(0));
1330 View3D v3d = {};
1331 v3d.local_collections_uid = ~(0);
1334 }
1335}
1336
1338
1339/* -------------------------------------------------------------------- */
1342
1343#ifdef WITH_XR_OPENXR
1344
1345static void view3d_xr_mirror_begin(RegionView3D *rv3d)
1346{
1347 /* If there is no session yet, changes below should not be applied! */
1349
1351 /* Force perspective view. This isn't reset but that's not really an issue. */
1352 rv3d->persp = RV3D_PERSP;
1353}
1354
1355static void view3d_xr_mirror_end(RegionView3D *rv3d)
1356{
1358}
1359
1360void ED_view3d_xr_mirror_update(const ScrArea *area, const View3D *v3d, const bool enable)
1361{
1362 ARegion *region_rv3d;
1363
1365
1366 if (ED_view3d_area_user_region(area, v3d, &region_rv3d)) {
1367 if (enable) {
1368 view3d_xr_mirror_begin(static_cast<RegionView3D *>(region_rv3d->regiondata));
1369 }
1370 else {
1371 view3d_xr_mirror_end(static_cast<RegionView3D *>(region_rv3d->regiondata));
1372 }
1373 }
1374}
1375
1376void ED_view3d_xr_shading_update(wmWindowManager *wm, const View3D *v3d, const Scene *scene)
1377{
1379 View3DShading *xr_shading = &wm->xr.session_settings.shading;
1380 /* Flags that shouldn't be overridden by the 3D View shading. */
1381 int flag_copy = 0;
1382 if (v3d->shading.type != OB_SOLID) {
1383 /* Don't set V3D_SHADING_WORLD_ORIENTATION for solid shading since it results in distorted
1384 * lighting when the view matrix has a scale factor. */
1385 flag_copy |= V3D_SHADING_WORLD_ORIENTATION;
1386 }
1387
1389
1390 if (v3d->shading.type == OB_RENDER) {
1392 /* Keep old shading while using Cycles or another engine, they are typically not usable in
1393 * VR. */
1394 return;
1395 }
1396 }
1397
1398 if (xr_shading->prop) {
1399 IDP_FreeProperty(xr_shading->prop);
1400 xr_shading->prop = nullptr;
1401 }
1402
1403 /* Copy shading from View3D to VR view. */
1404 const int old_xr_shading_flag = xr_shading->flag;
1405 *xr_shading = v3d->shading;
1406 xr_shading->flag = (xr_shading->flag & ~flag_copy) | (old_xr_shading_flag & flag_copy);
1407 if (v3d->shading.prop) {
1408 xr_shading->prop = IDP_CopyProperty(xr_shading->prop);
1409 }
1410 }
1411}
1412
1413bool ED_view3d_is_region_xr_mirror_active(const wmWindowManager *wm,
1414 const View3D *v3d,
1415 const ARegion *region)
1416{
1417 return (v3d->flag & V3D_XR_SESSION_MIRROR) &&
1418 /* The free region (e.g. the camera region in quad-view) is always
1419 * the last in the list base. We don't want any other to be affected. */
1420 !region->next && //
1422}
1423
1424#endif
1425
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
#define G_MAIN
@ G_FLAG_PICKSEL
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1227
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:861
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
void BKE_layer_collection_local_sync(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
#define FOREACH_BASE_IN_EDIT_MODE_BEGIN(_scene, _view_layer, _v3d, _instance)
Definition BKE_layer.hh:372
#define FOREACH_BASE_IN_EDIT_MODE_END
Definition BKE_layer.hh:375
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
Object * BKE_view_layer_edit_object_get(const ViewLayer *view_layer)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2456
ModifierData * BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *data)
General operations, lookup, etc. for blender objects.
void BKE_object_tfm_protected_backup(const Object *ob, ObjectTfmProtectedChannels *obtfm)
Object * BKE_object_pose_armature_get(Object *ob)
void BKE_object_tfm_protected_restore(Object *ob, const ObjectTfmProtectedChannels *obtfm, short protectflag)
bool BKE_object_is_mode_compat(const Object *ob, eObjectMode object_mode)
void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3])
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
bool BKE_scene_uses_blender_workbench(const Scene *scene)
Definition scene.cc:2777
bool BKE_scene_uses_blender_eevee(const Scene *scene)
Definition scene.cc:2771
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
MINLINE float max_fff(float a, float b, float c)
MINLINE float max_ff(float a, float b)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void normalize_m4_m4(float rmat[4][4], const float mat[4][4]) ATTR_NONNULL()
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
void mul_m4_v3(const float M[4][4], float r[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void quat_to_mat4(float m[4][4], const float q[4])
void mat4_normalized_to_quat(float q[4], const float mat[4][4])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v2_v2fl(float r[2], const float a[2], float f)
void BLI_rcti_init_pt_radius(struct rcti *rect, const int xy[2], int size)
Definition rct.c:470
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:197
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:201
unsigned short ushort
unsigned int uint
#define INIT_MINMAX(min, max)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_id_type_tag(Main *bmain, short id_type)
void DEG_tag_on_visible_update(Main *bmain, bool do_time)
void DEG_relations_tag_update(Main *bmain)
Object * DEG_get_original_object(Object *object)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1021
@ ID_RECALC_SELECT
Definition DNA_ID.h:1068
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1071
@ ID_OB
@ LAYER_COLLECTION_HIDE
@ eModifierType_GreasePencilArmature
@ eModifierType_Armature
@ OB_WIRE
@ OB_SOLID
@ OB_RENDER
#define OB_MODE_ALL_WEIGHT_PAINT
eObjectMode
@ OB_MODE_POSE
@ OB_MODE_OBJECT
@ OB_ARMATURE
#define BASE_SELECTED(v3d, base)
#define V3D_CAMERA_SCENE(scene, v3d)
@ SCE_OBJECT_MODE_LOCK
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
@ USER_GPU_FLAG_NO_DEPT_PICK
#define RV3D_LOCK_FLAGS(rv3d)
@ V3D_SHADING_WORLD_ORIENTATION
@ RV3D_VIEW_USER
@ RV3D_CAMOB
@ RV3D_PERSP
@ RV3D_ORTHO
@ RV3D_LOCK_ANY_TRANSFORM
@ RV3D_LOCK_ROTATION
@ V3D_LOCAL_COLLECTIONS
@ V3D_XR_SESSION_MIRROR
@ V3D_RUNTIME_LOCAL_MAYBE_EMPTY
@ V3D_RUNTIME_XR_SESSION_ROOT
void DRW_gpu_context_disable()
bool(*)(Object *ob, void *user_data) DRW_ObjectFilterFn
Definition DRW_engine.hh:63
void DRW_gpu_context_enable()
eDRWSelectStage
Definition DRW_engine.hh:58
@ DRW_SELECT_PASS_POST
Definition DRW_engine.hh:60
@ DRW_SELECT_PASS_PRE
Definition DRW_engine.hh:59
void DRW_draw_select_loop(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bool use_obedit_skip, bool draw_surface, bool use_nearest, bool do_material_sub_selection, const rcti *rect, DRW_SelectPassFn select_pass_fn, void *select_pass_user_data, DRW_ObjectFilterFn object_filter_fn, void *object_filter_user_data)
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:708
bool ED_operator_scene_editable(bContext *C)
bool ED_operator_view3d_active(bContext *C)
#define XRAY_ENABLED(v3d)
void ED_view3d_to_object(const Depsgraph *depsgraph, Object *ob, const float ofs[3], const float quat[4], float dist)
bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_region)
bool ED_view3d_lock(RegionView3D *rv3d)
void ED_view3d_lastview_store(RegionView3D *rv3d)
#define VIEW3D_MARGIN
#define XRAY_ACTIVE(v3d)
float ED_view3d_radius_to_dist(const View3D *v3d, const ARegion *region, const Depsgraph *depsgraph, char persp, bool use_aspect, float radius)
void ED_view3d_draw_setup_view(const wmWindowManager *wm, wmWindow *win, Depsgraph *depsgraph, Scene *scene, ARegion *region, View3D *v3d, const float viewmat[4][4], const float winmat[4][4], const rcti *rect)
bool ED_view3d_viewplane_get(const Depsgraph *depsgraph, const View3D *v3d, const RegionView3D *rv3d, int winx, int winy, rctf *r_viewplane, float *r_clip_start, float *r_clip_end, float *r_pixsize)
eV3DSelectMode
Definition ED_view3d.hh:937
@ VIEW3D_SELECT_PICK_ALL
Definition ED_view3d.hh:941
@ VIEW3D_SELECT_PICK_NEAREST
Definition ED_view3d.hh:943
bool ED_view3d_camera_to_view_selected(Main *bmain, Depsgraph *depsgraph, const Scene *scene, Object *camera_ob)
eV3DSelectObjectFilter
Definition ED_view3d.hh:946
@ VIEW3D_SELECT_FILTER_NOP
Definition ED_view3d.hh:948
@ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK
Definition ED_view3d.hh:950
@ VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK
Definition ED_view3d.hh:952
bool ED_operator_rv3d_user_region_poll(bContext *C)
bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion **r_region)
void GPU_matrix_ortho_set(float left, float right, float bottom, float top, float near, float far)
void GPU_matrix_frustum_set(float left, float right, float bottom, float top, float near, float far)
#define GPU_matrix_projection_get(x)
@ GPU_DRIVER_OFFICIAL
bool GPU_type_matches_ex(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver, eGPUBackendType backend)
@ GPU_OS_ANY
@ GPU_DEVICE_ATI
@ GPU_DEVICE_NVIDIA
void GPU_select_cache_end()
eGPUSelectMode
Definition GPU_select.hh:18
@ GPU_SELECT_NEAREST_SECOND_PASS
Definition GPU_select.hh:22
@ GPU_SELECT_NEAREST_FIRST_PASS
Definition GPU_select.hh:21
@ GPU_SELECT_PICK_ALL
Definition GPU_select.hh:24
@ GPU_SELECT_ALL
Definition GPU_select.hh:19
@ GPU_SELECT_PICK_NEAREST
Definition GPU_select.hh:25
bool GPU_select_is_cached()
unsigned int GPU_select_end()
void GPU_select_cache_load_id()
void GPU_select_begin_next(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode, int oldhits)
uint GPU_select_buffer_remove_by_id(blender::MutableSpan< GPUSelectResult > hit_results, uint select_id)
void GPU_select_cache_begin()
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:111
@ GPU_DEPTH_NONE
Definition GPU_state.hh:108
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition RandGen.cpp:29
void UI_Theme_Store(bThemeState *theme_state)
void UI_Theme_Restore(const bThemeState *theme_state)
void UI_SetTheme(int spacetype, int regionid)
#define ND_DRAW
Definition WM_types.hh:428
#define ND_OB_ACTIVE
Definition WM_types.hh:407
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define ND_OB_SELECT
Definition WM_types.hh:409
#define NC_SCENE
Definition WM_types.hh:345
#define ND_TRANSFORM
Definition WM_types.hh:423
#define NC_OBJECT
Definition WM_types.hh:346
#define U
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void reset()
clear internal cached data and reset random seed
int64_t size() const
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
#define printf
draw_view in_light_buf[] float
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
#define G(x, y, z)
void base_select(Base *base, eObjectSelect_Mode mode)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
#define min(a, b)
Definition sort.c:32
__int64 int64_t
Definition stdint.h:89
void * regiondata
struct ARegion * next
GPUSelectBuffer * buffer
eGPUSelectMode gpu_select_mode
GPUSelectStorage storage
Definition GPU_select.hh:46
ListBase layer_collections
unsigned short local_collections_bits
void * first
ListBase scenes
Definition BKE_main.hh:210
ListBase screens
Definition BKE_main.hh:225
struct ModifierData * next
struct bPose * pose
short protectflag
struct SmoothView3DStore * sms
struct RegionView3D * localvd
float viewmat[4][4]
float winmat[4][4]
struct ToolSettings * toolsettings
View3DCursor cursor
struct Object * camera
ListBase spacedata
ListBase regionbase
const char * undo_str
struct IDProperty * prop
struct SceneStats * local_stats
unsigned short local_collections_uid
View3D_Runtime runtime
struct Object * camera
struct View3D * localvd
char ob_center_bone[64]
short scenelock
short ob_center_cursor
struct Object * ob_center
View3DShading shading
unsigned short local_view_uid
float clip_start
RegionView3D * rv3d
Definition ED_view3d.hh:76
ARegion * region
Definition ED_view3d.hh:73
Scene * scene
Definition ED_view3d.hh:69
wmWindow * win
Definition ED_view3d.hh:75
ViewLayer * view_layer
Definition ED_view3d.hh:70
bContext * C
Definition ED_view3d.hh:62
View3D * v3d
Definition ED_view3d.hh:74
Object * obact
Definition ED_view3d.hh:71
Object * obedit
Definition ED_view3d.hh:72
Depsgraph * depsgraph
Definition ED_view3d.hh:68
struct Base * basact
struct View3DShading shading
float pose_mat[4][4]
float xmax
float xmin
float ymax
float ymin
int ymin
int ymax
int xmin
int xmax
struct ReportList * reports
struct PointerRNA * ptr
XrSessionSettings session_settings
float max
void ED_view3d_smooth_view(bContext *C, View3D *v3d, ARegion *region, int smooth_viewtx, const V3D_SmoothParams *sview)
void ED_view3d_smooth_view_force_finish_no_camera_lock(const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, const Scene *scene, View3D *v3d, ARegion *region)
void ED_view3d_smooth_view_ex(const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, ScrArea *area, View3D *v3d, ARegion *region, int smooth_viewtx, const V3D_SmoothParams *sview)
void view3d_opengl_select_cache_begin()
static void local_collections_reset_uuid(LayerCollection *layer_collection, const ushort local_view_bit)
void view3d_viewmatrix_set(const Depsgraph *depsgraph, const Scene *scene, const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2])
static int localview_remove_from_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_localview(wmOperatorType *ot)
static void view3d_local_collections_reset(const Main *bmain, const uint local_view_bit)
static uint free_localview_bit(Main *bmain)
static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
static int localview_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_localview_remove_from(wmOperatorType *ot)
void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot)
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data)
int view3d_opengl_select_ex(const ViewContext *vc, GPUSelectBuffer *buffer, const rcti *input, eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter, const bool do_material_slot_selection)
static bool view3d_localview_exit(const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, const Scene *scene, ViewLayer *view_layer, ScrArea *area, const bool frame_selected, const int smooth_viewtx)
int view3d_opengl_select(const ViewContext *vc, GPUSelectBuffer *buffer, const rcti *input, eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter)
static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void *user_data)
static void sync_viewport_camera_smoothview(bContext *C, View3D *v3d, Object *ob, const int smooth_viewtx)
bool ED_localview_exit_if_empty(const Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, wmWindowManager *wm, wmWindow *win, View3D *v3d, ScrArea *area, const bool frame_selected, const int smooth_viewtx)
static int view3d_camera_to_view_exec(bContext *C, wmOperator *)
eV3DSelectObjectFilter ED_view3d_select_filter_from_mode(const Scene *scene, const Object *obact)
static bool localview_remove_from_poll(bContext *C)
void ED_view3d_local_collections_reset(const bContext *C, const bool reset_all)
int view3d_opengl_select_with_id_filter(const ViewContext *vc, GPUSelectBuffer *buffer, const rcti *input, eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter, uint select_id)
bool ED_view3d_local_collections_set(const Main *bmain, View3D *v3d)
static uint free_localcollection_bit(const Main *bmain, ushort local_collections_uid, bool *r_reset)
static bool view3d_localview_init(const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, Main *bmain, const Scene *scene, ViewLayer *view_layer, ScrArea *area, const bool frame_selected, const int smooth_viewtx, ReportList *reports)
void view3d_opengl_select_cache_end()
void view3d_winmatrix_set(const Depsgraph *depsgraph, ARegion *region, const View3D *v3d, const rcti *rect)
void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
static bool view3d_camera_to_view_poll(bContext *C)
bool ED_operator_rv3d_user_region_poll(bContext *C)
static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
int xy[2]
Definition wm_draw.cc:170
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4125
int WM_operator_smooth_viewtx_get(const wmOperator *op)
bool WM_xr_session_is_ready(const wmXrData *xr)
bool WM_xr_session_exists(const wmXrData *xr)