61#include "RNA_prototypes.hh"
109 unique_curves.
add(
static_cast<Curves *
>(object->data));
114 return unique_curves;
118 const bool check_editable,
119 const bool check_surface,
120 const bool check_edit_mode)
123 if (
object ==
nullptr || object->type !=
OB_CURVES) {
126 if (check_editable) {
133 if (curves.surface ==
nullptr || curves.surface->type !=
OB_MESH) {
138 if (check_edit_mode) {
186namespace convert_to_particle_system {
194 if (possible_mface_indices.
size() == 1) {
195 return possible_mface_indices.
first();
199 float best_distance_sq =
FLT_MAX;
200 for (
const int possible_mface_i : possible_mface_indices) {
201 const MFace &possible_mface = mface[possible_mface_i];
206 positions[possible_mface.
v1],
207 positions[possible_mface.
v2],
208 positions[possible_mface.
v3]);
210 if (distance_sq < best_distance_sq) {
211 best_distance_sq = distance_sq;
212 mface_i = possible_mface_i;
216 if (possible_mface.
v4) {
220 positions[possible_mface.
v1],
221 positions[possible_mface.
v3],
222 positions[possible_mface.
v4]);
224 if (distance_sq < best_distance_sq) {
225 best_distance_sq = distance_sq;
226 mface_i = possible_mface_i;
242 float mface_positions_su[4][3];
251 mface_weights, positions[mface.
v1], positions[mface.
v2], positions[mface.
v3], position);
252 mface_weights[3] = 0.0f;
254 return mface_weights;
260 bool *r_could_not_convert_some_curves)
267 if (curves_id.
surface ==
nullptr) {
274 Mesh &surface_me = *
static_cast<Mesh *
>(surface_ob.
data);
281 const Span<int> tri_faces = surface_me.corner_tri_faces();
284 *r_could_not_convert_some_curves =
true;
290 curves.curves_range(),
GrainSize(4096), memory, [&](
const int curve_i) {
291 return points_by_curve[curve_i].
size() > 1;
294 const int hair_num = multi_point_curves.
size();
303 particle_system = psys;
307 if (particle_system ==
nullptr) {
310 particle_system = psmd.
psys;
318 settings.totpart = 0;
333 for (
const int mface_i : mface_to_poly_map.index_range()) {
334 const int face_i = mface_to_poly_map[mface_i];
335 poly_to_mface_map[face_i].append(mface_i);
342 const Span<float3> positions = surface_me.vert_positions();
344 multi_point_curves.
foreach_index([&](
const int curve_i,
const int new_hair_i) {
345 const IndexRange points = points_by_curve[curve_i];
347 const float3 &root_pos_cu = positions_cu[points.first()];
356 const int tri_i = nearest.index;
357 const int face_i = tri_faces[tri_i];
360 positions, mfaces, poly_to_mface_map[face_i], root_pos_su);
361 const MFace &mface = mfaces[mface_i];
366 const int num_keys = points.
size();
370 particle.
hair = hair_keys.data();
371 particle.
totkey = hair_keys.size();
373 particle.
num = mface_i;
381 hair_to_surface_mat.
location() = root_pos_su;
384 for (
const int key_i : hair_keys.index_range()) {
385 const float3 &key_pos_cu = positions_cu[points[key_i]];
389 HairKey &key = hair_keys[key_i];
391 const float key_fac = key_i /
float(hair_keys.size() - 1);
392 key.
time = 100.0f * key_fac;
393 key.
weight = 1.0f - key_fac;
397 particle_system->
particles = particles.data();
398 particle_system->
totpart = particles.size();
411 bool could_not_convert_some_curves =
false;
417 if (curves_ob != &active_object) {
423 if (could_not_convert_some_curves) {
426 "Some curves could not be converted because they were not attached to the surface");
438 ot->
name =
"Convert Curves to Particle System";
439 ot->
idname =
"CURVES_OT_convert_to_particle_system";
440 ot->
description =
"Add a new or update an existing hair particle system on the surface object";
448namespace convert_from_particle_system {
466 if (transfer_parents) {
467 for (
const int parent_i : parents_cache.index_range()) {
468 const int segments = parents_cache[parent_i]->segments;
472 parents_to_transfer.
append(parent_i);
473 curve_offsets.
append(points_num);
474 points_num += segments + 1;
477 for (
const int child_i : children_cache.index_range()) {
478 const int segments = children_cache[child_i]->segments;
482 children_to_transfer.
append(child_i);
483 curve_offsets.
append(points_num);
484 points_num += segments + 1;
486 const int curves_num = parents_to_transfer.
size() + children_to_transfer.
size();
487 curve_offsets.
append(points_num);
490 curves.offsets_for_write().copy_from(curve_offsets);
492 const float4x4 &object_to_world_mat =
object.object_to_world();
496 const OffsetIndices points_by_curve = curves.points_by_curve();
500 const int curve_index_offset) {
502 for (const int i : range) {
503 const int hair_i = indices_to_transfer[i];
504 const int curve_i = i + curve_index_offset;
505 const IndexRange points = points_by_curve[curve_i];
506 const Span<ParticleCacheKey> keys{hair_cache[hair_i], points.size()};
507 for (const int key_i : keys.index_range()) {
508 const float3 key_pos_wo = keys[key_i].co;
509 positions[points[key_i]] = math::transform_point(world_to_object_mat, key_pos_wo);
515 if (transfer_parents) {
516 copy_hair_to_curves(parents_cache, parents_to_transfer, 0);
518 copy_hair_to_curves(children_cache, children_to_transfer, parents_to_transfer.size());
520 curves.update_curve_types();
521 curves.tag_topology_changed();
534 if (psys_orig ==
nullptr) {
537 if (psys_orig ==
nullptr) {
550 psys_eval = psmd->
psys;
573 ot->
name =
"Convert Particle System to Curves";
574 ot->
idname =
"CURVES_OT_convert_from_particle_system";
575 ot->
description =
"Add a new curves object based on the current state of the particle system";
577 ot->
poll = convert_from_particle_system::curves_convert_from_particle_system_poll;
578 ot->
exec = convert_from_particle_system::curves_convert_from_particle_system_exec;
583namespace snap_curves_to_surface {
599 const Mesh &surface_mesh = *
static_cast<const Mesh *
>(surface_ob.
data);
600 const Span<float3> surface_positions = surface_mesh.vert_positions();
601 const Span<int> corner_verts = surface_mesh.corner_verts();
602 const Span<int3> surface_corner_tris = surface_mesh.corner_tris();
607 bke::AttrDomain::Corner);
610 const OffsetIndices points_by_curve = curves.points_by_curve();
616 switch (attach_mode) {
617 case AttachMode::Nearest: {
622 threading::parallel_for(curves.curves_range(), 256, [&](
const IndexRange curves_range) {
623 for (const int curve_i : curves_range) {
624 const IndexRange points = points_by_curve[curve_i];
625 const int first_point_i = points.first();
626 const float3 old_first_point_pos_cu = positions_cu[first_point_i];
627 const float3 old_first_point_pos_su = math::transform_point(transforms.curves_to_surface,
628 old_first_point_pos_cu);
630 BVHTreeNearest nearest;
632 nearest.dist_sq = FLT_MAX;
633 BLI_bvhtree_find_nearest(surface_bvh.tree,
634 old_first_point_pos_su,
636 surface_bvh.nearest_callback,
638 const int tri_index = nearest.index;
639 if (tri_index == -1) {
643 const float3 new_first_point_pos_su = nearest.co;
644 const float3 new_first_point_pos_cu = math::transform_point(transforms.surface_to_curves,
645 new_first_point_pos_su);
646 const float3 pos_diff_cu = new_first_point_pos_cu - old_first_point_pos_cu;
648 for (float3 &pos_cu : positions_cu.slice(points)) {
649 pos_cu += pos_diff_cu;
652 if (!surface_uv_map.is_empty()) {
653 const int3 &tri = surface_corner_tris[tri_index];
654 const float3 bary_coords = bke::mesh_surface_sample::compute_bary_coord_in_triangle(
655 surface_positions, corner_verts, tri, new_first_point_pos_su);
656 const float2 uv = bke::mesh_surface_sample::sample_corner_attribute_with_bary_coords(
657 bary_coords, tri, surface_uv_map);
658 surface_uv_coords[curve_i] = uv;
664 case AttachMode::Deform: {
666 *r_missing_uvs =
true;
670 ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_corner_tris};
672 threading::parallel_for(curves.curves_range(), 256, [&](
const IndexRange curves_range) {
673 for (const int curve_i : curves_range) {
674 const IndexRange points = points_by_curve[curve_i];
675 const int first_point_i = points.first();
676 const float3 old_first_point_pos_cu = positions_cu[first_point_i];
678 const float2 uv = surface_uv_coords[curve_i];
679 ReverseUVSampler::Result lookup_result = reverse_uv_sampler.sample(uv);
680 if (lookup_result.type != ReverseUVSampler::ResultType::Ok) {
681 *r_invalid_uvs = true;
685 const int3 &tri = surface_corner_tris[lookup_result.tri_index];
686 const float3 &bary_coords = lookup_result.bary_weights;
688 const float3 &p0_su = surface_positions[corner_verts[tri[0]]];
689 const float3 &p1_su = surface_positions[corner_verts[tri[1]]];
690 const float3 &p2_su = surface_positions[corner_verts[tri[2]]];
692 float3 new_first_point_pos_su;
693 interp_v3_v3v3v3(new_first_point_pos_su, p0_su, p1_su, p2_su, bary_coords);
694 const float3 new_first_point_pos_cu = math::transform_point(transforms.surface_to_curves,
695 new_first_point_pos_su);
697 const float3 pos_diff_cu = new_first_point_pos_cu - old_first_point_pos_cu;
698 for (float3 &pos_cu : positions_cu.slice(points)) {
699 pos_cu += pos_diff_cu;
707 curves.tag_positions_changed();
715 bool found_invalid_uvs =
false;
716 bool found_missing_uvs =
false;
722 Curves &curves_id = *
static_cast<Curves *
>(curves_ob->data);
723 if (curves_id.
surface ==
nullptr) {
730 *curves_ob, *curves_id.
surface, attach_mode, &found_invalid_uvs, &found_missing_uvs);
734 if (found_missing_uvs) {
737 "Curves do not have attachment information that can be used for deformation");
739 if (found_invalid_uvs) {
753 using namespace snap_curves_to_surface;
755 ot->
name =
"Snap Curves to Surface";
756 ot->
idname =
"CURVES_OT_snap_curves_to_surface";
757 ot->
description =
"Move curves so that the first point is exactly on the surface mesh";
760 ot->
exec = snap_curves_to_surface_exec;
765 {
int(AttachMode::Nearest),
769 "Find the closest point on the surface for the root point of every curve and move the root "
771 {
int(AttachMode::Deform),
775 "Re-attach curves to a deformed surface using the existing attachment information. This "
776 "only works when the topology of the surface mesh has not changed"},
777 {0,
nullptr, 0,
nullptr,
nullptr},
783 int(AttachMode::Nearest),
785 "How to find the point on the surface to attach to");
788namespace set_selection_domain {
799 curves_id->selection_domain = char(domain);
803 if (curves.points_num() == 0) {
812 std::string active_attribute;
816 active_attribute = layer->name;
819 if (
const GVArray src = *attributes.lookup(selection_name, domain)) {
820 const CPPType &type = src.type();
821 void *dst =
MEM_malloc_arrayN(attributes.domain_size(domain), type.size(), __func__);
822 src.materialize(dst);
824 attributes.remove(selection_name);
825 if (!attributes.add(selection_name,
827 bke::cpp_type_to_custom_data_type(type),
834 if (!active_attribute.empty()) {
855 ot->
name =
"Set Select Mode";
857 ot->
description =
"Change the mode used for selection masking in curves sculpt mode";
859 ot->
exec = set_selection_domain::curves_set_selection_domain_exec;
871 return std::any_of(curves_ids.
begin(), curves_ids.
end(), [](
const Curves *curves_id) {
872 return has_anything_selected(curves_id->geometry.wrap());
886 for (
Curves *curves_id : unique_curves) {
901 ot->
name =
"(De)select All";
902 ot->
idname =
"CURVES_OT_select_all";
920 for (
Curves *curves_id : unique_curves) {
923 const int domain_size = curves.attributes().domain_size(selection_domain);
927 curves, selection_domain,
seed, probability, memory)
933 if (!was_anything_selected) {
934 curves::fill_selection_true(selection.span);
937 curves::fill_selection_false(selection.span, inv_random_elements);
958 ot->
name =
"Select Random";
960 ot->
description =
"Randomizes existing selection or create new random selection";
963 ot->
poll = curves::editable_curves_poll;
974 "Source of randomness",
983 "Chance of every point or curve being included in the selection",
994 for (
Curves *curves_id : unique_curves) {
999 curves, amount_start, amount_end,
true, memory);
1004 if (!was_anything_selected) {
1008 if (selection.span.type().is<
bool>()) {
1009 index_mask::masked_fill(selection.span.typed<
bool>(),
false, inverted_end_points_mask);
1011 if (selection.span.type().is<
float>()) {
1012 index_mask::masked_fill(selection.span.typed<
float>(), 0.0f, inverted_end_points_mask);
1039 ot->
name =
"Select Ends";
1055 "Number of points to select from the front",
1064 "Number of points to select from the back",
1072 for (
Curves *curves_id : unique_curves) {
1086 ot->
name =
"Select Linked";
1088 ot->
description =
"Select all points in curves with any point selection";
1099 for (
Curves *curves_id : unique_curves) {
1113 ot->
name =
"Select More";
1126 for (
Curves *curves_id : unique_curves) {
1140 ot->
name =
"Select Less";
1150namespace surface_set {
1155 if (
object ==
nullptr) {
1158 if (object->type !=
OB_MESH) {
1171 Mesh &new_surface_mesh = *
static_cast<Mesh *
>(new_surface_ob.
data);
1179 Object &curves_ob = *selected_ob;
1183 if (new_uv_map_name !=
nullptr) {
1189 snap_curves_to_surface::snap_curves_to_surface_exec_object(
1192 snap_curves_to_surface::AttachMode::Nearest,
1199 curves_id.
surface = &new_surface_ob;
1200 object::parent_set(op->
reports,
1229 ot->
name =
"Set Curves Surface Object";
1232 "Use the active object as surface for selected curves objects and set it as the parent";
1234 ot->
exec = surface_set::surface_set_exec;
1235 ot->
poll = surface_set::surface_set_poll;
1240namespace curves_delete {
1261 ot->
description =
"Remove selected control points or curves";
1263 ot->
exec = curves_delete::delete_exec;
1269namespace curves_duplicate {
1277 case bke::AttrDomain::Point:
1280 case bke::AttrDomain::Curve:
1301 ot->
exec = curves_duplicate::delete_exec;
1307namespace clear_tilt {
1315 if (selection.is_empty()) {
1319 if (selection.size() == curves.points_num()) {
1320 curves.attributes_for_write().remove(
"tilt");
1323 index_mask::masked_fill(curves.tilt_for_write(), 0.0f, selection);
1326 curves.tag_normals_changed();
1339 ot->
description =
"Clear the tilt of selected control points";
1341 ot->
exec = clear_tilt::exec;
1347namespace cyclic_toggle {
1355 if (selection.is_empty()) {
1362 "cyclic", bke::AttrDomain::Curve);
1363 selection.foreach_index(
GrainSize(4096),
1364 [&](
const int i) { cyclic.span[i] = !cyclic.span[i]; });
1367 if (!cyclic.span.as_span().contains(
true)) {
1368 attributes.remove(
"cyclic");
1371 curves.calculate_bezier_auto_handles();
1383 ot->
name =
"Toggle Cyclic";
1387 ot->
exec = cyclic_toggle::exec;
1393namespace curve_type_set {
1404 if (selection.is_empty()) {
1409 options.convert_bezier_handles_to_poly_points = use_handles;
1410 options.convert_bezier_handles_to_catmull_rom_points = use_handles;
1411 options.keep_bezier_shape_as_nurbs = use_handles;
1412 options.keep_catmull_rom_shape_as_nurbs = use_handles;
1414 curves = geometry::convert_curves(curves, selection, dst_type, {},
options);
1426 ot->
name =
"Set Curve Type";
1430 ot->
exec = curve_type_set::exec;
1442 "Take handle information into account in the conversion");
1445namespace switch_direction {
1453 if (selection.is_empty()) {
1457 curves.reverse_curves(selection);
1469 ot->
name =
"Switch Direction";
1471 ot->
description =
"Reverse the direction of the selected curves";
1473 ot->
exec = switch_direction::exec;
1479namespace subdivide {
1495 points_selection.
to_bools(points_selection_span);
1497 Array<int> segment_cuts(points_num, number_cuts);
1499 const OffsetIndices points_by_curve = curves.points_by_curve();
1501 for (const int curve_i : range) {
1502 const IndexRange points = points_by_curve[curve_i];
1503 if (points.size() <= 1) {
1506 for (const int point_i : points.drop_back(1)) {
1507 if (!points_selection_span[point_i] || !points_selection_span[point_i + 1]) {
1508 segment_cuts[point_i] = 0;
1512 if (!points_selection_span[points.last()] || !points_selection_span[points.first()]) {
1513 segment_cuts[points.last()] = 0;
1518 curves = geometry::subdivide_curves(
1535 ot->
exec = subdivide::exec;
1541 prop =
RNA_def_int(
ot->
srna,
"number_cuts", 1, 1, 1000,
"Number of Cuts",
"", 1, 10);
1552 const int new_points_num = new_curves.
points_num();
1553 const int new_curves_num = new_curves.
curves_num();
1557 &curves_id, bke::GeometryOwnershipType::ReadOnly);
1559 bke::curves_new_nomain(std::move(new_curves)));
1565 object::add_generic_get_opts(C, &op,
'Z', location, rotation, scale,
nullptr,
nullptr,
nullptr);
1568 geometry::transform_geometry(new_geometry, transform);
1570 bke::GeometrySet joined_geometry = geometry::join_geometries({old_geometry, new_geometry}, {});
1573 dst_curves = std::move(joined_curves_id->geometry.wrap());
1577 const int new_element_num = selection_domain == bke::AttrDomain::Point ? new_points_num :
1588namespace add_circle {
1599 curves.cyclic_for_write().
fill(
true);
1602 curves.resolution_for_write().fill(12);
1605 positions[0] =
float3(-radius, 0, 0);
1606 positions[1] =
float3(0, radius, 0);
1607 positions[2] =
float3(radius, 0, 0);
1608 positions[3] =
float3(0, -radius, 0);
1611 curves.handle_positions_left_for_write();
1612 curves.handle_positions_right_for_write();
1614 curves.calculate_bezier_auto_handles();
1622 Curves *active_curves_id =
static_cast<Curves *
>(
object->data);
1640 ot->
exec = add_circle::exec;
1645 object::add_unit_props_radius(
ot);
1646 object::add_generic_props(
ot,
true);
1649namespace add_bezier {
1662 curves.resolution_for_write().fill(12);
1668 left_handles[0] =
float3(-1.5f, -0.5, 0) * radius;
1669 positions[0] =
float3(-1.0f, 0, 0) * radius;
1670 right_handles[0] =
float3(-0.5f, 0.5f, 0) * radius;
1672 left_handles[1] =
float3(0, 0, 0) * radius;
1673 positions[1] =
float3(1.0f, 0, 0) * radius;
1674 right_handles[1] =
float3(2.0f, 0, 0) * radius;
1682 Curves *active_curves_id =
static_cast<Curves *
>(
object->data);
1700 ot->
exec = add_bezier::exec;
1705 object::add_unit_props_radius(
ot);
1706 object::add_generic_props(
ot,
true);
1709namespace set_handle_type {
1720 ".selection", bke::AttrDomain::Point,
true);
1721 const VArraySpan<bool> selection_left = *attributes.lookup_or_default<
bool>(
1722 ".selection_handle_left", bke::AttrDomain::Point,
true);
1723 const VArraySpan<bool> selection_right = *attributes.lookup_or_default<
bool>(
1724 ".selection_handle_right", bke::AttrDomain::Point,
true);
1729 threading::parallel_for(curves.points_range(), 4096, [&](
const IndexRange range) {
1730 for (const int point_i : range) {
1731 if (selection_left[point_i] || selection[point_i]) {
1732 handle_types_left[point_i] = int8_t(dst_handle_type);
1734 if (selection_right[point_i] || selection[point_i]) {
1735 handle_types_right[point_i] = int8_t(dst_handle_type);
1740 curves.calculate_bezier_auto_handles();
1741 curves.tag_topology_changed();
1753 ot->
name =
"Set Handle Type";
1758 ot->
exec = set_handle_type::exec;
1803 "Make copies of selected elements and move them",
1812 "Extrude Curve and Move",
1813 "Extrude curve and move result",
void BKE_attributes_active_set(AttributeOwner &owner, const char *name)
struct CustomDataLayer * BKE_attributes_active_get(AttributeOwner &owner)
void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
BVHTree * BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data, const Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
@ BVHTREE_FROM_CORNER_TRIS
#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)
A KD-tree for nearest neighbor search.
#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])
#define BLI_SCOPED_DEFER(function_to_defer)
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)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ 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)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
static unsigned long seed
static AttributeOwner from_id(ID *id)
constexpr void fill(const T &value) 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
void tag_topology_changed()
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 int select_linked_exec(bContext *C, wmOperator *)
static int delete_exec(bContext *C, wmOperator *op)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
static int select_all_exec(bContext *C, wmOperator *op)
static CurvesGeometry generate_bezier_primitive(const float radius)
static CurvesGeometry generate_circle_primitive(const float radius)
static int 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 curves_convert_to_particle_system_exec(bContext *C, wmOperator *op)
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 void try_convert_single_object(Object &curves_ob, Main &bmain, Scene &scene, bool *r_could_not_convert_some_curves)
static int curves_set_selection_domain_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 int snap_curves_to_surface_exec(bContext *C, wmOperator *op)
static int 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 int select_ends_exec(bContext *C, wmOperator *op)
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)
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_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 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_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)
IndexMask random_mask(const bke::CurvesGeometry &curves, const IndexMask &mask, const bke::AttrDomain selection_domain, const uint32_t random_seed, const float probability, IndexMaskMemory &memory)
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 int select_random_exec(bContext *C, wmOperator *op)
static int select_more_exec(bContext *C, wmOperator *)
static int select_less_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)
BVHTree_NearestPointCallback nearest_callback
struct ParticleSystem * psys
struct ParticleCacheKey ** childcache
struct ParticleCacheKey ** pathcache
const c_style_mat & ptr() const
Curves * get_curves_for_write()
bool(* poll)(struct bContext *)
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* exec)(bContext *C, wmOperator *op) 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)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)