ViewLayer: fix missing sync in object APIs (fixes T101128, T101204)

Since D15885, most (all?) python based importers are failing with an
error like RuntimeError: Error: Object 'Cube' can't be selected
because it is not in View Layer, whenever they try to mark
just-created objects selected via obj.select_set(True). Happens at
least in FBX and (legacy) OBJ importers -- effectively they end up
creating just the first imported object before failing with this
exception.

Looks like BKE_view_layer_synced_ensure calls were missing before
BKE_view_layer_base_find in rna_object_api.c.

Reviewed By: Campbell Barton
Differential Revision: https://developer.blender.org/D16004
This commit is contained in:
Aras Pranckevicius 2022-09-20 09:45:18 +03:00
parent b950a8fb79
commit e00f76c6a8
Notes: blender-bot 2023-02-14 18:14:59 +01:00
Referenced by issue #103031, Regression: My blend file crashes when rendering in Blender 3.4 upwards, because of an unchecked NULL in the code. (stack trace provided)
Referenced by issue #101272, Missing view layer updates handling collections in python
Referenced by issue #101128, Regression: Torus Adding Error (can't be selected because it is not in View Layer)
Referenced by issue blender/blender-addons#101204, Import FBX ERROR
1 changed files with 52 additions and 45 deletions

View File

