Files
test2/source/blender/editors/screen/screen_context.cc
Falk David 20383e4d82 Python: Rename legacy Grease Pencil types to Annotation
This renames the legacy Grease Pencil python types to what
they are used for now: Annotations!

## Updated types
| Before | After |
| --- | --- |
| `bpy.types.GPencilStrokePoint` | `bpy.types.AnnotationStrokePoint` |
| `bpy.types.GPencilStroke` | `bpy.types.AnnotationStroke` |
| `bpy.types.GPencilFrame` | `bpy.types.AnnotationFrame` |
| `bpy.types.GPencilFrames` | `bpy.types.AnnotationFrames` |
| `bpy.types.GPencilLayer` | `bpy.types.AnnotationLayer` |
| `bpy.types.GPencilLayers` | `bpy.types.AnnotationLayers` |
| `bpy.types.GreasePencil` | `bpy.types.Annotation` |
| `bpy.types.BlendDataGreasePencils` | `bpy.types.BlendDataAnnotations` |

## Updated properties
| Before | After |
| --- | --- |
| `bpy.data.grease_pencils` | `bpy.types.annotations` |
| `MovieClip.grease_pencil` | `MovieClip.annotation` |
| `NodeTree.grease_pencil` | `NodeTree.annotation` |
| `Scene.grease_pencil` | `Scene.annotation` |
| `SpaceImageEditor.grease_pencil` | `SpaceImageEditor.annotation` |
| `SpaceSequenceEditor.grease_pencil` | `SpaceSequenceEditor.annotation` |
| `MovieTrackingTrack.grease_pencil` | `MovieTrackingTrack.annotation` |

Pull Request: https://projects.blender.org/blender/blender/pulls/142236
2025-07-18 12:57:01 +02:00

1289 lines
46 KiB
C++

