Fix #139133: Crash entering edit mode for curve/text objects
- Make Curve::type the source of truth for the curve type, instead of Curve::vfont, since it's possible for this to be set to null from RNA which effectively changed it's type. See #138730. - Update objects to match the curve type on file read. Without this, an object may link to a curve in another file which can be replaced by a curve data-block of a different type. Note that updating the object type was already being done when reloading library data and setting object data, just not on file load. Ref !139137
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 72
|
||||
#define BLENDER_FILE_SUBVERSION 73
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
||||
@@ -99,7 +99,7 @@ void BKE_curve_editfont_free(Curve *cu);
|
||||
void BKE_curve_init(Curve *cu, short curve_type);
|
||||
Curve *BKE_curve_add(Main *bmain, const char *name, int type);
|
||||
short BKE_curve_type_get(const Curve *cu);
|
||||
void BKE_curve_type_test(Object *ob);
|
||||
void BKE_curve_type_test(Object *ob, bool dimension_update);
|
||||
void BKE_curve_dimension_update(Curve *cu);
|
||||
|
||||
void BKE_curve_texspace_calc(Curve *cu);
|
||||
|
||||
@@ -179,7 +179,7 @@ static void curve_blend_write(BlendWriter *writer, ID *id, const void *id_addres
|
||||
/* direct data */
|
||||
BLO_write_pointer_array(writer, cu->totcol, cu->mat);
|
||||
|
||||
if (cu->vfont) {
|
||||
if (cu->type == OB_FONT) {
|
||||
BLO_write_string(writer, cu->str);
|
||||
BLO_write_struct_array(writer, CharInfo, cu->len_char32 + 1, cu->strinfo);
|
||||
BLO_write_struct_array(writer, TextBox, cu->totbox, cu->tb);
|
||||
@@ -223,7 +223,7 @@ static void curve_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
BLO_read_struct_array(reader, CharInfo, cu->len_char32 + 1, &cu->strinfo);
|
||||
BLO_read_struct_array(reader, TextBox, cu->totbox, &cu->tb);
|
||||
|
||||
if (cu->vfont == nullptr) {
|
||||
if (cu->type != OB_FONT) {
|
||||
BLO_read_struct_list(reader, Nurb, &(cu->nurb));
|
||||
}
|
||||
else {
|
||||
@@ -255,7 +255,7 @@ static void curve_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
BLO_read_struct_array(reader, BPoint, nu->pntsu * nu->pntsv, &nu->bp);
|
||||
BLO_read_float_array(reader, KNOTSU(nu), &nu->knotsu);
|
||||
BLO_read_float_array(reader, KNOTSV(nu), &nu->knotsv);
|
||||
if (cu->vfont == nullptr) {
|
||||
if (cu->type != OB_FONT) {
|
||||
nu->charidx = 0;
|
||||
}
|
||||
}
|
||||
@@ -420,24 +420,7 @@ const ListBase *BKE_curve_editNurbs_get_for_read(const Curve *cu)
|
||||
|
||||
short BKE_curve_type_get(const Curve *cu)
|
||||
{
|
||||
int type = cu->type;
|
||||
|
||||
if (cu->vfont) {
|
||||
return OB_FONT;
|
||||
}
|
||||
|
||||
if (!cu->type) {
|
||||
type = OB_CURVES_LEGACY;
|
||||
|
||||
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
|
||||
if (nu->pntsv > 1) {
|
||||
type = OB_SURF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
return cu->type;
|
||||
}
|
||||
|
||||
void BKE_curve_dimension_update(Curve *cu)
|
||||
@@ -457,14 +440,16 @@ void BKE_curve_dimension_update(Curve *cu)
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_curve_type_test(Object *ob)
|
||||
void BKE_curve_type_test(Object *ob, const bool dimension_update)
|
||||
{
|
||||
ob->type = BKE_curve_type_get((Curve *)ob->data);
|
||||
|
||||
if (ob->type == OB_CURVES_LEGACY) {
|
||||
Curve *cu = (Curve *)ob->data;
|
||||
if (CU_IS_2D(cu)) {
|
||||
BKE_curve_dimension_update(cu);
|
||||
if (dimension_update) {
|
||||
if (ob->type == OB_CURVES_LEGACY) {
|
||||
Curve *cu = (Curve *)ob->data;
|
||||
if (CU_IS_2D(cu)) {
|
||||
BKE_curve_dimension_update(cu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1785,7 +1785,7 @@ Key **BKE_key_from_id_p(ID *id)
|
||||
}
|
||||
case ID_CU_LEGACY: {
|
||||
Curve *cu = (Curve *)id;
|
||||
if (cu->vfont == nullptr) {
|
||||
if (cu->type != OB_FONT) {
|
||||
return &cu->key;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -412,7 +412,7 @@ static void libblock_remap_data_postprocess_obdata_relink(Main *bmain, Object *o
|
||||
multires_force_sculpt_rebuild(ob);
|
||||
break;
|
||||
case ID_CU_LEGACY:
|
||||
BKE_curve_type_test(ob);
|
||||
BKE_curve_type_test(ob, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -940,6 +940,20 @@ static void object_blend_read_after_liblink(BlendLibReader *reader, ID *id)
|
||||
reports->count.missing_obdata++;
|
||||
}
|
||||
|
||||
if (ob->data && ELEM(ob->type, OB_FONT, OB_CURVES_LEGACY, OB_SURF)) {
|
||||
/* NOTE: This case may happen when linked curve data changes it's type,
|
||||
* since a #Curve may be used for Text/Surface/Curve.
|
||||
* Since the same ID type is used for all of these.
|
||||
* Within a file (no library linking) this should never happen.
|
||||
* see: #139133. */
|
||||
|
||||
const ID *ob_data_id = static_cast<ID *>(ob->data);
|
||||
BLI_assert(GS(ob_data_id->name) == ID_CU_LEGACY);
|
||||
/* Don't recalculate any internal curve data is this is low level logic
|
||||
* intended to avoid errors when switching between font/curve types. */
|
||||
BKE_curve_type_test(ob, false);
|
||||
}
|
||||
|
||||
/* When the object is local and the data is library its possible
|
||||
* the material list size gets out of sync. #22663. */
|
||||
if (ob->data && ob->id.lib != static_cast<ID *>(ob->data)->lib) {
|
||||
@@ -1778,7 +1792,7 @@ char *BKE_object_data_editmode_flush_ptr_get(ID *id)
|
||||
break;
|
||||
}
|
||||
case ID_CU_LEGACY: {
|
||||
if (((Curve *)id)->vfont != nullptr) {
|
||||
if (((Curve *)id)->type == OB_FONT) {
|
||||
EditFont *ef = ((Curve *)id)->editfont;
|
||||
if (ef != nullptr) {
|
||||
return &ef->needs_flush_to_id;
|
||||
|
||||
@@ -5161,6 +5161,30 @@ void blo_do_versions_450(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||
version_set_default_bone_drawtype(bmain);
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 405, 73)) {
|
||||
/* Make #Curve::type the source of truth for the curve type.
|
||||
* Previously #Curve::vfont was checked which is error prone
|
||||
* since the member can become null at run-time, see: #139133. */
|
||||
LISTBASE_FOREACH (Curve *, cu, &bmain->curves) {
|
||||
if (ELEM(cu->type, OB_CURVES_LEGACY, OB_FONT, OB_SURF)) {
|
||||
continue;
|
||||
}
|
||||
short type = OB_CURVES_LEGACY;
|
||||
if (cu->vfont) {
|
||||
type = OB_FONT;
|
||||
}
|
||||
else {
|
||||
LISTBASE_FOREACH (const Nurb *, nu, &cu->nurb) {
|
||||
if (nu->pntsv > 1) {
|
||||
type = OB_SURF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cu->type = type;
|
||||
}
|
||||
}
|
||||
|
||||
/* Always run this versioning (keep at the bottom of the function). Meshes are written with the
|
||||
* legacy format which always needs to be converted to the new format on file load. To be moved
|
||||
* to a subversion check in 5.0. */
|
||||
|
||||
@@ -231,7 +231,13 @@ typedef struct Curve {
|
||||
float texspace_location[3];
|
||||
float texspace_size[3];
|
||||
|
||||
/** Creation-time type of curve datablock. */
|
||||
/**
|
||||
* Object type of curve data-block (#ObjectType).
|
||||
* This must be one of:
|
||||
* - #OB_CURVES_LEGACY.
|
||||
* - #OB_FONT.
|
||||
* - #OB_SURF.
|
||||
*/
|
||||
short type;
|
||||
|
||||
char texspace_flag;
|
||||
|
||||
@@ -559,7 +559,7 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, ReportList *r
|
||||
BKE_object_materials_sync_length(G_MAIN, ob, id);
|
||||
|
||||
if (GS(id->name) == ID_CU_LEGACY) {
|
||||
BKE_curve_type_test(ob);
|
||||
BKE_curve_type_test(ob, true);
|
||||
}
|
||||
else if (ob->type == OB_ARMATURE) {
|
||||
BKE_pose_rebuild(G_MAIN, ob, static_cast<bArmature *>(ob->data), true);
|
||||
|
||||
Reference in New Issue
Block a user