Fix #123220: Export GP SVG/PDF crash when active object is not GP
`GpencilIOParams.ob` is set to `CTX_data_active_object` at the beginning of the export [which is not ensured to be a valid `OB_GPENCIL_LEGACY` object, non-valid objects are filtered out later in `create_object_list`]. From this (potential non-greasepencil) object's data, a "global `bGPdata` is stored in `GpencilIOParams`. From here, it can only go downwards as `stroke_point_radius_get`, `export_stroke_to_polyline`, `BKE_gpencil_stroke_perimeter_from_view` all use this "global" `bGPdata`. Two possible solutions might exist: - [1] just cancel the operator if the active object is not a `OB_GPENCIL_LEGACY` object - [2] make sure we use corresponding `bGPdata` when iterating over valid objects to export This PR chooses [2] since it also seems wrong to always use the `bGPdata` from the active object for certain calculations when iterating many objects. For example, the export ignores different values for `Thickness Scale` on different objects and always takes the value from the active object, which does not seem to be by design. NOTE: this changes behavior (see above) but for the better Pull Request: https://projects.blender.org/blender/blender/pulls/123224
This commit is contained in:
committed by
Philipp Oeser
parent
9d5f46b1b8
commit
751745b2de
@@ -251,14 +251,14 @@ float2 GpencilIO::gpencil_3D_point_to_2D(const float3 co)
|
||||
return result;
|
||||
}
|
||||
|
||||
float GpencilIO::stroke_point_radius_get(bGPDlayer *gpl, bGPDstroke *gps)
|
||||
float GpencilIO::stroke_point_radius_get(bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
|
||||
{
|
||||
bGPDspoint *pt = &gps->points[0];
|
||||
const float2 screen_co = gpencil_3D_point_to_2D(&pt->x);
|
||||
|
||||
/* Radius. */
|
||||
bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
|
||||
rv3d_->viewmat, gpd_, gpl, gps, 3, diff_mat_.ptr(), 0.0f);
|
||||
rv3d_->viewmat, gpd, gpl, gps, 3, diff_mat_.ptr(), 0.0f);
|
||||
|
||||
pt = &gps_perimeter->points[0];
|
||||
const float2 screen_ex = gpencil_3D_point_to_2D(&pt->x);
|
||||
|
||||
@@ -79,7 +79,7 @@ class GpencilIO {
|
||||
float2 gpencil_3D_point_to_2D(const float3 co);
|
||||
|
||||
/** Get radius of point. */
|
||||
float stroke_point_radius_get(bGPDlayer *gpl, bGPDstroke *gps);
|
||||
float stroke_point_radius_get(bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps);
|
||||
/** Create a list of selected objects sorted from back to front */
|
||||
void create_object_list();
|
||||
|
||||
|
||||
@@ -192,24 +192,24 @@ void GpencilExporterPDF::export_gpencil_layers()
|
||||
/* Fill. */
|
||||
if ((is_fill) && (params_.flag & GP_EXPORT_FILL)) {
|
||||
/* Fill is exported as polygon for fill and stroke in a different shape. */
|
||||
export_stroke_to_polyline(gpl, gps_duplicate, is_stroke, true, false);
|
||||
export_stroke_to_polyline(gpd_eval, gpl, gps_duplicate, is_stroke, true, false);
|
||||
}
|
||||
|
||||
/* Stroke. */
|
||||
if (is_stroke) {
|
||||
if (is_normalized) {
|
||||
export_stroke_to_polyline(gpl, gps_duplicate, is_stroke, false, true);
|
||||
export_stroke_to_polyline(gpd_eval, gpl, gps_duplicate, is_stroke, false, true);
|
||||
}
|
||||
else {
|
||||
bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
|
||||
rv3d_->viewmat, gpd_, gpl, gps_duplicate, 3, diff_mat_.ptr(), 0.0f);
|
||||
rv3d_->viewmat, gpd_eval, gpl, gps_duplicate, 3, diff_mat_.ptr(), 0.0f);
|
||||
|
||||
/* Sample stroke. */
|
||||
if (params_.stroke_sample > 0.0f) {
|
||||
BKE_gpencil_stroke_sample(gpd_eval, gps_perimeter, params_.stroke_sample, false, 0);
|
||||
}
|
||||
|
||||
export_stroke_to_polyline(gpl, gps_perimeter, is_stroke, false, false);
|
||||
export_stroke_to_polyline(gpd_eval, gpl, gps_perimeter, is_stroke, false, false);
|
||||
|
||||
BKE_gpencil_free_stroke(gps_perimeter);
|
||||
}
|
||||
@@ -220,7 +220,8 @@ void GpencilExporterPDF::export_gpencil_layers()
|
||||
}
|
||||
}
|
||||
|
||||
void GpencilExporterPDF::export_stroke_to_polyline(bGPDlayer *gpl,
|
||||
void GpencilExporterPDF::export_stroke_to_polyline(bGPdata *gpd,
|
||||
bGPDlayer *gpl,
|
||||
bGPDstroke *gps,
|
||||
const bool is_stroke,
|
||||
const bool do_fill,
|
||||
@@ -238,7 +239,7 @@ void GpencilExporterPDF::export_stroke_to_polyline(bGPDlayer *gpl,
|
||||
copy_v3_v3(&pt_dst->x, &pt_src->x);
|
||||
pt_dst->pressure = avg_pressure;
|
||||
|
||||
const float radius = stroke_point_radius_get(gpl, gps_temp);
|
||||
const float radius = stroke_point_radius_get(gpd, gpl, gps_temp);
|
||||
|
||||
BKE_gpencil_free_stroke(gps_temp);
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ class GpencilExporterPDF : public GpencilExporter {
|
||||
* \param do_fill: True if the stroke is only fill
|
||||
*/
|
||||
void export_stroke_to_polyline(
|
||||
bGPDlayer *gpl, bGPDstroke *gps, bool is_stroke, bool do_fill, bool normalize);
|
||||
bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, bool is_stroke, bool do_fill, bool normalize);
|
||||
/**
|
||||
* Set color.
|
||||
* \param do_fill: True if the stroke is only fill.
|
||||
|
||||
@@ -213,17 +213,17 @@ void GpencilExporterSVG::export_gpencil_layers()
|
||||
if ((is_fill) && (params_.flag & GP_EXPORT_FILL)) {
|
||||
/* Fill is always exported as polygon because the stroke of the fill is done
|
||||
* in a different SVG command. */
|
||||
export_stroke_to_polyline(gpl, gps_duplicate, node_gpl, is_stroke, true);
|
||||
export_stroke_to_polyline(gpd_eval, gpl, gps_duplicate, node_gpl, is_stroke, true);
|
||||
}
|
||||
|
||||
/* Stroke. */
|
||||
if (is_stroke) {
|
||||
if (is_normalized) {
|
||||
export_stroke_to_polyline(gpl, gps_duplicate, node_gpl, is_stroke, false);
|
||||
export_stroke_to_polyline(gpd_eval, gpl, gps_duplicate, node_gpl, is_stroke, false);
|
||||
}
|
||||
else {
|
||||
bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
|
||||
rv3d_->viewmat, gpd_, gpl, gps_duplicate, 3, diff_mat_.ptr(), 0.0f);
|
||||
rv3d_->viewmat, gpd_eval, gpl, gps_duplicate, 3, diff_mat_.ptr(), 0.0f);
|
||||
|
||||
/* Sample stroke. */
|
||||
if (params_.stroke_sample > 0.0f) {
|
||||
@@ -286,7 +286,8 @@ void GpencilExporterSVG::export_stroke_to_path(bGPDlayer *gpl,
|
||||
node_gps.append_attribute("d").set_value(txt.c_str());
|
||||
}
|
||||
|
||||
void GpencilExporterSVG::export_stroke_to_polyline(bGPDlayer *gpl,
|
||||
void GpencilExporterSVG::export_stroke_to_polyline(bGPdata *gpd,
|
||||
bGPDlayer *gpl,
|
||||
bGPDstroke *gps,
|
||||
pugi::xml_node node_gpl,
|
||||
const bool is_stroke,
|
||||
@@ -304,7 +305,7 @@ void GpencilExporterSVG::export_stroke_to_polyline(bGPDlayer *gpl,
|
||||
copy_v3_v3(&pt_dst->x, &pt_src->x);
|
||||
pt_dst->pressure = avg_pressure;
|
||||
|
||||
const float radius = stroke_point_radius_get(gpl, gps_temp);
|
||||
const float radius = stroke_point_radius_get(gpd, gpl, gps_temp);
|
||||
|
||||
BKE_gpencil_free_stroke(gps_temp);
|
||||
|
||||
|
||||
@@ -88,8 +88,12 @@ class GpencilExporterSVG : public GpencilExporter {
|
||||
* \param node_gpl: Node of the layer.
|
||||
* \param do_fill: True if the stroke is only fill
|
||||
*/
|
||||
void export_stroke_to_polyline(
|
||||
bGPDlayer *gpl, bGPDstroke *gps, pugi::xml_node node_gpl, bool is_stroke, bool do_fill);
|
||||
void export_stroke_to_polyline(bGPdata *gpd,
|
||||
bGPDlayer *gpl,
|
||||
bGPDstroke *gps,
|
||||
pugi::xml_node node_gpl,
|
||||
bool is_stroke,
|
||||
bool do_fill);
|
||||
|
||||
/**
|
||||
* Set color SVG string for stroke
|
||||
|
||||
Reference in New Issue
Block a user