/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edscr
*/
#include <cstdlib>
#include <cstring>
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_grease_pencil_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_workspace_types.h"
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "BLI_set.hh"
#include "BLI_utildefines.h"
#include "BKE_action.hh"
#include "BKE_armature.hh"
#include "BKE_context.hh"
#include "BKE_gpencil_legacy.h"
#include "BKE_layer.hh"
#include "BKE_library.hh"
#include "BKE_object.hh"
#include "BKE_tracking.h"
#include "RNA_access.hh"
#include "RNA_prototypes.hh"
#include "ED_anim_api.hh"
#include "ED_armature.hh"
#include "ED_clip.hh"
#include "ED_gpencil_legacy.hh"
#include "SEQ_channels.hh"
#include "SEQ_select.hh"
#include "SEQ_sequencer.hh"
#include "SEQ_transform.hh"
#include "UI_interface.hh"
#include "WM_api.hh"
#include "ANIM_armature.hh"
#include "ANIM_bone_collections.hh"
#include "screen_intern.hh"
using blender::Vector;
const char *screen_context_dir[] = {
"scene",
"view_layer",
"visible_objects",
"selectable_objects",
"selected_objects",
"editable_objects",
"selected_editable_objects",
"objects_in_mode",
"objects_in_mode_unique_data",
"visible_bones",
"editable_bones",
"selected_bones",
"selected_editable_bones",
"visible_pose_bones",
"selected_pose_bones",
"selected_pose_bones_from_active_object",
"active_bone",
"active_pose_bone",
"active_object",
"object",
"edit_object",
"sculpt_object",
"vertex_paint_object",
"weight_paint_object",
"image_paint_object",
"particle_edit_object",
"pose_object",
"active_sequence_strip", /* DEPRECATED - use "active_strip" */
"sequences", /* DEPRECATED - use "strips" */
"selected_sequences", /* DEPRECATED - use "selected_strips" */
"selected_editable_sequences", /* DEPRECATED - use "selected_editable_strips" */
"active_nla_track",
"active_nla_strip",
"selected_nla_strips", /* nla editor */
"selected_movieclip_tracks",
/* Legacy Grease Pencil */
"annotation_data",
"annotation_data_owner",
"active_annotation_layer",
/* Grease Pencil */
"grease_pencil",
"active_operator",
"active_action",
"selected_visible_actions",
"selected_editable_actions",
"visible_fcurves",
"editable_fcurves",
"selected_visible_fcurves",
"selected_editable_fcurves",
"active_editable_fcurve",
"selected_editable_keyframes",
"ui_list",
"property",
"asset_library_reference",
"active_strip",
"strips",
"selected_strips",
"selected_editable_strips",
nullptr,
};
/* Each function `screen_ctx_XXX()` will be called when the screen context "XXX" is requested.
* ensure_ed_screen_context_functions() is responsible for creating the hash map from context
* member name to function. */
static eContextResult screen_ctx_scene(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
CTX_data_id_pointer_set(result, &scene->id);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_visible_objects(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be nullptr in a lot of cases. */
Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
if (BASE_VISIBLE(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_selectable_objects(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be nullptr in a lot of cases. */
Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
if (BASE_SELECTABLE(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_selected_objects(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be nullptr in a lot of cases. */
Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
if (BASE_SELECTED(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_selected_editable_objects(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be nullptr in a lot of cases. */
Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
if (BASE_SELECTED_EDITABLE(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_editable_objects(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be nullptr in a lot of cases. */
Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
/* Visible + Editable, but not necessarily selected */
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
if (BASE_EDITABLE(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_objects_in_mode(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be nullptr in a lot of cases. */
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact && (obact->mode != OB_MODE_OBJECT)) {
FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, obact->type, obact->mode, ob_iter) {
CTX_data_id_list_add(result, &ob_iter->id);
}
FOREACH_OBJECT_IN_MODE_END;
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_objects_in_mode_unique_data(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be nullptr in a lot of cases. */
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact && (obact->mode != OB_MODE_OBJECT)) {
FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, obact->type, obact->mode, ob_iter) {
ob_iter->id.tag |= ID_TAG_DOIT;
}
FOREACH_OBJECT_IN_MODE_END;
FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, obact->type, obact->mode, ob_iter) {
if (ob_iter->id.tag & ID_TAG_DOIT) {
ob_iter->id.tag &= ~ID_TAG_DOIT;
CTX_data_id_list_add(result, &ob_iter->id);
}
}
FOREACH_OBJECT_IN_MODE_END;
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_visible_or_editable_bones_(const bContext *C,
bContextDataResult *result,
const bool editable_bones)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obedit = BKE_view_layer_edit_object_get(view_layer);
bArmature *arm = static_cast<bArmature *>(
(obedit && obedit->type == OB_ARMATURE) ? obedit->data : nullptr);
EditBone *flipbone = nullptr;
if (arm && arm->edbo) {
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
scene, view_layer, CTX_wm_view3d(C));
for (Object *ob : objects) {
arm = static_cast<bArmature *>(ob->data);
/* Attention: X-Axis Mirroring is also handled here... */
LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
/* first and foremost, bone must be visible and selected */
if (blender::animrig::bone_is_visible_editbone(arm, ebone)) {
/* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
* so that most users of this data don't need to explicitly check for it themselves.
*
* We need to make sure that these mirrored copies are not selected, otherwise some
* bones will be operated on twice.
*/
if (arm->flag & ARM_MIRROR_EDIT) {
flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
}
/* if we're filtering for editable too, use the check for that instead,
* as it has selection check too */
if (editable_bones) {
/* only selected + editable */
if (EBONE_EDITABLE(ebone)) {
CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
if ((flipbone) && !(flipbone->flag & BONE_SELECTED)) {
CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
}
}
}
else {
/* only include bones if visible */
CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
if ((flipbone) && blender::animrig::bone_is_visible_editbone(arm, flipbone) == 0) {
CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
}
}
}
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_visible_bones(const bContext *C, bContextDataResult *result)
{
return screen_ctx_visible_or_editable_bones_(C, result, false);
}
static eContextResult screen_ctx_editable_bones(const bContext *C, bContextDataResult *result)
{
return screen_ctx_visible_or_editable_bones_(C, result, true);
}
static eContextResult screen_ctx_selected_bones_(const bContext *C,
bContextDataResult *result,
const bool selected_editable_bones)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obedit = BKE_view_layer_edit_object_get(view_layer);
bArmature *arm = static_cast<bArmature *>(
(obedit && obedit->type == OB_ARMATURE) ? obedit->data : nullptr);
EditBone *flipbone = nullptr;
if (arm && arm->edbo) {
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
scene, view_layer, CTX_wm_view3d(C));
for (Object *ob : objects) {
arm = static_cast<bArmature *>(ob->data);
/* Attention: X-Axis Mirroring is also handled here... */
LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
/* first and foremost, bone must be visible and selected */
if (blender::animrig::bone_is_visible_editbone(arm, ebone) &&
(ebone->flag & BONE_SELECTED))
{
/* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
* so that most users of this data don't need to explicitly check for it themselves.
*
* We need to make sure that these mirrored copies are not selected, otherwise some
* bones will be operated on twice.
*/
if (arm->flag & ARM_MIRROR_EDIT) {
flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
}
/* if we're filtering for editable too, use the check for that instead,
* as it has selection check too */
if (selected_editable_bones) {
/* only selected + editable */
if (EBONE_EDITABLE(ebone)) {
CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
if ((flipbone) && !(flipbone->flag & BONE_SELECTED)) {
CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
}
}
}
else {
/* only include bones if selected */
CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
if ((flipbone) && !(flipbone->flag & BONE_SELECTED)) {
CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
}
}
}
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_bones(const bContext *C, bContextDataResult *result)
{
return screen_ctx_selected_bones_(C, result, false);
}
static eContextResult screen_ctx_selected_editable_bones(const bContext *C,
bContextDataResult *result)
{
return screen_ctx_selected_bones_(C, result, true);
}
static eContextResult screen_ctx_visible_pose_bones(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be nullptr in a lot of cases. */
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
Object *obpose = BKE_object_pose_armature_get(obact);
if (obpose && obpose->pose && obpose->data) {
if (obpose != obact) {
FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (obpose, pchan) {
CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
}
FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
}
else if (obact->mode & OB_MODE_POSE) {
FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (ob_iter, pchan) {
CTX_data_list_add(result, &ob_iter->id, &RNA_PoseBone, pchan);
}
FOREACH_PCHAN_VISIBLE_IN_OBJECT_END;
}
FOREACH_OBJECT_IN_MODE_END;
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_pose_bones(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be nullptr in a lot of cases. */
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
Object *obact = BKE_view_layer_active_object_get(view_layer);
Object *obpose = BKE_object_pose_armature_get(obact);
if (obpose && obpose->pose && obpose->data) {
if (obpose != obact) {
FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (obpose, pchan) {
CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
}
FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
}
else if (obact->mode & OB_MODE_POSE) {
FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) {
CTX_data_list_add(result, &ob_iter->id, &RNA_PoseBone, pchan);
}
FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
}
FOREACH_OBJECT_IN_MODE_END;
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_pose_bones_from_active_object(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
Object *obpose = BKE_object_pose_armature_get(obact);
if (obpose && obpose->pose && obpose->data) {
if (obpose != obact) {
FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (obpose, pchan) {
CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
}
FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
}
else if (obact->mode & OB_MODE_POSE) {
FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (obact, pchan) {
CTX_data_list_add(result, &obact->id, &RNA_PoseBone, pchan);
}
FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_active_bone(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact && obact->type == OB_ARMATURE) {
bArmature *arm = static_cast<bArmature *>(obact->data);
if (arm->edbo) {
if (arm->act_edbone) {
CTX_data_pointer_set(result, &arm->id, &RNA_EditBone, arm->act_edbone);
return CTX_RESULT_OK;
}
}
else {
if (arm->act_bone) {
CTX_data_pointer_set(result, &arm->id, &RNA_Bone, arm->act_bone);
return CTX_RESULT_OK;
}
}
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_active_pose_bone(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
Object *obpose = BKE_object_pose_armature_get(obact);
bPoseChannel *pchan = BKE_pose_channel_active_if_bonecoll_visible(obpose);
if (pchan) {
CTX_data_pointer_set(result, &obpose->id, &RNA_PoseBone, pchan);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_active_object(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact) {
CTX_data_id_pointer_set(result, &obact->id);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_property(const bContext *C, bContextDataResult *result)
{
PointerRNA ptr;
PropertyRNA *prop;
int index;
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.data && prop) {
/* UI_context_active_but_prop_get returns an index of 0 if the property is not
* an array, but other functions expect -1 for non-arrays. */
if (!RNA_property_array_check(prop)) {
index = -1;
}
CTX_data_type_set(result, CTX_DATA_TYPE_PROPERTY);
CTX_data_pointer_set_ptr(result, &ptr);
CTX_data_prop_set(result, prop, index);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_object(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact) {
CTX_data_id_pointer_set(result, &obact->id);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_edit_object(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obedit = BKE_view_layer_edit_object_get(view_layer);
/* convenience for now, 1 object per scene in editmode */
if (obedit) {
CTX_data_id_pointer_set(result, &obedit->id);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_sculpt_object(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact && (obact->mode & OB_MODE_SCULPT)) {
CTX_data_id_pointer_set(result, &obact->id);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_vertex_paint_object(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact && (obact->mode & OB_MODE_VERTEX_PAINT)) {
CTX_data_id_pointer_set(result, &obact->id);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_weight_paint_object(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact && (obact->mode & OB_MODE_ALL_WEIGHT_PAINT)) {
CTX_data_id_pointer_set(result, &obact->id);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_image_paint_object(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) {
CTX_data_id_pointer_set(result, &obact->id);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_particle_edit_object(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) {
CTX_data_id_pointer_set(result, &obact->id);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_pose_object(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
Object *obpose = BKE_object_pose_armature_get(obact);
if (obpose) {
CTX_data_id_pointer_set(result, &obpose->id);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_active_sequence_strip(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
Strip *strip = blender::seq::select_active_get(scene);
if (strip) {
CTX_data_pointer_set(result, &scene->id, &RNA_Strip, strip);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_sequences(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
Editing *ed = blender::seq::editing_get(scene);
if (ed) {
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
CTX_data_list_add(result, &scene->id, &RNA_Strip, strip);
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_sequences(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
Editing *ed = blender::seq::editing_get(scene);
if (ed) {
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
if (strip->flag & SELECT) {
CTX_data_list_add(result, &scene->id, &RNA_Strip, strip);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_editable_sequences(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
Editing *ed = blender::seq::editing_get(scene);
if (ed == nullptr) {
return CTX_RESULT_NO_DATA;
}
ListBase *channels = blender::seq::channels_displayed_get(ed);
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
if (strip->flag & SELECT && !blender::seq::transform_is_locked(channels, strip)) {
CTX_data_list_add(result, &scene->id, &RNA_Strip, strip);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_active_nla_track(const bContext *C, bContextDataResult *result)
{
PointerRNA ptr;
if (ANIM_nla_context_track_ptr(C, &ptr)) {
CTX_data_pointer_set_ptr(result, &ptr);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_active_nla_strip(const bContext *C, bContextDataResult *result)
{
PointerRNA ptr;
if (ANIM_nla_context_strip_ptr(C, &ptr)) {
CTX_data_pointer_set_ptr(result, &ptr);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_nla_strips(const bContext *C, bContextDataResult *result)
{
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) != 0) {
ListBase anim_data = {nullptr, nullptr};
ANIM_animdata_filter(
&ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac.data, eAnimCont_Types(ac.datatype));
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (ale->datatype != ALE_NLASTRIP) {
continue;
}
NlaTrack *nlt = (NlaTrack *)ale->data;
LISTBASE_FOREACH (NlaStrip *, strip, &nlt->strips) {
if (strip->flag & NLASTRIP_FLAG_SELECT) {
CTX_data_list_add(result, ale->id, &RNA_NlaStrip, strip);
}
}
}
ANIM_animdata_freelist(&anim_data);
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_movieclip_tracks(const bContext *C,
bContextDataResult *result)
{
SpaceClip *space_clip = CTX_wm_space_clip(C);
if (space_clip == nullptr) {
return CTX_RESULT_NO_DATA;
}
MovieClip *clip = ED_space_clip_get_clip(space_clip);
if (clip == nullptr) {
return CTX_RESULT_NO_DATA;
}
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
if (!TRACK_SELECTED(track)) {
continue;
}
CTX_data_list_add(result, &clip->id, &RNA_MovieTrackingTrack, track);
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_annotation_data(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *area = CTX_wm_area(C);
Scene *scene = WM_window_get_active_scene(win);
bGPdata *gpd = ED_annotation_data_get_active_direct((ID *)screen, area, scene);
if (gpd) {
CTX_data_id_pointer_set(result, &gpd->id);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_annotation_data_owner(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *area = CTX_wm_area(C);
Scene *scene = WM_window_get_active_scene(win);
/* Pointer to which data/datablock owns the reference to the Grease Pencil data being used. */
PointerRNA ptr;
bGPdata **gpd_ptr = ED_annotation_data_get_pointers_direct((ID *)screen, area, scene, &ptr);
if (gpd_ptr) {
CTX_data_pointer_set_ptr(result, &ptr);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_active_annotation_layer(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *area = CTX_wm_area(C);
Scene *scene = WM_window_get_active_scene(win);
bGPdata *gpd = ED_annotation_data_get_active_direct((ID *)screen, area, scene);
if (gpd) {
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_AnnotationLayer, gpl);
return CTX_RESULT_OK;
}
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_grease_pencil_data(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
if (obact && obact->type == OB_GREASE_PENCIL) {
GreasePencil *grease_pencil = static_cast<GreasePencil *>(obact->data);
CTX_data_id_pointer_set(result, &grease_pencil->id);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_active_operator(const bContext *C, bContextDataResult *result)
{
wmOperator *op = nullptr;
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile) {
op = sfile->op;
}
else if ((op = UI_context_active_operator_get(C))) {
/* do nothing */
}
else {
/* NOTE: this checks poll, could be a problem, but this also
* happens for the toolbar */
op = WM_operator_last_redo(C);
}
/* TODO: get the operator from popup's. */
if (op && op->ptr) {
CTX_data_pointer_set(result, nullptr, &RNA_Operator, op);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_sel_actions_impl(const bContext *C,
bContextDataResult *result,
bool active_only,
bool editable)
{
bAnimContext ac;
if (!ANIM_animdata_get_context(C, &ac) || !ELEM(ac.spacetype, SPACE_ACTION, SPACE_GRAPH)) {
return CTX_RESULT_NO_DATA;
}
/* In the Action and Shape Key editor always use the action field at the top. */
if (ac.spacetype == SPACE_ACTION) {
SpaceAction *saction = (SpaceAction *)ac.sl;
if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY)) {
if (active_only) {
CTX_data_id_pointer_set(result, (ID *)saction->action);
}
else {
if (saction->action && !(editable && !ID_IS_EDITABLE(saction->action))) {
CTX_data_id_list_add(result, &saction->action->id);
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
}
return CTX_RESULT_OK;
}
}
/* Search for selected animation data items. */
ListBase anim_data = {nullptr, nullptr};
int filter = ANIMFILTER_DATA_VISIBLE;
bool check_selected = false;
switch (ac.spacetype) {
case SPACE_GRAPH:
filter |= ANIMFILTER_FCURVESONLY | ANIMFILTER_CURVE_VISIBLE |
(active_only ? ANIMFILTER_ACTIVE : ANIMFILTER_SEL);
break;
case SPACE_ACTION:
filter |= ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS;
check_selected = true;
break;
default:
BLI_assert_unreachable();
}
ANIM_animdata_filter(
&ac, &anim_data, eAnimFilter_Flags(filter), ac.data, eAnimCont_Types(ac.datatype));
blender::Set<bAction *> seen_set;
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
/* In dope-sheet check selection status of individual items, skipping
* if not selected or has no selection flag. This is needed so that
* selecting action or group rows without any channels works. */
if (check_selected && ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_SELECT) <= 0) {
continue;
}
bAction *action = ANIM_channel_action_get(ale);
if (!action) {
continue;
}
if (active_only) {
CTX_data_id_pointer_set(result, (ID *)action);
break;
}
if (editable && !ID_IS_EDITABLE(action)) {
continue;
}
/* Add the action to the output list if not already added. */
if (seen_set.add(action)) {
CTX_data_id_list_add(result, &action->id);
}
}
ANIM_animdata_freelist(&anim_data);
if (!active_only) {
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
}
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_active_action(const bContext *C, bContextDataResult *result)
{
return screen_ctx_sel_actions_impl(C, result, true, false);
}
static eContextResult screen_ctx_selected_visible_actions(const bContext *C,
bContextDataResult *result)
{
return screen_ctx_sel_actions_impl(C, result, false, false);
}
static eContextResult screen_ctx_selected_editable_actions(const bContext *C,
bContextDataResult *result)
{
return screen_ctx_sel_actions_impl(C, result, false, true);
}
static eContextResult screen_ctx_sel_edit_fcurves_(const bContext *C,
bContextDataResult *result,
const int extra_filter)
{
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) && ELEM(ac.spacetype, SPACE_ACTION, SPACE_GRAPH)) {
ListBase anim_data = {nullptr, nullptr};
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS) |
(ac.spacetype == SPACE_GRAPH ?
(ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY) :
ANIMFILTER_LIST_VISIBLE) |
extra_filter;
ANIM_animdata_filter(
&ac, &anim_data, eAnimFilter_Flags(filter), ac.data, eAnimCont_Types(ac.datatype));
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
CTX_data_list_add(result, ale->fcurve_owner_id, &RNA_FCurve, ale->data);
}
}
ANIM_animdata_freelist(&anim_data);
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_editable_fcurves(const bContext *C, bContextDataResult *result)
{
return screen_ctx_sel_edit_fcurves_(C, result, ANIMFILTER_FOREDIT);
}
static eContextResult screen_ctx_visible_fcurves(const bContext *C, bContextDataResult *result)
{
return screen_ctx_sel_edit_fcurves_(C, result, 0);
}
static eContextResult screen_ctx_selected_editable_fcurves(const bContext *C,
bContextDataResult *result)
{
return screen_ctx_sel_edit_fcurves_(C, result, ANIMFILTER_SEL | ANIMFILTER_FOREDIT);
}
static eContextResult screen_ctx_selected_visible_fcurves(const bContext *C,
bContextDataResult *result)
{
return screen_ctx_sel_edit_fcurves_(C, result, ANIMFILTER_SEL);
}
static eContextResult screen_ctx_active_editable_fcurve(const bContext *C,
bContextDataResult *result)
{
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) && ELEM(ac.spacetype, SPACE_GRAPH)) {
ListBase anim_data = {nullptr, nullptr};
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT |
ANIMFILTER_FCURVESONLY | ANIMFILTER_CURVE_VISIBLE);
ANIM_animdata_filter(
&ac, &anim_data, eAnimFilter_Flags(filter), ac.data, eAnimCont_Types(ac.datatype));
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
CTX_data_pointer_set(result, ale->fcurve_owner_id, &RNA_FCurve, ale->data);
break;
}
}
ANIM_animdata_freelist(&anim_data);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_editable_keyframes(const bContext *C,
bContextDataResult *result)
{
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) && ELEM(ac.spacetype, SPACE_ACTION, SPACE_GRAPH)) {
ListBase anim_data = {nullptr, nullptr};
/* Use keyframes from editable selected FCurves. */
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS | ANIMFILTER_FOREDIT |
ANIMFILTER_SEL) |
(ac.spacetype == SPACE_GRAPH ?
(ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY) :
ANIMFILTER_LIST_VISIBLE);
ANIM_animdata_filter(
&ac, &anim_data, eAnimFilter_Flags(filter), ac.data, eAnimCont_Types(ac.datatype));
int i;
FCurve *fcurve;
BezTriple *bezt;
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (!ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
continue;
}
fcurve = (FCurve *)ale->data;
if (fcurve->bezt == nullptr) {
/* Skip baked FCurves. */
continue;
}
for (i = 0, bezt = fcurve->bezt; i < fcurve->totvert; i++, bezt++) {
if ((bezt->f2 & SELECT) == 0) {
continue;
}
CTX_data_list_add(result, ale->fcurve_owner_id, &RNA_Keyframe, bezt);
}
}
ANIM_animdata_freelist(&anim_data);
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_asset_library(const bContext *C, bContextDataResult *result)
{
WorkSpace *workspace = CTX_wm_workspace(C);
CTX_data_pointer_set(
result, &workspace->id, &RNA_AssetLibraryReference, &workspace->asset_library_ref);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_ui_list(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
ARegion *region = CTX_wm_region(C);
if (region) {
uiList *list = UI_list_find_mouse_over(region, win->eventstate);
if (list) {
CTX_data_pointer_set(result, nullptr, &RNA_UIList, list);
return CTX_RESULT_OK;
}
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_active_strip(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
Strip *strip = blender::seq::select_active_get(scene);
if (strip) {
CTX_data_pointer_set(result, &scene->id, &RNA_Strip, strip);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_strips(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
Editing *ed = blender::seq::editing_get(scene);
if (ed) {
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
CTX_data_list_add(result, &scene->id, &RNA_Strip, strip);
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_strips(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
Editing *ed = blender::seq::editing_get(scene);
if (ed) {
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
if (strip->flag & SELECT) {
CTX_data_list_add(result, &scene->id, &RNA_Strip, strip);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_editable_strips(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
Editing *ed = blender::seq::editing_get(scene);
if (ed == nullptr) {
return CTX_RESULT_NO_DATA;
}
ListBase *channels = blender::seq::channels_displayed_get(ed);
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
if (strip->flag & SELECT && !blender::seq::transform_is_locked(channels, strip)) {
CTX_data_list_add(result, &scene->id, &RNA_Strip, strip);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
/* Registry of context callback functions. */
using context_callback = eContextResult (*)(const bContext *C, bContextDataResult *result);
static const blender::Map<blender::StringRef, context_callback> &
ensure_ed_screen_context_functions()
{
static blender::Map<blender::StringRef, context_callback> screen_context_functions = []() {
blender::Map<blender::StringRef, context_callback> map;
map.add("scene", screen_ctx_scene);
map.add("visible_objects", screen_ctx_visible_objects);
map.add("selectable_objects", screen_ctx_selectable_objects);
map.add("selected_objects", screen_ctx_selected_objects);
map.add("selected_editable_objects", screen_ctx_selected_editable_objects);
map.add("editable_objects", screen_ctx_editable_objects);
map.add("objects_in_mode", screen_ctx_objects_in_mode);
map.add("objects_in_mode_unique_data", screen_ctx_objects_in_mode_unique_data);
map.add("visible_bones", screen_ctx_visible_bones);
map.add("editable_bones", screen_ctx_editable_bones);
map.add("selected_bones", screen_ctx_selected_bones);
map.add("selected_editable_bones", screen_ctx_selected_editable_bones);
map.add("visible_pose_bones", screen_ctx_visible_pose_bones);
map.add("selected_pose_bones", screen_ctx_selected_pose_bones);
map.add("selected_pose_bones_from_active_object",
screen_ctx_selected_pose_bones_from_active_object);
map.add("active_bone", screen_ctx_active_bone);
map.add("active_pose_bone", screen_ctx_active_pose_bone);
map.add("active_object", screen_ctx_active_object);
map.add("object", screen_ctx_object);
map.add("edit_object", screen_ctx_edit_object);
map.add("sculpt_object", screen_ctx_sculpt_object);
map.add("vertex_paint_object", screen_ctx_vertex_paint_object);
map.add("weight_paint_object", screen_ctx_weight_paint_object);
map.add("image_paint_object", screen_ctx_image_paint_object);
map.add("particle_edit_object", screen_ctx_particle_edit_object);
map.add("pose_object", screen_ctx_pose_object);
map.add("active_sequence_strip", screen_ctx_active_sequence_strip); /* DEPRECATED */
map.add("sequences", screen_ctx_sequences); /* DEPRECATED */
map.add("selected_sequences", screen_ctx_selected_sequences); /* DEPRECATED */
map.add("selected_editable_sequences",
screen_ctx_selected_editable_sequences); /* DEPRECATED */
map.add("active_nla_track", screen_ctx_active_nla_track);
map.add("active_nla_strip", screen_ctx_active_nla_strip);
map.add("selected_nla_strips", screen_ctx_selected_nla_strips);
map.add("selected_movieclip_tracks", screen_ctx_selected_movieclip_tracks);
map.add("annotation_data", screen_ctx_annotation_data);
map.add("annotation_data_owner", screen_ctx_annotation_data_owner);
map.add("active_annotation_layer", screen_ctx_active_annotation_layer);
map.add("grease_pencil", screen_ctx_grease_pencil_data);
map.add("active_operator", screen_ctx_active_operator);
map.add("active_action", screen_ctx_active_action);
map.add("selected_visible_actions", screen_ctx_selected_visible_actions);
map.add("selected_editable_actions", screen_ctx_selected_editable_actions);
map.add("editable_fcurves", screen_ctx_editable_fcurves);
map.add("visible_fcurves", screen_ctx_visible_fcurves);
map.add("selected_editable_fcurves", screen_ctx_selected_editable_fcurves);
map.add("selected_visible_fcurves", screen_ctx_selected_visible_fcurves);
map.add("active_editable_fcurve", screen_ctx_active_editable_fcurve);
map.add("selected_editable_keyframes", screen_ctx_selected_editable_keyframes);
map.add("asset_library_reference", screen_ctx_asset_library);
map.add("ui_list", screen_ctx_ui_list);
map.add("property", screen_ctx_property);
map.add("active_strip", screen_ctx_active_strip);
map.add("strips", screen_ctx_strips);
map.add("selected_strips", screen_ctx_selected_strips);
map.add("selected_editable_strips", screen_ctx_selected_editable_strips);
return map;
}();
return screen_context_functions;
}
int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
{
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, screen_context_dir);
return CTX_RESULT_OK;
}
const blender::Map<blender::StringRef, context_callback> &functions =
ensure_ed_screen_context_functions();
context_callback callback = functions.lookup_default(member, nullptr);
if (callback == nullptr) {
return CTX_RESULT_MEMBER_NOT_FOUND;
}
return callback(C, result);
}