Files
test2/source/blender/editors/space_view3d/view3d_context.cc

139 lines
3.9 KiB
C++

/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spview3d
*/
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "BKE_context.hh"
#include "BKE_layer.hh"
#include "BKE_screen.hh"
#include "ED_view3d.hh"
#include "view3d_intern.hh"
/* -------------------------------------------------------------------- */
/** \name View3D Context Callback
* \{ */
const char *view3d_context_dir[] = {
"active_object",
"selected_ids",
nullptr,
};
int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
{
/* fallback to the scene layer,
* allows duplicate and other object operators to run outside the 3d view */
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, view3d_context_dir);
return CTX_RESULT_OK;
}
if (CTX_data_equals(member, "active_object")) {
/* In most cases the active object is the `view_layer->basact->object`.
* For the 3D view however it can be nullptr when hidden.
*
* This is ignored in the case the object is in any mode (besides object-mode),
* since the object's mode impacts the current tool, cursor, gizmos etc.
* If we didn't have this exception, changing visibility would need to perform
* many of the same updates as changing the objects mode.
*
* Further, there are multiple ways to hide objects - by collection, by object type, etc.
* it's simplest if all these methods behave consistently - respecting the object-mode
* without showing the object.
*
* See #85532 for alternatives that were considered. */
const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(scene, view_layer);
Base *base = BKE_view_layer_active_base_get(view_layer);
if (base) {
Object *ob = base->object;
/* if hidden but in edit mode, we still display, can happen with animation */
if ((base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) != 0 ||
(ob->mode != OB_MODE_OBJECT))
{
CTX_data_id_pointer_set(result, &ob->id);
}
}
return CTX_RESULT_OK;
}
if (CTX_data_equals(member, "selected_ids")) {
blender::Vector<PointerRNA> selected_objects;
CTX_data_selected_objects(C, &selected_objects);
for (const PointerRNA &ptr : selected_objects) {
ID *selected_id = ptr.owner_id;
CTX_data_id_list_add(result, selected_id);
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_MEMBER_NOT_FOUND;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name View3D Context Queries
* \{ */
RegionView3D *ED_view3d_context_rv3d(bContext *C)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d == nullptr) {
ScrArea *area = CTX_wm_area(C);
if (area && area->spacetype == SPACE_VIEW3D) {
ARegion *region = BKE_area_find_region_active_win(area);
if (region) {
rv3d = static_cast<RegionView3D *>(region->regiondata);
}
}
}
return rv3d;
}
bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_region)
{
ScrArea *area = CTX_wm_area(C);
*r_v3d = nullptr;
*r_region = nullptr;
if (area && area->spacetype == SPACE_VIEW3D) {
ARegion *region = CTX_wm_region(C);
View3D *v3d = (View3D *)area->spacedata.first;
if (region) {
RegionView3D *rv3d;
if ((region->regiontype == RGN_TYPE_WINDOW) &&
(rv3d = static_cast<RegionView3D *>(region->regiondata)) &&
(rv3d->viewlock & RV3D_LOCK_ROTATION) == 0)
{
*r_v3d = v3d;
*r_region = region;
return true;
}
if (ED_view3d_area_user_region(area, v3d, r_region)) {
*r_v3d = v3d;
return true;
}
}
}
return false;
}
/** \} */