Fix #112068: Crash when loading converted curves

In 2788fa915b the `CurvesGeometry::blend_write` and `CurvesGeometry::blend_read` functions were added. Unfortunately, the commit also altered the writing logic and introduced a bug where loading a file with a converted `Curves` object would crash. See https://projects.blender.org/blender/blender/issues/112068.

This PR fixes the issue by making sure that `CustomData_blend_write_prepare` is called before `BKE_id_blend_write`, which is the root cause of the crash that happens on load.

The  `CurvesGeometry::blend_write` function is split into  `CurvesGeometry::blend_write_prepare` and `CurvesGeometry::blend_write`.

Pull Request: https://projects.blender.org/blender/blender/pulls/112280
This commit is contained in:
Falk David
2023-09-12 16:02:04 +02:00
committed by Falk David
parent e7b024a691
commit 97d2dbb24e
4 changed files with 35 additions and 11 deletions

View File

@@ -393,9 +393,22 @@ class CurvesGeometry : public ::CurvesGeometry {
/* --------------------------------------------------------------------
* File Read/Write.
*/
void blend_read(BlendDataReader &reader);
void blend_write(BlendWriter &writer, ID &id);
/**
* Helper struct for `CurvesGeometry::blend_write_*` functions.
*/
struct BlendWriteData {
/* The point custom data layers to be written. */
Vector<CustomDataLayer, 16> point_layers;
/* The curve custom data layers to be written. */
Vector<CustomDataLayer, 16> curve_layers;
};
/**
* This function needs to be called before `blend_write` and before the `CurvesGeometry` struct
* is written because it can mutate the `CustomData` struct.
*/
BlendWriteData blend_write_prepare();
void blend_write(BlendWriter &writer, ID &id, const BlendWriteData &write_data);
};
static_assert(sizeof(blender::bke::CurvesGeometry) == sizeof(::CurvesGeometry));

View File

@@ -105,12 +105,15 @@ static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_addre
{
Curves *curves = (Curves *)id;
blender::bke::CurvesGeometry::BlendWriteData write_data =
curves->geometry.wrap().blend_write_prepare();
/* Write LibData */
BLO_write_id_struct(writer, Curves, id_address, &curves->id);
BKE_id_blend_write(writer, &curves->id);
/* Direct data */
curves->geometry.wrap().blend_write(*writer, curves->id);
curves->geometry.wrap().blend_write(*writer, curves->id, write_data);
BLO_write_string(writer, curves->surface_uv_map);

View File

@@ -1477,17 +1477,22 @@ void CurvesGeometry::blend_read(BlendDataReader &reader)
this->update_curve_types();
}
void CurvesGeometry::blend_write(BlendWriter &writer, ID &id)
CurvesGeometry::BlendWriteData CurvesGeometry::blend_write_prepare()
{
Vector<CustomDataLayer, 16> point_layers;
Vector<CustomDataLayer, 16> curve_layers;
CustomData_blend_write_prepare(this->point_data, point_layers);
CustomData_blend_write_prepare(this->curve_data, curve_layers);
CurvesGeometry::BlendWriteData write_data;
CustomData_blend_write_prepare(this->point_data, write_data.point_layers);
CustomData_blend_write_prepare(this->curve_data, write_data.curve_layers);
return write_data;
}
void CurvesGeometry::blend_write(BlendWriter &writer,
ID &id,
const CurvesGeometry::BlendWriteData &write_data)
{
CustomData_blend_write(
&writer, &this->point_data, point_layers, this->point_num, CD_MASK_ALL, &id);
&writer, &this->point_data, write_data.point_layers, this->point_num, CD_MASK_ALL, &id);
CustomData_blend_write(
&writer, &this->curve_data, curve_layers, this->curve_num, CD_MASK_ALL, &id);
&writer, &this->curve_data, write_data.curve_layers, this->curve_num, CD_MASK_ALL, &id);
BLO_write_int32_array(&writer, this->curve_num + 1, this->curve_offsets);
}

View File

@@ -2048,14 +2048,17 @@ static void read_drawing_array(GreasePencil &grease_pencil, BlendDataReader *rea
static void write_drawing_array(GreasePencil &grease_pencil, BlendWriter *writer)
{
using namespace blender;
BLO_write_pointer_array(writer, grease_pencil.drawing_array_num, grease_pencil.drawing_array);
for (int i = 0; i < grease_pencil.drawing_array_num; i++) {
GreasePencilDrawingBase *drawing_base = grease_pencil.drawing_array[i];
switch (drawing_base->type) {
case GP_DRAWING: {
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
bke::CurvesGeometry::BlendWriteData write_data =
drawing->wrap().strokes_for_write().blend_write_prepare();
BLO_write_struct(writer, GreasePencilDrawing, drawing);
drawing->wrap().strokes_for_write().blend_write(*writer, grease_pencil.id);
drawing->wrap().strokes_for_write().blend_write(*writer, grease_pencil.id, write_data);
break;
}
case GP_DRAWING_REFERENCE: {