64 return float(brush->
size);
71 const bool include_first_point)
73 if (include_first_point) {
80 const float step = 1.0f / float(dst.
size());
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() ||
self.placement_.use_project_to_surface()) {
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");
425 u_scale.span[active_curve] = 1.0f;
426 curve_attributes_to_skip.
add(
"u_scale");
433 curve_attributes_to_skip.
add(
"aspect_ratio");
434 aspect_ratio.finish();
441 rotations.span[last_active_point] = start_rotation;
442 point_attributes_to_skip.
add(
"rotation");
452 start_caps.span[active_curve] =
settings_->caps_type;
453 curve_attributes_to_skip.
add(
"start_cap");
462 end_caps.span[active_curve] =
settings_->caps_type;
463 curve_attributes_to_skip.
add(
"end_cap");
468 if (use_fill && (start_opacity < 1.0f || attributes.
contains(
"fill_opacity"))) {
475 fill_opacities.span[active_curve] = start_opacity;
476 curve_attributes_to_skip.
add(
"fill_opacity");
477 fill_opacities.finish();
485 init_times.span[active_curve] = float(
uint64_t(
self.start_time_ * 1e3)) / float(1e3);
486 curve_attributes_to_skip.
add(
"init_time");
490 if (
self.do_fill_guides_) {
495 is_fill_boundary.span[active_curve] =
true;
496 curve_attributes_to_skip.
add(
".is_fill_guide");
497 is_fill_boundary.finish();
502 curve_attributes_to_skip.
add(
"curve_type");
503 curves.update_curve_types();
505 if (
self.placement_.use_project_to_stroke() ||
self.placement_.use_project_to_surface()) {
506 self.stroke_placement_depths_.append(
self.stroke_placement_depths_.is_empty() ?
508 self.stroke_placement_depths_.last());
510 self.update_stroke_depth_placement(
C, start_sample);
525 self.drawing_->tag_topology_changed();
530 const Span<float2> coords_to_smooth =
self.screen_space_coords_orig_.as_span().slice(
534 const float corner_min_radius_px = 5.0f;
535 const float corner_max_radius_px = 30.0f;
536 const int64_t corner_max_samples = 64;
537 const float corner_angle_threshold = 0.6f;
541 corner_min_radius_px,
542 corner_max_radius_px,
544 corner_angle_threshold,
550 const int pre_blur_iterations = 3;
561 const float max_error_threshold_px = 5.0f;
563 coords_pre_blur, max_error_threshold_px *
settings_->active_smooth, corner_mask);
566 const int64_t sample_resolution = 32;
575 const float converging_threshold_px = 0.1f;
576 bool stop_counting_converged =
false;
577 int num_converged = 0;
580 self.screen_space_curve_fitted_coords_[window_i].append(coords_smoothed[window_i]);
586 if (!stop_counting_converged) {
587 float2 prev_pos = window_coords[window_i];
588 if (
math::distance(new_pos, prev_pos) < converging_threshold_px) {
592 stop_counting_converged =
true;
597 window_coords[window_i] = new_pos;
601 if (num_converged > 0) {
602 self.active_smooth_start_index_ += num_converged;
603 self.screen_space_curve_fitted_coords_.remove(0, num_converged);
608 const int new_points_num,
609 const float brush_radius_px,
610 const float pressure,
614 float jitter_factor = 1.0f;
620 for ([[maybe_unused]]
const int _ :
IndexRange(new_points_num)) {
621 const float rand =
self.rng_.get_float() * 2.0f - 1.0f;
622 const float factor = rand *
settings_->draw_jitter * jitter_factor;
623 self.screen_space_jitter_offsets_.append(cotangent * factor * brush_radius_px);
625 const Span<float2> jitter_slice =
self.screen_space_jitter_offsets_.as_mutable_span().slice(
628 self.screen_space_smoothed_coords_.as_mutable_span().slice(active_window);
632 if (
self.placement_.use_project_to_stroke() ||
self.placement_.use_project_to_surface()) {
633 BLI_assert(
self.stroke_placement_depths_.size() ==
self.screen_space_coords_orig_.size());
635 self.stroke_placement_depths_.as_span().slice(active_window);
637 final_coords[window_i] = smoothed_coords[window_i] + jitter_slice[window_i];
638 const std::optional<float> depth = stroke_depths[window_i];
639 positions_slice[window_i] = depth ?
self.placement_.place(final_coords[window_i], *depth) :
640 self.placement_.project(final_coords[window_i]);
645 final_coords[window_i] = smoothed_coords[window_i] + jitter_slice[window_i];
646 positions_slice[window_i] =
self.placement_.project(final_coords[window_i]);
662 if (
self.placement_.use_project_to_stroke() ||
self.placement_.use_project_to_surface()) {
663 const std::optional<float> depth =
self.stroke_placement_depths_.is_empty() ?
665 self.stroke_placement_depths_.last();
667 position =
self.placement_.place(coords, *depth);
670 position =
self.placement_.project(coords);
674 position =
self.placement_.project(coords);
682 self.placement_.to_world_space(),
694 const int active_curve = on_back ?
curves.curves_range().first() :
695 curves.curves_range().last();
696 const IndexRange curve_points = points_by_curve[active_curve];
697 const int last_active_point = curve_points.
last();
699 const float2 prev_coords =
self.screen_space_coords_orig_.last();
700 float prev_radius =
self.drawing_->radii()[last_active_point];
701 const float prev_opacity =
self.drawing_->opacities()[last_active_point];
702 const ColorGeometry4f prev_vertex_color =
self.drawing_->vertex_colors()[last_active_point];
704 const bool is_first_sample = (curve_points.
size() == 1);
709 if (is_first_sample) {
710 self.smoothed_pen_direction_ =
self.screen_space_coords_orig_.last() - coords;
717 constexpr float smoothing_rate_factor = 0.3f;
719 self.screen_space_coords_orig_.last() -
721 smoothing_rate_factor);
725 float radius_factor = 1.0f;
726 if (
settings_->draw_angle_factor > 0.0f) {
738 radius *= radius_factor;
743 constexpr float point_override_threshold_px = 2.0f;
744 if (distance_px < point_override_threshold_px) {
745 self.accum_distance_ += distance_px;
747 if (!is_first_sample) {
748 curves.positions_for_write()[last_active_point] = position;
752 self.stroke_random_radius_factor_,
753 self.accum_distance_,
759 self.stroke_random_opacity_factor_,
760 self.accum_distance_,
764 self.drawing_->radii_for_write()[last_active_point] =
math::max(radius, prev_radius);
765 self.drawing_->opacities_for_write()[last_active_point] =
math::max(opacity, prev_opacity);
770 if (is_first_sample &&
settings_->draw_angle_factor > 0.0f) {
771 self.drawing_->radii_for_write()[last_active_point] *= radius_factor;
772 prev_radius =
self.drawing_->radii()[last_active_point];
776 constexpr int max_points_per_pixel = 4;
778 const float max_spacing_px =
math::max((
float(
brush_->spacing) / 100.0f) *
779 float(brush_radius_px),
780 1.0f /
float(max_points_per_pixel));
782 const int new_points_num = (distance_px > max_spacing_px) ?
787 curves, on_back ==
false, curve_points.
size() + new_points_num);
791 const IndexRange new_points =
curves.points_by_curve()[active_curve].take_back(new_points_num);
802 point_attributes_to_skip.
add_multiple({
"position",
"radius",
"opacity"});
808 self.stroke_random_radius_factor_,
809 self.accum_distance_ +
820 self.stroke_random_opacity_factor_,
821 self.accum_distance_ +
838 self.stroke_random_rotation_factor_,
841 point_attributes_to_skip.
add(
"rotation");
849 self.drawing_->vertex_colors_for_write().slice(new_points);
851 prev_vertex_color,
vertex_color_, new_vertex_colors, is_first_sample);
856 self.stroke_random_hue_factor_,
857 self.stroke_random_sat_factor_,
858 self.stroke_random_val_factor_,
859 self.accum_distance_ +
861 new_vertex_colors[
i],
865 point_attributes_to_skip.
add(
"vertex_color");
873 float(new_delta_time),
874 delta_times.span.slice(new_points),
876 point_attributes_to_skip.
add(
"delta_time");
877 delta_times.finish();
881 self.accum_distance_ += distance_px;
884 self.delta_time_ = new_delta_time;
887 self.screen_space_coords_orig_.extend(new_screen_space_coords);
888 self.screen_space_smoothed_coords_.extend(new_screen_space_coords);
889 self.screen_space_final_coords_.extend(new_screen_space_coords);
890 for (
float2 new_position : new_screen_space_coords) {
893 if (
self.placement_.use_project_to_stroke() ||
self.placement_.use_project_to_surface()) {
894 const std::optional<float> last_depth =
self.stroke_placement_depths_.is_empty() ?
896 self.stroke_placement_depths_.last();
897 self.stroke_placement_depths_.append_n_times(last_depth, new_points_num);
901 constexpr int64_t min_active_smoothing_points_num = 8;
902 const IndexRange smooth_window =
self.screen_space_coords_orig_.index_range().drop_front(
903 self.active_smooth_start_index_);
904 if (smooth_window.
size() < min_active_smoothing_points_num) {
905 if (
self.placement_.use_project_to_stroke() ||
self.placement_.use_project_to_surface()) {
907 self.stroke_placement_depths_.as_mutable_span().take_back(new_points_num);
909 const std::optional<float> depth = new_depths[
i];
911 new_positions[
i] =
self.placement_.place(coords, *depth);
914 new_positions[
i] =
self.placement_.project(coords);
919 self.placement_.project(new_screen_space_coords, new_positions);
941 self.screen_space_smoothed_coords_.as_mutable_span().slice(smooth_window);
947 if (
self.placement_.use_project_to_stroke() ||
self.placement_.use_project_to_surface()) {
948 BLI_assert(
self.stroke_placement_depths_.size() ==
self.screen_space_coords_orig_.size());
950 self.stroke_placement_depths_.as_mutable_span().slice(smooth_window);
952 const std::optional<float> depth = stroke_depths[window_i];
953 curve_positions_slice[window_i] = depth ?
954 self.placement_.place(final_coords[window_i],
956 self.placement_.project(final_coords[window_i]);
961 curve_positions_slice[window_i] =
self.placement_.project(final_coords[window_i]);
966 if (
self.placement_.use_project_to_stroke() ||
self.placement_.use_project_to_surface()) {
968 self.update_stroke_depth_placement(
C, extension_sample);
976 curves.points_range().take_back(new_points_num));
978 self.drawing_->set_texture_matrices({
self.texture_space_},
990 const int active_curve = on_back ?
curves.curves_range().first() :
991 curves.curves_range().last();
1019 BLI_assert(placement_.use_project_to_stroke() || placement_.use_project_to_surface());
1021 const std::optional<float> new_stroke_placement_depth = placement_.get_depth(
1023 if (!new_stroke_placement_depth) {
1028 switch (snap_mode) {
1030 const float start_depth = last_stroke_placement_depth_ ? *last_stroke_placement_depth_ :
1031 *new_stroke_placement_depth;
1032 const float end_depth = *new_stroke_placement_depth;
1034 C, last_stroke_placement_point_, start_depth, end_depth);
1036 if (!reprojected_points.
is_empty()) {
1037 last_stroke_placement_point_ = reprojected_points.
one_after_last();
1040 last_stroke_placement_depth_ = new_stroke_placement_depth;
1044 const float start_depth = last_stroke_placement_depth_ ? *last_stroke_placement_depth_ :
1045 *new_stroke_placement_depth;
1046 const float end_depth = *new_stroke_placement_depth;
1048 C, last_stroke_placement_point_, start_depth, end_depth);
1051 if (!last_stroke_placement_depth_) {
1053 if (!reprojected_points.
is_empty()) {
1054 last_stroke_placement_point_ = reprojected_points.
one_after_last();
1056 last_stroke_placement_depth_ = new_stroke_placement_depth;
1062 if (!last_stroke_placement_depth_) {
1063 const float start_depth = *new_stroke_placement_depth;
1064 const float end_depth = *new_stroke_placement_depth;
1067 last_stroke_placement_depth_ = new_stroke_placement_depth;
1077 std::optional<int> start_point,
1078 const float from_depth,
1079 const float to_depth)
1092 const IndexRange all_points = points_by_curve[active_curve];
1093 BLI_assert(screen_space_final_coords_.size() == all_points.
size());
1110 active_curve_points);
1114 active_curve_points);
1115 const float step_size = 1.0f / std::max(
int(active_points.
size()) - 1, 1);
1119 positions[
i] = placement_.place(final_coords[
i], *depths[
i]);
1122 return active_points;
1134 saved_active_brush_ = current_brush;
1142 saved_active_brush_ =
nullptr;
1145 fill_guides_brush_ =
nullptr;
1158 if (do_fill_guides_) {
1165 if (
brush->gpencil_settings ==
nullptr) {
1180 BLI_assert(grease_pencil->has_active_layer());
1184 if (placement_.use_project_to_surface() || placement_.use_project_to_stroke()) {
1200 stroke_random_radius_factor_ = rng_.get_float() * 2.0f - 1.0f;
1201 stroke_random_opacity_factor_ = rng_.get_float() * 2.0f - 1.0f;
1202 stroke_random_rotation_factor_ = rng_.get_float() * 2.0f - 1.0f;
1204 stroke_random_hue_factor_ = rng_.get_float() * 2.0f - 1.0f;
1205 stroke_random_sat_factor_ = rng_.get_float() * 2.0f - 1.0f;
1206 stroke_random_val_factor_ = rng_.get_float() * 2.0f - 1.0f;
1214 frame_number_ = scene->
r.
cfra;
1215 drawing_ = grease_pencil->get_editable_drawing_at(layer, frame_number_);
1220 grease_pencil->
runtime->is_drawing_stroke =
true;
1240 executor.
execute(*
this,
C, extension_sample);
1247 const float influence,
1248 const int iterations,
1249 const int active_curve)
1300 const float epsilon,
1301 const int active_curve)
1307 ".draw_tool_screen_space_positions");
1316 curves.cyclic()[active_curve],
1318 screen_space_positions,
1323 if (!points_to_delete.
is_empty()) {
1334 std::array<bke::GeometrySet, 2> geometry_sets;
1349 const int active_curve,
1356 ".draw_tool_screen_space_positions");
1365 rcti screen_space_bounds;
1376 screen_space_positions,
1377 {screen_space_bounds},
1395 const int active_curve,
1398 const float outline_radius,
1399 const int material_index,
1423 const float epsilon,
1425 const int active_curve)
1432 int64_t num_points_to_remove = 0;
1434 if (radii[index] < epsilon) {
1435 num_points_to_remove++;
1442 if (num_points_to_remove <= 0) {
1447 if (points.
size() - num_points_to_remove < 1) {
1448 num_points_to_remove = points.
size() - 1;
1453 curves.offsets_for_write().last() =
curves.points_num();
1454 return num_points_to_remove;
1458 const int last_active_point =
curves.points_by_curve()[0].last();
1470 using T = decltype(dummy);
1471 MutableSpan<T> span_data = attribute_data.typed<T>();
1473 for (int i = last_active_point - num_points_to_remove + 1;
1474 i < curves.points_num() - num_points_to_remove;
1477 span_data[i] = span_data[i + num_points_to_remove];
1485 for (
const int src_curve :
curves.curves_range().drop_front(1)) {
1486 offsets[src_curve] = offsets[src_curve] - num_points_to_remove;
1490 return num_points_to_remove;
1495 const int active_curve)
1520 const int active_curve)
1545 Object *ob_arm =
nullptr;
1558 if (amd ==
nullptr) {
1569 if (channel ==
nullptr) {
1578 if (channel ==
nullptr) {
1584 const float4x4 postmat = obinv * ob_arm->object_to_world();
1592 for (float3 &position : positions.slice(range)) {
1593 position = math::transform_point(matrix, position);
1611 src_offsets.as_span(),
1612 dst_offsets.as_span(),
1616 src_offsets = {curve, curve + 1};
1617 dst_offsets = {0, 1};
1623 src_offsets.as_span(),
1624 dst_offsets.as_span(),
1633 const int current_frame,
1640 if (drawing_info.frame_number == current_frame) {
1665 BLI_assert(grease_pencil.has_active_layer());
1672 const IndexRange points = points_by_curve[active_curve];
1681 screen_space_positions.
span.slice(points).copy_from(this->screen_space_final_coords_);
1682 screen_space_positions.
finish();
1690 if (do_post_processing) {
1704 const float outline_radius =
brush->unprojected_radius * settings->
outline_fac * 0.5f;
1705 const int material_index = [&]() {
1720 attributes.
remove(
".draw_tool_screen_space_positions");
1724 if (do_automerge_endpoints) {
1725 constexpr float merge_distance = 20.0f;
1729 *region, drawing.
strokes(), layer_to_world, merge_distance, selection, {});
1737 if (use_multi_frame_editing) {
1739 drawing.
strokes(), active_curve, frame_number_, on_back, multi_frame_drawings_);
1743 grease_pencil.
runtime->is_drawing_stroke =
false;
1745 if (do_fill_guides_) {
1755 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)
const std::optional< BrushColorJitterSettings > BKE_brush_color_jitter_get_settings(const Scene *scene, 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)
void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[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 ForSingle(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, eCustomDataType 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, eCustomDataType 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, eCustomDataType 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)
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)
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)
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)
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)
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)
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)
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)