Fix: New generic attributes uninitialized after curves draw tool
Add a utility to set attribute values to their default, use it in a few places that have already done this samething. Also: - Don't create resolution or cyclic attributes unnecessarily - Use API function to set new curve's type - Always create the new selection on the curve domain - Remove selection before resize to avoid unnecessary work
This commit is contained in:
parent
0e8c874166
commit
f5adfa6acd
|
@ -914,4 +914,9 @@ void copy_attributes_group_to_group(AttributeAccessor src_attributes,
|
||||||
const IndexMask &selection,
|
const IndexMask &selection,
|
||||||
MutableAttributeAccessor dst_attributes);
|
MutableAttributeAccessor dst_attributes);
|
||||||
|
|
||||||
|
void fill_attribute_range_default(MutableAttributeAccessor dst_attributes,
|
||||||
|
eAttrDomain domain,
|
||||||
|
const Set<std::string> &skip,
|
||||||
|
IndexRange range);
|
||||||
|
|
||||||
} // namespace blender::bke
|
} // namespace blender::bke
|
||||||
|
|
|
@ -1052,4 +1052,25 @@ void copy_attributes_group_to_group(const AttributeAccessor src_attributes,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fill_attribute_range_default(MutableAttributeAccessor attributes,
|
||||||
|
const eAttrDomain domain,
|
||||||
|
const Set<std::string> &skip,
|
||||||
|
const IndexRange range)
|
||||||
|
{
|
||||||
|
attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
|
||||||
|
if (meta_data.domain != domain) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (skip.contains(id.name())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
||||||
|
const CPPType &type = attribute.span.type();
|
||||||
|
GMutableSpan data = attribute.span.slice(range);
|
||||||
|
type.fill_assign_n(type.default_value(), data.data(), data.size());
|
||||||
|
attribute.finish();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::bke
|
} // namespace blender::bke
|
||||||
|
|
|
@ -655,13 +655,16 @@ static int curves_draw_exec(bContext *C, wmOperator *op)
|
||||||
|
|
||||||
Curves *curves_id = static_cast<Curves *>(obedit->data);
|
Curves *curves_id = static_cast<Curves *>(obedit->data);
|
||||||
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||||
const eAttrDomain selection_domain = eAttrDomain(curves_id->selection_domain);
|
|
||||||
const int curve_index = curves.curves_num();
|
const int curve_index = curves.curves_num();
|
||||||
|
|
||||||
const bool use_pressure_radius = (cps->flag & CURVE_PAINT_FLAG_PRESSURE_RADIUS) ||
|
const bool use_pressure_radius = (cps->flag & CURVE_PAINT_FLAG_PRESSURE_RADIUS) ||
|
||||||
((cps->radius_taper_start != 0.0f) ||
|
((cps->radius_taper_start != 0.0f) ||
|
||||||
(cps->radius_taper_end != 0.0f));
|
(cps->radius_taper_end != 0.0f));
|
||||||
|
|
||||||
|
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||||
|
|
||||||
|
attributes.remove(".selection");
|
||||||
|
|
||||||
if (cdd->curve_type == CU_BEZIER) {
|
if (cdd->curve_type == CU_BEZIER) {
|
||||||
/* Allow to interpolate multiple channels */
|
/* Allow to interpolate multiple channels */
|
||||||
int dims = 3;
|
int dims = 3;
|
||||||
|
@ -761,30 +764,18 @@ static int curves_draw_exec(bContext *C, wmOperator *op)
|
||||||
|
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
curves.resize(curves.points_num() + cubic_spline_len, curve_index + 1);
|
curves.resize(curves.points_num() + cubic_spline_len, curve_index + 1);
|
||||||
MutableSpan<int8_t> curve_types = curves.curve_types_for_write();
|
curves.fill_curve_types(IndexRange(curve_index, 1), CURVE_TYPE_BEZIER);
|
||||||
curve_types[curve_index] = CURVE_TYPE_BEZIER;
|
|
||||||
curves.update_curve_types();
|
|
||||||
|
|
||||||
|
MutableSpan<float3> positions = curves.positions_for_write();
|
||||||
MutableSpan<float3> handle_positions_l = curves.handle_positions_left_for_write();
|
MutableSpan<float3> handle_positions_l = curves.handle_positions_left_for_write();
|
||||||
MutableSpan<float3> handle_positions_r = curves.handle_positions_right_for_write();
|
MutableSpan<float3> handle_positions_r = curves.handle_positions_right_for_write();
|
||||||
MutableSpan<int8_t> handle_types_l = curves.handle_types_left_for_write();
|
MutableSpan<int8_t> handle_types_l = curves.handle_types_left_for_write();
|
||||||
MutableSpan<int8_t> handle_types_r = curves.handle_types_right_for_write();
|
MutableSpan<int8_t> handle_types_r = curves.handle_types_right_for_write();
|
||||||
MutableSpan<bool> cyclic = curves.cyclic_for_write();
|
|
||||||
MutableSpan<int> resolution = curves.resolution_for_write();
|
|
||||||
|
|
||||||
resolution[curve_index] = 12;
|
const IndexRange new_points = curves.points_by_curve()[curve_index];
|
||||||
IndexRange new_points = curves.points_by_curve()[curve_index];
|
|
||||||
MutableSpan<float3> positions = curves.positions_for_write();
|
|
||||||
|
|
||||||
bke::MutableAttributeAccessor curves_attributes = curves.attributes_for_write();
|
bke::SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_only_span<float>(
|
||||||
bke::SpanAttributeWriter<float> radius_attribute =
|
"radius", ATTR_DOMAIN_POINT);
|
||||||
curves_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
|
|
||||||
MutableSpan<float> radii = radius_attribute.span;
|
|
||||||
|
|
||||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
|
||||||
curves, selection_domain, CD_PROP_BOOL);
|
|
||||||
|
|
||||||
curves::fill_selection_false(selection.span);
|
|
||||||
|
|
||||||
float *co = cubic_spline;
|
float *co = cubic_spline;
|
||||||
|
|
||||||
|
@ -800,17 +791,13 @@ static int curves_draw_exec(bContext *C, wmOperator *op)
|
||||||
const float radius = (radius_index != -1) ?
|
const float radius = (radius_index != -1) ?
|
||||||
(pt[radius_index] * cdd->radius.range) + cdd->radius.min :
|
(pt[radius_index] * cdd->radius.range) + cdd->radius.min :
|
||||||
radius_max;
|
radius_max;
|
||||||
radii[i] = radius;
|
radii.span[i] = radius;
|
||||||
|
|
||||||
handle_types_l[i] = BEZIER_HANDLE_ALIGN;
|
handle_types_l[i] = BEZIER_HANDLE_ALIGN;
|
||||||
handle_types_r[i] = BEZIER_HANDLE_ALIGN;
|
handle_types_r[i] = BEZIER_HANDLE_ALIGN;
|
||||||
co += (dims * 3);
|
co += (dims * 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
curves::fill_selection_true(
|
|
||||||
selection.span,
|
|
||||||
selection.domain == ATTR_DOMAIN_POINT ? new_points : IndexRange(curve_index, 1));
|
|
||||||
selection.finish();
|
|
||||||
// bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
|
// bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
|
||||||
|
|
||||||
if (corners_index) {
|
if (corners_index) {
|
||||||
|
@ -829,9 +816,35 @@ static int curves_draw_exec(bContext *C, wmOperator *op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cyclic[curve_index] = bool(calc_flag & CURVE_FIT_CALC_CYCLIC);
|
radii.finish();
|
||||||
|
|
||||||
radius_attribute.finish();
|
bke::AttributeWriter<bool> selection = attributes.lookup_or_add_for_write<bool>(
|
||||||
|
".selection", ATTR_DOMAIN_CURVE);
|
||||||
|
selection.varray.set(curve_index, true);
|
||||||
|
selection.finish();
|
||||||
|
|
||||||
|
if (attributes.contains("resolution")) {
|
||||||
|
curves.resolution_for_write()[curve_index] = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.contains("cyclic") || bool(calc_flag & CURVE_FIT_CALC_CYCLIC)) {
|
||||||
|
curves.cyclic_for_write()[curve_index] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bke::fill_attribute_range_default(attributes,
|
||||||
|
ATTR_DOMAIN_POINT,
|
||||||
|
{"position",
|
||||||
|
"radius",
|
||||||
|
"handle_left",
|
||||||
|
"handle_right",
|
||||||
|
"handle_type_left",
|
||||||
|
"handle_type_right",
|
||||||
|
".selection"},
|
||||||
|
new_points);
|
||||||
|
bke::fill_attribute_range_default(attributes,
|
||||||
|
ATTR_DOMAIN_CURVE,
|
||||||
|
{"curve_type", "resolution", "cyclic", ".selection"},
|
||||||
|
IndexRange(curve_index, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (corners_index) {
|
if (corners_index) {
|
||||||
|
@ -844,20 +857,13 @@ static int curves_draw_exec(bContext *C, wmOperator *op)
|
||||||
}
|
}
|
||||||
else { /* CU_POLY */
|
else { /* CU_POLY */
|
||||||
curves.resize(curves.points_num() + stroke_len, curve_index + 1);
|
curves.resize(curves.points_num() + stroke_len, curve_index + 1);
|
||||||
MutableSpan<int8_t> curve_types = curves.curve_types_for_write();
|
curves.fill_curve_types(IndexRange(curve_index, 1), CURVE_TYPE_POLY);
|
||||||
curve_types[curve_index] = CURVE_TYPE_POLY;
|
|
||||||
curves.update_curve_types();
|
|
||||||
|
|
||||||
IndexRange new_points = curves.points_by_curve()[curve_index];
|
|
||||||
MutableSpan<float3> positions = curves.positions_for_write();
|
MutableSpan<float3> positions = curves.positions_for_write();
|
||||||
bke::MutableAttributeAccessor curves_attributes = curves.attributes_for_write();
|
bke::SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_only_span<float>(
|
||||||
bke::SpanAttributeWriter<float> radius_attribute =
|
"radius", ATTR_DOMAIN_POINT);
|
||||||
curves_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
|
|
||||||
MutableSpan<float> radii = radius_attribute.span;
|
|
||||||
|
|
||||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
const IndexRange new_points = curves.points_by_curve()[curve_index];
|
||||||
curves, selection_domain, CD_PROP_BOOL);
|
|
||||||
curves::fill_selection_false(selection.span);
|
|
||||||
|
|
||||||
IndexRange::Iterator points_iter = new_points.begin();
|
IndexRange::Iterator points_iter = new_points.begin();
|
||||||
|
|
||||||
|
@ -872,14 +878,21 @@ static int curves_draw_exec(bContext *C, wmOperator *op)
|
||||||
positions[i][2] = 0.0f;
|
positions[i][2] = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
radii[i] = use_pressure_radius ? (selem->pressure * radius_range) + radius_min :
|
radii.span[i] = use_pressure_radius ? (selem->pressure * radius_range) + radius_min :
|
||||||
cps->radius_max;
|
cps->radius_max;
|
||||||
}
|
}
|
||||||
curves::fill_selection_true(
|
|
||||||
selection.span,
|
radii.finish();
|
||||||
selection.domain == ATTR_DOMAIN_POINT ? new_points : IndexRange(curve_index, 1));
|
|
||||||
|
bke::AttributeWriter<bool> selection = attributes.lookup_or_add_for_write<bool>(
|
||||||
|
".selection", ATTR_DOMAIN_CURVE);
|
||||||
|
selection.varray.set(curve_index, true);
|
||||||
selection.finish();
|
selection.finish();
|
||||||
radius_attribute.finish();
|
|
||||||
|
bke::fill_attribute_range_default(
|
||||||
|
attributes, ATTR_DOMAIN_POINT, {"position", "radius", ".selection"}, new_points);
|
||||||
|
bke::fill_attribute_range_default(
|
||||||
|
attributes, ATTR_DOMAIN_CURVE, {"curve_type", ".selection"}, IndexRange(curve_index, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
||||||
|
|
|
@ -238,27 +238,14 @@ struct PaintOperationExecutor {
|
||||||
curves.update_curve_types();
|
curves.update_curve_types();
|
||||||
|
|
||||||
/* Initialize the rest of the attributes with default values. */
|
/* Initialize the rest of the attributes with default values. */
|
||||||
Set<std::string> attributes_to_skip{{"position",
|
bke::fill_attribute_range_default(attributes,
|
||||||
"curve_type",
|
ATTR_DOMAIN_POINT,
|
||||||
"material_index",
|
{"position", "radius", "opacity", "vertex_color"},
|
||||||
"cyclic",
|
curves.points_range().take_back(1));
|
||||||
"radius",
|
bke::fill_attribute_range_default(attributes,
|
||||||
"opacity",
|
ATTR_DOMAIN_CURVE,
|
||||||
"vertex_color"}};
|
{"curve_type", "material_index", "cyclic"},
|
||||||
attributes.for_all(
|
|
||||||
[&](const bke::AttributeIDRef &id, const bke::AttributeMetaData /*meta_data*/) {
|
|
||||||
if (attributes_to_skip.contains(id.name())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bke::GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
|
||||||
const CPPType &type = attribute.span.type();
|
|
||||||
GMutableSpan new_data = attribute.span.slice(attribute.domain == ATTR_DOMAIN_POINT ?
|
|
||||||
curves.points_range().take_back(1) :
|
|
||||||
curves.curves_range().take_back(1));
|
curves.curves_range().take_back(1));
|
||||||
type.fill_assign_n(type.default_value(), new_data.data(), new_data.size());
|
|
||||||
attribute.finish();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
drawing_->tag_topology_changed();
|
drawing_->tag_topology_changed();
|
||||||
}
|
}
|
||||||
|
@ -417,18 +404,10 @@ struct PaintOperationExecutor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the rest of the attributes with default values. */
|
/* Initialize the rest of the attributes with default values. */
|
||||||
Set<std::string> attributes_to_skip{{"position", "radius", "opacity", "vertex_color"}};
|
bke::fill_attribute_range_default(attributes,
|
||||||
attributes.for_all([&](const bke::AttributeIDRef &id, const bke::AttributeMetaData meta_data) {
|
ATTR_DOMAIN_POINT,
|
||||||
if (attributes_to_skip.contains(id.name()) || meta_data.domain != ATTR_DOMAIN_POINT) {
|
{"position", "radius", "opacity", "vertex_color"},
|
||||||
return true;
|
curves.points_range().take_back(1));
|
||||||
}
|
|
||||||
bke::GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
|
||||||
const CPPType &type = attribute.span.type();
|
|
||||||
GMutableSpan new_data = attribute.span.slice(new_points);
|
|
||||||
type.fill_assign_n(type.default_value(), new_data.data(), new_data.size());
|
|
||||||
attribute.finish();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(PaintOperation &self, const bContext &C, const InputSample &extension_sample)
|
void execute(PaintOperation &self, const bContext &C, const InputSample &extension_sample)
|
||||||
|
|
|
@ -397,22 +397,12 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Explicitly set all other attributes besides those processed above to default values. */
|
/* Explicitly set all other attributes besides those processed above to default values. */
|
||||||
Set<std::string> attributes_to_skip{
|
bke::fill_attribute_range_default(
|
||||||
{"position", "curve_type", "surface_uv_coordinate", "resolution"}};
|
attributes, ATTR_DOMAIN_POINT, {"position"}, outputs.new_points_range);
|
||||||
attributes.for_all(
|
bke::fill_attribute_range_default(attributes,
|
||||||
[&](const bke::AttributeIDRef &id, const bke::AttributeMetaData /*meta_data*/) {
|
ATTR_DOMAIN_CURVE,
|
||||||
if (attributes_to_skip.contains(id.name())) {
|
{"curve_type", "surface_uv_coordinate", "resolution"},
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bke::GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
|
||||||
const CPPType &type = attribute.span.type();
|
|
||||||
GMutableSpan new_data = attribute.span.slice(attribute.domain == ATTR_DOMAIN_POINT ?
|
|
||||||
outputs.new_points_range :
|
|
||||||
outputs.new_curves_range);
|
outputs.new_curves_range);
|
||||||
type.fill_assign_n(type.default_value(), new_data.data(), new_data.size());
|
|
||||||
attribute.finish();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue