71 const bool include_first_point)
73 if (include_first_point) {
97 if (num_handles == 1) {
100 const int64_t num_segments = num_handles - 1;
101 const int64_t num_points = num_segments * resolution;
106 for (
const int64_t segment_i : range) {
107 IndexRange segment_range(segment_i * resolution, resolution);
109 curve_segments[segment_i * 3 + 1],
110 curve_segments[segment_i * 3 + 2],
111 curve_segments[segment_i * 3 + 3],
134 accumulated_lengths_target, accumulated_lengths_src, segment_indices, segment_factors);
137 target, segment_indices, segment_factors, dst.
drop_back(1));
174 fill_guides_brush->
spacing = 100;
179 return fill_guides_brush;
207 int active_smooth_start_index_ = 0;
213 std::optional<float> last_stroke_placement_depth_;
215 std::optional<int> last_stroke_placement_point_;
221 float accum_distance_ = 0.0f;
225 float stroke_random_radius_factor_;
226 float stroke_random_opacity_factor_;
227 float stroke_random_rotation_factor_;
229 float stroke_random_hue_factor_;
230 float stroke_random_sat_factor_;
231 float stroke_random_val_factor_;
239 bool do_fill_guides_;
243 Brush *saved_active_brush_;
244 Brush *fill_guides_brush_;
251 PaintOperation(
const bool do_fill_guides =
false) : do_fill_guides_(do_fill_guides) {}
256 std::optional<int> start_point,
312 const int material_index,
320 if (
self.placement_.use_project_to_stroke()) {
321 const std::optional<float> depth =
self.placement_.get_depth(start_coords);
323 start_location =
self.placement_.place(start_coords, *depth);
326 start_location =
self.placement_.project(start_coords);
330 start_location =
self.placement_.project(start_coords);
338 self.placement_.to_world_space(),
346 self.stroke_random_opacity_factor_,
357 self.stroke_random_hue_factor_,
358 self.stroke_random_sat_factor_,
359 self.stroke_random_val_factor_,
367 self.screen_space_coords_orig_.append(start_coords);
369 self.screen_space_jitter_offsets_.append(
float2(0.0f));
370 self.screen_space_smoothed_coords_.append(start_coords);
371 self.screen_space_final_coords_.append(start_coords);
377 const int active_curve = on_back ?
curves.curves_range().first() :
378 curves.curves_range().last();
380 const int last_active_point = curve_points.
last();
385 curves.positions_for_write()[last_active_point] = start_location;
386 self.drawing_->radii_for_write()[last_active_point] = start_radius;
387 self.drawing_->opacities_for_write()[last_active_point] = start_opacity;
388 point_attributes_to_skip.
add_multiple({
"position",
"radius",
"opacity"});
391 point_attributes_to_skip.
add(
"vertex_color");
393 if (use_fill || attributes.
contains(
"fill_color")) {
395 curve_attributes_to_skip.
add(
"fill_color");
400 delta_times.span[last_active_point] = 0.0f;
401 point_attributes_to_skip.
add(
"delta_time");
402 delta_times.finish();
409 cyclic.
span[active_curve] =
false;
410 materials.
span[active_curve] = material_index;
411 curve_attributes_to_skip.
add_multiple({
"material_index",
"cyclic"});
419 curve_attributes_to_skip.
add(
"softness");
427 u_scale.span[active_curve] = 1.0f;
428 curve_attributes_to_skip.
add(
"u_scale");
438 curve_attributes_to_skip.
add(
"aspect_ratio");
439 aspect_ratio.finish();
446 rotations.span[last_active_point] = start_rotation;
447 point_attributes_to_skip.
add(
"rotation");
457 start_caps.span[active_curve] =
settings_->caps_type;
458 curve_attributes_to_skip.
add(
"start_cap");
467 end_caps.span[active_curve] =
settings_->caps_type;
468 curve_attributes_to_skip.
add(
"end_cap");
473 if (use_fill && (start_opacity < 1.0f || attributes.
contains(
"fill_opacity"))) {
480 fill_opacities.span[active_curve] = start_opacity;
481 curve_attributes_to_skip.
add(
"fill_opacity");
482 fill_opacities.finish();
491 curve_attributes_to_skip.
add(
"init_time");
495 if (
self.do_fill_guides_) {
500 is_fill_boundary.span[active_curve] =
true;
501 curve_attributes_to_skip.
add(
".is_fill_guide");
502 is_fill_boundary.finish();
507 curve_attributes_to_skip.
add(
"curve_type");
508 curves.update_curve_types();
510 if (
self.placement_.use_project_to_stroke()) {
511 self.stroke_placement_depths_.append(
self.stroke_placement_depths_.is_empty() ?
513 self.stroke_placement_depths_.last());
515 self.update_stroke_depth_placement(
C, start_sample);
530 self.drawing_->tag_topology_changed();
535 const Span<float2> coords_to_smooth =
self.screen_space_coords_orig_.as_span().slice(
539 const float corner_min_radius_px = 5.0f;
540 const float corner_max_radius_px = 30.0f;
541 const int64_t corner_max_samples = 64;
542 const float corner_angle_threshold = 0.6f;
546 corner_min_radius_px,
547 corner_max_radius_px,
549 corner_angle_threshold,
555 const int pre_blur_iterations = 3;
566 const float max_error_threshold_px = 5.0f;
568 coords_pre_blur, max_error_threshold_px *
settings_->active_smooth, corner_mask);
571 const int64_t sample_resolution = 32;
580 const float converging_threshold_px = 0.1f;
581 bool stop_counting_converged =
false;
582 int num_converged = 0;
585 self.screen_space_curve_fitted_coords_[window_i].append(coords_smoothed[window_i]);
591 if (!stop_counting_converged) {
592 float2 prev_pos = window_coords[window_i];
593 if (
math::distance(new_pos, prev_pos) < converging_threshold_px) {
597 stop_counting_converged =
true;
602 window_coords[window_i] = new_pos;
606 if (num_converged > 0) {
607 self.active_smooth_start_index_ += num_converged;
608 self.screen_space_curve_fitted_coords_.remove(0, num_converged);
613 const int new_points_num,
614 const float brush_radius_px,
615 const float pressure,
619 float jitter_factor = 1.0f;
625 for ([[maybe_unused]]
const int _ :
IndexRange(new_points_num)) {
626 const float rand =
self.rng_.get_float() * 2.0f - 1.0f;
627 const float factor = rand *
settings_->draw_jitter * jitter_factor;
628 self.screen_space_jitter_offsets_.append(cotangent * factor * brush_radius_px);
630 const Span<float2> jitter_slice =
self.screen_space_jitter_offsets_.as_mutable_span().slice(
633 self.screen_space_smoothed_coords_.as_mutable_span().slice(active_window);
637 if (
self.placement_.use_project_to_stroke()) {
638 BLI_assert(
self.stroke_placement_depths_.size() ==
self.screen_space_coords_orig_.size());
640 self.stroke_placement_depths_.as_span().slice(active_window);
642 final_coords[window_i] = smoothed_coords[window_i] + jitter_slice[window_i];
643 const std::optional<float> depth = stroke_depths[window_i];
644 positions_slice[window_i] = depth ?
self.placement_.place(final_coords[window_i], *depth) :
645 self.placement_.project(final_coords[window_i]);
650 final_coords[window_i] = smoothed_coords[window_i] + jitter_slice[window_i];
651 positions_slice[window_i] =
self.placement_.project(final_coords[window_i]);
667 if (
self.placement_.use_project_to_stroke()) {
668 const std::optional<float> depth =
self.stroke_placement_depths_.is_empty() ?
670 self.stroke_placement_depths_.last();
672 position =
self.placement_.place(coords, *depth);
675 position =
self.placement_.project(coords);
679 position =
self.placement_.project(coords);
687 self.placement_.to_world_space(),
699 const int active_curve = on_back ?
curves.curves_range().first() :
700 curves.curves_range().last();
701 const IndexRange curve_points = points_by_curve[active_curve];
702 const int last_active_point = curve_points.
last();
704 const float2 prev_coords =
self.screen_space_coords_orig_.last();
705 float prev_radius =
self.drawing_->radii()[last_active_point];
706 const float prev_opacity =
self.drawing_->opacities()[last_active_point];
707 const ColorGeometry4f prev_vertex_color =
self.drawing_->vertex_colors()[last_active_point];
709 const bool is_first_sample = (curve_points.
size() == 1);
714 if (is_first_sample) {
715 self.smoothed_pen_direction_ =
self.screen_space_coords_orig_.last() - coords;
722 constexpr float smoothing_rate_factor = 0.3f;
724 self.screen_space_coords_orig_.last() -
726 smoothing_rate_factor);
730 float radius_factor = 1.0f;
731 if (
settings_->draw_angle_factor > 0.0f) {
743 radius *= radius_factor;
748 constexpr float point_override_threshold_px = 2.0f;
749 if (distance_px < point_override_threshold_px) {
750 self.accum_distance_ += distance_px;
752 if (!is_first_sample) {
753 curves.positions_for_write()[last_active_point] = position;
757 self.stroke_random_radius_factor_,
758 self.accum_distance_,
764 self.stroke_random_opacity_factor_,
765 self.accum_distance_,
769 self.drawing_->radii_for_write()[last_active_point] =
math::max(radius, prev_radius);
770 self.drawing_->opacities_for_write()[last_active_point] =
math::max(opacity, prev_opacity);
775 if (is_first_sample &&
settings_->draw_angle_factor > 0.0f) {
776 self.drawing_->radii_for_write()[last_active_point] *= radius_factor;
777 prev_radius =
self.drawing_->radii()[last_active_point];
781 constexpr int max_points_per_pixel = 4;
783 const float max_spacing_px =
math::max((
float(
brush_->spacing) / 100.0f) *
784 float(brush_radius_px),
785 1.0f /
float(max_points_per_pixel));
787 const int new_points_num = (distance_px > max_spacing_px) ?
792 curves, on_back ==
false, curve_points.
size() + new_points_num);
796 const IndexRange new_points =
curves.points_by_curve()[active_curve].take_back(new_points_num);
807 point_attributes_to_skip.
add_multiple({
"position",
"radius",
"opacity"});
813 self.stroke_random_radius_factor_,
814 self.accum_distance_ +
825 self.stroke_random_opacity_factor_,
826 self.accum_distance_ +
843 self.stroke_random_rotation_factor_,
846 point_attributes_to_skip.
add(
"rotation");
854 self.drawing_->vertex_colors_for_write().slice(new_points);
856 prev_vertex_color,
vertex_color_, new_vertex_colors, is_first_sample);
861 self.stroke_random_hue_factor_,
862 self.stroke_random_sat_factor_,
863 self.stroke_random_val_factor_,
864 self.accum_distance_ +
866 new_vertex_colors[
i],
870 point_attributes_to_skip.
add(
"vertex_color");
878 float(new_delta_time),
879 delta_times.span.slice(new_points),
881 point_attributes_to_skip.
add(
"delta_time");
882 delta_times.finish();
886 self.accum_distance_ += distance_px;
889 self.delta_time_ = new_delta_time;
892 self.screen_space_coords_orig_.extend(new_screen_space_coords);
893 self.screen_space_smoothed_coords_.extend(new_screen_space_coords);
894 self.screen_space_final_coords_.extend(new_screen_space_coords);
895 for (
float2 new_position : new_screen_space_coords) {
898 if (
self.placement_.use_project_to_stroke()) {
899 const std::optional<float> last_depth =
self.stroke_placement_depths_.is_empty() ?
901 self.stroke_placement_depths_.last();
902 self.stroke_placement_depths_.append_n_times(last_depth, new_points_num);
906 constexpr int64_t min_active_smoothing_points_num = 8;
907 const IndexRange smooth_window =
self.screen_space_coords_orig_.index_range().drop_front(
908 self.active_smooth_start_index_);
909 if (smooth_window.
size() < min_active_smoothing_points_num) {
910 if (
self.placement_.use_project_to_stroke()) {
912 self.stroke_placement_depths_.as_mutable_span().take_back(new_points_num);
914 const std::optional<float> depth = new_depths[
i];
916 new_positions[
i] =
self.placement_.place(coords, *depth);
919 new_positions[
i] =
self.placement_.project(coords);
924 self.placement_.project(new_screen_space_coords, new_positions);
946 self.screen_space_smoothed_coords_.as_mutable_span().slice(smooth_window);
952 if (
self.placement_.use_project_to_stroke()) {
953 BLI_assert(
self.stroke_placement_depths_.size() ==
self.screen_space_coords_orig_.size());
955 self.stroke_placement_depths_.as_mutable_span().slice(smooth_window);
957 const std::optional<float> depth = stroke_depths[window_i];
958 curve_positions_slice[window_i] = depth ?
959 self.placement_.place(final_coords[window_i],
961 self.placement_.project(final_coords[window_i]);
966 curve_positions_slice[window_i] =
self.placement_.project(final_coords[window_i]);
971 if (
self.placement_.use_project_to_stroke()) {
973 self.update_stroke_depth_placement(
C, extension_sample);
981 curves.points_range().take_back(new_points_num));
983 self.drawing_->set_texture_matrices({
self.texture_space_},
995 const int active_curve = on_back ?
curves.curves_range().first() :
996 curves.curves_range().last();
1024 BLI_assert(placement_.use_project_to_stroke());
1026 const std::optional<float> new_stroke_placement_depth = placement_.get_depth(
1028 if (!new_stroke_placement_depth) {
1033 switch (snap_mode) {
1035 const float start_depth = last_stroke_placement_depth_ ? *last_stroke_placement_depth_ :
1036 *new_stroke_placement_depth;
1037 const float end_depth = *new_stroke_placement_depth;
1039 C, last_stroke_placement_point_, start_depth, end_depth);
1041 if (!reprojected_points.
is_empty()) {
1042 last_stroke_placement_point_ = reprojected_points.
one_after_last();
1045 last_stroke_placement_depth_ = new_stroke_placement_depth;
1049 const float start_depth = last_stroke_placement_depth_ ? *last_stroke_placement_depth_ :
1050 *new_stroke_placement_depth;
1051 const float end_depth = *new_stroke_placement_depth;
1053 C, last_stroke_placement_point_, start_depth, end_depth);
1056 if (!last_stroke_placement_depth_) {
1058 if (!reprojected_points.
is_empty()) {
1059 last_stroke_placement_point_ = reprojected_points.
one_after_last();
1061 last_stroke_placement_depth_ = new_stroke_placement_depth;
1067 if (!last_stroke_placement_depth_) {
1068 const float start_depth = *new_stroke_placement_depth;
1069 const float end_depth = *new_stroke_placement_depth;
1072 last_stroke_placement_depth_ = new_stroke_placement_depth;
1082 std::optional<int> start_point,
1083 const float from_depth,
1084 const float to_depth)
1097 const IndexRange all_points = points_by_curve[active_curve];
1098 BLI_assert(screen_space_final_coords_.size() == all_points.
size());
1115 active_curve_points);
1119 active_curve_points);
1120 const float step_size = 1.0f / std::max(
int(active_points.
size()) - 1, 1);
1124 positions[
i] = placement_.place(final_coords[
i], *depths[
i]);
1127 return active_points;
1139 saved_active_brush_ = current_brush;
1147 saved_active_brush_ =
nullptr;
1150 fill_guides_brush_ =
nullptr;
1163 if (do_fill_guides_) {
1170 if (
brush->gpencil_settings ==
nullptr) {
1185 BLI_assert(grease_pencil->has_active_layer());
1189 if (placement_.use_project_to_surface()) {
1192 else if (placement_.use_project_to_stroke()) {
1208 stroke_random_radius_factor_ = rng_.get_float() * 2.0f - 1.0f;
1209 stroke_random_opacity_factor_ = rng_.get_float() * 2.0f - 1.0f;
1210 stroke_random_rotation_factor_ = rng_.get_float() * 2.0f - 1.0f;
1212 stroke_random_hue_factor_ = rng_.get_float() * 2.0f - 1.0f;
1213 stroke_random_sat_factor_ = rng_.get_float() * 2.0f - 1.0f;
1214 stroke_random_val_factor_ = rng_.get_float() * 2.0f - 1.0f;
1222 frame_number_ = scene->
r.
cfra;
1223 drawing_ = grease_pencil->get_editable_drawing_at(layer, frame_number_);
1228 grease_pencil->
runtime->is_drawing_stroke =
true;
1248 executor.
execute(*
this,
C, extension_sample);
1255 const float influence,
1256 const int iterations,
1257 const int active_curve)
1308 const float epsilon,
1309 const int active_curve)
1315 ".draw_tool_screen_space_positions");
1324 curves.cyclic()[active_curve],
1326 screen_space_positions,
1331 if (!points_to_delete.
is_empty()) {
1342 std::array<bke::GeometrySet, 2> geometry_sets;
1357 const int active_curve,
1364 ".draw_tool_screen_space_positions");
1373 rcti screen_space_bounds;
1384 screen_space_positions,
1385 {screen_space_bounds},
1403 const int active_curve,
1406 const float outline_radius,
1407 const int material_index,
1431 const float epsilon,
1433 const int active_curve)
1440 int64_t num_points_to_remove = 0;
1442 if (radii[index] < epsilon) {
1443 num_points_to_remove++;
1450 if (num_points_to_remove <= 0) {
1455 if (points.
size() - num_points_to_remove < 1) {
1456 num_points_to_remove = points.
size() - 1;
1461 curves.offsets_for_write().last() =
curves.points_num();
1462 return num_points_to_remove;
1466 const int last_active_point =
curves.points_by_curve()[0].last();
1478 using T = decltype(dummy);
1479 MutableSpan<T> span_data = attribute_data.typed<T>();
1481 for (int i = last_active_point - num_points_to_remove + 1;
1482 i < curves.points_num() - num_points_to_remove;
1485 span_data[i] = span_data[i + num_points_to_remove];
1493 for (
const int src_curve :
curves.curves_range().drop_front(1)) {
1494 offsets[src_curve] = offsets[src_curve] - num_points_to_remove;
1498 return num_points_to_remove;
1503 const int active_curve)
1528 const int active_curve)
1553 Object *ob_arm =
nullptr;
1566 if (amd ==
nullptr) {
1577 if (channel ==
nullptr) {
1586 if (channel ==
nullptr) {
1592 const float4x4 postmat = obinv * ob_arm->object_to_world();
1615 src_offsets.as_span(),
1616 dst_offsets.as_span(),
1620 src_offsets = {curve, curve + 1};
1621 dst_offsets = {0, 1};
1627 src_offsets.as_span(),
1628 dst_offsets.as_span(),
1637 const int current_frame,
1644 if (drawing_info.frame_number == current_frame) {
1669 BLI_assert(grease_pencil.has_active_layer());
1676 const IndexRange points = points_by_curve[active_curve];
1685 screen_space_positions.
span.slice(points).copy_from(this->screen_space_final_coords_);
1686 screen_space_positions.
finish();
1694 if (do_post_processing) {
1708 const float outline_radius =
brush->unprojected_size / 2.0f * settings->
outline_fac * 0.5f;
1709 const int material_index = [&]() {
1724 attributes.
remove(
".draw_tool_screen_space_positions");
1728 if (do_automerge_endpoints) {
1729 constexpr float merge_distance = 20.0f;
1733 *region, drawing.
strokes(), layer_to_world, merge_distance, selection, {});
1741 if (use_multi_frame_editing) {
1743 drawing.
strokes(), active_curve, frame_number_, on_back, multi_frame_drawings_);
1747 grease_pencil.
runtime->is_drawing_stroke =
false;
1749 if (do_fill_guides_) {
1759 return std::make_unique<PaintOperation>(do_fill_guides);
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
std::optional< BrushColorJitterSettings > BKE_brush_color_jitter_get_settings(const Paint *paint, const Brush *brush)
void BKE_brush_init_gpencil_settings(Brush *brush)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
Low-level operations for curves.
Low-level operations for grease pencil.
Material * BKE_grease_pencil_object_material_alt_ensure_from_brush(Main *bmain, Object *ob, Brush *brush)
Material * BKE_grease_pencil_object_material_ensure_from_brush(Main *bmain, Object *ob, Brush *brush)
Utility functions for vertex groups in grease pencil objects.
void * BKE_id_new_nomain(short type, const char *name)
void BKE_id_free_ex(Main *bmain, void *idv, int flag_orig, bool use_flag_from_idtag)
General operations, lookup, etc. for materials.
int BKE_object_material_index_get(Object *ob, const Material *ma)
bool BKE_paint_brush_set(Paint *paint, Brush *brush)
Paint * BKE_paint_get_active_from_context(const bContext *C)
Brush * BKE_paint_brush(Paint *paint)
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Platform independent time functions.
double BLI_time_now_seconds(void)
void DEG_id_tag_update(ID *id, unsigned int flags)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ GP_BRUSH_MODE_VERTEXCOLOR
@ GP_BRUSH_OUTLINE_STROKE
@ GP_BRUSH_GROUP_SETTINGS
@ GP_BRUSH_USE_JITTER_PRESSURE
@ GP_STROKE_CAP_TYPE_ROUND
@ eModifierType_GreasePencilArmature
@ OB_MODE_PAINT_GREASE_PENCIL
@ GP_PROJECT_DEPTH_STROKE_ENDPOINTS
@ GP_PROJECT_DEPTH_STROKE_FIRST
@ GP_TOOL_FLAG_PAINT_ONBACK
@ GP_TOOL_FLAG_AUTOMERGE_STROKE
@ GP_TOOL_FLAG_CREATE_WEIGHTS
@ GP_USE_MULTI_FRAME_EDITING
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
BPy_StructRNA * depsgraph
unsigned long long int uint64_t
MutableSpan< T > as_mutable_span()
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType & type() const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr int64_t first() const
constexpr int64_t one_after_last() const
constexpr IndexRange shift(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr int64_t start() const
static constexpr IndexRange from_single(const int64_t index)
constexpr IndexRange index_range() const
static constexpr IndexRange from_begin_end_inclusive(const int64_t begin, const int64_t last)
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr MutableSpan drop_back(const int64_t n) const
constexpr IndexRange index_range() const
constexpr void copy_from(Span< T > values) const
constexpr T & last(const int64_t n=0) const
static RandomNumberGenerator from_random_seed()
void add_multiple(Span< Key > keys)
constexpr Span drop_front(int64_t n) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr Span drop_back(int64_t n) const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
constexpr const T * end() const
constexpr const T * begin() const
constexpr const char * data() const
Span< T > get_internal_span() const
static VArray from_single(T value, const int64_t size)
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
bool contains(StringRef attribute_id) const
GAttributeReader lookup(const StringRef attribute_id) const
MutableSpan< float3 > positions_for_write()
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
MutableAttributeAccessor attributes_for_write()
Span< float3 > positions() const
void remove_curves(const IndexMask &curves_to_delete, const AttributeFilter &attribute_filter)
AttributeAccessor attributes() const
void remove_points(const IndexMask &points_to_delete, const AttributeFilter &attribute_filter)
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
VArray< float > radii() const
void tag_positions_changed()
void tag_topology_changed()
VArray< float > opacities() const
void set_texture_matrices(Span< float4x2 > matrices, const IndexMask &selection)
float4x4 to_world_space(const Object &object) const
float4x4 to_object_space(const Object &object) const
float3 reproject(float3 pos) const
friend struct PaintOperationExecutor
IndexRange interpolate_stroke_depth(const bContext &C, std::optional< int > start_point, float from_depth, float to_depth)
PaintOperation(const bool do_fill_guides=false)
void on_stroke_done(const bContext &C) override
void toggle_fill_guides_brush_off(const bContext &C)
void toggle_fill_guides_brush_on(const bContext &C)
void on_stroke_extended(const bContext &C, const InputSample &extension_sample) override
bool update_stroke_depth_placement(const bContext &C, const InputSample &sample)
void on_stroke_begin(const bContext &C, const InputSample &start_sample) override
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
blender::bke::AttrDomain ED_grease_pencil_edit_selection_domain_get(const ToolSettings *tool_settings)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
T mix2(float factor, const T &a, const T &b)
void evaluate_segment(const T &point_0, const T &point_1, const T &point_2, const T &point_3, MutableSpan< T > result)
void assign_to_vertex_group_from_mask(CurvesGeometry &curves, const IndexMask &mask, StringRef name, float weight)
CurvesGeometry curves_copy_curve_selection(const CurvesGeometry &curves, const IndexMask &curves_to_copy, const AttributeFilter &attribute_filter)
auto attribute_filter_from_skip_ref(const Span< StringRef > skip)
void fill_attribute_range_default(MutableAttributeAccessor dst_attributes, AttrDomain domain, const AttributeFilter &attribute_filter, IndexRange range)
void copy_attributes_group_to_group(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
Curves * curves_new_nomain(int points_num, int curves_num)
std::optional< Bounds< T > > min_max(const std::optional< Bounds< T > > &a, const T &b)
void fill_selection_false(GMutableSpan selection)
bke::GSpanAttributeWriter ensure_selection_attribute(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain, bke::AttrType create_type, StringRef attribute_name)
bke::CurvesGeometry trim_curve_segments(const bke::CurvesGeometry &src, const Span< float2 > screen_space_positions, const Span< rcti > screen_space_curve_bounds, const IndexMask &curve_selection, const Vector< Vector< int > > &selected_points_in_curves, const bool keep_caps)
float randomize_rotation(const BrushGpencilSettings &settings, const float stroke_factor, const float distance, const float pressure)
void resize_single_curve(bke::CurvesGeometry &curves, const bool at_end, const int new_points_num)
float randomize_opacity(const BrushGpencilSettings &settings, const float stroke_factor, const float distance, const float opacity, const float pressure)
float opacity_from_input_sample(const float pressure, const Brush *brush, const BrushGpencilSettings *settings)
ColorGeometry4f randomize_color(const BrushGpencilSettings &settings, const std::optional< BrushColorJitterSettings > &jitter, const float stroke_hue_factor, const float stroke_saturation_factor, const float stroke_value_factor, const float distance, const ColorGeometry4f color, const float pressure)
void add_single_curve(bke::CurvesGeometry &curves, const bool at_end)
float randomize_radius(const BrushGpencilSettings &settings, const float stroke_factor, const float distance, const float radius, const float pressure)
IndexMask polyline_detect_corners(Span< float2 > points, const float radius_min, const float radius_max, const int samples_max, const float angle_threshold, IndexMaskMemory &memory)
bke::CurvesGeometry curves_merge_endpoints_by_distance(const ARegion ®ion, const bke::CurvesGeometry &src_curves, const float4x4 &layer_to_world, const float merge_distance, const IndexMask &selection, const bke::AttributeFilter &attribute_filter)
Array< float2 > polyline_fit_curve(Span< float2 > points, const float error_threshold, const IndexMask &corner_mask)
Vector< MutableDrawingInfo > retrieve_editable_drawings(const Scene &scene, GreasePencil &grease_pencil)
float radius_from_input_sample(const RegionView3D *rv3d, const ARegion *region, const Brush *brush, const float pressure, const float3 &location, const float4x4 &to_world, const BrushGpencilSettings *settings)
float4x2 calculate_texture_space(const Scene *scene, const ARegion *region, const float2 &mouse, const DrawingPlacement &placement)
bke::CurvesGeometry create_curves_outline(const bke::greasepencil::Drawing &drawing, const IndexMask &strokes, const float4x4 &transform, const int corner_subdivisions, const float outline_radius, const float outline_offset, const int material_index)
static StrokeSnapMode get_snap_mode(const bContext &C)
static void linear_interpolation(const T &a, const T &b, MutableSpan< T > dst, const bool include_first_point)
static void deselect_stroke(const bContext &C, bke::greasepencil::Drawing &drawing, const int active_curve)
static void append_stroke_to_multiframe_drawings(const bke::CurvesGeometry &src_strokes, const int curve, const int current_frame, const bool on_back, Span< ed::greasepencil::MutableDrawingInfo > drawings)
std::unique_ptr< GreasePencilStrokeOperation > new_paint_operation(bool do_fill_guides=false)
static void trim_stroke_ends(bke::greasepencil::Drawing &drawing, const int active_curve, const bool on_back)
static float2 arithmetic_mean(Span< float2 > values)
static bke::CurvesGeometry get_single_stroke(const bke::CurvesGeometry &src, const int curve)
static int trim_end_points(bke::greasepencil::Drawing &drawing, const float epsilon, const bool on_back, const int active_curve)
static float brush_radius_to_pixel_radius(const RegionView3D *rv3d, const Brush *brush, const float3 pos)
bool brush_using_vertex_color(const GpPaint *gp_paint, const Brush *brush)
static void morph_points_to_curve(Span< float2 > src, Span< float2 > target, MutableSpan< float2 > dst)
static void simplify_stroke(bke::greasepencil::Drawing &drawing, const float epsilon, const int active_curve)
static void process_stroke_weights(const Scene &scene, const Object &object, bke::greasepencil::Drawing &drawing, const int active_curve)
static void smooth_stroke(bke::greasepencil::Drawing &drawing, const float influence, const int iterations, const int active_curve)
static Brush * create_fill_guide_brush()
static Array< float2 > sample_curve_2d(Span< float2 > positions, const int64_t resolution)
static void outline_stroke(bke::greasepencil::Drawing &drawing, const int active_curve, const float4x4 &viewmat, const ed::greasepencil::DrawingPlacement &placement, const float outline_radius, const int material_index, const bool on_back)
static void add_strokes_to_drawing(const bool on_back, Curves *strokes, bke::greasepencil::Drawing &drawing)
bke::GeometrySet join_geometries(Span< bke::GeometrySet > geometries, const bke::AttributeFilter &attribute_filter, const std::optional< Span< bke::GeometryComponent::Type > > &component_types_to_join=std::nullopt, bool allow_merging_instance_references=true)
void smooth_curve_attribute(const IndexMask &curves_to_smooth, const OffsetIndices< int > points_by_curve, const VArray< bool > &point_selection, const VArray< bool > &cyclic, int iterations, float influence, bool smooth_ends, bool keep_shape, GMutableSpan attribute_data)
void curve_simplify(const Span< float3 > positions, const bool cyclic, const float epsilon, const GSpan attribute_data, MutableSpan< bool > points_to_delete)
void gaussian_blur_1D(const GSpan src, int iterations, const VArray< float > &influence_by_point, const bool smooth_ends, const bool keep_shape, const bool is_cyclic, GMutableSpan dst)
void accumulate_lengths(const Span< T > values, const bool cyclic, MutableSpan< float > lengths)
void sample_at_lengths(Span< float > accumulated_segment_lengths, Span< float > sample_lengths, MutableSpan< int > r_segment_indices, MutableSpan< float > r_factors)
void interpolate(const Span< T > src, const Span< int > indices, const Span< float > factors, MutableSpan< T > dst)
T cos(const AngleRadianBase< T > &a)
T distance(const T &a, const T &b)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
CartesianBasis invert(const CartesianBasis &basis)
T interpolate(const T &a, const T &b, const FactorT &t)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T sin(const AngleRadianBase< T > &a)
T max(const T &a, const T &b)
void transform_points(const float4x4 &transform, MutableSpan< float3 > points, bool use_threading=true)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
MatBase< float, 4, 4 > float4x4
VecBase< float, 2 > float2
MatBase< float, 4, 2 > float4x2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
struct CurveMapping * curve_sensitivity
struct CurveMapping * curve_strength
struct CurveMapping * curve_jitter
struct CurveMapping * curve_rand_pressure
struct CurveMapping * curve_rand_strength
struct CurveMapping * curve_rand_uv
struct CurveMapping * curve_rand_saturation
struct CurveMapping * curve_rand_hue
struct CurveMapping * curve_rand_value
struct BrushGpencilSettings * gpencil_settings
GreasePencilRuntimeHandle * runtime
struct MaterialGPencilStyle * gp_style
struct ToolSettings * toolsettings
static MatBase identity()
static GeometrySet from_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
MutableVArraySpan< T > span
GreasePencil * grease_pencil_
void active_smoothing(PaintOperation &self, const IndexRange smooth_window)
void process_extension_sample(PaintOperation &self, const bContext &C, const InputSample &extension_sample)
ColorGeometry4f vertex_color_
ColorGeometry4f fill_color_
BrushGpencilSettings * settings_
bool use_settings_random_
std::optional< BrushColorJitterSettings > jitter_settings_
void active_jitter(PaintOperation &self, const int new_points_num, const float brush_radius_px, const float pressure, const IndexRange active_window, MutableSpan< float3 > curve_positions)
void execute(PaintOperation &self, const bContext &C, const InputSample &extension_sample)
PaintOperationExecutor(const bContext &C)
void process_start_sample(PaintOperation &self, const bContext &C, const InputSample &start_sample, const int material_index, const bool use_fill)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)