Curves: fix edit mode detection

This adds missing cases to detect edit mode for Curves objects.
Unlike other object types, Curves do not have specific edit data,
rather we edit the original data directly, and rely on `Object.mode`.

For this, `BKE_object_data_is_in_editmode` had to be modified to
take a pointer to the object. This affects two places: the outliner
and the dependency graph. For the former place, the object pointer
is readily available, and we can use it. For the latter, the object
pointer is not available, however since it is used to update edit
mode pointers, and since Curves do not have such data, we can
safely pass null to the function here.

This also fixes the assertion failure that happens when closing a file
in edit mode.

Differential Revision: https://developer.blender.org/D14330
This commit is contained in:
Kévin Dietrich 2022-04-05 19:59:20 +02:00
parent 4de704a6df
commit fc8bcd26c0
5 changed files with 19 additions and 5 deletions

View File

@ -140,7 +140,7 @@ bool BKE_object_is_in_wpaint_select_vert(const struct Object *ob);
bool BKE_object_has_mode_data(const struct Object *ob, eObjectMode object_mode);
bool BKE_object_is_mode_compat(const struct Object *ob, eObjectMode object_mode);
bool BKE_object_data_is_in_editmode(const struct ID *id);
bool BKE_object_data_is_in_editmode(const struct Object *ob, const struct ID *id);
char *BKE_object_data_editmode_flush_ptr_get(struct ID *id);

View File

@ -1897,6 +1897,8 @@ bool BKE_object_is_in_editmode(const Object *ob)
case OB_GPENCIL:
/* Grease Pencil object has no edit mode data. */
return GPENCIL_EDIT_MODE((bGPdata *)ob->data);
case OB_CURVES:
return ob->mode == OB_MODE_EDIT;
default:
return false;
}
@ -1907,7 +1909,7 @@ bool BKE_object_is_in_editmode_vgroup(const Object *ob)
return (OB_TYPE_SUPPORT_VGROUP(ob->type) && BKE_object_is_in_editmode(ob));
}
bool BKE_object_data_is_in_editmode(const ID *id)
bool BKE_object_data_is_in_editmode(const Object *ob, const ID *id)
{
const short type = GS(id->name);
BLI_assert(OB_DATA_SUPPORT_EDITMODE(type));
@ -1923,6 +1925,11 @@ bool BKE_object_data_is_in_editmode(const ID *id)
return ((const Lattice *)id)->editlatt != nullptr;
case ID_AR:
return ((const bArmature *)id)->edbo != nullptr;
case ID_CV:
if (ob) {
return BKE_object_is_in_editmode(ob);
}
return false;
default:
BLI_assert_unreachable();
return false;
@ -1970,6 +1977,10 @@ char *BKE_object_data_editmode_flush_ptr_get(struct ID *id)
bArmature *arm = (bArmature *)id;
return &arm->needs_flush_to_id;
}
case ID_CV: {
/* Curves have no edit mode data. */
return nullptr;
}
default:
BLI_assert_unreachable();
return nullptr;

View File

@ -872,7 +872,9 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode
* TODO: Investigate modes besides edit-mode. */
if (check_datablock_expanded(id_cow) && !id_node->is_cow_explicitly_tagged) {
const ID_Type id_type = GS(id_orig->name);
if (OB_DATA_SUPPORT_EDITMODE(id_type) && BKE_object_data_is_in_editmode(id_orig)) {
/* Pass nullptr as the object is only needed for Curves which do not have edit mode pointers.
*/
if (OB_DATA_SUPPORT_EDITMODE(id_type) && BKE_object_data_is_in_editmode(nullptr, id_orig)) {
/* Make sure pointers in the edit mode data are updated in the copy.
* This allows depsgraph to pick up changes made in another context after it has been
* evaluated. Consider the following scenario:

View File

@ -120,7 +120,7 @@ static bool is_object_data_in_editmode(const ID *id, const Object *obact)
}
return ((obact && (obact->mode & OB_MODE_EDIT)) && (id && OB_DATA_SUPPORT_EDITMODE(id_type)) &&
(GS(((ID *)obact->data)->name) == id_type) && BKE_object_data_is_in_editmode(id));
(GS(((ID *)obact->data)->name) == id_type) && BKE_object_data_is_in_editmode(obact, id));
}
/** \} */

View File

@ -534,7 +534,8 @@ enum {
(ELEM(_type, OB_MESH, OB_SURF, OB_CURVES_LEGACY, OB_LATTICE))
/** Matches #OB_TYPE_SUPPORT_EDITMODE. */
#define OB_DATA_SUPPORT_EDITMODE(_type) (ELEM(_type, ID_ME, ID_CU_LEGACY, ID_MB, ID_LT, ID_AR))
#define OB_DATA_SUPPORT_EDITMODE(_type) \
(ELEM(_type, ID_ME, ID_CU_LEGACY, ID_MB, ID_LT, ID_AR, ID_CV))
/* is this ID type used as object data */
#define OB_DATA_SUPPORT_ID(_id_type) \