Refactor: GPv3: legacy_gpencil_to_grease_pencil

This is part of #121565.

Refactors `legacy_gpencil_to_grease_pencil` to use
`GreasePencil::insert_frame` instead of manually creating
the drawing array.

Now `legacy_gpencil_frame_to_grease_pencil_drawing`
actually returns a drawing by value.

Note: This means that we're now resizing the drawing
array for every frame in every layer, but this can be optimized
later.
This commit is contained in:
Falk David
2024-05-08 17:10:04 +02:00
parent 149e547de6
commit 9a3abe22a3
3 changed files with 57 additions and 35 deletions

View File

@@ -71,6 +71,9 @@ class Drawing : public ::GreasePencilDrawing {
public:
Drawing();
Drawing(const Drawing &other);
Drawing &operator=(const Drawing &other);
Drawing(Drawing &&other);
Drawing &operator=(Drawing &&other);
~Drawing();
const bke::CurvesGeometry &strokes() const;

View File

@@ -315,6 +315,39 @@ Drawing::Drawing(const Drawing &other)
this->runtime->curve_texture_matrices = other.runtime->curve_texture_matrices;
}
Drawing &Drawing::operator=(const Drawing &other)
{
if (this == &other) {
return *this;
}
std::destroy_at(this);
new (this) Drawing(other);
return *this;
}
Drawing::Drawing(Drawing &&other)
{
this->base.type = GP_DRAWING;
other.base.type = GP_DRAWING;
this->base.flag = other.base.flag;
other.base.flag = 0;
new (&this->geometry) bke::CurvesGeometry(std::move(other.geometry.wrap()));
this->runtime = other.runtime;
other.runtime = nullptr;
}
Drawing &Drawing::operator=(Drawing &&other)
{
if (this == &other) {
return *this;
}
std::destroy_at(this);
new (this) Drawing(std::move(other));
return *this;
}
Drawing::~Drawing()
{
this->strokes().~CurvesGeometry();

View File

@@ -665,14 +665,11 @@ static blender::float4x2 get_legacy_texture_matrix(bGPDstroke *gps)
return texture_matrix * strokemat4x3;
}
static void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
const ListBase &vertex_group_names,
GreasePencilDrawing &r_drawing)
static Drawing legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
const ListBase &vertex_group_names)
{
/* Construct an empty CurvesGeometry in-place. */
new (&r_drawing.geometry) CurvesGeometry();
r_drawing.base.type = GP_DRAWING;
r_drawing.runtime = MEM_new<bke::greasepencil::DrawingRuntime>(__func__);
/* Create a new empty drawing. */
Drawing drawing;
/* Get the number of points, number of strokes and the offsets for each stroke. */
Vector<int> offsets;
@@ -703,11 +700,10 @@ static void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
/* Return if the legacy frame contains no strokes (or zero points). */
if (num_strokes == 0) {
return;
return drawing;
}
/* Resize the CurvesGeometry. */
Drawing &drawing = r_drawing.wrap();
CurvesGeometry &curves = drawing.strokes_for_write();
curves.resize(num_points, num_strokes);
curves.offsets_for_write().copy_from(offsets);
@@ -904,6 +900,8 @@ static void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
stroke_hardnesses.finish();
stroke_point_aspect_ratios.finish();
stroke_materials.finish();
return drawing;
}
static void legacy_gpencil_to_grease_pencil(ConversionData &conversion_data,
@@ -930,16 +928,7 @@ static void legacy_gpencil_to_grease_pencil(ConversionData &conversion_data,
SET_FLAG_FROM_TEST(
grease_pencil.flag, (gpd.draw_mode == GP_DRAWMODE_3D), GREASE_PENCIL_STROKE_ORDER_3D);
int num_drawings = 0;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd.layers) {
num_drawings += BLI_listbase_count(&gpl->frames);
}
grease_pencil.drawing_array_num = num_drawings;
grease_pencil.drawing_array = reinterpret_cast<GreasePencilDrawingBase **>(
MEM_cnew_array<GreasePencilDrawing *>(num_drawings, __func__));
int i = 0, layer_idx = 0;
int layer_idx = 0;
LISTBASE_FOREACH_INDEX (bGPDlayer *, gpl, &gpd.layers, layer_idx) {
/* Create a new layer. */
Layer &new_layer = grease_pencil.add_layer(
@@ -984,28 +973,25 @@ static void legacy_gpencil_to_grease_pencil(ConversionData &conversion_data,
new_layer.opacity = gpl->opacity;
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
grease_pencil.drawing_array[i] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<GreasePencilDrawing>(__func__));
GreasePencilDrawing &drawing = *reinterpret_cast<GreasePencilDrawing *>(
grease_pencil.drawing_array[i]);
/* Convert the frame to a drawing. */
legacy_gpencil_frame_to_grease_pencil_drawing(*gpf, gpd.vertex_group_names, drawing);
/* Add the frame to the layer. */
if (GreasePencilFrame *new_frame = new_layer.add_frame(gpf->framenum)) {
new_frame->drawing_index = i;
new_frame->type = gpf->key_type;
SET_FLAG_FROM_TEST(new_frame->flag, (gpf->flag & GP_FRAME_SELECT), GP_FRAME_SELECTED);
Drawing *dst_drawing = grease_pencil.insert_frame(
new_layer, gpf->framenum, 0, eBezTriple_KeyframeType(gpf->key_type));
if (dst_drawing == nullptr) {
/* Might fail because GPv2 technically allowed overlapping keyframes on the same frame
* (very unlikely to occur in real world files). In GPv3, keyframes always have to be on
* different frames. In this case we can't create a keyframe and have to skip it. */
continue;
}
i++;
/* Convert the frame to a drawing. */
*dst_drawing = legacy_gpencil_frame_to_grease_pencil_drawing(*gpf, gpd.vertex_group_names);
/* This frame was just inserted above, so it should always exist. */
GreasePencilFrame &new_frame = *new_layer.frame_at(gpf->framenum);
SET_FLAG_FROM_TEST(new_frame.flag, (gpf->flag & GP_FRAME_SELECT), GP_FRAME_SELECTED);
}
if ((gpl->flag & GP_LAYER_ACTIVE) != 0) {
grease_pencil.set_active_layer(&new_layer);
}
/* TODO: Update drawing user counts. */
}
/* Second loop, to write to layer attributes after all layers were created. */