56#include "RNA_prototypes.hh"
109 return unique_curves;
113 const bool check_editable,
114 const bool check_surface,
115 const bool check_edit_mode)
121 if (check_editable) {
133 if (check_edit_mode) {
181namespace convert_to_particle_system {
189 if (possible_mface_indices.
size() == 1) {
190 return possible_mface_indices.
first();
194 float best_distance_sq =
FLT_MAX;
195 for (
const int possible_mface_i : possible_mface_indices) {
196 const MFace &possible_mface = mface[possible_mface_i];
201 positions[possible_mface.
v1],
202 positions[possible_mface.
v2],
203 positions[possible_mface.
v3]);
205 if (distance_sq < best_distance_sq) {
206 best_distance_sq = distance_sq;
207 mface_i = possible_mface_i;
211 if (possible_mface.
v4) {
215 positions[possible_mface.
v1],
216 positions[possible_mface.
v3],
217 positions[possible_mface.
v4]);
219 if (distance_sq < best_distance_sq) {
220 best_distance_sq = distance_sq;
221 mface_i = possible_mface_i;
237 float mface_positions_su[4][3];
246 mface_weights, positions[mface.
v1], positions[mface.
v2], positions[mface.
v3], position);
247 mface_weights[3] = 0.0f;
249 return mface_weights;
255 bool *r_could_not_convert_some_curves)
262 if (curves_id.
surface ==
nullptr) {
269 Mesh &surface_me = *
static_cast<Mesh *
>(surface_ob.
data);
274 const Span<int> tri_faces = surface_me.corner_tri_faces();
277 *r_could_not_convert_some_curves =
true;
284 return points_by_curve[curve_i].
size() > 1;
287 const int hair_num = multi_point_curves.
size();
296 particle_system = psys;
300 if (particle_system ==
nullptr) {
303 particle_system = psmd.
psys;
325 for (
const int mface_i : mface_to_poly_map.index_range()) {
326 const int face_i = mface_to_poly_map[mface_i];
327 poly_to_mface_map[face_i].append(mface_i);
334 const Span<float3> positions = surface_me.vert_positions();
336 multi_point_curves.
foreach_index([&](
const int curve_i,
const int new_hair_i) {
337 const IndexRange points = points_by_curve[curve_i];
339 const float3 &root_pos_cu = positions_cu[points.
first()];
348 const int tri_i = nearest.
index;
349 const int face_i = tri_faces[tri_i];
352 positions, mfaces, poly_to_mface_map[face_i], root_pos_su);
353 const MFace &mface = mfaces[mface_i];
358 const int num_keys = points.
size();
361 particle.
hair = hair_keys.data();
362 particle.
totkey = hair_keys.size();
364 particle.
num = mface_i;
372 hair_to_surface_mat.
location() = root_pos_su;
375 for (
const int key_i : hair_keys.index_range()) {
376 const float3 &key_pos_cu = positions_cu[points[key_i]];
382 const float key_fac = key_i / float(hair_keys.size() - 1);
383 key.time = 100.0f * key_fac;
384 key.weight = 1.0f - key_fac;
388 particle_system->
particles = particles.data();
389 particle_system->
totpart = particles.size();
402 bool could_not_convert_some_curves =
false;
408 if (curves_ob != &active_object) {
414 if (could_not_convert_some_curves) {
417 "Some curves could not be converted because they were not attached to the surface");
429 ot->
name =
"Convert Curves to Particle System";
430 ot->
idname =
"CURVES_OT_convert_to_particle_system";
431 ot->
description =
"Add a new or update an existing hair particle system on the surface object";
439namespace convert_from_particle_system {
457 if (transfer_parents) {
458 for (
const int parent_i : parents_cache.index_range()) {
459 const int segments = parents_cache[parent_i]->segments;
463 parents_to_transfer.
append(parent_i);
464 curve_offsets.
append(points_num);
465 points_num += segments + 1;
468 for (
const int child_i : children_cache.index_range()) {
469 const int segments = children_cache[child_i]->segments;
473 children_to_transfer.
append(child_i);
474 curve_offsets.
append(points_num);
475 points_num += segments + 1;
477 const int curves_num = parents_to_transfer.
size() + children_to_transfer.
size();
478 curve_offsets.
append(points_num);
483 const float4x4 &object_to_world_mat =
object.object_to_world();
491 const int curve_index_offset) {
493 for (const int i : range) {
494 const int hair_i = indices_to_transfer[i];
495 const int curve_i = i + curve_index_offset;
496 const IndexRange points = points_by_curve[curve_i];
497 const Span<ParticleCacheKey> keys{hair_cache[hair_i], points.size()};
498 for (const int key_i : keys.index_range()) {
499 const float3 key_pos_wo = keys[key_i].co;
500 positions[points[key_i]] = math::transform_point(world_to_object_mat, key_pos_wo);
506 if (transfer_parents) {
507 copy_hair_to_curves(parents_cache, parents_to_transfer, 0);
509 copy_hair_to_curves(children_cache, children_to_transfer, parents_to_transfer.size());
511 curves.update_curve_types();
512 curves.tag_topology_changed();
525 if (psys_orig ==
nullptr) {
528 if (psys_orig ==
nullptr) {
541 psys_eval = psmd->
psys;
564 ot->
name =
"Convert Particle System to Curves";
565 ot->
idname =
"CURVES_OT_convert_from_particle_system";
566 ot->
description =
"Add a new curves object based on the current state of the particle system";
568 ot->
poll = convert_from_particle_system::curves_convert_from_particle_system_poll;
569 ot->
exec = convert_from_particle_system::curves_convert_from_particle_system_exec;
574namespace snap_curves_to_surface {
590 const Mesh &surface_mesh = *
static_cast<const Mesh *
>(surface_ob.
data);
591 const Span<float3> surface_positions = surface_mesh.vert_positions();
592 const Span<int> corner_verts = surface_mesh.corner_verts();
593 const Span<int3> surface_corner_tris = surface_mesh.corner_tris();
598 bke::AttrDomain::Corner);
607 switch (attach_mode) {
608 case AttachMode::Nearest: {
612 for (const int curve_i : curves_range) {
613 const IndexRange points = points_by_curve[curve_i];
614 const int first_point_i = points.first();
615 const float3 old_first_point_pos_cu = positions_cu[first_point_i];
616 const float3 old_first_point_pos_su = math::transform_point(transforms.curves_to_surface,
617 old_first_point_pos_cu);
619 BVHTreeNearest nearest;
621 nearest.dist_sq = FLT_MAX;
622 BLI_bvhtree_find_nearest(surface_bvh.tree,
623 old_first_point_pos_su,
625 surface_bvh.nearest_callback,
627 const int tri_index = nearest.index;
628 if (tri_index == -1) {
632 const float3 new_first_point_pos_su = nearest.co;
633 const float3 new_first_point_pos_cu = math::transform_point(transforms.surface_to_curves,
634 new_first_point_pos_su);
635 const float3 pos_diff_cu = new_first_point_pos_cu - old_first_point_pos_cu;
637 for (float3 &pos_cu : positions_cu.slice(points)) {
638 pos_cu += pos_diff_cu;
641 if (!surface_uv_map.is_empty()) {
642 const int3 &tri = surface_corner_tris[tri_index];
643 const float3 bary_coords = bke::mesh_surface_sample::compute_bary_coord_in_triangle(
644 surface_positions, corner_verts, tri, new_first_point_pos_su);
645 const float2 uv = bke::mesh_surface_sample::sample_corner_attribute_with_bary_coords(
646 bary_coords, tri, surface_uv_map);
647 surface_uv_coords[curve_i] = uv;
653 case AttachMode::Deform: {
655 *r_missing_uvs =
true;
659 ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_corner_tris};
662 for (const int curve_i : curves_range) {
663 const IndexRange points = points_by_curve[curve_i];
664 const int first_point_i = points.first();
665 const float3 old_first_point_pos_cu = positions_cu[first_point_i];
667 const float2 uv = surface_uv_coords[curve_i];
668 ReverseUVSampler::Result lookup_result = reverse_uv_sampler.sample(uv);
669 if (lookup_result.type != ReverseUVSampler::ResultType::Ok) {
670 *r_invalid_uvs = true;
674 const int3 &tri = surface_corner_tris[lookup_result.tri_index];
675 const float3 &bary_coords = lookup_result.bary_weights;
677 const float3 &p0_su = surface_positions[corner_verts[tri[0]]];
678 const float3 &p1_su = surface_positions[corner_verts[tri[1]]];
679 const float3 &p2_su = surface_positions[corner_verts[tri[2]]];
681 float3 new_first_point_pos_su;
682 interp_v3_v3v3v3(new_first_point_pos_su, p0_su, p1_su, p2_su, bary_coords);
683 const float3 new_first_point_pos_cu = math::transform_point(transforms.surface_to_curves,
684 new_first_point_pos_su);
686 const float3 pos_diff_cu = new_first_point_pos_cu - old_first_point_pos_cu;
687 for (float3 &pos_cu : positions_cu.slice(points)) {
688 pos_cu += pos_diff_cu;
696 curves.tag_positions_changed();
704 bool found_invalid_uvs =
false;
705 bool found_missing_uvs =
false;
711 Curves &curves_id = *
static_cast<Curves *
>(curves_ob->data);
712 if (curves_id.
surface ==
nullptr) {
719 *curves_ob, *curves_id.
surface, attach_mode, &found_invalid_uvs, &found_missing_uvs);
723 if (found_missing_uvs) {
726 "Curves do not have attachment information that can be used for deformation");
728 if (found_invalid_uvs) {
742 using namespace snap_curves_to_surface;
744 ot->
name =
"Snap Curves to Surface";
745 ot->
idname =
"CURVES_OT_snap_curves_to_surface";
746 ot->
description =
"Move curves so that the first point is exactly on the surface mesh";
749 ot->
exec = snap_curves_to_surface_exec;
754 {int(AttachMode::Nearest),
758 "Find the closest point on the surface for the root point of every curve and move the root "
760 {int(AttachMode::Deform),
764 "Re-attach curves to a deformed surface using the existing attachment information. This "
765 "only works when the topology of the surface mesh has not changed"},
766 {0,
nullptr, 0,
nullptr,
nullptr},
772 int(AttachMode::Nearest),
774 "How to find the point on the surface to attach to");
777namespace set_selection_domain {
788 curves_id->selection_domain = char(domain);
804 if (
const GVArray src = *attributes.
lookup(selection_name, domain)) {
805 const CPPType &type = src.type();
807 src.materialize(dst);
809 attributes.
remove(selection_name);
810 if (!attributes.
add(selection_name,
812 bke::cpp_type_to_custom_data_type(type),
819 if (!active_attribute.empty()) {
840 ot->
name =
"Set Select Mode";
842 ot->
description =
"Change the mode used for selection masking in curves sculpt mode";
844 ot->
exec = set_selection_domain::curves_set_selection_domain_exec;
856 return std::any_of(curves_ids.
begin(), curves_ids.
end(), [](
const Curves *curves_id) {
857 return has_anything_selected(curves_id->geometry.wrap());
871 for (
Curves *curves_id : unique_curves) {
886 ot->
name =
"(De)select All";
887 ot->
idname =
"CURVES_OT_select_all";
905 for (
Curves *curves_id : unique_curves) {
911 const IndexMask inv_random_elements = random_mask(domain_size,
seed, probability, memory)
917 if (!was_anything_selected) {
918 curves::fill_selection_true(selection.
span);
921 curves::fill_selection_false(selection.
span, inv_random_elements);
942 ot->
name =
"Select Random";
944 ot->
description =
"Randomizes existing selection or create new random selection";
947 ot->
poll = curves::editable_curves_poll;
958 "Source of randomness",
967 "Chance of every point or curve being included in the selection",
978 for (
Curves *curves_id : unique_curves) {
983 curves, amount_start, amount_end,
true, memory);
988 if (!was_anything_selected) {
993 index_mask::masked_fill(selection.
span.
typed<
bool>(),
false, inverted_end_points_mask);
996 index_mask::masked_fill(selection.
span.
typed<
float>(), 0.0f, inverted_end_points_mask);
1023 ot->
name =
"Select Ends";
1039 "Number of points to select from the front",
1048 "Number of points to select from the back",
1056 for (
Curves *curves_id : unique_curves) {
1070 ot->
name =
"Select Linked";
1072 ot->
description =
"Select all points in curves with any point selection";
1083 for (
Curves *curves_id : unique_curves) {
1097 ot->
name =
"Select More";
1110 for (
Curves *curves_id : unique_curves) {
1124 ot->
name =
"Select Less";
1139 for (
Curves *curves_id : unique_curves) {
1165 ot->
exec = split::split_exec;
1171namespace surface_set {
1176 if (
object ==
nullptr) {
1192 Mesh &new_surface_mesh = *
static_cast<Mesh *
>(new_surface_ob.
data);
1200 Object &curves_ob = *selected_ob;
1204 if (new_uv_map_name !=
nullptr) {
1210 snap_curves_to_surface::snap_curves_to_surface_exec_object(
1213 snap_curves_to_surface::AttachMode::Nearest,
1220 curves_id.
surface = &new_surface_ob;
1221 object::parent_set(op->
reports,
1250 ot->
name =
"Set Curves Surface Object";
1253 "Use the active object as surface for selected curves objects and set it as the parent";
1255 ot->
exec = surface_set::surface_set_exec;
1256 ot->
poll = surface_set::surface_set_poll;
1261namespace curves_delete {
1282 ot->
description =
"Remove selected control points or curves";
1284 ot->
exec = curves_delete::delete_exec;
1290namespace curves_duplicate {
1298 case bke::AttrDomain::Point:
1301 case bke::AttrDomain::Curve:
1322 ot->
exec = curves_duplicate::duplicate_exec;
1328namespace clear_tilt {
1344 index_mask::masked_fill(curves.
tilt_for_write(), 0.0f, selection);
1360 ot->
description =
"Clear the tilt of selected control points";
1362 ot->
exec = clear_tilt::exec;
1368namespace cyclic_toggle {
1383 "cyclic", bke::AttrDomain::Curve);
1385 [&](
const int i) { cyclic.
span[i] = !cyclic.
span[i]; });
1388 if (!cyclic.
span.contains(
true)) {
1389 attributes.
remove(
"cyclic");
1404 ot->
name =
"Toggle Cyclic";
1408 ot->
exec = cyclic_toggle::exec;
1414namespace curve_type_set {
1430 options.convert_bezier_handles_to_poly_points = use_handles;
1431 options.convert_bezier_handles_to_catmull_rom_points = use_handles;
1432 options.keep_bezier_shape_as_nurbs = use_handles;
1433 options.keep_catmull_rom_shape_as_nurbs = use_handles;
1435 curves = geometry::convert_curves(curves, selection, dst_type, {},
options);
1447 ot->
name =
"Set Curve Type";
1451 ot->
exec = curve_type_set::exec;
1463 "Take handle information into account in the conversion");
1466namespace switch_direction {
1490 ot->
name =
"Switch Direction";
1492 ot->
description =
"Reverse the direction of the selected curves";
1494 ot->
exec = switch_direction::exec;
1500namespace subdivide {
1516 points_selection.
to_bools(points_selection_span);
1518 Array<int> segment_cuts(points_num, number_cuts);
1522 for (const int curve_i : range) {
1523 const IndexRange points = points_by_curve[curve_i];
1524 if (points.size() <= 1) {
1527 for (const int point_i : points.drop_back(1)) {
1528 if (!points_selection_span[point_i] || !points_selection_span[point_i + 1]) {
1529 segment_cuts[point_i] = 0;
1533 if (!points_selection_span[points.last()] || !points_selection_span[points.first()]) {
1534 segment_cuts[points.last()] = 0;
1539 curves = geometry::subdivide_curves(
1556 ot->
exec = subdivide::exec;
1562 prop =
RNA_def_int(
ot->
srna,
"number_cuts", 1, 1, 1000,
"Number of Cuts",
"", 1, 10);
1573 const int new_points_num = new_curves.
points_num();
1574 const int new_curves_num = new_curves.
curves_num();
1578 &curves_id, bke::GeometryOwnershipType::ReadOnly);
1580 bke::curves_new_nomain(std::move(new_curves)));
1586 object::add_generic_get_opts(C, &op,
'Z', location, rotation, scale,
nullptr,
nullptr,
nullptr);
1589 geometry::transform_geometry(new_geometry,
transform);
1591 bke::GeometrySet joined_geometry = geometry::join_geometries({old_geometry, new_geometry}, {});
1594 dst_curves = std::move(joined_curves_id->geometry.wrap());
1598 const int new_element_num = selection_domain == bke::AttrDomain::Point ? new_points_num :
1609namespace add_circle {
1620 curves.cyclic_for_write().
fill(
true);
1623 curves.resolution_for_write().fill(12);
1626 positions[0] =
float3(-radius, 0, 0);
1627 positions[1] =
float3(0, radius, 0);
1628 positions[2] =
float3(radius, 0, 0);
1629 positions[3] =
float3(0, -radius, 0);
1632 curves.handle_positions_left_for_write();
1633 curves.handle_positions_right_for_write();
1635 curves.calculate_bezier_auto_handles();
1643 Curves *active_curves_id =
static_cast<Curves *
>(
object->data);
1661 ot->
exec = add_circle::exec;
1666 object::add_unit_props_radius(
ot);
1667 object::add_generic_props(
ot,
true);
1670namespace add_bezier {
1683 curves.resolution_for_write().fill(12);
1689 left_handles[0] =
float3(-1.5f, -0.5, 0) * radius;
1690 positions[0] =
float3(-1.0f, 0, 0) * radius;
1691 right_handles[0] =
float3(-0.5f, 0.5f, 0) * radius;
1693 left_handles[1] =
float3(0, 0, 0) * radius;
1694 positions[1] =
float3(1.0f, 0, 0) * radius;
1695 right_handles[1] =
float3(2.0f, 0, 0) * radius;
1703 Curves *active_curves_id =
static_cast<Curves *
>(
object->data);
1721 ot->
exec = add_bezier::exec;
1726 object::add_unit_props_radius(
ot);
1727 object::add_generic_props(
ot,
true);
1730namespace set_handle_type {
1741 ".selection", bke::AttrDomain::Point,
true);
1743 ".selection_handle_left", bke::AttrDomain::Point,
true);
1745 ".selection_handle_right", bke::AttrDomain::Point,
true);
1751 for (const int point_i : range) {
1752 if (selection_left[point_i] || selection[point_i]) {
1753 handle_types_left[point_i] = int8_t(dst_handle_type);
1755 if (selection_right[point_i] || selection[point_i]) {
1756 handle_types_right[point_i] = int8_t(dst_handle_type);
1761 curves.calculate_bezier_auto_handles();
1762 curves.tag_topology_changed();
1774 ot->
name =
"Set Handle Type";
1779 ot->
exec = set_handle_type::exec;
1826 "Make copies of selected elements and move them",
1834 "Extrude Curve and Move",
1835 "Extrude curve and move result",
std::optional< blender::StringRefNull > BKE_attributes_active_name_get(AttributeOwner &owner)
void BKE_attributes_active_set(AttributeOwner &owner, blender::StringRef name)
#define CTX_DATA_BEGIN(C, Type, instance, member)
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
void BKE_mesh_tessface_calc(Mesh *mesh)
General operations, lookup, etc. for blender objects.
void BKE_object_apply_mat4(Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
Object * BKE_object_add(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name) ATTR_NONNULL(1
struct ModifierData * object_add_particle_system(struct Main *bmain, const struct Scene *scene, struct Object *ob, const char *name)
void psys_mat_hair_to_object(struct Object *ob, struct Mesh *mesh, short from, struct ParticleData *pa, float hairmat[4][4])
void psys_free_particles(struct ParticleSystem *psys)
void psys_changed_type(struct Object *ob, struct ParticleSystem *psys)
struct ParticleSystem * psys_get_current(struct Object *ob)
void BKE_report(ReportList *reports, eReportType type, const char *message)
#define BLI_assert_unreachable()
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
#define LISTBASE_FOREACH(type, var, list)
void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
void interp_weights_poly_v3(float w[], float v[][3], int n, const float co[3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ eModifierType_ParticleSystem
Object is a sort of wrapper for general info.
@ OB_MODIFIER_FLAG_ADD_REST_POSITION
bool ED_operator_object_active_editable_ex(bContext *C, const Object *ob)
static void split(const char *text, const char *seps, char ***str, int *count)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static unsigned long seed
static AttributeOwner from_id(ID *id)
GMutableSpan take_back(const int64_t n) const
GMutableSpan drop_back(const int64_t n) const
const CPPType & type() const
MutableSpan< T > typed() const
constexpr int64_t first() const
constexpr int64_t size() const
constexpr void fill(const T &value) const
constexpr void copy_from(Span< T > values) const
constexpr const T & first() const
constexpr int64_t size() const
constexpr const T * end() const
constexpr IndexRange index_range() const
constexpr const T * begin() const
constexpr bool is_empty() const
void add_new(const Key &key)
void append(const T &value)
GAttributeReader lookup(const StringRef attribute_id) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
int domain_size(const AttrDomain domain) const
void reverse_curves(const IndexMask &curves_to_reverse)
MutableSpan< float3 > positions_for_write()
OffsetIndices< int > points_by_curve() const
MutableSpan< int8_t > handle_types_right_for_write()
IndexRange curves_range() const
MutableAttributeAccessor attributes_for_write()
MutableSpan< float > tilt_for_write()
void tag_normals_changed()
MutableSpan< float2 > surface_uv_coords_for_write()
IndexRange points_range() const
Span< float3 > positions() const
void tag_topology_changed()
AttributeAccessor attributes() const
MutableSpan< int > offsets_for_write()
void calculate_bezier_auto_handles()
MutableSpan< int8_t > handle_types_left_for_write()
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)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void to_bools(MutableSpan< bool > r_bools) const
void foreach_index(Fn &&fn) const
IndexRange index_range() const
CCL_NAMESPACE_BEGIN struct Options options
const Depsgraph * depsgraph
static wmOperatorStatus duplicate_exec(bContext *C, wmOperator *op)
static wmOperatorStatus select_linked_exec(bContext *C, wmOperator *)
static wmOperatorStatus delete_exec(bContext *C, wmOperator *op)
VecBase< float, 3 > float3
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
static wmOperatorStatus select_all_exec(bContext *C, wmOperator *op)
static CurvesGeometry generate_bezier_primitive(const float radius)
static CurvesGeometry generate_circle_primitive(const float radius)
static wmOperatorStatus curves_convert_from_particle_system_exec(bContext *C, wmOperator *)
static bke::CurvesGeometry particles_to_curves(Object &object, ParticleSystem &psys)
static bool curves_convert_from_particle_system_poll(bContext *C)
static float4 compute_mface_weights_for_position(const Span< float3 > positions, const MFace &mface, const float3 &position)
static int find_mface_for_root_position(const Span< float3 > positions, const MFace *mface, const Span< int > possible_mface_indices, const float3 &root_pos)
static wmOperatorStatus curves_convert_to_particle_system_exec(bContext *C, wmOperator *op)
static void try_convert_single_object(Object &curves_ob, Main &bmain, Scene &scene, bool *r_could_not_convert_some_curves)
static wmOperatorStatus curves_set_selection_domain_exec(bContext *C, wmOperator *op)
static wmOperatorStatus snap_curves_to_surface_exec(bContext *C, wmOperator *op)
static void snap_curves_to_surface_exec_object(Object &curves_ob, const Object &surface_ob, const AttachMode attach_mode, bool *r_invalid_uvs, bool *r_missing_uvs)
static wmOperatorStatus split_exec(bContext *C, wmOperator *)
static wmOperatorStatus surface_set_exec(bContext *C, wmOperator *op)
static bool surface_set_poll(bContext *C)
static void CURVES_OT_surface_set(wmOperatorType *ot)
void select_linked(bke::CurvesGeometry &curves, const IndexMask &curves_mask)
void operatormacros_curves()
bool remove_selection(bke::CurvesGeometry &curves, const bke::AttrDomain selection_domain)
static void CURVES_OT_convert_from_particle_system(wmOperatorType *ot)
void keymap_curves(wmKeyConfig *keyconf)
void CURVES_OT_draw(wmOperatorType *ot)
static bool has_anything_selected(const Span< Curves * > curves_ids)
static void CURVES_OT_select_less(wmOperatorType *ot)
static void CURVES_OT_convert_to_particle_system(wmOperatorType *ot)
static void CURVES_OT_select_random(wmOperatorType *ot)
IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
static void CURVES_OT_select_ends(wmOperatorType *ot)
void select_all(bke::CurvesGeometry &curves, const IndexMask &mask, const bke::AttrDomain selection_domain, int action)
void operatortypes_curves()
static bool editable_curves_point_domain_poll(bContext *C)
void duplicate_curves(bke::CurvesGeometry &curves, const IndexMask &mask)
static void CURVES_OT_add_bezier(wmOperatorType *ot)
void duplicate_points(bke::CurvesGeometry &curves, const IndexMask &mask)
static void CURVES_OT_select_linked(wmOperatorType *ot)
VectorSet< Curves * > get_unique_editable_curves(const bContext &C)
bool editable_curves_poll(bContext *C)
void select_adjacent(bke::CurvesGeometry &curves, const IndexMask &curves_mask, const bool deselect)
static void CURVES_OT_handle_type_set(wmOperatorType *ot)
static void CURVES_OT_subdivide(wmOperatorType *ot)
void foreach_selection_attribute_writer(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain, blender::FunctionRef< void(bke::GSpanAttributeWriter &selection)> fn)
static void CURVES_OT_select_more(wmOperatorType *ot)
static void CURVES_OT_select_all(wmOperatorType *ot)
static void CURVES_OT_switch_direction(wmOperatorType *ot)
IndexMask retrieve_all_selected_points(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
bke::CurvesGeometry split_points(const bke::CurvesGeometry &curves, const IndexMask &points_to_split)
void fill_selection_false(GMutableSpan selection)
bool object_has_editable_curves(const Main &bmain, const Object &object)
static void select_random_ui(bContext *, wmOperator *op)
bool editable_curves_in_edit_mode_poll(bContext *C)
static void CURVES_OT_split(wmOperatorType *ot)
static void CURVES_OT_tilt_clear(wmOperatorType *ot)
static void CURVES_OT_duplicate(wmOperatorType *ot)
void fill_selection_true(GMutableSpan selection)
static bool curves_poll_impl(bContext *C, const bool check_editable, const bool check_surface, const bool check_edit_mode)
Span< StringRef > get_curves_selection_attribute_names(const bke::CurvesGeometry &curves)
static void CURVES_OT_curve_type_set(wmOperatorType *ot)
static void CURVES_OT_cyclic_toggle(wmOperatorType *ot)
static wmOperatorStatus select_ends_exec(bContext *C, wmOperator *op)
static void CURVES_OT_delete(wmOperatorType *ot)
static void CURVES_OT_snap_curves_to_surface(wmOperatorType *ot)
void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob)
static void append_primitive_curve(bContext *C, Curves &curves_id, CurvesGeometry new_curves, wmOperator &op)
IndexMask end_points(const bke::CurvesGeometry &curves, const IndexMask &curves_mask, const int amount_start, const int amount_end, const bool inverted, IndexMaskMemory &memory)
bool curves_with_surface_poll(bContext *C)
static void select_ends_ui(bContext *, wmOperator *op)
bke::GSpanAttributeWriter ensure_selection_attribute(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain, eCustomDataType create_type, StringRef attribute_name)
void CURVES_OT_separate(wmOperatorType *ot)
void CURVES_OT_attribute_set(wmOperatorType *ot)
bool curves_poll(bContext *C)
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
void CURVES_OT_extrude(wmOperatorType *ot)
void CURVES_OT_select_linked_pick(wmOperatorType *ot)
static void CURVES_OT_set_selection_domain(wmOperatorType *ot)
static void CURVES_OT_add_circle(wmOperatorType *ot)
bool editable_curves_with_surface_poll(bContext *C)
Object * context_active_object(const bContext *C)
CartesianBasis invert(const CartesianBasis &basis)
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &scale)
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))
static void exec(void *data, int, bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
static wmOperatorStatus select_random_exec(bContext *C, wmOperator *op)
static wmOperatorStatus select_less_exec(bContext *C, wmOperator *)
static wmOperatorStatus select_more_exec(bContext *C, wmOperator *)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const EnumPropertyItem rna_enum_attribute_curves_domain_items[]
const EnumPropertyItem rna_enum_curves_handle_type_items[]
const EnumPropertyItem rna_enum_curves_type_items[]
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
struct ParticleSystem * psys
struct ParticleCacheKey ** childcache
struct ParticleCacheKey ** pathcache
const c_style_mat & ptr() const
BVHTree_NearestPointCallback nearest_callback
Curves * get_curves_for_write()
MutableVArraySpan< T > span
uiLayout & column(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
bool(* poll)(struct bContext *)
wmOperatorStatus(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
wmOperatorStatus(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
void(* ui)(bContext *C, wmOperator *op)
struct ReportList * reports
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
void WM_operator_properties_select_all(wmOperatorType *ot)
wmOperatorTypeMacro * WM_operatortype_macro_define(wmOperatorType *ot, const char *idname)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
wmOperatorType * WM_operatortype_append_macro(const char *idname, const char *name, const char *description, int flag)
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)