@ -77,13 +77,36 @@ static const EnumPropertyItem space_items[] = {
# include "MEM_guardedalloc.h"
static void rna_Object_select_set(
Object *ob, bContext *C, ReportList *reports, bool select, ViewLayer *view_layer)
static Base *find_view_layer_base_with_synced_ensure(
Object *ob, bContext *C, PointerRNA *view_layer_ptr, Scene **r_scene, ViewLayer **r_view_layer)
{
if (view_layer == NULL) {
Scene *scene;
ViewLayer *view_layer;
if (view_layer_ptr->data) {
scene = (Scene *)view_layer_ptr->owner_id;
view_layer = view_layer_ptr->data;
}
else {
scene = CTX_data_scene(C);
view_layer = CTX_data_view_layer(C);
}
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (r_scene != NULL) {
*r_scene = scene;
}
if (r_view_layer != NULL) {
*r_view_layer = view_layer;
}
BKE_view_layer_synced_ensure(scene, view_layer);
return BKE_view_layer_base_find(view_layer, ob);
}
static void rna_Object_select_set(
Object *ob, bContext *C, ReportList *reports, bool select, PointerRNA *view_layer_ptr)
{
Scene *scene;
ViewLayer *view_layer;
Base *base = find_view_layer_base_with_synced_ensure(ob, C, view_layer_ptr, &scene, &view_layer);
if (!base) {
if (select) {
@ -98,19 +121,14 @@ static void rna_Object_select_set(
ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
Scene *scene = CTX_data_scene(C);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
ED_outliner_select_sync_from_object_tag(C);
}
static bool rna_Object_select_get(Object *ob, bContext *C, ViewLayer *view_layer)
static bool rna_Object_select_get(Object *ob, bContext *C, PointerRNA *view_layer_ptr)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
}
Base *base = BKE_view_layer_base_find(view_layer, ob);
Base *base = find_view_layer_base_with_synced_ensure(ob, C, view_layer_ptr, NULL, NULL);
if (!base) {
return false;
}
@ -119,13 +137,11 @@ static bool rna_Object_select_get(Object *ob, bContext *C, ViewLayer *view_layer
}
static void rna_Object_hide_set(
Object *ob, bContext *C, ReportList *reports, bool hide, ViewLayer *view_layer)
Object *ob, bContext *C, ReportList *reports, bool hide, PointerRNA *view_layer_ptr)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
}
Base *base = BKE_view_layer_base_find(view_layer, ob);
Scene *scene;
ViewLayer *view_layer;
Base *base = find_view_layer_base_with_synced_ensure(ob, C, view_layer_ptr, &scene, &view_layer);
if (!base) {
if (hide) {
BKE_reportf(reports,
@ -144,19 +160,14 @@ static void rna_Object_hide_set(
base->flag &= ~BASE_HIDDEN;
}
Scene *scene = CTX_data_scene(C);
BKE_view_layer_need_resync_tag(view_layer);
DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
static bool rna_Object_hide_get(Object *ob, bContext *C, ViewLayer *view_layer)
static bool rna_Object_hide_get(Object *ob, bContext *C, PointerRNA *view_layer_ptr)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
}
Base *base = BKE_view_layer_base_find(view_layer, ob);
Base *base = find_view_layer_base_with_synced_ensure(ob, C, view_layer_ptr, NULL, NULL);
if (!base) {
return false;
}
@ -164,15 +175,15 @@ static bool rna_Object_hide_get(Object *ob, bContext *C, ViewLayer *view_layer)
return ((base->flag & BASE_HIDDEN) != 0);
}
static bool rna_Object_visible_get(Object *ob, bContext *C, ViewLayer *view_layer, View3D *v3d)
static bool rna_Object_visible_get(Object *ob,
bContext *C,
PointerRNA *view_layer_ptr,
View3D *v3d)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
}
Base *base = find_view_layer_base_with_synced_ensure(ob, C, view_layer_ptr, NULL, NULL);
if (v3d == NULL) {
v3d = CTX_wm_view3d(C);
}
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
return false;
@ -181,13 +192,9 @@ static bool rna_Object_visible_get(Object *ob, bContext *C, ViewLayer *view_laye
return BASE_VISIBLE(v3d, base);
}
static bool rna_Object_holdout_get(Object *ob, bContext *C, ViewLayer *view_layer)
static bool rna_Object_holdout_get(Object *ob, bContext *C, PointerRNA *view_layer_ptr)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
}
Base *base = BKE_view_layer_base_find(view_layer, ob);
Base *base = find_view_layer_base_with_synced_ensure(ob, C, view_layer_ptr, NULL, NULL);
if (!base) {
return false;
}
@ -195,17 +202,9 @@ static bool rna_Object_holdout_get(Object *ob, bContext *C, ViewLayer *view_laye
return ((base->flag & BASE_HOLDOUT) != 0);
}
static bool rna_Object_indirect_only_get(Object *ob, bContext *C, ViewLayer *view_layer)
static bool rna_Object_indirect_only_get(Object *ob, bContext *C, PointerRNA *view_layer_ptr)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
}
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
return false;
}
Base *base = find_view_layer_base_with_synced_ensure(ob, C, view_layer_ptr, NULL, NULL);
return ((base->flag & BASE_INDIRECT_ONLY) != 0);
}
@ -227,6 +226,7 @@ static Base *rna_Object_local_view_property_helper(bScreen *screen,
view_layer = WM_window_get_active_view_layer(win);
}
BKE_view_layer_synced_ensure(win ? WM_window_get_active_scene(win) : NULL, view_layer);
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (base == NULL) {
BKE_reportf(
@ -831,6 +831,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
parm = RNA_def_boolean(func, "result", 0, "", "Object selected");
RNA_def_function_return(func, parm);
@ -842,6 +843,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
func = RNA_def_function(srna, "hide_get", "rna_Object_hide_get");
RNA_def_function_ui_description(
@ -850,6 +852,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
parm = RNA_def_boolean(func, "result", 0, "", "Object hidden");
RNA_def_function_return(func, parm);
@ -861,6 +864,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
func = RNA_def_function(srna, "visible_get", "rna_Object_visible_get");
RNA_def_function_ui_description(func,
@ -869,6 +873,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
parm = RNA_def_pointer(
func, "viewport", "SpaceView3D", "", "Use this instead of the active 3D viewport");
parm = RNA_def_boolean(func, "result", 0, "", "Object visible");
@ -879,6 +884,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
parm = RNA_def_boolean(func, "result", 0, "", "Object holdout");
RNA_def_function_return(func, parm);
@ -889,6 +895,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
parm = RNA_def_boolean(func, "result", 0, "", "Object indirect only");
RNA_def_function_return(func, parm);