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:
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user