diff options
Diffstat (limited to 'source/blender')
67 files changed, 30 insertions, 12214 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 904f06f2734..3e964b038c4 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1363,37 +1363,13 @@ struct TexResult; * \{ */ #define GEO_NODE_TRIANGULATE 1000 -#define GEO_NODE_LEGACY_EDGE_SPLIT 1001 #define GEO_NODE_TRANSFORM 1002 #define GEO_NODE_MESH_BOOLEAN 1003 -#define GEO_NODE_LEGACY_POINT_DISTRIBUTE 1004 -#define GEO_NODE_LEGACY_POINT_INSTANCE 1005 -#define GEO_NODE_LEGACY_SUBDIVISION_SURFACE 1006 #define GEO_NODE_OBJECT_INFO 1007 -#define GEO_NODE_LEGACY_ATTRIBUTE_RANDOMIZE 1008 -#define GEO_NODE_LEGACY_ATTRIBUTE_MATH 1009 #define GEO_NODE_JOIN_GEOMETRY 1010 -#define GEO_NODE_LEGACY_ATTRIBUTE_FILL 1011 -#define GEO_NODE_LEGACY_ATTRIBUTE_MIX 1012 -#define GEO_NODE_LEGACY_ATTRIBUTE_COLOR_RAMP 1013 -#define GEO_NODE_LEGACY_POINT_SEPARATE 1014 -#define GEO_NODE_LEGACY_ATTRIBUTE_COMPARE 1015 -#define GEO_NODE_LEGACY_POINT_ROTATE 1016 -#define GEO_NODE_LEGACY_ATTRIBUTE_VECTOR_MATH 1017 -#define GEO_NODE_LEGACY_ALIGN_ROTATION_TO_VECTOR 1018 -#define GEO_NODE_LEGACY_POINT_TRANSLATE 1019 -#define GEO_NODE_LEGACY_POINT_SCALE 1020 -#define GEO_NODE_LEGACY_ATTRIBUTE_SAMPLE_TEXTURE 1021 -#define GEO_NODE_LEGACY_POINTS_TO_VOLUME 1022 #define GEO_NODE_COLLECTION_INFO 1023 #define GEO_NODE_IS_VIEWPORT 1024 -#define GEO_NODE_LEGACY_ATTRIBUTE_PROXIMITY 1025 -#define GEO_NODE_LEGACY_VOLUME_TO_MESH 1026 -#define GEO_NODE_LEGACY_ATTRIBUTE_COMBINE_XYZ 1027 -#define GEO_NODE_LEGACY_ATTRIBUTE_SEPARATE_XYZ 1028 #define GEO_NODE_SUBDIVIDE_MESH 1029 -#define GEO_NODE_LEGACY_ATTRIBUTE_REMOVE 1030 -#define GEO_NODE_LEGACY_ATTRIBUTE_CONVERT 1031 #define GEO_NODE_MESH_PRIMITIVE_CUBE 1032 #define GEO_NODE_MESH_PRIMITIVE_CIRCLE 1033 #define GEO_NODE_MESH_PRIMITIVE_UV_SPHERE 1034 @@ -1402,28 +1378,15 @@ struct TexResult; #define GEO_NODE_MESH_PRIMITIVE_CONE 1037 #define GEO_NODE_MESH_PRIMITIVE_LINE 1038 #define GEO_NODE_MESH_PRIMITIVE_GRID 1039 -#define GEO_NODE_LEGACY_ATTRIBUTE_MAP_RANGE 1040 -#define GEO_NODE_LEGACY_ATTRIBUTE_CLAMP 1041 #define GEO_NODE_BOUNDING_BOX 1042 #define GEO_NODE_SWITCH 1043 -#define GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER 1044 #define GEO_NODE_CURVE_TO_MESH 1045 -#define GEO_NODE_LEGACY_ATTRIBUTE_CURVE_MAP 1046 #define GEO_NODE_RESAMPLE_CURVE 1047 -#define GEO_NODE_LEGACY_ATTRIBUTE_VECTOR_ROTATE 1048 -#define GEO_NODE_LEGACY_MATERIAL_ASSIGN 1049 #define GEO_NODE_INPUT_MATERIAL 1050 #define GEO_NODE_REPLACE_MATERIAL 1051 -#define GEO_NODE_LEGACY_MESH_TO_CURVE 1052 -#define GEO_NODE_LEGACY_DELETE_GEOMETRY 1053 #define GEO_NODE_CURVE_LENGTH 1054 -#define GEO_NODE_LEGACY_SELECT_BY_MATERIAL 1055 #define GEO_NODE_CONVEX_HULL 1056 -#define GEO_NODE_LEGACY_CURVE_TO_POINTS 1057 -#define GEO_NODE_LEGACY_CURVE_REVERSE 1058 #define GEO_NODE_SEPARATE_COMPONENTS 1059 -#define GEO_NODE_LEGACY_CURVE_SUBDIVIDE 1060 -#define GEO_NODE_LEGACY_RAYCAST 1061 #define GEO_NODE_CURVE_PRIMITIVE_STAR 1062 #define GEO_NODE_CURVE_PRIMITIVE_SPIRAL 1063 #define GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER 1064 @@ -1431,12 +1394,8 @@ struct TexResult; #define GEO_NODE_CURVE_PRIMITIVE_CIRCLE 1066 #define GEO_NODE_VIEWER 1067 #define GEO_NODE_CURVE_PRIMITIVE_LINE 1068 -#define GEO_NODE_LEGACY_CURVE_ENDPOINTS 1069 #define GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL 1070 #define GEO_NODE_TRIM_CURVE 1071 -#define GEO_NODE_LEGACY_CURVE_SET_HANDLES 1072 -#define GEO_NODE_LEGACY_CURVE_SPLINE_TYPE 1073 -#define GEO_NODE_LEGACY_CURVE_SELECT_HANDLES 1074 #define GEO_NODE_FILL_CURVE 1075 #define GEO_NODE_INPUT_POSITION 1076 #define GEO_NODE_SET_POSITION 1077 diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 9a573919165..83eb831b177 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -532,13 +532,6 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB, SH_NODE_CURVE_FLOAT)) { BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage); } - else if ((ntree->type == NTREE_GEOMETRY) && - (node->type == GEO_NODE_LEGACY_ATTRIBUTE_CURVE_MAP)) { - BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage); - NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)node->storage; - BKE_curvemapping_blend_write(writer, (const CurveMapping *)data->curve_vec); - BKE_curvemapping_blend_write(writer, (const CurveMapping *)data->curve_rgb); - } else if (ntree->type == NTREE_SHADER && (node->type == SH_NODE_SCRIPT)) { NodeShaderScript *nss = (NodeShaderScript *)node->storage; if (nss->bytecode) { @@ -715,18 +708,6 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) BKE_curvemapping_blend_read(reader, (CurveMapping *)node->storage); break; } - case GEO_NODE_LEGACY_ATTRIBUTE_CURVE_MAP: { - NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)node->storage; - BLO_read_data_address(reader, &data->curve_vec); - if (data->curve_vec) { - BKE_curvemapping_blend_read(reader, data->curve_vec); - } - BLO_read_data_address(reader, &data->curve_rgb); - if (data->curve_rgb) { - BKE_curvemapping_blend_read(reader, data->curve_rgb); - } - break; - } case SH_NODE_SCRIPT: { NodeShaderScript *nss = (NodeShaderScript *)node->storage; BLO_read_data_address(reader, &nss->bytecode); @@ -3616,15 +3597,13 @@ void nodeSetActive(bNodeTree *ntree, bNode *node) LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) { tnode->flag &= ~NODE_ACTIVE; - if ((node->typeinfo->nclass == NODE_CLASS_TEXTURE) || - (node->typeinfo->type == GEO_NODE_LEGACY_ATTRIBUTE_SAMPLE_TEXTURE)) { + if ((node->typeinfo->nclass == NODE_CLASS_TEXTURE)) { tnode->flag &= ~NODE_ACTIVE_TEXTURE; } } node->flag |= NODE_ACTIVE; - if ((node->typeinfo->nclass == NODE_CLASS_TEXTURE) || - (node->typeinfo->type == GEO_NODE_LEGACY_ATTRIBUTE_SAMPLE_TEXTURE)) { + if ((node->typeinfo->nclass == NODE_CLASS_TEXTURE)) { node->flag |= NODE_ACTIVE_TEXTURE; } } @@ -4692,45 +4671,10 @@ static void registerGeometryNodes() { register_node_type_geo_group(); - register_node_type_geo_legacy_attribute_proximity(); - register_node_type_geo_legacy_attribute_randomize(); - register_node_type_geo_legacy_attribute_remove(); - register_node_type_geo_legacy_attribute_transfer(); - register_node_type_geo_legacy_curve_endpoints(); - register_node_type_geo_legacy_curve_reverse(); - register_node_type_geo_legacy_curve_set_handles(); - register_node_type_geo_legacy_curve_spline_type(); - register_node_type_geo_legacy_curve_subdivide(); - register_node_type_geo_legacy_curve_to_points(); - register_node_type_geo_legacy_delete_geometry(); - register_node_type_geo_legacy_edge_split(); - register_node_type_geo_legacy_material_assign(); - register_node_type_geo_legacy_mesh_to_curve(); - register_node_type_geo_legacy_points_to_volume(); - register_node_type_geo_legacy_raycast(); - register_node_type_geo_legacy_select_by_handle_type(); - register_node_type_geo_legacy_select_by_material(); - register_node_type_geo_legacy_subdivision_surface(); - register_node_type_geo_legacy_volume_to_mesh(); - register_node_type_geo_accumulate_field(); - register_node_type_geo_align_rotation_to_vector(); register_node_type_geo_attribute_capture(); - register_node_type_geo_attribute_clamp(); - register_node_type_geo_attribute_color_ramp(); - register_node_type_geo_attribute_combine_xyz(); - register_node_type_geo_attribute_compare(); - register_node_type_geo_attribute_convert(); - register_node_type_geo_attribute_curve_map(); register_node_type_geo_attribute_domain_size(); - register_node_type_geo_attribute_fill(); - register_node_type_geo_attribute_map_range(); - register_node_type_geo_attribute_math(); - register_node_type_geo_attribute_mix(); - register_node_type_geo_attribute_separate_xyz(); register_node_type_geo_attribute_statistic(); - register_node_type_geo_attribute_vector_math(); - register_node_type_geo_attribute_vector_rotate(); register_node_type_geo_boolean(); register_node_type_geo_bounding_box(); register_node_type_geo_collection_info(); @@ -4811,12 +4755,6 @@ static void registerGeometryNodes() register_node_type_geo_mesh_to_curve(); register_node_type_geo_mesh_to_points(); register_node_type_geo_object_info(); - register_node_type_geo_point_distribute(); - register_node_type_geo_point_instance(); - register_node_type_geo_point_rotate(); - register_node_type_geo_point_scale(); - register_node_type_geo_point_separate(); - register_node_type_geo_point_translate(); register_node_type_geo_points_to_vertices(); register_node_type_geo_points_to_volume(); register_node_type_geo_proximity(); @@ -4824,7 +4762,6 @@ static void registerGeometryNodes() register_node_type_geo_realize_instances(); register_node_type_geo_remove_attribute(); register_node_type_geo_rotate_instances(); - register_node_type_geo_sample_texture(); register_node_type_geo_scale_elements(); register_node_type_geo_scale_instances(); register_node_type_geo_separate_components(); @@ -4855,8 +4792,6 @@ static void registerGeometryNodes() static void registerFunctionNodes() { - register_node_type_fn_legacy_random_float(); - register_node_type_fn_align_euler_to_vector(); register_node_type_fn_boolean_math(); register_node_type_fn_compare(); diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 3ae26dea767..079d69be4d9 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1510,27 +1510,6 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } if (!MAIN_VERSION_ATLEAST(bmain, 292, 9)) { - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type == NTREE_GEOMETRY) { - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->type == GEO_NODE_LEGACY_ATTRIBUTE_MATH && node->storage == NULL) { - const int old_use_attibute_a = (1 << 0); - const int old_use_attibute_b = (1 << 1); - NodeAttributeMath *data = MEM_callocN(sizeof(NodeAttributeMath), "NodeAttributeMath"); - data->operation = NODE_MATH_ADD; - data->input_type_a = (node->custom2 & old_use_attibute_a) ? - GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE : - GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - data->input_type_b = (node->custom2 & old_use_attibute_b) ? - GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE : - GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - node->storage = data; - } - } - } - } - FOREACH_NODETREE_END; - /* Default properties editors to auto outliner sync. */ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { @@ -1668,39 +1647,6 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - if (!MAIN_VERSION_ATLEAST(bmain, 293, 3)) { - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type != NTREE_GEOMETRY) { - continue; - } - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->type == GEO_NODE_LEGACY_POINT_INSTANCE && node->storage == NULL) { - NodeGeometryPointInstance *data = (NodeGeometryPointInstance *)MEM_callocN( - sizeof(NodeGeometryPointInstance), __func__); - data->instance_type = node->custom1; - data->flag = (node->custom2 ? 0 : GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION); - node->storage = data; - } - } - } - FOREACH_NODETREE_END; - } - - if (!MAIN_VERSION_ATLEAST(bmain, 293, 4)) { - /* Add support for all operations to the "Attribute Math" node. */ - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type == NTREE_GEOMETRY) { - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->type == GEO_NODE_LEGACY_ATTRIBUTE_MATH) { - NodeAttributeMath *data = (NodeAttributeMath *)node->storage; - data->input_type_c = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - } - } - } - } - FOREACH_NODETREE_END; - } - if (!MAIN_VERSION_ATLEAST(bmain, 293, 5)) { /* Change Nishita sky model Altitude unit. */ FOREACH_NODETREE_BEGIN (bmain, ntree, id) { @@ -1744,24 +1690,6 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) FOREACH_NODETREE_END; } - if (!MAIN_VERSION_ATLEAST(bmain, 293, 8)) { - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type != NTREE_GEOMETRY) { - continue; - } - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->type == GEO_NODE_LEGACY_ATTRIBUTE_RANDOMIZE && node->storage == NULL) { - NodeAttributeRandomize *data = (NodeAttributeRandomize *)MEM_callocN( - sizeof(NodeAttributeRandomize), __func__); - data->data_type = node->custom1; - data->operation = GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE; - node->storage = data; - } - } - } - FOREACH_NODETREE_END; - } - if (!MAIN_VERSION_ATLEAST(bmain, 293, 9)) { if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "bokeh_overblur")) { LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { @@ -1784,23 +1712,9 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type == NTREE_GEOMETRY) { - version_node_socket_name(ntree, GEO_NODE_LEGACY_ATTRIBUTE_PROXIMITY, "Result", "Distance"); - } - } - FOREACH_NODETREE_END; } if (!MAIN_VERSION_ATLEAST(bmain, 293, 10)) { - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type == NTREE_GEOMETRY) { - version_node_socket_name( - ntree, GEO_NODE_LEGACY_ATTRIBUTE_PROXIMITY, "Location", "Position"); - } - } - FOREACH_NODETREE_END; - LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { /* Fix old scene with too many samples that were not being used. * Now they are properly used and might produce a huge slowdown. @@ -1886,16 +1800,6 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) light->volume_fac = 1.0f; } } - - LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { - if (ntree->type == NTREE_GEOMETRY) { - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->type == GEO_NODE_LEGACY_ATTRIBUTE_FILL) { - node->custom2 = ATTR_DOMAIN_AUTO; - } - } - } - } } if (!MAIN_VERSION_ATLEAST(bmain, 293, 15)) { @@ -1940,13 +1844,6 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } if (!MAIN_VERSION_ATLEAST(bmain, 293, 18)) { - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type == NTREE_GEOMETRY) { - version_node_socket_name(ntree, GEO_NODE_LEGACY_VOLUME_TO_MESH, "Grid", "Density"); - } - } - FOREACH_NODETREE_END; - if (!DNA_struct_elem_find(fd->filesdna, "bArmature", "float", "axes_position")) { /* Convert the axes draw position to its old default (tip of bone). */ LISTBASE_FOREACH (struct bArmature *, arm, &bmain->armatures) { diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index eead735b305..5b1964aa35c 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -527,7 +527,6 @@ static void version_geometry_nodes_add_realize_instance_nodes(bNodeTree *ntree) GEO_NODE_TRIM_CURVE, GEO_NODE_REPLACE_MATERIAL, GEO_NODE_SUBDIVIDE_MESH, - GEO_NODE_LEGACY_ATTRIBUTE_REMOVE, GEO_NODE_TRIANGULATE)) { bNodeSocket *geometry_socket = node->inputs.first; add_realize_instances_before_socket(ntree, node, geometry_socket); @@ -600,30 +599,6 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports)) } if (!MAIN_VERSION_ATLEAST(bmain, 300, 3)) { - /* Use new texture socket in Attribute Sample Texture node. */ - LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { - if (ntree->type != NTREE_GEOMETRY) { - continue; - } - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->type != GEO_NODE_LEGACY_ATTRIBUTE_SAMPLE_TEXTURE) { - continue; - } - if (node->id == NULL) { - continue; - } - LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { - if (socket->type == SOCK_TEXTURE) { - bNodeSocketValueTexture *socket_value = (bNodeSocketValueTexture *) - socket->default_value; - socket_value->value = (Tex *)node->id; - break; - } - } - node->id = NULL; - } - } - sort_linked_ids(bmain); assert_sorted_ids(bmain); } @@ -951,141 +926,6 @@ static bNodeSocket *do_version_replace_float_size_with_vector(bNodeTree *ntree, return new_socket; } -static bool geometry_node_is_293_legacy(const short node_type) -{ - switch (node_type) { - /* Not legacy: No attribute inputs or outputs. */ - case GEO_NODE_TRIANGULATE: - case GEO_NODE_TRANSFORM: - case GEO_NODE_MESH_BOOLEAN: - case GEO_NODE_IS_VIEWPORT: - case GEO_NODE_SUBDIVIDE_MESH: - case GEO_NODE_MESH_PRIMITIVE_CUBE: - case GEO_NODE_MESH_PRIMITIVE_CIRCLE: - case GEO_NODE_MESH_PRIMITIVE_UV_SPHERE: - case GEO_NODE_MESH_PRIMITIVE_CYLINDER: - case GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE: - case GEO_NODE_MESH_PRIMITIVE_CONE: - case GEO_NODE_MESH_PRIMITIVE_LINE: - case GEO_NODE_MESH_PRIMITIVE_GRID: - case GEO_NODE_BOUNDING_BOX: - case GEO_NODE_RESAMPLE_CURVE: - case GEO_NODE_INPUT_MATERIAL: - case GEO_NODE_REPLACE_MATERIAL: - case GEO_NODE_CURVE_LENGTH: - case GEO_NODE_CONVEX_HULL: - case GEO_NODE_SEPARATE_COMPONENTS: - case GEO_NODE_CURVE_PRIMITIVE_STAR: - case GEO_NODE_CURVE_PRIMITIVE_SPIRAL: - case GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER: - case GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT: - case GEO_NODE_CURVE_PRIMITIVE_CIRCLE: - case GEO_NODE_VIEWER: - case GEO_NODE_CURVE_PRIMITIVE_LINE: - case GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL: - case GEO_NODE_FILL_CURVE: - case GEO_NODE_TRIM_CURVE: - case GEO_NODE_CURVE_TO_MESH: - return false; - - /* Not legacy: Newly added with fields patch. */ - case GEO_NODE_INPUT_POSITION: - case GEO_NODE_SET_POSITION: - case GEO_NODE_INPUT_INDEX: - case GEO_NODE_INPUT_NORMAL: - case GEO_NODE_CAPTURE_ATTRIBUTE: - return false; - - /* Maybe legacy: Might need special attribute handling, depending on design. */ - case GEO_NODE_SWITCH: - case GEO_NODE_JOIN_GEOMETRY: - case GEO_NODE_LEGACY_ATTRIBUTE_REMOVE: - case GEO_NODE_OBJECT_INFO: - case GEO_NODE_COLLECTION_INFO: - return false; - - /* Maybe legacy: Special case for grid names? Or finish patch from level set branch to - * generate a mesh for all grids in the volume. */ - case GEO_NODE_LEGACY_VOLUME_TO_MESH: - return false; - - /* Legacy: Transferred *all* attributes before, will not transfer all built-ins now. */ - case GEO_NODE_LEGACY_CURVE_ENDPOINTS: - case GEO_NODE_LEGACY_CURVE_TO_POINTS: - return true; - - /* Legacy: Attribute operation completely replaced by field nodes. */ - case GEO_NODE_LEGACY_ATTRIBUTE_RANDOMIZE: - case GEO_NODE_LEGACY_ATTRIBUTE_MATH: - case GEO_NODE_LEGACY_ATTRIBUTE_FILL: - case GEO_NODE_LEGACY_ATTRIBUTE_MIX: - case GEO_NODE_LEGACY_ATTRIBUTE_COLOR_RAMP: - case GEO_NODE_LEGACY_ATTRIBUTE_COMPARE: - case GEO_NODE_LEGACY_POINT_ROTATE: - case GEO_NODE_LEGACY_ALIGN_ROTATION_TO_VECTOR: - case GEO_NODE_LEGACY_POINT_SCALE: - case GEO_NODE_LEGACY_ATTRIBUTE_SAMPLE_TEXTURE: - case GEO_NODE_LEGACY_ATTRIBUTE_VECTOR_ROTATE: - case GEO_NODE_LEGACY_ATTRIBUTE_CURVE_MAP: - case GEO_NODE_LEGACY_ATTRIBUTE_MAP_RANGE: - case GEO_NODE_LEGACY_ATTRIBUTE_CLAMP: - case GEO_NODE_LEGACY_ATTRIBUTE_VECTOR_MATH: - case GEO_NODE_LEGACY_ATTRIBUTE_COMBINE_XYZ: - case GEO_NODE_LEGACY_ATTRIBUTE_SEPARATE_XYZ: - return true; - - /* Legacy: Replaced by field node depending on another geometry. */ - case GEO_NODE_LEGACY_RAYCAST: - case GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER: - case GEO_NODE_LEGACY_ATTRIBUTE_PROXIMITY: - return true; - - /* Legacy: Simple selection attribute input. */ - case GEO_NODE_LEGACY_MESH_TO_CURVE: - case GEO_NODE_LEGACY_POINT_SEPARATE: - case GEO_NODE_LEGACY_CURVE_SELECT_HANDLES: - case GEO_NODE_LEGACY_CURVE_SPLINE_TYPE: - case GEO_NODE_LEGACY_CURVE_REVERSE: - case GEO_NODE_LEGACY_MATERIAL_ASSIGN: - case GEO_NODE_LEGACY_CURVE_SET_HANDLES: - return true; - - /* Legacy: More complex attribute inputs or outputs. */ - case GEO_NODE_LEGACY_SUBDIVISION_SURFACE: /* Used "crease" attribute. */ - case GEO_NODE_LEGACY_EDGE_SPLIT: /* Needs selection input version. */ - case GEO_NODE_LEGACY_DELETE_GEOMETRY: /* Needs field input, domain drop-down. */ - case GEO_NODE_LEGACY_CURVE_SUBDIVIDE: /* Needs field count input. */ - case GEO_NODE_LEGACY_POINTS_TO_VOLUME: /* Needs field radius input. */ - case GEO_NODE_LEGACY_SELECT_BY_MATERIAL: /* Output anonymous attribute. */ - case GEO_NODE_LEGACY_POINT_TRANSLATE: /* Needs field inputs. */ - case GEO_NODE_LEGACY_POINT_INSTANCE: /* Needs field inputs. */ - case GEO_NODE_LEGACY_POINT_DISTRIBUTE: /* Needs field input, remove max for random mode. */ - case GEO_NODE_LEGACY_ATTRIBUTE_CONVERT: /* Attribute Capture, Store Attribute. */ - return true; - } - return false; -} - -static void version_geometry_nodes_change_legacy_names(bNodeTree *ntree) -{ - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (geometry_node_is_293_legacy(node->type)) { - if (strstr(node->idname, "Legacy")) { - /* Make sure we haven't changed this idname already, better safe than sorry. */ - continue; - } - - char temp_idname[sizeof(node->idname)]; - BLI_strncpy(temp_idname, node->idname, sizeof(node->idname)); - - BLI_snprintf(node->idname, - sizeof(node->idname), - "GeometryNodeLegacy%s", - temp_idname + strlen("GeometryNode")); - } - } -} - static bool seq_transform_origin_set(Sequence *seq, void *UNUSED(user_data)) { StripTransform *transform = seq->strip->transform; @@ -1873,24 +1713,6 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } if (!MAIN_VERSION_ATLEAST(bmain, 300, 19)) { - /* Add node storage for subdivision surface node. */ - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type == NTREE_GEOMETRY) { - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->type == GEO_NODE_LEGACY_SUBDIVISION_SURFACE) { - if (node->storage == NULL) { - NodeGeometrySubdivisionSurface *data = MEM_callocN( - sizeof(NodeGeometrySubdivisionSurface), __func__); - data->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES; - data->boundary_smooth = SUBSURF_BOUNDARY_SMOOTH_ALL; - node->storage = data; - } - } - } - } - } - FOREACH_NODETREE_END; - /* Disable Fade Inactive Overlay by default as it is redundant after introducing flash on * mode transfer. */ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { @@ -2091,30 +1913,6 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } - - /* Deprecate the random float node in favor of the random value node. */ - LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { - if (ntree->type != NTREE_GEOMETRY) { - continue; - } - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->type != FN_NODE_LEGACY_RANDOM_FLOAT) { - continue; - } - if (strstr(node->idname, "Legacy")) { - /* Make sure we haven't changed this idname already. */ - continue; - } - - char temp_idname[sizeof(node->idname)]; - BLI_strncpy(temp_idname, node->idname, sizeof(node->idname)); - - BLI_snprintf(node->idname, - sizeof(node->idname), - "FunctionNodeLegacy%s", - temp_idname + strlen("FunctionNode")); - } - } } if (!MAIN_VERSION_ATLEAST(bmain, 300, 29)) { @@ -2141,12 +1939,6 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } - - LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { - if (ntree->type == NTREE_GEOMETRY) { - version_geometry_nodes_change_legacy_names(ntree); - } - } } if (!MAIN_VERSION_ATLEAST(bmain, 300, 31)) { @@ -2304,7 +2096,6 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } version_node_id(ntree, FN_NODE_SLICE_STRING, "FunctionNodeSliceString"); version_geometry_nodes_set_position_node_offset(ntree); - version_node_id(ntree, GEO_NODE_LEGACY_VOLUME_TO_MESH, "GeometryNodeLegacyVolumeToMesh"); } /* Add storage to viewer node. */ @@ -2637,14 +2428,5 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ - - /* Deprecate the attribute remove node. It was hidden and is replaced by a version without a - * multi-input socket. */ - LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { - if (ntree->type == NTREE_GEOMETRY) { - version_node_id( - ntree, GEO_NODE_LEGACY_ATTRIBUTE_REMOVE, "GeometryNodeLegacyAttributeRemove"); - } - } } } diff --git a/source/blender/editors/space_node/link_drag_search.cc b/source/blender/editors/space_node/link_drag_search.cc index ccd3333fcc5..c524de2c55d 100644 --- a/source/blender/editors/space_node/link_drag_search.cc +++ b/source/blender/editors/space_node/link_drag_search.cc @@ -121,9 +121,6 @@ static void gather_socket_link_operations(bNodeTree &node_tree, Vector<SocketLinkOperation> &search_link_ops) { NODE_TYPES_BEGIN (node_type) { - if (StringRef(node_type->idname).find("Legacy") != StringRef::not_found) { - continue; - } const char *disabled_hint; if (!(node_type->poll && node_type->poll(node_type, &node_tree, &disabled_hint))) { continue; diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc index 30bd0fb528b..7fb15d69ab5 100644 --- a/source/blender/editors/space_node/node_add.cc +++ b/source/blender/editors/space_node/node_add.cc @@ -517,113 +517,6 @@ void NODE_OT_add_object(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Add Node Texture Operator - * \{ */ - -static Tex *node_add_texture_get_and_poll_texture_node_tree(Main *bmain, wmOperator *op) -{ - if (RNA_struct_property_is_set(op->ptr, "session_uuid")) { - const uint32_t session_uuid = (uint32_t)RNA_int_get(op->ptr, "session_uuid"); - return (Tex *)BKE_libblock_find_session_uuid(bmain, ID_TE, session_uuid); - } - - char name[MAX_ID_NAME - 2]; - RNA_string_get(op->ptr, "name", name); - return (Tex *)BKE_libblock_find_name(bmain, ID_TE, name); -} - -static int node_add_texture_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - SpaceNode *snode = CTX_wm_space_node(C); - bNodeTree *ntree = snode->edittree; - Tex *texture; - - if (!(texture = node_add_texture_get_and_poll_texture_node_tree(bmain, op))) { - return OPERATOR_CANCELLED; - } - - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - - bNode *texture_node = node_add_node(*C, - nullptr, - GEO_NODE_LEGACY_ATTRIBUTE_SAMPLE_TEXTURE, - snode->runtime->cursor[0], - snode->runtime->cursor[1]); - if (!texture_node) { - BKE_report(op->reports, RPT_WARNING, "Could not add texture node"); - return OPERATOR_CANCELLED; - } - - texture_node->id = &texture->id; - id_us_plus(&texture->id); - - nodeSetActive(ntree, texture_node); - ED_node_tree_propagate_change(C, bmain, ntree); - DEG_relations_tag_update(bmain); - - return OPERATOR_FINISHED; -} - -static int node_add_texture_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - ARegion *region = CTX_wm_region(C); - SpaceNode *snode = CTX_wm_space_node(C); - - /* Convert mouse coordinates to v2d space. */ - UI_view2d_region_to_view(®ion->v2d, - event->mval[0], - event->mval[1], - &snode->runtime->cursor[0], - &snode->runtime->cursor[1]); - - snode->runtime->cursor[0] /= UI_DPI_FAC; - snode->runtime->cursor[1] /= UI_DPI_FAC; - - return node_add_texture_exec(C, op); -} - -static bool node_add_texture_poll(bContext *C) -{ - const SpaceNode *snode = CTX_wm_space_node(C); - return ED_operator_node_editable(C) && ELEM(snode->nodetree->type, NTREE_GEOMETRY) && - !UI_but_active_drop_name(C); -} - -void NODE_OT_add_texture(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Add Node Texture"; - ot->description = "Add a texture to the current node editor"; - ot->idname = "NODE_OT_add_texture"; - - /* callbacks */ - ot->exec = node_add_texture_exec; - ot->invoke = node_add_texture_invoke; - ot->poll = node_add_texture_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - - RNA_def_string( - ot->srna, "name", "Texture", MAX_ID_NAME - 2, "Name", "Data-block name to assign"); - prop = RNA_def_int(ot->srna, - "session_uuid", - 0, - INT32_MIN, - INT32_MAX, - "Session UUID", - "Session UUID of the data-block to assign", - INT32_MIN, - INT32_MAX); - RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Add Node Collection Operator * \{ */ diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index e638816e3fc..e221fac5ef9 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -1418,8 +1418,6 @@ static int node_error_type_to_icon(const geo_log::NodeWarningType type) return ICON_ERROR; case geo_log::NodeWarningType::Info: return ICON_INFO; - case geo_log::NodeWarningType::Legacy: - return ICON_ERROR; } BLI_assert(false); @@ -1430,8 +1428,6 @@ static uint8_t node_error_type_priority(const geo_log::NodeWarningType type) { switch (type) { case geo_log::NodeWarningType::Error: - return 4; - case geo_log::NodeWarningType::Legacy: return 3; case geo_log::NodeWarningType::Warning: return 2; diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index 319f97e57f5..cd40573607d 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -178,7 +178,6 @@ bool space_node_view_flag( void NODE_OT_view_all(wmOperatorType *ot); void NODE_OT_view_selected(wmOperatorType *ot); -void NODE_OT_geometry_node_view_legacy(wmOperatorType *ot); void NODE_OT_backimage_move(wmOperatorType *ot); void NODE_OT_backimage_zoom(wmOperatorType *ot); @@ -241,7 +240,6 @@ void NODE_OT_add_reroute(wmOperatorType *ot); void NODE_OT_add_group(wmOperatorType *ot); void NODE_OT_add_object(wmOperatorType *ot); void NODE_OT_add_collection(wmOperatorType *ot); -void NODE_OT_add_texture(wmOperatorType *ot); void NODE_OT_add_file(wmOperatorType *ot); void NODE_OT_add_mask(wmOperatorType *ot); void NODE_OT_new_node_tree(wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.cc b/source/blender/editors/space_node/node_ops.cc index e9903299300..ce000aba1da 100644 --- a/source/blender/editors/space_node/node_ops.cc +++ b/source/blender/editors/space_node/node_ops.cc @@ -37,7 +37,6 @@ void node_operatortypes() WM_operatortype_append(NODE_OT_view_all); WM_operatortype_append(NODE_OT_view_selected); - WM_operatortype_append(NODE_OT_geometry_node_view_legacy); WM_operatortype_append(NODE_OT_mute_toggle); WM_operatortype_append(NODE_OT_hide_toggle); @@ -79,7 +78,6 @@ void node_operatortypes() WM_operatortype_append(NODE_OT_add_group); WM_operatortype_append(NODE_OT_add_object); WM_operatortype_append(NODE_OT_add_collection); - WM_operatortype_append(NODE_OT_add_texture); WM_operatortype_append(NODE_OT_add_file); WM_operatortype_append(NODE_OT_add_mask); diff --git a/source/blender/editors/space_node/node_view.cc b/source/blender/editors/space_node/node_view.cc index 36fdcf37fd7..f5f5a9e6f67 100644 --- a/source/blender/editors/space_node/node_view.cc +++ b/source/blender/editors/space_node/node_view.cc @@ -686,90 +686,4 @@ void NODE_OT_backimage_sample(wmOperatorType *ot) /** \} */ -/* -------------------------------------------------------------------- */ -/** \name View Geometry Nodes Legacy Operator - * - * This operator should be removed when the 2.93 legacy nodes are removed. - * \{ */ - -static int space_node_view_geometry_nodes_legacy(bContext *C, SpaceNode *snode, wmOperator *op) -{ - ARegion *region = CTX_wm_region(C); - - /* Only use the node editor's active node tree. Otherwise this will be too complicated. */ - bNodeTree *node_tree = snode->nodetree; - if (node_tree == nullptr || node_tree->type != NTREE_GEOMETRY) { - return OPERATOR_CANCELLED; - } - - bool found_legacy_node = false; - LISTBASE_FOREACH_BACKWARD (bNode *, node, &node_tree->nodes) { - StringRef idname{node->idname}; - if (idname.find("Legacy") == StringRef::not_found) { - node->flag &= ~NODE_SELECT; - } - else { - found_legacy_node = true; - node->flag |= NODE_SELECT; - } - } - - if (!found_legacy_node) { - WM_report(RPT_INFO, "Legacy node not found, may be in nested node group"); - } - - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - if (space_node_view_flag(*C, *snode, *region, NODE_SELECT, smooth_viewtx)) { - return OPERATOR_FINISHED; - } - return OPERATOR_CANCELLED; -} - -static int geometry_node_view_legacy_exec(bContext *C, wmOperator *op) -{ - /* Allow running this operator directly in a specific node editor. */ - if (SpaceNode *snode = CTX_wm_space_node(C)) { - return space_node_view_geometry_nodes_legacy(C, snode, op); - } - - /* Since the operator is meant to be called from a button in the modifier panel, the node tree - * must be found from the screen, using the largest node editor if there is more than one. */ - if (ScrArea *area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_NODE, 0)) { - if (SpaceNode *snode = static_cast<SpaceNode *>(area->spacedata.first)) { - ScrArea *old_area = CTX_wm_area(C); - ARegion *old_region = CTX_wm_region(C); - - /* Override the context since it is used by the View2D panning code. */ - CTX_wm_area_set(C, area); - CTX_wm_region_set(C, static_cast<ARegion *>(area->regionbase.last)); - const int result = space_node_view_geometry_nodes_legacy(C, snode, op); - CTX_wm_area_set(C, old_area); - CTX_wm_region_set(C, old_region); - return result; - } - } - - return OPERATOR_CANCELLED; -} - -static bool geometry_node_view_legacy_poll(bContext *C) -{ - /* Allow direct execution in a node editor, but also affecting any visible node editor. */ - return ED_operator_node_active(C) || BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_NODE, 0); -} - -void NODE_OT_geometry_node_view_legacy(wmOperatorType *ot) -{ - ot->name = "View Deprecated Geometry Nodes"; - ot->idname = "NODE_OT_geometry_node_view_legacy"; - ot->description = "Select and view legacy geometry nodes in the node editor"; - - ot->exec = geometry_node_view_legacy_exec; - ot->poll = geometry_node_view_legacy_poll; - - ot->flag = OPTYPE_INTERNAL; -} - -/** \} */ - } // namespace blender::ed::space_node diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index a1fa0517c63..82b850653be 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -622,11 +622,6 @@ static bool node_collection_drop_poll(bContext *UNUSED(C), return WM_drag_is_ID_type(drag, ID_GR); } -static bool node_texture_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) -{ - return WM_drag_is_ID_type(drag, ID_TE); -} - static bool node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_PATH) { @@ -687,12 +682,6 @@ static void node_dropboxes() WM_drag_free_imported_drag_ID, nullptr); WM_dropbox_add(lb, - "NODE_OT_add_texture", - node_texture_drop_poll, - node_id_drop_copy, - WM_drag_free_imported_drag_ID, - nullptr); - WM_dropbox_add(lb, "NODE_OT_add_group", node_group_drop_poll, node_group_drop_copy, diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 5bd44868741..609862eff4f 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1210,53 +1210,6 @@ typedef struct NodeMapRange { char _pad[5]; } NodeMapRange; -typedef struct NodeAttributeClamp { - /* CustomDataType. */ - uint8_t data_type; - - /* NodeClampOperation. */ - uint8_t operation; -} NodeAttributeClamp; - -typedef struct NodeAttributeCompare { - /* FloatCompareOperation. */ - uint8_t operation; - - /* GeometryNodeAttributeInputMode */ - uint8_t input_type_a; - uint8_t input_type_b; - - char _pad[5]; -} NodeAttributeCompare; - -typedef struct NodeAttributeMapRange { - /* GeometryNodeAttributeDataType */ - uint8_t data_type; - - /* NodeMapRangeType. */ - uint8_t interpolation_type; -} NodeAttributeMapRange; - -typedef struct NodeAttributeMath { - /* NodeMathOperation. */ - uint8_t operation; - - /* GeometryNodeAttributeInputMode */ - uint8_t input_type_a; - uint8_t input_type_b; - uint8_t input_type_c; -} NodeAttributeMath; - -typedef struct NodeAttributeMix { - /* e.g. MA_RAMP_BLEND. */ - uint8_t blend_type; - - /* GeometryNodeAttributeInputMode */ - uint8_t input_type_factor; - uint8_t input_type_a; - uint8_t input_type_b; -} NodeAttributeMix; - typedef struct NodeRandomValue { /* CustomDataType. */ uint8_t data_type; @@ -1269,51 +1222,6 @@ typedef struct NodeAccumulateField { uint8_t domain; } NodeAccumulateField; -typedef struct NodeAttributeRandomize { - /* CustomDataType. */ - uint8_t data_type; - /* AttributeDomain. */ - uint8_t domain; - /* GeometryNodeAttributeRandomizeMode. */ - uint8_t operation; - char _pad[1]; -} NodeAttributeRandomize; - -typedef struct NodeAttributeVectorMath { - /* NodeVectorMathOperation */ - uint8_t operation; - - /* GeometryNodeAttributeInputMode */ - uint8_t input_type_a; - uint8_t input_type_b; - uint8_t input_type_c; -} NodeAttributeVectorMath; - -typedef struct NodeAttributeVectorRotate { - /* GeometryNodeAttributeVectorRotateMode */ - uint8_t mode; - - /* GeometryNodeAttributeInputMode */ - uint8_t input_type_vector; - uint8_t input_type_center; - uint8_t input_type_axis; - uint8_t input_type_angle; - uint8_t input_type_rotation; - char _pad[2]; -} NodeAttributeVectorRotate; - -typedef struct NodeAttributeColorRamp { - ColorBand color_ramp; -} NodeAttributeColorRamp; - -typedef struct NodeAttributeCurveMap { - /* CustomDataType. */ - uint8_t data_type; - char _pad[7]; - CurveMapping *curve_vec; - CurveMapping *curve_rgb; -} NodeAttributeCurveMap; - typedef struct NodeInputBool { uint8_t boolean; } NodeInputBool; @@ -1334,40 +1242,6 @@ typedef struct NodeInputString { char *string; } NodeInputString; -typedef struct NodeGeometryRotatePoints { - /* GeometryNodeRotatePointsType */ - uint8_t type; - /* GeometryNodeRotatePointsSpace */ - uint8_t space; - - /* GeometryNodeAttributeInputMode */ - uint8_t input_type_axis; - uint8_t input_type_angle; - uint8_t input_type_rotation; - char _pad[3]; -} NodeGeometryRotatePoints; - -typedef struct NodeGeometryAlignRotationToVector { - /* GeometryNodeAlignRotationToVectorAxis */ - uint8_t axis; - /* GeometryNodeAlignRotationToVectorPivotAxis */ - uint8_t pivot_axis; - - /* GeometryNodeAttributeInputMode */ - uint8_t input_type_factor; - uint8_t input_type_vector; -} NodeGeometryAlignRotationToVector; - -typedef struct NodeGeometryPointScale { - /* GeometryNodeAttributeInputMode */ - uint8_t input_type; -} NodeGeometryPointScale; - -typedef struct NodeGeometryPointTranslate { - /* GeometryNodeAttributeInputMode */ - uint8_t input_type; -} NodeGeometryPointTranslate; - typedef struct NodeGeometryExtrudeMesh { /* GeometryNodeExtrudeMeshMode */ uint8_t mode; @@ -1378,13 +1252,6 @@ typedef struct NodeGeometryObjectInfo { uint8_t transform_space; } NodeGeometryObjectInfo; -typedef struct NodeGeometryPointInstance { - /* GeometryNodePointInstanceType. */ - uint8_t instance_type; - /* GeometryNodePointInstanceFlag. */ - uint8_t flag; -} NodeGeometryPointInstance; - typedef struct NodeGeometryPointsToVolume { /* GeometryNodePointsToVolumeResolutionMode */ uint8_t resolution_mode; @@ -1397,11 +1264,6 @@ typedef struct NodeGeometryCollectionInfo { uint8_t transform_space; } NodeGeometryCollectionInfo; -typedef struct NodeGeometryAttributeProximity { - /* GeometryNodeAttributeProximityTargetType. */ - uint8_t target_geometry_element; -} NodeGeometryAttributeProximity; - typedef struct NodeGeometryProximity { /* GeometryNodeProximityTargetType. */ uint8_t target_element; @@ -1412,27 +1274,6 @@ typedef struct NodeGeometryVolumeToMesh { uint8_t resolution_mode; } NodeGeometryVolumeToMesh; -typedef struct NodeAttributeCombineXYZ { - /* GeometryNodeAttributeInputMode. */ - uint8_t input_type_x; - uint8_t input_type_y; - uint8_t input_type_z; - - char _pad[1]; -} NodeAttributeCombineXYZ; - -typedef struct NodeAttributeSeparateXYZ { - /* GeometryNodeAttributeInputMode. */ - uint8_t input_type; -} NodeAttributeSeparateXYZ; - -typedef struct NodeAttributeConvert { - /* CustomDataType. */ - int8_t data_type; - /* AttributeDomain. */ - int8_t domain; -} NodeAttributeConvert; - typedef struct NodeGeometrySubdivisionSurface { /* eSubsurfUVSmooth. */ uint8_t uv_smooth; @@ -1521,11 +1362,6 @@ typedef struct NodeGeometryCurveResample { uint8_t mode; } NodeGeometryCurveResample; -typedef struct NodeGeometryCurveSubdivide { - /* GeometryNodeAttributeInputMode (integer or attribute). */ - uint8_t cuts_type; -} NodeGeometryCurveSubdivide; - typedef struct NodeGeometryCurveFillet { /* GeometryNodeCurveFilletMode. */ uint8_t mode; @@ -1546,13 +1382,6 @@ typedef struct NodeGeometryCurveSample { uint8_t mode; } NodeGeometryCurveSample; -typedef struct NodeGeometryAttributeTransfer { - /* AttributeDomain. */ - int8_t domain; - /* GeometryNodeAttributeTransferMapMode. */ - uint8_t mapping; -} NodeGeometryAttributeTransfer; - typedef struct NodeGeometryTransferAttribute { /* CustomDataType. */ int8_t data_type; @@ -2080,12 +1909,6 @@ typedef enum NodeShaderOutputTarget { /* Geometry Nodes */ -typedef enum GeometryNodeAttributeProximityTargetType { - GEO_NODE_PROXIMITY_TARGET_POINTS = 0, - GEO_NODE_PROXIMITY_TARGET_EDGES = 1, - GEO_NODE_PROXIMITY_TARGET_FACES = 2, -} GeometryNodeAttributeProximityTargetType; - typedef enum GeometryNodeProximityTargetType { GEO_NODE_PROX_TARGET_POINTS = 0, GEO_NODE_PROX_TARGET_EDGES = 1, @@ -2134,30 +1957,6 @@ typedef enum GeometryNodeTriangulateQuads { GEO_NODE_TRIANGULATE_QUAD_LONGEDGE = 4, } GeometryNodeTriangulateQuads; -typedef enum GeometryNodePointInstanceType { - GEO_NODE_POINT_INSTANCE_TYPE_OBJECT = 0, - GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION = 1, - GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY = 2, -} GeometryNodePointInstanceType; - -typedef enum GeometryNodePointInstanceFlag { - GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION = (1 << 0), -} GeometryNodePointInstanceFlag; - -typedef enum GeometryNodeAttributeInputMode { - GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE = 0, - GEO_NODE_ATTRIBUTE_INPUT_FLOAT = 1, - GEO_NODE_ATTRIBUTE_INPUT_VECTOR = 2, - GEO_NODE_ATTRIBUTE_INPUT_COLOR = 3, - GEO_NODE_ATTRIBUTE_INPUT_BOOLEAN = 4, - GEO_NODE_ATTRIBUTE_INPUT_INTEGER = 5, -} GeometryNodeAttributeInputMode; - -typedef enum GeometryNodePointDistributeMode { - GEO_NODE_POINT_DISTRIBUTE_RANDOM = 0, - GEO_NODE_POINT_DISTRIBUTE_POISSON = 1, -} GeometryNodePointDistributeMode; - typedef enum GeometryNodeDistributePointsOnFacesMode { GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_RANDOM = 0, GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_POISSON = 1, @@ -2169,54 +1968,16 @@ typedef enum GeometryNodeExtrudeMeshMode { GEO_NODE_EXTRUDE_MESH_FACES = 2, } GeometryNodeExtrudeMeshMode; -typedef enum GeometryNodeRotatePointsType { - GEO_NODE_POINT_ROTATE_TYPE_EULER = 0, - GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE = 1, -} GeometryNodeRotatePointsType; - -typedef enum FunctionNodeRotatePointsType { +typedef enum FunctionNodeRotateEulerType { FN_NODE_ROTATE_EULER_TYPE_EULER = 0, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE = 1, -} FunctionNodeRotatePointsType; - -typedef enum GeometryNodeAttributeVectorRotateMode { - GEO_NODE_VECTOR_ROTATE_TYPE_AXIS = 0, - GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_X = 1, - GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Y = 2, - GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Z = 3, - GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ = 4, -} GeometryNodeAttributeVectorRotateMode; - -typedef enum GeometryNodeAttributeRandomizeMode { - GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE = 0, - GEO_NODE_ATTRIBUTE_RANDOMIZE_ADD = 1, - GEO_NODE_ATTRIBUTE_RANDOMIZE_SUBTRACT = 2, - GEO_NODE_ATTRIBUTE_RANDOMIZE_MULTIPLY = 3, -} GeometryNodeAttributeRandomizeMode; - -typedef enum GeometryNodeRotatePointsSpace { - GEO_NODE_POINT_ROTATE_SPACE_OBJECT = 0, - GEO_NODE_POINT_ROTATE_SPACE_POINT = 1, -} GeometryNodeRotatePointsSpace; +} FunctionNodeRotateEulerType; typedef enum FunctionNodeRotateEulerSpace { FN_NODE_ROTATE_EULER_SPACE_OBJECT = 0, FN_NODE_ROTATE_EULER_SPACE_LOCAL = 1, } FunctionNodeRotateEulerSpace; -typedef enum GeometryNodeAlignRotationToVectorAxis { - GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_X = 0, - GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_Y = 1, - GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_Z = 2, -} GeometryNodeAlignRotationToVectorAxis; - -typedef enum GeometryNodeAlignRotationToVectorPivotAxis { - GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_AUTO = 0, - GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_X = 1, - GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_Y = 2, - GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_Z = 3, -} GeometryNodeAlignRotationToVectorPivotAxis; - typedef enum NodeAlignEulerToVectorAxis { FN_NODE_ALIGN_EULER_TO_VECTOR_AXIS_X = 0, FN_NODE_ALIGN_EULER_TO_VECTOR_AXIS_Y = 1, @@ -2295,11 +2056,6 @@ typedef enum GeometryNodeCurveFilletMode { GEO_NODE_CURVE_FILLET_POLY = 1, } GeometryNodeCurveFilletMode; -typedef enum GeometryNodeAttributeTransferMapMode { - GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED = 0, - GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER_NEAREST = 1, -} GeometryNodeAttributeTransferMapMode; - typedef enum GeometryNodeAttributeTransferMode { GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED = 0, GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST = 1, diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 31b67d4eb19..373aec975c2 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -173,11 +173,7 @@ static char *rna_ColorRamp_path(PointerRNA *ptr) char *node_path; for (node = ntree->nodes.first; node; node = node->next) { - if (ELEM(node->type, - SH_NODE_VALTORGB, - CMP_NODE_VALTORGB, - TEX_NODE_VALTORGB, - GEO_NODE_LEGACY_ATTRIBUTE_COLOR_RAMP)) { + if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) { if (node->storage == ptr->data) { /* all node color ramp properties called 'color_ramp' * prepend path from ID to the node @@ -304,11 +300,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA * bNode *node; for (node = ntree->nodes.first; node; node = node->next) { - if (ELEM(node->type, - SH_NODE_VALTORGB, - CMP_NODE_VALTORGB, - TEX_NODE_VALTORGB, - GEO_NODE_LEGACY_ATTRIBUTE_COLOR_RAMP)) { + if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) { BKE_ntree_update_tag_node_property(ntree, node); ED_node_tree_propagate_change(NULL, bmain, ntree); } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index f212b4a1d23..2c6a4f5adeb 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -461,30 +461,6 @@ const EnumPropertyItem rna_enum_node_filter_items[] = { {0, NULL, 0, NULL, NULL}, }; -static const EnumPropertyItem rna_node_geometry_attribute_randomize_operation_items[] = { - {GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE, - "REPLACE_CREATE", - ICON_NONE, - "Replace/Create", - "Replace the value and data type of an existing attribute, or create a new one"}, - {GEO_NODE_ATTRIBUTE_RANDOMIZE_ADD, - "ADD", - ICON_NONE, - "Add", - "Add the random values to the existing attribute values"}, - {GEO_NODE_ATTRIBUTE_RANDOMIZE_SUBTRACT, - "SUBTRACT", - ICON_NONE, - "Subtract", - "Subtract random values from the existing attribute values"}, - {GEO_NODE_ATTRIBUTE_RANDOMIZE_MULTIPLY, - "MULTIPLY", - ICON_NONE, - "Multiply", - "Multiply the existing attribute values with the random values"}, - {0, NULL, 0, NULL, NULL}, -}; - static const EnumPropertyItem rna_node_geometry_curve_handle_type_items[] = { {GEO_NODE_CURVE_HANDLE_FREE, "FREE", @@ -547,73 +523,8 @@ static EnumPropertyItem rna_node_geometry_mesh_circle_fill_type_items[] = { }; #endif -#define ITEM_ATTRIBUTE \ - { \ - GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE, "ATTRIBUTE", 0, "Attribute", "" \ - } -#define ITEM_FLOAT \ - { \ - GEO_NODE_ATTRIBUTE_INPUT_FLOAT, "FLOAT", 0, "Float", "" \ - } -#define ITEM_VECTOR \ - { \ - GEO_NODE_ATTRIBUTE_INPUT_VECTOR, "VECTOR", 0, "Vector", "" \ - } -#define ITEM_COLOR \ - { \ - GEO_NODE_ATTRIBUTE_INPUT_COLOR, "COLOR", 0, "Color", "" \ - } -#define ITEM_INTEGER \ - { \ - GEO_NODE_ATTRIBUTE_INPUT_INTEGER, "INTEGER", 0, "Integer", "" \ - } -#define ITEM_BOOLEAN \ - { \ - GEO_NODE_ATTRIBUTE_INPUT_BOOLEAN, "BOOLEAN", 0, "Boolean", "" \ - } - -/* Used in both runtime and static code. */ -static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_any[] = { - ITEM_ATTRIBUTE, - ITEM_FLOAT, - ITEM_VECTOR, - ITEM_COLOR, - ITEM_INTEGER, - ITEM_BOOLEAN, - {0, NULL, 0, NULL, NULL}, -}; - #ifndef RNA_RUNTIME -static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_vector[] = { - ITEM_ATTRIBUTE, - ITEM_VECTOR, - {0, NULL, 0, NULL, NULL}, -}; -static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_float_vector[] = { - ITEM_ATTRIBUTE, - ITEM_FLOAT, - ITEM_VECTOR, - {0, NULL, 0, NULL, NULL}, -}; -static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_float[] = { - ITEM_ATTRIBUTE, - ITEM_FLOAT, - {0, NULL, 0, NULL, NULL}, -}; -static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_int[] = { - ITEM_ATTRIBUTE, - ITEM_INTEGER, - {0, NULL, 0, NULL, NULL}, -}; -static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_no_boolean[] = { - ITEM_ATTRIBUTE, - ITEM_FLOAT, - ITEM_VECTOR, - ITEM_COLOR, - {0, NULL, 0, NULL, NULL}, -}; - #endif #undef ITEM_ATTRIBUTE @@ -2170,31 +2081,6 @@ static const EnumPropertyItem *rna_FunctionNodeCompare_operation_itemf(bContext } } -static bool attribute_clamp_type_supported(const EnumPropertyItem *item) -{ - return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_INT32, CD_PROP_COLOR); -} - -static const EnumPropertyItem *rna_GeometryNodeAttributeClamp_type_itemf(bContext *UNUSED(C), - PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), - bool *r_free) -{ - *r_free = true; - return itemf_function_check(rna_enum_attribute_type_items, attribute_clamp_type_supported); -} - -static bool attribute_random_type_supported(const EnumPropertyItem *item) -{ - return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_BOOL, CD_PROP_INT32); -} -static const EnumPropertyItem *rna_GeometryNodeAttributeRandom_type_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) -{ - *r_free = true; - return itemf_function_check(rna_enum_attribute_type_items, attribute_random_type_supported); -} - static bool random_value_type_supported(const EnumPropertyItem *item) { return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_BOOL, CD_PROP_INT32); @@ -2222,49 +2108,6 @@ static const EnumPropertyItem *rna_GeoNodeAccumulateField_type_itemf(bContext *U return itemf_function_check(rna_enum_attribute_type_items, accumulate_field_type_supported); } -static const EnumPropertyItem *rna_GeometryNodeAttributeRandomize_operation_itemf( - bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) -{ - bNode *node = ptr->data; - const NodeAttributeRandomize *node_storage = (NodeAttributeRandomize *)node->storage; - const CustomDataType data_type = (CustomDataType)node_storage->data_type; - - EnumPropertyItem *item_array = NULL; - int items_len = 0; - for (const EnumPropertyItem *item = rna_node_geometry_attribute_randomize_operation_items; - item->identifier != NULL; - item++) { - if (data_type == CD_PROP_BOOL) { - if (item->value == GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE) { - RNA_enum_item_add(&item_array, &items_len, item); - } - } - else { - RNA_enum_item_add(&item_array, &items_len, item); - } - } - RNA_enum_item_end(&item_array, &items_len); - - *r_free = true; - return item_array; -} - -static void rna_GeometryNodeAttributeRandomize_data_type_update(Main *bmain, - Scene *scene, - PointerRNA *ptr) -{ - bNode *node = ptr->data; - NodeAttributeRandomize *node_storage = (NodeAttributeRandomize *)node->storage; - - /* The boolean data type has no extra operations besides, - * replace, so make sure the enum value is set properly. */ - if (node_storage->data_type == CD_PROP_BOOL) { - node_storage->operation = GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE; - } - - rna_Node_socket_update(bmain, scene, ptr); -} - static void rna_GeometryNodeCompare_data_type_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bNode *node = ptr->data; @@ -2289,37 +2132,18 @@ static void rna_GeometryNodeCompare_data_type_update(Main *bmain, Scene *scene, rna_Node_socket_update(bmain, scene, ptr); } -static bool attribute_convert_type_supported(const EnumPropertyItem *item) -{ - return ELEM(item->value, - CD_AUTO_FROM_NAME, - CD_PROP_FLOAT, - CD_PROP_FLOAT2, - CD_PROP_FLOAT3, - CD_PROP_COLOR, - CD_PROP_BOOL, - CD_PROP_INT32); -} -static const EnumPropertyItem *rna_GeometryNodeAttributeConvert_type_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) -{ - *r_free = true; - return itemf_function_check(rna_enum_attribute_type_with_auto_items, - attribute_convert_type_supported); -} - -static bool attribute_fill_type_supported(const EnumPropertyItem *item) +static bool generic_attribute_type_supported(const EnumPropertyItem *item) { return ELEM( item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_COLOR, CD_PROP_BOOL, CD_PROP_INT32); } -static const EnumPropertyItem *rna_GeometryNodeAttributeFill_type_itemf(bContext *UNUSED(C), +static const EnumPropertyItem *rna_GeometryNodeAttributeType_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) { *r_free = true; - return itemf_function_check(rna_enum_attribute_type_items, attribute_fill_type_supported); + return itemf_function_check(rna_enum_attribute_type_items, generic_attribute_type_supported); } static bool transfer_attribute_type_supported(const EnumPropertyItem *item) @@ -2327,7 +2151,6 @@ static bool transfer_attribute_type_supported(const EnumPropertyItem *item) return ELEM( item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_COLOR, CD_PROP_BOOL, CD_PROP_INT32); } - static const EnumPropertyItem *rna_NodeGeometryTransferAttribute_type_itemf( bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) { @@ -2346,122 +2169,6 @@ static const EnumPropertyItem *rna_GeometryNodeAttributeStatistic_type_itemf( return itemf_function_check(rna_enum_attribute_type_items, attribute_statistic_type_supported); } -/** - * This bit of ugly code makes sure the float / attribute option shows up instead of - * vector / attribute if the node uses an operation that uses a float for input B or C. - */ -static const EnumPropertyItem *rna_GeometryNodeAttributeVectorMath_input_type_b_itemf( - bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) -{ - bNode *node = ptr->data; - NodeAttributeVectorMath *node_storage = (NodeAttributeVectorMath *)node->storage; - - EnumPropertyItem *item_array = NULL; - int items_len = 0; - for (const EnumPropertyItem *item = rna_node_geometry_attribute_input_type_items_any; - item->identifier != NULL; - item++) { - if (item->value == GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE) { - RNA_enum_item_add(&item_array, &items_len, item); - } - else if (item->value == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) { - if (node_storage->operation == NODE_VECTOR_MATH_SCALE) { - RNA_enum_item_add(&item_array, &items_len, item); - } - } - else if (item->value == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) { - if (node_storage->operation != NODE_VECTOR_MATH_SCALE) { - RNA_enum_item_add(&item_array, &items_len, item); - } - } - } - RNA_enum_item_end(&item_array, &items_len); - - *r_free = true; - return item_array; -} - -static const EnumPropertyItem *rna_GeometryNodeAttributeVectorMath_input_type_c_itemf( - bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) -{ - bNode *node = ptr->data; - NodeAttributeVectorMath *node_storage = (NodeAttributeVectorMath *)node->storage; - - EnumPropertyItem *item_array = NULL; - int items_len = 0; - for (const EnumPropertyItem *item = rna_node_geometry_attribute_input_type_items_any; - item->identifier != NULL; - item++) { - if (item->value == GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE) { - RNA_enum_item_add(&item_array, &items_len, item); - } - else if (item->value == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) { - if (node_storage->operation == NODE_VECTOR_MATH_REFRACT) { - RNA_enum_item_add(&item_array, &items_len, item); - } - } - else if (item->value == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) { - if (node_storage->operation != NODE_VECTOR_MATH_REFRACT) { - RNA_enum_item_add(&item_array, &items_len, item); - } - } - } - RNA_enum_item_end(&item_array, &items_len); - - *r_free = true; - return item_array; -} - -static void rna_GeometryNodeAttributeVectorMath_operation_update(Main *bmain, - Scene *scene, - PointerRNA *ptr) -{ - bNode *node = ptr->data; - NodeAttributeVectorMath *node_storage = (NodeAttributeVectorMath *)node->storage; - - const NodeVectorMathOperation operation = (NodeVectorMathOperation)node_storage->operation; - - /* The scale operation can't use a vector input, so reset - * the input type enum in case it's set to vector. */ - if (operation == NODE_VECTOR_MATH_SCALE) { - if (node_storage->input_type_b == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) { - node_storage->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - } - } - - /* Scale is also the only operation that uses the float input type, so a - * a check is also necessary for the other direction. */ - if (operation != NODE_VECTOR_MATH_SCALE) { - if (node_storage->input_type_b == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) { - node_storage->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - } - } - - rna_Node_socket_update(bmain, scene, ptr); -} - -static bool attribute_map_range_type_supported(const EnumPropertyItem *item) -{ - return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3); -} -static const EnumPropertyItem *rna_GeometryNodeAttributeMapRange_type_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) -{ - *r_free = true; - return itemf_function_check(rna_enum_attribute_type_items, attribute_map_range_type_supported); -} - -static bool attribute_curve_map_type_supported(const EnumPropertyItem *item) -{ - return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_COLOR); -} -static const EnumPropertyItem *rna_GeometryNodeAttributeCurveMap_type_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) -{ - *r_free = true; - return itemf_function_check(rna_enum_attribute_type_items, attribute_curve_map_type_supported); -} - static StructRNA *rna_ShaderNode_register(Main *bmain, ReportList *reports, void *data, @@ -9636,71 +9343,6 @@ static void def_fn_random_value(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_attribute_randomize(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeRandomize", "storage"); - - prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "data_type"); - RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeRandom_type_itemf"); - RNA_def_property_enum_default(prop, CD_PROP_FLOAT); - RNA_def_property_ui_text(prop, "Data Type", "Type of data stored in attribute"); - RNA_def_property_update( - prop, NC_NODE | NA_EDITED, "rna_GeometryNodeAttributeRandomize_data_type_update"); - - prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "operation"); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_randomize_operation_items); - RNA_def_property_enum_funcs( - prop, NULL, NULL, "rna_GeometryNodeAttributeRandomize_operation_itemf"); - RNA_def_property_enum_default(prop, GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE); - RNA_def_property_ui_text(prop, "Operation", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - -static void def_geo_attribute_fill(StructRNA *srna) -{ - PropertyRNA *prop; - - prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeFill_type_itemf"); - RNA_def_property_enum_default(prop, CD_PROP_FLOAT); - RNA_def_property_ui_text(prop, "Data Type", "Type of data stored in attribute"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update"); - - prop = RNA_def_property(srna, "domain", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom2"); - RNA_def_property_enum_items(prop, rna_enum_attribute_domain_with_auto_items); - RNA_def_property_enum_default(prop, ATTR_DOMAIN_AUTO); - RNA_def_property_ui_text(prop, "Domain", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -} - -static void def_geo_attribute_convert(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeConvert", "storage"); - - prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_attribute_type_with_auto_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeConvert_type_itemf"); - RNA_def_property_enum_default(prop, CD_AUTO_FROM_NAME); - RNA_def_property_ui_text(prop, "Data Type", "The data type to save the result attribute with"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update"); - - prop = RNA_def_property(srna, "domain", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_attribute_domain_with_auto_items); - RNA_def_property_enum_default(prop, ATTR_DOMAIN_AUTO); - RNA_def_property_ui_text(prop, "Domain", "The geometry domain to save the result attribute in"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -} - static void def_geo_attribute_statistic(StructRNA *srna) { PropertyRNA *prop; @@ -9724,229 +9366,6 @@ static void def_geo_attribute_statistic(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static void def_geo_attribute_math(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeMath", "storage"); - - prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "operation"); - RNA_def_property_enum_items(prop, rna_enum_node_math_items); - RNA_def_property_enum_default(prop, NODE_MATH_ADD); - RNA_def_property_ui_text(prop, "Operation", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_a", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_a"); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type A", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_b", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_b"); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type B", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_c", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_c"); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type C", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - -static void def_geo_attribute_vector_math(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeVectorMath", "storage"); - - prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "operation"); - RNA_def_property_enum_items(prop, rna_enum_node_vec_math_items); - RNA_def_property_ui_text(prop, "Operation", ""); - RNA_def_property_update( - prop, NC_NODE | NA_EDITED, "rna_GeometryNodeAttributeVectorMath_operation_update"); - - prop = RNA_def_property(srna, "input_type_a", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_a"); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type A", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_b", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_b"); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_any); - RNA_def_property_enum_funcs( - prop, NULL, NULL, "rna_GeometryNodeAttributeVectorMath_input_type_b_itemf"); - RNA_def_property_ui_text(prop, "Input Type B", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_c", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_c"); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_any); - RNA_def_property_enum_funcs( - prop, NULL, NULL, "rna_GeometryNodeAttributeVectorMath_input_type_c_itemf"); - RNA_def_property_ui_text(prop, "Input Type C", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - -static void def_geo_attribute_map_range(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeMapRange", "storage"); - - prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "data_type"); - RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeMapRange_type_itemf"); - RNA_def_property_ui_text(prop, "Data Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "interpolation_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "interpolation_type"); - RNA_def_property_enum_items(prop, rna_enum_node_map_range_items); - RNA_def_property_ui_text(prop, "Interpolation Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); -} - -static void def_geo_point_instance(StructRNA *srna) -{ - static const EnumPropertyItem instance_type_items[] = { - {GEO_NODE_POINT_INSTANCE_TYPE_OBJECT, - "OBJECT", - ICON_NONE, - "Object", - "Instance an individual object on all points"}, - {GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION, - "COLLECTION", - ICON_NONE, - "Collection", - "Instance an entire collection on all points"}, - {GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY, - "GEOMETRY", - ICON_NONE, - "Geometry", - "Copy geometry to all points"}, - {0, NULL, 0, NULL, NULL}, - }; - - PropertyRNA *prop; - RNA_def_struct_sdna_from(srna, "NodeGeometryPointInstance", "storage"); - - prop = RNA_def_property(srna, "instance_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "instance_type"); - RNA_def_property_enum_items(prop, instance_type_items); - RNA_def_property_enum_default(prop, GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); - RNA_def_property_ui_text(prop, "Instance Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "use_whole_collection", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION); - RNA_def_property_ui_text(prop, "Whole Collection", "Instance entire collection on each point"); - RNA_def_property_update(prop, 0, "rna_Node_socket_update"); -} - -static void def_geo_attribute_mix(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeMix", "storage"); - - prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_ramp_blend_items); - RNA_def_property_enum_default(prop, MA_RAMP_BLEND); - RNA_def_property_ui_text(prop, "Blending Mode", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - - prop = RNA_def_property(srna, "input_type_factor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type Factor", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_a", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_no_boolean); - RNA_def_property_ui_text(prop, "Input Type A", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_b", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_no_boolean); - RNA_def_property_ui_text(prop, "Input Type B", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - -static void def_geo_attribute_clamp(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeClamp", "storage"); - - prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "data_type"); - RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeClamp_type_itemf"); - RNA_def_property_ui_text(prop, "Data Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_node_clamp_items); - RNA_def_property_enum_default(prop, NODE_CLAMP_MINMAX); - RNA_def_property_ui_text(prop, "Operation", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -} - -static void def_geo_attribute_attribute_compare(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeCompare", "storage"); - - prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_node_float_compare_items); - RNA_def_property_enum_default(prop, NODE_COMPARE_GREATER_THAN); - RNA_def_property_ui_text(prop, "Operation", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_a", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_no_boolean); - RNA_def_property_ui_text(prop, "Input Type A", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_b", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_no_boolean); - RNA_def_property_ui_text(prop, "Input Type B", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - -static void def_geo_point_distribute(StructRNA *srna) -{ - PropertyRNA *prop; - - static const EnumPropertyItem rna_node_geometry_point_distribute_method_items[] = { - {GEO_NODE_POINT_DISTRIBUTE_RANDOM, - "RANDOM", - 0, - "Random", - "Distribute points randomly on the surface"}, - {GEO_NODE_POINT_DISTRIBUTE_POISSON, - "POISSON", - 0, - "Poisson Disk", - "Distribute the points randomly on the surface while taking a minimum distance between " - "points into account"}, - {0, NULL, 0, NULL, NULL}, - }; - - prop = RNA_def_property(srna, "distribute_method", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, rna_node_geometry_point_distribute_method_items); - RNA_def_property_enum_default(prop, GEO_NODE_POINT_DISTRIBUTE_RANDOM); - RNA_def_property_ui_text(prop, "Distribution Method", "Method to use for scattering points"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_extrude_mesh(StructRNA *srna) { PropertyRNA *prop; @@ -9995,97 +9414,6 @@ static void def_geo_distribute_points_on_faces(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_attribute_color_ramp(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeColorRamp", "storage"); - - prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "ColorRamp"); - RNA_def_property_ui_text(prop, "Color Ramp", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -} - -static void def_geo_attribute_curve_map(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeCurveMap", "storage"); - - prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "data_type"); - RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeCurveMap_type_itemf"); - RNA_def_property_ui_text(prop, "Data Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "curve_vec", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "CurveMapping"); - RNA_def_property_ui_text(prop, "Mapping", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - - prop = RNA_def_property(srna, "curve_rgb", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "CurveMapping"); - RNA_def_property_ui_text(prop, "Mapping", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -} - -static void def_geo_attribute_vector_rotate(StructRNA *srna) -{ - static const EnumPropertyItem rotate_mode_items[] = { - {GEO_NODE_VECTOR_ROTATE_TYPE_AXIS, - "AXIS_ANGLE", - 0, - "Axis Angle", - "Rotate a point using axis angle"}, - {GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_X, "X_AXIS", 0, "X Axis", "Rotate a point using X axis"}, - {GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Y, "Y_AXIS", 0, "Y Axis", "Rotate a point using Y axis"}, - {GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Z, "Z_AXIS", 0, "Z Axis", "Rotate a point using Z axis"}, - {GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ, - "EULER_XYZ", - 0, - "Euler", - "Rotate a point using XYZ order"}, - {0, NULL, 0, NULL, NULL}, - }; - - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeVectorRotate", "storage"); - - prop = RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "mode"); - RNA_def_property_enum_items(prop, rotate_mode_items); - RNA_def_property_ui_text(prop, "Mode", "Type of rotation"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); - - prop = RNA_def_property(srna, "input_type_vector", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type Vector", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_center", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type Center", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_axis", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type Axis", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_angle", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type Angle", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_rotation", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type Rotation", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_curve_spline_type(StructRNA *srna) { static const EnumPropertyItem type_items[] = { @@ -10121,24 +9449,6 @@ static void def_geo_curve_set_handle_type(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_legacy_curve_set_handles(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryCurveSetHandles", "storage"); - - prop = RNA_def_property(srna, "handle_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "handle_type"); - RNA_def_property_enum_items(prop, rna_node_geometry_curve_handle_type_items); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_curve_handle_side_items); - RNA_def_property_ui_text(prop, "Mode", "Whether to update left and right handles"); - RNA_def_property_flag(prop, PROP_ENUM_FLAG); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_curve_set_handle_positions(StructRNA *srna) { PropertyRNA *prop; @@ -10151,24 +9461,6 @@ static void def_geo_curve_set_handle_positions(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_curve_select_handles(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryCurveSelectHandles", "storage"); - - prop = RNA_def_property(srna, "handle_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "handle_type"); - RNA_def_property_enum_items(prop, rna_node_geometry_curve_handle_type_items); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_curve_handle_side_items); - RNA_def_property_ui_text(prop, "Mode", "Whether to check the type of left and right handles"); - RNA_def_property_flag(prop, PROP_ENUM_FLAG); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_curve_handle_type_selection(StructRNA *srna) { PropertyRNA *prop; @@ -10266,66 +9558,6 @@ static void def_geo_curve_primitive_line(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_point_rotate(StructRNA *srna) -{ - static const EnumPropertyItem type_items[] = { - {GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE, - "AXIS_ANGLE", - ICON_NONE, - "Axis Angle", - "Rotate around an axis by an angle"}, - {GEO_NODE_POINT_ROTATE_TYPE_EULER, - "EULER", - ICON_NONE, - "Euler", - "Rotate around the X, Y, and Z axes"}, - {0, NULL, 0, NULL, NULL}, - }; - - static const EnumPropertyItem space_items[] = { - {GEO_NODE_POINT_ROTATE_SPACE_OBJECT, - "OBJECT", - ICON_NONE, - "Object", - "Rotate points in the local space of the object"}, - {GEO_NODE_POINT_ROTATE_SPACE_POINT, - "POINT", - ICON_NONE, - "Point", - "Rotate every point in its local space (as defined by the 'rotation' attribute)"}, - {0, NULL, 0, NULL, NULL}, - }; - - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryRotatePoints", "storage"); - - prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, type_items); - RNA_def_property_ui_text(prop, "Type", "Method used to describe the rotation"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, space_items); - RNA_def_property_ui_text(prop, "Space", "Base orientation of the points"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - - prop = RNA_def_property(srna, "input_type_axis", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type Axis", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_angle", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type Angle", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_rotation", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type Rotation", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_fn_rotate_euler(StructRNA *srna) { static const EnumPropertyItem type_items[] = { @@ -10371,76 +9603,6 @@ static void def_fn_rotate_euler(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static void def_geo_align_rotation_to_vector(StructRNA *srna) -{ - static const EnumPropertyItem axis_items[] = { - {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_X, - "X", - ICON_NONE, - "X", - "Align the X axis with the vector"}, - {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_Y, - "Y", - ICON_NONE, - "Y", - "Align the Y axis with the vector"}, - {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_Z, - "Z", - ICON_NONE, - "Z", - "Align the Z axis with the vector"}, - {0, NULL, 0, NULL, NULL}, - }; - - static const EnumPropertyItem pivot_axis_items[] = { - {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_AUTO, - "AUTO", - ICON_NONE, - "Auto", - "Automatically detect the best rotation axis to rotate towards the vector"}, - {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_X, - "X", - ICON_NONE, - "X", - "Rotate around the local X axis"}, - {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_Y, - "Y", - ICON_NONE, - "Y", - "Rotate around the local Y axis"}, - {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_Z, - "Z", - ICON_NONE, - "Z", - "Rotate around the local Z axis"}, - {0, NULL, 0, NULL, NULL}, - }; - - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryAlignRotationToVector", "storage"); - - prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, axis_items); - RNA_def_property_ui_text(prop, "Axis", "Axis to align to the vector"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - - prop = RNA_def_property(srna, "pivot_axis", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, pivot_axis_items); - RNA_def_property_ui_text(prop, "Pivot Axis", "Axis to rotate around"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - - prop = RNA_def_property(srna, "input_type_factor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type Factor", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_vector", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type Vector", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_fn_align_euler_to_vector(StructRNA *srna) { static const EnumPropertyItem axis_items[] = { @@ -10501,30 +9663,6 @@ static void def_fn_align_euler_to_vector(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static void def_geo_point_scale(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryPointScale", "storage"); - - prop = RNA_def_property(srna, "input_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float_vector); - RNA_def_property_ui_text(prop, "Input Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - -static void def_geo_point_translate(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryPointTranslate", "storage"); - - prop = RNA_def_property(srna, "input_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_object_info(StructRNA *srna) { PropertyRNA *prop; @@ -10555,37 +9693,6 @@ static void def_geo_object_info(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations"); } -static void def_geo_legacy_points_to_volume(StructRNA *srna) -{ - PropertyRNA *prop; - - static EnumPropertyItem resolution_mode_items[] = { - {GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT, - "VOXEL_AMOUNT", - 0, - "Amount", - "Specify the approximate number of voxels along the diagonal"}, - {GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE, - "VOXEL_SIZE", - 0, - "Size", - "Specify the voxel side length"}, - {0, NULL, 0, NULL, NULL}, - }; - - RNA_def_struct_sdna_from(srna, "NodeGeometryPointsToVolume", "storage"); - - prop = RNA_def_property(srna, "resolution_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, resolution_mode_items); - RNA_def_property_ui_text(prop, "Resolution Mode", "How the voxel size is specified"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_radius", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Radius Input Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_points_to_volume(StructRNA *srna) { PropertyRNA *prop; @@ -10639,39 +9746,6 @@ static void def_geo_collection_info(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations"); } -static void def_geo_legacy_attribute_proximity(StructRNA *srna) -{ - static const EnumPropertyItem target_geometry_element[] = { - {GEO_NODE_PROXIMITY_TARGET_POINTS, - "POINTS", - ICON_NONE, - "Points", - "Calculate proximity to the target's points (usually faster than the other two modes)"}, - {GEO_NODE_PROXIMITY_TARGET_EDGES, - "EDGES", - ICON_NONE, - "Edges", - "Calculate proximity to the target's edges"}, - {GEO_NODE_PROXIMITY_TARGET_FACES, - "FACES", - ICON_NONE, - "Faces", - "Calculate proximity to the target's faces"}, - {0, NULL, 0, NULL, NULL}, - }; - - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryAttributeProximity", "storage"); - - prop = RNA_def_property(srna, "target_geometry_element", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, target_geometry_element); - RNA_def_property_enum_default(prop, GEO_NODE_PROXIMITY_TARGET_FACES); - RNA_def_property_ui_text( - prop, "Target Geometry", "Element of the target geometry to calculate the distance from"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_proximity(StructRNA *srna) { static const EnumPropertyItem target_element_items[] = { @@ -10736,40 +9810,6 @@ static void def_geo_volume_to_mesh(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_attribute_combine_xyz(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeCombineXYZ", "storage"); - - prop = RNA_def_property(srna, "input_type_x", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type X", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_y", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type Y", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_z", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type Z", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - -static void def_geo_attribute_separate_xyz(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeAttributeSeparateXYZ", "storage"); - - prop = RNA_def_property(srna, "input_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_mesh_circle(StructRNA *srna) { PropertyRNA *prop; @@ -10936,18 +9976,6 @@ static void def_geo_curve_resample(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_legacy_curve_subdivide(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryCurveSubdivide", "storage"); - - prop = RNA_def_property(srna, "cuts_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_int); - RNA_def_property_ui_text(prop, "Cuts Type", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_curve_fillet(StructRNA *srna) { PropertyRNA *prop; @@ -10974,38 +10002,6 @@ static void def_geo_curve_fillet(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_legacy_curve_to_points(StructRNA *srna) -{ - PropertyRNA *prop; - - static EnumPropertyItem mode_items[] = { - {GEO_NODE_CURVE_RESAMPLE_EVALUATED, - "EVALUATED", - 0, - "Evaluated", - "Create points from the curve's evaluated points, based on the resolution attribute for " - "NURBS and Bezier splines"}, - {GEO_NODE_CURVE_RESAMPLE_COUNT, - "COUNT", - 0, - "Count", - "Sample each spline by evenly distributing the specified number of points"}, - {GEO_NODE_CURVE_RESAMPLE_LENGTH, - "LENGTH", - 0, - "Length", - "Sample each spline by splitting it into segments with the specified length"}, - {0, NULL, 0, NULL, NULL}, - }; - - RNA_def_struct_sdna_from(srna, "NodeGeometryCurveToPoints", "storage"); - - prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, mode_items); - RNA_def_property_ui_text(prop, "Mode", "How to generate points from the input curve"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_curve_to_points(StructRNA *srna) { PropertyRNA *prop; @@ -11100,40 +10096,6 @@ static void def_geo_curve_trim(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_attribute_transfer(StructRNA *srna) -{ - static EnumPropertyItem mapping_items[] = { - {GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED, - "NEAREST_FACE_INTERPOLATED", - 0, - "Nearest Face Interpolated", - "Transfer the attribute from the nearest face on a surface (loose points and edges are " - "ignored)"}, - {GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER_NEAREST, - "NEAREST", - 0, - "Nearest", - "Transfer the element from the nearest element (using face and edge centers for the " - "distance computation)"}, - {0, NULL, 0, NULL, NULL}, - }; - - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryAttributeTransfer", "storage"); - - prop = RNA_def_property(srna, "domain", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_attribute_domain_with_auto_items); - RNA_def_property_enum_default(prop, ATTR_DOMAIN_AUTO); - RNA_def_property_ui_text(prop, "Domain", "The geometry domain to save the result attribute in"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - - prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, mapping_items); - RNA_def_property_ui_text(prop, "Mapping", "Mapping between geometries"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -} - static void def_geo_transfer_attribute(StructRNA *srna) { static EnumPropertyItem mapping_items[] = { @@ -11194,42 +10156,6 @@ static void def_geo_input_material(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static void def_geo_legacy_raycast(StructRNA *srna) -{ - static EnumPropertyItem mapping_items[] = { - {GEO_NODE_RAYCAST_INTERPOLATED, - "INTERPOLATED", - 0, - "Interpolated", - "Interpolate the attribute from the corners of the hit face"}, - {GEO_NODE_RAYCAST_NEAREST, - "NEAREST", - 0, - "Nearest", - "Use the attribute value of the closest mesh element"}, - {0, NULL, 0, NULL, NULL}, - }; - - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometryRaycast", "storage"); - - prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, mapping_items); - RNA_def_property_ui_text(prop, "Mapping", "Mapping from the target geometry to hit points"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - - prop = RNA_def_property(srna, "input_type_ray_direction", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); - RNA_def_property_ui_text(prop, "Input Type Ray Direction", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); - - prop = RNA_def_property(srna, "input_type_ray_length", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); - RNA_def_property_ui_text(prop, "Input Type Ray Length", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_raycast(StructRNA *srna) { static EnumPropertyItem mapping_items[] = { @@ -11257,7 +10183,7 @@ static void def_geo_raycast(StructRNA *srna) prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeFill_type_itemf"); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeType_type_itemf"); RNA_def_property_enum_default(prop, CD_PROP_FLOAT); RNA_def_property_ui_text(prop, "Data Type", "Type of data stored in attribute"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update"); @@ -11289,7 +10215,7 @@ static void def_geo_store_named_attribute(StructRNA *srna) prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeFill_type_itemf"); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeType_type_itemf"); RNA_def_property_enum_default(prop, CD_PROP_FLOAT); RNA_def_property_ui_text(prop, "Data Type", "Type of data stored in attribute"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update"); @@ -11309,7 +10235,7 @@ static void def_geo_input_named_attribute(StructRNA *srna) prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeFill_type_itemf"); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeType_type_itemf"); RNA_def_property_enum_default(prop, CD_PROP_FLOAT); RNA_def_property_ui_text(prop, "Data Type", "The data type used to read the attribute values"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update"); @@ -11323,7 +10249,7 @@ static void def_geo_attribute_capture(StructRNA *srna) prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeFill_type_itemf"); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeType_type_itemf"); RNA_def_property_enum_default(prop, CD_PROP_FLOAT); RNA_def_property_ui_text(prop, "Data Type", "Type of data stored in attribute"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update"); @@ -11550,7 +10476,7 @@ static void def_geo_viewer(StructRNA *srna) prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeFill_type_itemf"); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeType_type_itemf"); RNA_def_property_enum_default(prop, CD_PROP_FLOAT); RNA_def_property_ui_text(prop, "Data Type", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update"); @@ -11580,7 +10506,7 @@ static void def_geo_field_at_index(StructRNA *srna) prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom2"); RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeFill_type_itemf"); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeType_type_itemf"); RNA_def_property_ui_text(prop, "Data Type", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update"); } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 7cf425c6e27..0b3d9a6a8ad 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -1607,29 +1607,17 @@ static void panel_draw(const bContext *C, Panel *panel) } /* Draw node warnings. */ - bool has_legacy_node = false; if (nmd->runtime_eval_log != nullptr) { const geo_log::ModifierLog &log = *static_cast<geo_log::ModifierLog *>(nmd->runtime_eval_log); log.foreach_node_log([&](const geo_log::NodeLog &node_log) { for (const geo_log::NodeWarning &warning : node_log.warnings()) { - if (warning.type == geo_log::NodeWarningType::Legacy) { - has_legacy_node = true; - } - else if (warning.type != geo_log::NodeWarningType::Info) { + if (warning.type != geo_log::NodeWarningType::Info) { uiItemL(layout, warning.message.c_str(), ICON_ERROR); } } }); } - if (has_legacy_node) { - uiLayout *row = uiLayoutRow(layout, false); - uiItemL(row, TIP_("Node tree has legacy node"), ICON_ERROR); - uiLayout *sub = uiLayoutRow(row, false); - uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT); - uiItemO(sub, "", ICON_VIEWZOOM, "NODE_OT_geometry_node_view_legacy"); - } - modifier_panel_end(layout, ptr); } diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index c4aa023faa6..3733b3f69ad 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -980,15 +980,11 @@ class GeometryNodesEvaluator { void execute_geometry_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state) { + using Clock = std::chrono::steady_clock; const bNode &bnode = *node->bnode(); NodeParamsProvider params_provider{*this, node, node_state, run_state}; GeoNodeExecParams params{params_provider}; - if (node->idname().find("Legacy") != StringRef::not_found) { - params.error_message_add(geo_log::NodeWarningType::Legacy, - TIP_("Legacy node will be removed before Blender 4.0")); - } - using Clock = std::chrono::steady_clock; Clock::time_point begin = Clock::now(); bnode.typeinfo->geometry_node_execute(params); Clock::time_point end = Clock::now(); @@ -1004,14 +1000,6 @@ class GeometryNodesEvaluator { NodeState &node_state, NodeTaskRunState *run_state) { - if (node->idname().find("Legacy") != StringRef::not_found) { - /* Create geometry nodes params just for creating an error message. */ - NodeParamsProvider params_provider{*this, node, node_state, run_state}; - GeoNodeExecParams params{params_provider}; - params.error_message_add(geo_log::NodeWarningType::Legacy, - TIP_("Legacy node will be removed before Blender 4.0")); - } - LinearAllocator<> &allocator = local_allocators_.local(); bool any_input_is_field = false; diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h index a33cdc1b64c..cde4b67e120 100644 --- a/source/blender/nodes/NOD_function.h +++ b/source/blender/nodes/NOD_function.h @@ -6,8 +6,6 @@ extern "C" { #endif -void register_node_type_fn_legacy_random_float(void); - void register_node_type_fn_align_euler_to_vector(void); void register_node_type_fn_boolean_math(void); void register_node_type_fn_compare(void); diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index be21dd4b88f..064112b7efd 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -15,45 +15,11 @@ void register_node_tree_type_geo(void); void register_node_type_geo_group(void); void register_node_type_geo_custom_group(bNodeType *ntype); -void register_node_type_geo_legacy_attribute_proximity(void); -void register_node_type_geo_legacy_attribute_randomize(void); -void register_node_type_geo_legacy_attribute_transfer(void); -void register_node_type_geo_legacy_curve_endpoints(void); -void register_node_type_geo_legacy_curve_reverse(void); -void register_node_type_geo_legacy_curve_set_handles(void); -void register_node_type_geo_legacy_curve_spline_type(void); -void register_node_type_geo_legacy_curve_subdivide(void); -void register_node_type_geo_legacy_curve_to_points(void); -void register_node_type_geo_legacy_delete_geometry(void); -void register_node_type_geo_legacy_edge_split(void); -void register_node_type_geo_legacy_material_assign(void); -void register_node_type_geo_legacy_mesh_to_curve(void); -void register_node_type_geo_legacy_points_to_volume(void); -void register_node_type_geo_legacy_raycast(void); -void register_node_type_geo_legacy_select_by_handle_type(void); -void register_node_type_geo_legacy_select_by_material(void); -void register_node_type_geo_legacy_subdivision_surface(void); -void register_node_type_geo_legacy_volume_to_mesh(void); - void register_node_type_geo_accumulate_field(void); -void register_node_type_geo_align_rotation_to_vector(void); void register_node_type_geo_attribute_capture(void); -void register_node_type_geo_attribute_clamp(void); -void register_node_type_geo_attribute_color_ramp(void); -void register_node_type_geo_attribute_combine_xyz(void); -void register_node_type_geo_attribute_compare(void); -void register_node_type_geo_attribute_convert(void); -void register_node_type_geo_attribute_curve_map(void); void register_node_type_geo_attribute_domain_size(void); -void register_node_type_geo_attribute_fill(void); -void register_node_type_geo_attribute_map_range(void); -void register_node_type_geo_attribute_math(void); -void register_node_type_geo_attribute_mix(void); -void register_node_type_geo_legacy_attribute_remove(void); void register_node_type_geo_attribute_separate_xyz(void); void register_node_type_geo_attribute_statistic(void); -void register_node_type_geo_attribute_vector_math(void); -void register_node_type_geo_attribute_vector_rotate(void); void register_node_type_geo_boolean(void); void register_node_type_geo_bounding_box(void); void register_node_type_geo_collection_info(void); @@ -134,12 +100,6 @@ void register_node_type_geo_mesh_subdivide(void); void register_node_type_geo_mesh_to_curve(void); void register_node_type_geo_mesh_to_points(void); void register_node_type_geo_object_info(void); -void register_node_type_geo_point_distribute(void); -void register_node_type_geo_point_instance(void); -void register_node_type_geo_point_rotate(void); -void register_node_type_geo_point_scale(void); -void register_node_type_geo_point_separate(void); -void register_node_type_geo_point_translate(void); void register_node_type_geo_points_to_vertices(void); void register_node_type_geo_points_to_volume(void); void register_node_type_geo_proximity(void); @@ -147,7 +107,6 @@ void register_node_type_geo_raycast(void); void register_node_type_geo_realize_instances(void); void register_node_type_geo_remove_attribute(void); void register_node_type_geo_rotate_instances(void); -void register_node_type_geo_sample_texture(void); void register_node_type_geo_scale_elements(void); void register_node_type_geo_scale_instances(void); void register_node_type_geo_select_by_handle_type(void); diff --git a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh index 7ef149d5dc5..113a7efb0a5 100644 --- a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh +++ b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh @@ -144,7 +144,6 @@ enum class NodeWarningType { Error, Warning, Info, - Legacy, }; struct NodeWarning { diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 97a6b8a6e63..0e1f181eff1 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -254,8 +254,6 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_NOISE, 0, "TEX_NO DefNode(TextureNode, TEX_NODE_PROC+TEX_STUCCI, 0, "TEX_STUCCI", TexStucci, "Stucci", "" ) DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DISTNOISE", TexDistNoise, "Distorted Noise", "" ) -DefNode(FunctionNode, FN_NODE_LEGACY_RANDOM_FLOAT, 0, "LEGACY_RANDOM_FLOAT", LegacyRandomFloat, "Random Float", "") - DefNode(FunctionNode, FN_NODE_ALIGN_EULER_TO_VECTOR, def_fn_align_euler_to_vector, "ALIGN_EULER_TO_VECTOR", AlignEulerToVector, "Align Euler To Vector", "") DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "") DefNode(FunctionNode, FN_NODE_COMPARE, def_compare, "COMPARE", Compare, "Compare", "") @@ -273,48 +271,6 @@ DefNode(FunctionNode, FN_NODE_SLICE_STRING, 0, "SLICE_STRING", SliceString, "Sli DefNode(FunctionNode, FN_NODE_STRING_LENGTH, 0, "STRING_LENGTH", StringLength, "String Length", "") DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ALIGN_ROTATION_TO_VECTOR, def_geo_align_rotation_to_vector, "LEGACY_ALIGN_ROTATION_TO_VECTOR", LegacyAlignRotationToVector, "Align Rotation to Vector", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_CLAMP, def_geo_attribute_clamp, "LEGACY_ATTRIBUTE_CLAMP", LegacyAttributeClamp, "Attribute Clamp", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_COLOR_RAMP, def_geo_attribute_color_ramp, "LEGACY_ATTRIBUTE_COLOR_RAMP", LegacyAttributeColorRamp, "Attribute Color Ramp", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_COMBINE_XYZ, def_geo_attribute_combine_xyz, "LEGACY_ATTRIBUTE_COMBINE_XYZ", LegacyAttributeCombineXYZ, "Attribute Combine XYZ", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_COMPARE, def_geo_attribute_attribute_compare, "LEGACY_ATTRIBUTE_COMPARE", LegacyAttributeCompare, "Attribute Compare", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_CONVERT, def_geo_attribute_convert, "LEGACY_ATTRIBUTE_CONVERT", LegacyAttributeConvert, "Attribute Convert", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_CURVE_MAP, def_geo_attribute_curve_map, "LEGACY_ATTRIBUTE_CURVE_MAP", LegacyAttributeCurveMap, "Attribute Curve Map", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_FILL, def_geo_attribute_fill, "LEGACY_ATTRIBUTE_FILL", LegacyAttributeFill, "Attribute Fill", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_MAP_RANGE, def_geo_attribute_map_range, "LEGACY_ATTRIBUTE_MAP_RANGE", LegacyAttributeMapRange, "Attribute Map Range", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_MATH, def_geo_attribute_math, "LEGACY_ATTRIBUTE_MATH", LegacyAttributeMath, "Attribute Math", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_MIX, def_geo_attribute_mix, "LEGACY_ATTRIBUTE_MIX", LegacyAttributeMix, "Attribute Mix", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_PROXIMITY, def_geo_legacy_attribute_proximity, "LEGACY_ATTRIBUTE_PROXIMITY", LegacyAttributeProximity, "Attribute Proximity", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_RANDOMIZE, def_geo_attribute_randomize, "LEGACY_ATTRIBUTE_RANDOMIZE", LegacyAttributeRandomize, "Attribute Randomize", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_REMOVE, 0, "LEGACY_ATTRIBUTE_REMOVE", LegacyAttributeRemove, "Attribute Remove", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_SAMPLE_TEXTURE, 0, "LEGACY_ATTRIBUTE_SAMPLE_TEXTURE", LegacyAttributeSampleTexture, "Attribute Sample Texture", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_SEPARATE_XYZ, def_geo_attribute_separate_xyz, "LEGACY_ATTRIBUTE_SEPARATE_XYZ", LegacyAttributeSeparateXYZ, "Attribute Separate XYZ", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER, def_geo_attribute_transfer, "LEGACY_ATTRIBUTE_TRANSFER", LegacyAttributeTransfer, "Attribute Transfer", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_VECTOR_MATH, def_geo_attribute_vector_math, "LEGACY_ATTRIBUTE_VECTOR_MATH", LegacyAttributeVectorMath, "Attribute Vector Math", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_VECTOR_ROTATE, def_geo_attribute_vector_rotate, "LEGACY_ATTRIBUTE_VECTOR_ROTATE", LegacyAttributeVectorRotate, "Attribute Vector Rotate", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_CURVE_ENDPOINTS, 0, "LEGACY_CURVE_ENDPOINTS", LegacyCurveEndpoints, "Curve Endpoints", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_CURVE_REVERSE, 0, "LEGACY_CURVE_REVERSE", LegacyCurveReverse, "Curve Reverse", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_CURVE_SELECT_HANDLES, def_geo_curve_select_handles, "LEGACY_CURVE_SELECT_HANDLES", LegacyCurveSelectHandles, "Select by Handle Type", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_CURVE_SET_HANDLES, def_geo_legacy_curve_set_handles, "LEGACY_CURVE_SET_HANDLES", LegacyCurveSetHandles, "Set Handle Type", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_CURVE_SPLINE_TYPE, def_geo_curve_spline_type, "LEGACY_CURVE_SPLINE_TYPE", LegacyCurveSplineType, "Set Spline Type", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_CURVE_SUBDIVIDE, def_geo_legacy_curve_subdivide, "LEGACY_CURVE_SUBDIVIDE", LegacyCurveSubdivide, "Curve Subdivide", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_CURVE_TO_POINTS, def_geo_legacy_curve_to_points, "LEGACY_CURVE_TO_POINTS", LegacyCurveToPoints, "Curve to Points", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_DELETE_GEOMETRY, 0, "LEGACY_DELETE_GEOMETRY", LegacyDeleteGeometry, "Delete Geometry", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_EDGE_SPLIT, 0, "LEGACY_EDGE_SPLIT", LegacyEdgeSplit, "Edge Split", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_MATERIAL_ASSIGN, 0, "LEGACY_MATERIAL_ASSIGN", LegacyMaterialAssign, "Material Assign", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_MESH_TO_CURVE, 0, "LEGACY_MESH_TO_CURVE", LegacyMeshToCurve, "Mesh to Curve", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_POINT_DISTRIBUTE, def_geo_point_distribute, "LEGACY_POINT_DISTRIBUTE", LegacyPointDistribute, "Point Distribute", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_POINT_INSTANCE, def_geo_point_instance, "LEGACY_POINT_INSTANCE", LegacyPointInstance, "Point Instance", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_POINT_ROTATE, def_geo_point_rotate, "LEGACY_POINT_ROTATE", LegacyRotatePoints, "Point Rotate", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_POINT_SCALE, def_geo_point_scale, "LEGACY_POINT_SCALE", LegacyPointScale, "Point Scale", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_POINT_SEPARATE, 0, "LEGACY_POINT_SEPARATE", LegacyPointSeparate, "Point Separate", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_POINT_TRANSLATE, def_geo_point_translate, "LEGACY_POINT_TRANSLATE", LegacyPointTranslate, "Point Translate", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_POINTS_TO_VOLUME, def_geo_legacy_points_to_volume, "LEGACY_POINTS_TO_VOLUME", LegacyPointsToVolume, "Points to Volume", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_RAYCAST, def_geo_legacy_raycast, "LEGACY_RAYCAST", LegacyRaycast, "Raycast", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_SELECT_BY_MATERIAL, 0, "LEGACY_SELECT_BY_MATERIAL", LegacySelectByMaterial, "Select by Material", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_SUBDIVISION_SURFACE, def_geo_subdivision_surface, "LEGACY_SUBDIVISION_SURFACE", LegacySubdivisionSurface, "Subdivision Surface", "") -DefNode(GeometryNode, GEO_NODE_LEGACY_VOLUME_TO_MESH, def_geo_volume_to_mesh, "LEGACY_VOLUME_TO_MESH", LegacyVolumeToMesh, "Volume to Mesh", "") - DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_DOMAIN_SIZE, def_geo_attribute_domain_size, "ATTRIBUTE_DOMAIN_SIZE", AttributeDomainSize, "Domain Size", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_STATISTIC, def_geo_attribute_statistic, "ATTRIBUTE_STATISTIC", AttributeStatistic, "Attribute Statistic", "") DefNode(GeometryNode, GEO_NODE_BOUNDING_BOX, 0, "BOUNDING_BOX", BoundBox, "Bounding Box", "") diff --git a/source/blender/nodes/function/CMakeLists.txt b/source/blender/nodes/function/CMakeLists.txt index 7ffc5c71b66..6ccc4c7bf5c 100644 --- a/source/blender/nodes/function/CMakeLists.txt +++ b/source/blender/nodes/function/CMakeLists.txt @@ -18,8 +18,6 @@ set(INC set(SRC - nodes/legacy/node_fn_random_float.cc - nodes/node_fn_align_euler_to_vector.cc nodes/node_fn_boolean_math.cc nodes/node_fn_compare.cc diff --git a/source/blender/nodes/function/nodes/legacy/node_fn_random_float.cc b/source/blender/nodes/function/nodes/legacy/node_fn_random_float.cc deleted file mode 100644 index a34cfe578d0..00000000000 --- a/source/blender/nodes/function/nodes/legacy/node_fn_random_float.cc +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "node_function_util.hh" - -#include "BLI_hash.h" - -namespace blender::nodes::node_fn_random_float_cc { - -static void fn_node_legacy_random_float_declare(NodeDeclarationBuilder &b) -{ - b.is_function_node(); - b.add_input<decl::Float>(N_("Min")).min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>(N_("Max")).default_value(1.0f).min(-10000.0f).max(10000.0f); - b.add_input<decl::Int>(N_("Seed")).min(-10000).max(10000); - b.add_output<decl::Float>(N_("Value")); -} - -class RandomFloatFunction : public blender::fn::MultiFunction { - public: - RandomFloatFunction() - { - static blender::fn::MFSignature signature = create_signature(); - this->set_signature(&signature); - } - - static blender::fn::MFSignature create_signature() - { - blender::fn::MFSignatureBuilder signature{"Random float"}; - signature.single_input<float>("Min"); - signature.single_input<float>("Max"); - signature.single_input<int>("Seed"); - signature.single_output<float>("Value"); - return signature.build(); - } - - void call(blender::IndexMask mask, - blender::fn::MFParams params, - blender::fn::MFContext UNUSED(context)) const override - { - const blender::VArray<float> &min_values = params.readonly_single_input<float>(0, "Min"); - const blender::VArray<float> &max_values = params.readonly_single_input<float>(1, "Max"); - const blender::VArray<int> &seeds = params.readonly_single_input<int>(2, "Seed"); - blender::MutableSpan<float> values = params.uninitialized_single_output<float>(3, "Value"); - - for (int64_t i : mask) { - const float min_value = min_values[i]; - const float max_value = max_values[i]; - const int seed = seeds[i]; - const float value = BLI_hash_int_01(static_cast<uint32_t>(seed)); - values[i] = value * (max_value - min_value) + min_value; - } - } -}; - -static void fn_node_legacy_random_float_build_multi_function( - blender::nodes::NodeMultiFunctionBuilder &builder) -{ - static RandomFloatFunction fn; - builder.set_matching_fn(fn); -} - -} // namespace blender::nodes::node_fn_random_float_cc - -void register_node_type_fn_legacy_random_float() -{ - namespace file_ns = blender::nodes::node_fn_random_float_cc; - - static bNodeType ntype; - - fn_node_type_base(&ntype, FN_NODE_LEGACY_RANDOM_FLOAT, "Random Float", 0); - ntype.declare = file_ns::fn_node_legacy_random_float_declare; - ntype.build_multi_function = file_ns::fn_node_legacy_random_float_build_multi_function; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 0e99d8ad646..3e6d7c6b408 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -25,48 +25,6 @@ set(INC set(SRC - nodes/legacy/node_geo_legacy_align_rotation_to_vector.cc - nodes/legacy/node_geo_legacy_attribute_clamp.cc - nodes/legacy/node_geo_legacy_attribute_color_ramp.cc - nodes/legacy/node_geo_legacy_attribute_combine_xyz.cc - nodes/legacy/node_geo_legacy_attribute_compare.cc - nodes/legacy/node_geo_legacy_attribute_convert.cc - nodes/legacy/node_geo_legacy_attribute_curve_map.cc - nodes/legacy/node_geo_legacy_attribute_fill.cc - nodes/legacy/node_geo_legacy_attribute_map_range.cc - nodes/legacy/node_geo_legacy_attribute_math.cc - nodes/legacy/node_geo_legacy_attribute_mix.cc - nodes/legacy/node_geo_legacy_attribute_proximity.cc - nodes/legacy/node_geo_legacy_attribute_randomize.cc - nodes/legacy/node_geo_legacy_attribute_remove.cc - nodes/legacy/node_geo_legacy_attribute_sample_texture.cc - nodes/legacy/node_geo_legacy_attribute_separate_xyz.cc - nodes/legacy/node_geo_legacy_attribute_transfer.cc - nodes/legacy/node_geo_legacy_attribute_vector_math.cc - nodes/legacy/node_geo_legacy_attribute_vector_rotate.cc - nodes/legacy/node_geo_legacy_curve_endpoints.cc - nodes/legacy/node_geo_legacy_curve_reverse.cc - nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc - nodes/legacy/node_geo_legacy_curve_set_handles.cc - nodes/legacy/node_geo_legacy_curve_spline_type.cc - nodes/legacy/node_geo_legacy_curve_subdivide.cc - nodes/legacy/node_geo_legacy_curve_to_points.cc - nodes/legacy/node_geo_legacy_delete_geometry.cc - nodes/legacy/node_geo_legacy_edge_split.cc - nodes/legacy/node_geo_legacy_material_assign.cc - nodes/legacy/node_geo_legacy_mesh_to_curve.cc - nodes/legacy/node_geo_legacy_point_distribute.cc - nodes/legacy/node_geo_legacy_point_instance.cc - nodes/legacy/node_geo_legacy_point_rotate.cc - nodes/legacy/node_geo_legacy_point_scale.cc - nodes/legacy/node_geo_legacy_point_separate.cc - nodes/legacy/node_geo_legacy_point_translate.cc - nodes/legacy/node_geo_legacy_points_to_volume.cc - nodes/legacy/node_geo_legacy_raycast.cc - nodes/legacy/node_geo_legacy_select_by_material.cc - nodes/legacy/node_geo_legacy_subdivision_surface.cc - nodes/legacy/node_geo_legacy_volume_to_mesh.cc - nodes/node_geo_accumulate_field.cc nodes/node_geo_attribute_capture.cc nodes/node_geo_attribute_domain_size.cc diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc index fc1c73d2851..7f9ec329efd 100644 --- a/source/blender/nodes/geometry/node_geometry_util.cc +++ b/source/blender/nodes/geometry/node_geometry_util.cc @@ -14,29 +14,6 @@ namespace blender::nodes { -using bke::GeometryInstanceGroup; - -void update_attribute_input_socket_availabilities(bNodeTree &ntree, - bNode &node, - const StringRef name, - const GeometryNodeAttributeInputMode mode, - const bool name_is_available) -{ - const GeometryNodeAttributeInputMode mode_ = (GeometryNodeAttributeInputMode)mode; - LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { - if (name == socket->name) { - const bool socket_is_available = - name_is_available && - ((socket->type == SOCK_STRING && mode_ == GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE) || - (socket->type == SOCK_FLOAT && mode_ == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) || - (socket->type == SOCK_INT && mode_ == GEO_NODE_ATTRIBUTE_INPUT_INTEGER) || - (socket->type == SOCK_VECTOR && mode_ == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) || - (socket->type == SOCK_RGBA && mode_ == GEO_NODE_ATTRIBUTE_INPUT_COLOR)); - nodeSetSocketAvailability(&ntree, socket, socket_is_available); - } - } -} - std::optional<CustomDataType> node_data_type_to_custom_data_type(const eNodeSocketDatatype type) { switch (type) { diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 101613acc21..5b7211e44b4 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -28,21 +28,6 @@ bool geo_node_poll_default(struct bNodeType *ntype, const char **r_disabled_hint); namespace blender::nodes { -/** - * Update the availability of a group of input sockets with the same name, - * used for switching between attribute inputs or single values. - * - * \param mode: Controls which socket of the group to make available. - * \param name_is_available: If false, make all sockets with this name unavailable. - */ -void update_attribute_input_socket_availabilities(bNodeTree &ntree, - bNode &node, - const StringRef name, - GeometryNodeAttributeInputMode mode, - bool name_is_available = true); - -Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &component, - AttributeDomain domain); void transform_mesh(Mesh &mesh, const float3 translation, @@ -93,28 +78,6 @@ void separate_geometry(GeometrySet &geometry_set, bool invert, bool &r_is_error); -struct CurveToPointsResults { - int result_size; - MutableSpan<float3> positions; - MutableSpan<float> radii; - MutableSpan<float> tilts; - - Map<AttributeIDRef, GMutableSpan> point_attributes; - - MutableSpan<float3> tangents; - MutableSpan<float3> normals; - MutableSpan<float3> rotations; -}; -/** - * Create references for all result point cloud attributes to simplify accessing them later on. - */ -CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points, - const CurveEval &curve); - -void curve_create_default_rotation_attribute(Span<float3> tangents, - Span<float3> normals, - MutableSpan<float3> rotations); - std::optional<CustomDataType> node_data_type_to_custom_data_type(eNodeSocketDatatype type); std::optional<CustomDataType> node_socket_to_custom_data_type(const bNodeSocket &socket); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_align_rotation_to_vector.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_align_rotation_to_vector.cc deleted file mode 100644 index eefcfcb2880..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_align_rotation_to_vector.cc +++ /dev/null @@ -1,228 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_math_rotation.h" -#include "BLI_task.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_align_rotation_to_vector_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Factor")); - b.add_input<decl::Float>(N_("Factor"), "Factor_001") - .default_value(1.0f) - .min(0.0f) - .max(1.0f) - .subtype(PROP_FACTOR); - b.add_input<decl::String>(N_("Vector")); - b.add_input<decl::Vector>(N_("Vector"), "Vector_001") - .default_value({0.0, 0.0, 1.0}) - .subtype(PROP_ANGLE); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "axis", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "pivot_axis", 0, IFACE_("Pivot"), ICON_NONE); - uiLayout *col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "input_type_factor", 0, IFACE_("Factor"), ICON_NONE); - uiItemR(col, ptr, "input_type_vector", 0, IFACE_("Vector"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeGeometryAlignRotationToVector *node_storage = MEM_cnew<NodeGeometryAlignRotationToVector>( - __func__); - - node_storage->axis = GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_X; - node_storage->input_type_factor = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - node_storage->input_type_vector = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - - node->storage = node_storage; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeGeometryAlignRotationToVector *node_storage = (NodeGeometryAlignRotationToVector *) - node->storage; - update_attribute_input_socket_availabilities( - *ntree, *node, "Factor", (GeometryNodeAttributeInputMode)node_storage->input_type_factor); - update_attribute_input_socket_availabilities( - *ntree, *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type_vector); -} - -static void align_rotations_auto_pivot(const VArray<float3> &vectors, - const VArray<float> &factors, - const float3 local_main_axis, - const MutableSpan<float3> rotations) -{ - threading::parallel_for(IndexRange(vectors.size()), 128, [&](IndexRange range) { - for (const int i : range) { - const float3 vector = vectors[i]; - if (is_zero_v3(vector)) { - continue; - } - - float old_rotation[3][3]; - eul_to_mat3(old_rotation, rotations[i]); - float3 old_axis; - mul_v3_m3v3(old_axis, old_rotation, local_main_axis); - - const float3 new_axis = math::normalize(vector); - float3 rotation_axis = math::cross_high_precision(old_axis, new_axis); - if (is_zero_v3(rotation_axis)) { - /* The vectors are linearly dependent, so we fall back to another axis. */ - rotation_axis = math::cross_high_precision(old_axis, float3(1, 0, 0)); - if (is_zero_v3(rotation_axis)) { - /* This is now guaranteed to not be zero. */ - rotation_axis = math::cross_high_precision(old_axis, float3(0, 1, 0)); - } - } - - const float full_angle = angle_normalized_v3v3(old_axis, new_axis); - const float angle = factors[i] * full_angle; - - float rotation[3][3]; - axis_angle_to_mat3(rotation, rotation_axis, angle); - - float new_rotation_matrix[3][3]; - mul_m3_m3m3(new_rotation_matrix, rotation, old_rotation); - - float3 new_rotation; - mat3_to_eul(new_rotation, new_rotation_matrix); - - rotations[i] = new_rotation; - } - }); -} - -static void align_rotations_fixed_pivot(const VArray<float3> &vectors, - const VArray<float> &factors, - const float3 local_main_axis, - const float3 local_pivot_axis, - const MutableSpan<float3> rotations) -{ - if (local_main_axis == local_pivot_axis) { - /* Can't compute any meaningful rotation angle in this case. */ - return; - } - - threading::parallel_for(IndexRange(vectors.size()), 128, [&](IndexRange range) { - for (const int i : range) { - const float3 vector = vectors[i]; - if (is_zero_v3(vector)) { - continue; - } - - float old_rotation[3][3]; - eul_to_mat3(old_rotation, rotations[i]); - float3 old_axis; - mul_v3_m3v3(old_axis, old_rotation, local_main_axis); - float3 pivot_axis; - mul_v3_m3v3(pivot_axis, old_rotation, local_pivot_axis); - - float full_angle = angle_signed_on_axis_v3v3_v3(vector, old_axis, pivot_axis); - if (full_angle > M_PI) { - /* Make sure the point is rotated as little as possible. */ - full_angle -= 2.0f * M_PI; - } - const float angle = factors[i] * full_angle; - - float rotation[3][3]; - axis_angle_to_mat3(rotation, pivot_axis, angle); - - float new_rotation_matrix[3][3]; - mul_m3_m3m3(new_rotation_matrix, rotation, old_rotation); - - float3 new_rotation; - mat3_to_eul(new_rotation, new_rotation_matrix); - - rotations[i] = new_rotation; - } - }); -} - -static void align_rotations_on_component(GeometryComponent &component, - const GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - const NodeGeometryAlignRotationToVector &storage = *(const NodeGeometryAlignRotationToVector *) - node.storage; - - OutputAttribute_Typed<float3> rotations = component.attribute_try_get_for_output<float3>( - "rotation", ATTR_DOMAIN_POINT, {0, 0, 0}); - if (!rotations) { - return; - } - - VArray<float> factors = params.get_input_attribute<float>( - "Factor", component, ATTR_DOMAIN_POINT, 1.0f); - VArray<float3> vectors = params.get_input_attribute<float3>( - "Vector", component, ATTR_DOMAIN_POINT, {0, 0, 1}); - - float3 local_main_axis{0, 0, 0}; - local_main_axis[storage.axis] = 1; - if (storage.pivot_axis == GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_AUTO) { - align_rotations_auto_pivot(vectors, factors, local_main_axis, rotations.as_span()); - } - else { - float3 local_pivot_axis{0, 0, 0}; - local_pivot_axis[storage.pivot_axis - 1] = 1; - align_rotations_fixed_pivot( - vectors, factors, local_main_axis, local_pivot_axis, rotations.as_span()); - } - - rotations.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - align_rotations_on_component(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - align_rotations_on_component(geometry_set.get_component_for_write<PointCloudComponent>(), - params); - } - if (geometry_set.has<CurveComponent>()) { - align_rotations_on_component(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_align_rotation_to_vector_cc - -void register_node_type_geo_align_rotation_to_vector() -{ - namespace file_ns = blender::nodes::node_geo_legacy_align_rotation_to_vector_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, - GEO_NODE_LEGACY_ALIGN_ROTATION_TO_VECTOR, - "Align Rotation to Vector", - NODE_CLASS_GEOMETRY); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - node_type_storage(&ntype, - "NodeGeometryAlignRotationToVector", - node_free_standard_storage, - node_copy_standard_storage); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_clamp.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_clamp.cc deleted file mode 100644 index 71cc2332c78..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_clamp.cc +++ /dev/null @@ -1,267 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_clamp_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Attribute")); - b.add_input<decl::String>(N_("Result")); - b.add_input<decl::Vector>(N_("Min")); - b.add_input<decl::Vector>(N_("Max")).default_value({1.0f, 1.0f, 1.0f}); - b.add_input<decl::Float>(N_("Min"), "Min_001"); - b.add_input<decl::Float>(N_("Max"), "Max_001").default_value(1.0f); - b.add_input<decl::Int>(N_("Min"), "Min_002").min(-100000).max(100000); - b.add_input<decl::Int>(N_("Max"), "Max_002").default_value(100).min(-100000).max(100000); - b.add_input<decl::Color>(N_("Min"), "Min_003").default_value({0.5f, 0.5f, 0.5f, 1.0f}); - b.add_input<decl::Color>(N_("Max"), "Max_003").default_value({0.5f, 0.5f, 0.5f, 1.0f}); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeAttributeClamp *data = MEM_cnew<NodeAttributeClamp>(__func__); - data->data_type = CD_PROP_FLOAT; - data->operation = NODE_CLAMP_MINMAX; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - bNodeSocket *sock_min_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 3); - bNodeSocket *sock_max_vector = sock_min_vector->next; - bNodeSocket *sock_min_float = sock_max_vector->next; - bNodeSocket *sock_max_float = sock_min_float->next; - bNodeSocket *sock_min_int = sock_max_float->next; - bNodeSocket *sock_max_int = sock_min_int->next; - bNodeSocket *sock_min_color = sock_max_int->next; - bNodeSocket *sock_max_color = sock_min_color->next; - - const NodeAttributeClamp &storage = *(const NodeAttributeClamp *)node->storage; - const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type); - nodeSetSocketAvailability(ntree, sock_min_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, sock_max_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, sock_min_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, sock_max_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, sock_min_int, data_type == CD_PROP_INT32); - nodeSetSocketAvailability(ntree, sock_max_int, data_type == CD_PROP_INT32); - nodeSetSocketAvailability(ntree, sock_min_color, data_type == CD_PROP_COLOR); - nodeSetSocketAvailability(ntree, sock_max_color, data_type == CD_PROP_COLOR); -} - -template<typename T> T clamp_value(const T val, const T min, const T max); - -template<> inline float clamp_value(const float val, const float min, const float max) -{ - return std::min(std::max(val, min), max); -} - -template<> inline int clamp_value(const int val, const int min, const int max) -{ - return std::min(std::max(val, min), max); -} - -template<> inline float3 clamp_value(const float3 val, const float3 min, const float3 max) -{ - float3 tmp; - tmp.x = std::min(std::max(val.x, min.x), max.x); - tmp.y = std::min(std::max(val.y, min.y), max.y); - tmp.z = std::min(std::max(val.z, min.z), max.z); - return tmp; -} - -template<> -inline ColorGeometry4f clamp_value(const ColorGeometry4f val, - const ColorGeometry4f min, - const ColorGeometry4f max) -{ - ColorGeometry4f tmp; - tmp.r = std::min(std::max(val.r, min.r), max.r); - tmp.g = std::min(std::max(val.g, min.g), max.g); - tmp.b = std::min(std::max(val.b, min.b), max.b); - tmp.a = std::min(std::max(val.a, min.a), max.a); - return tmp; -} - -template<typename T> -static void clamp_attribute(const VArray<T> &inputs, - const MutableSpan<T> outputs, - const T min, - const T max) -{ - for (const int i : IndexRange(outputs.size())) { - outputs[i] = clamp_value<T>(inputs[i], min, max); - } -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - StringRef source_name, - StringRef result_name) -{ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - std::optional<AttributeMetaData> source_info = component.attribute_get_meta_data(source_name); - if (source_info) { - return source_info->domain; - } - return ATTR_DOMAIN_POINT; -} - -static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParams ¶ms) -{ - const std::string attribute_name = params.get_input<std::string>("Attribute"); - const std::string result_name = params.get_input<std::string>("Result"); - - if (attribute_name.empty() || result_name.empty()) { - return; - } - - if (!component.attribute_exists(attribute_name)) { - params.error_message_add(NodeWarningType::Error, - TIP_("No attribute with name \"") + attribute_name + "\""); - return; - } - - const NodeAttributeClamp &storage = *(const NodeAttributeClamp *)params.node().storage; - const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type); - const AttributeDomain domain = get_result_domain(component, attribute_name, result_name); - const int operation = static_cast<int>(storage.operation); - - GVArray attribute_input = component.attribute_try_get_for_read( - attribute_name, domain, data_type); - - OutputAttribute attribute_result = component.attribute_try_get_for_output_only( - result_name, domain, data_type); - - if (!attribute_result) { - params.error_message_add(NodeWarningType::Error, - TIP_("Could not find or create attribute with name \"") + - result_name + "\""); - return; - } - - switch (data_type) { - case CD_PROP_FLOAT3: { - float3 min = params.get_input<float3>("Min"); - float3 max = params.get_input<float3>("Max"); - if (operation == NODE_CLAMP_RANGE) { - if (min.x > max.x) { - std::swap(min.x, max.x); - } - if (min.y > max.y) { - std::swap(min.y, max.y); - } - if (min.z > max.z) { - std::swap(min.z, max.z); - } - } - MutableSpan<float3> results = attribute_result.as_span<float3>(); - clamp_attribute<float3>(attribute_input.typed<float3>(), results, min, max); - break; - } - case CD_PROP_FLOAT: { - const float min = params.get_input<float>("Min_001"); - const float max = params.get_input<float>("Max_001"); - MutableSpan<float> results = attribute_result.as_span<float>(); - if (operation == NODE_CLAMP_RANGE && min > max) { - clamp_attribute<float>(attribute_input.typed<float>(), results, max, min); - } - else { - clamp_attribute<float>(attribute_input.typed<float>(), results, min, max); - } - break; - } - case CD_PROP_INT32: { - const int min = params.get_input<int>("Min_002"); - const int max = params.get_input<int>("Max_002"); - MutableSpan<int> results = attribute_result.as_span<int>(); - if (operation == NODE_CLAMP_RANGE && min > max) { - clamp_attribute<int>(attribute_input.typed<int>(), results, max, min); - } - else { - clamp_attribute<int>(attribute_input.typed<int>(), results, min, max); - } - break; - } - case CD_PROP_COLOR: { - ColorGeometry4f min = params.get_input<ColorGeometry4f>("Min_003"); - ColorGeometry4f max = params.get_input<ColorGeometry4f>("Max_003"); - if (operation == NODE_CLAMP_RANGE) { - if (min.r > max.r) { - std::swap(min.r, max.r); - } - if (min.g > max.g) { - std::swap(min.g, max.g); - } - if (min.b > max.b) { - std::swap(min.b, max.b); - } - if (min.a > max.a) { - std::swap(min.a, max.a); - } - } - MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>(); - clamp_attribute<ColorGeometry4f>( - attribute_input.typed<ColorGeometry4f>(), results, min, max); - break; - } - default: { - BLI_assert(false); - break; - } - } - - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - clamp_attribute(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - clamp_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - clamp_attribute(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_clamp_cc - -void register_node_type_geo_attribute_clamp() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_clamp_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_CLAMP, "Attribute Clamp", NODE_CLASS_ATTRIBUTE); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - node_type_storage( - &ntype, "NodeAttributeClamp", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_color_ramp.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_color_ramp.cc deleted file mode 100644 index 5a5cadaea12..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_color_ramp.cc +++ /dev/null @@ -1,123 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_task.hh" - -#include "BKE_colorband.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_color_ramp_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Attribute")); - b.add_input<decl::String>(N_("Result")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiTemplateColorRamp(layout, ptr, "color_ramp", false); -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeAttributeColorRamp *node_storage = MEM_cnew<NodeAttributeColorRamp>(__func__); - BKE_colorband_init(&node_storage->color_ramp, true); - node->storage = node_storage; -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - StringRef input_name, - StringRef result_name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - - /* Otherwise use the input attribute's domain if it exists. */ - std::optional<AttributeMetaData> source_info = component.attribute_get_meta_data(input_name); - if (source_info) { - return source_info->domain; - } - - return ATTR_DOMAIN_POINT; -} - -static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryComponent &component) -{ - const bNode &bnode = params.node(); - NodeAttributeColorRamp *node_storage = (NodeAttributeColorRamp *)bnode.storage; - const std::string result_name = params.get_input<std::string>("Result"); - const std::string input_name = params.get_input<std::string>("Attribute"); - - /* Always output a color attribute for now. We might want to allow users to customize. - * Using the type of an existing attribute could work, but does not have a real benefit - * currently. */ - const AttributeDomain result_domain = get_result_domain(component, input_name, result_name); - - OutputAttribute_Typed<ColorGeometry4f> attribute_result = - component.attribute_try_get_for_output_only<ColorGeometry4f>(result_name, result_domain); - if (!attribute_result) { - return; - } - - VArray<float> attribute_in = component.attribute_get_for_read<float>( - input_name, result_domain, 0.0f); - - MutableSpan<ColorGeometry4f> results = attribute_result.as_span(); - - ColorBand *color_ramp = &node_storage->color_ramp; - threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) { - for (const int i : range) { - BKE_colorband_evaluate(color_ramp, attribute_in[i], results[i]); - } - }); - - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<MeshComponent>()); - } - if (geometry_set.has<PointCloudComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<PointCloudComponent>()); - } - if (geometry_set.has<CurveComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<CurveComponent>()); - } - - params.set_output("Geometry", std::move(geometry_set)); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_color_ramp_cc - -void register_node_type_geo_attribute_color_ramp() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_color_ramp_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_COLOR_RAMP, "Attribute Color Ramp", NODE_CLASS_ATTRIBUTE); - node_type_storage( - &ntype, "NodeAttributeColorRamp", node_free_standard_storage, node_copy_standard_storage); - node_type_init(&ntype, file_ns::node_init); - node_type_size_preset(&ntype, NODE_SIZE_LARGE); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_combine_xyz.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_combine_xyz.cc deleted file mode 100644 index ec6c65aa8bc..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_combine_xyz.cc +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_combine_xyz_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("X")); - b.add_input<decl::Float>(N_("X"), "X_001"); - b.add_input<decl::String>(N_("Y")); - b.add_input<decl::Float>(N_("Y"), "Y_001"); - b.add_input<decl::String>(N_("Z")); - b.add_input<decl::Float>(N_("Z"), "Z_001"); - b.add_input<decl::String>(N_("Result")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiLayout *col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "input_type_x", 0, IFACE_("X"), ICON_NONE); - uiItemR(col, ptr, "input_type_y", 0, IFACE_("Y"), ICON_NONE); - uiItemR(col, ptr, "input_type_z", 0, IFACE_("Z"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeAttributeCombineXYZ *data = MEM_cnew<NodeAttributeCombineXYZ>(__func__); - - data->input_type_x = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - data->input_type_y = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - data->input_type_z = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeAttributeCombineXYZ *node_storage = (NodeAttributeCombineXYZ *)node->storage; - update_attribute_input_socket_availabilities( - *ntree, *node, "X", (GeometryNodeAttributeInputMode)node_storage->input_type_x); - update_attribute_input_socket_availabilities( - *ntree, *node, "Y", (GeometryNodeAttributeInputMode)node_storage->input_type_y); - update_attribute_input_socket_availabilities( - *ntree, *node, "Z", (GeometryNodeAttributeInputMode)node_storage->input_type_z); -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - const GeoNodeExecParams ¶ms, - StringRef result_name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - - /* Otherwise use the highest priority domain from existing input attributes, or the default. */ - return params.get_highest_priority_input_domain({"X", "Y", "Z"}, component, ATTR_DOMAIN_POINT); -} - -static void combine_attributes(GeometryComponent &component, const GeoNodeExecParams ¶ms) -{ - const std::string result_name = params.get_input<std::string>("Result"); - if (result_name.empty()) { - return; - } - const AttributeDomain result_domain = get_result_domain(component, params, result_name); - - OutputAttribute_Typed<float3> attribute_result = - component.attribute_try_get_for_output_only<float3>(result_name, result_domain); - if (!attribute_result) { - return; - } - VArray<float> attribute_x = params.get_input_attribute<float>( - "X", component, result_domain, 0.0f); - VArray<float> attribute_y = params.get_input_attribute<float>( - "Y", component, result_domain, 0.0f); - VArray<float> attribute_z = params.get_input_attribute<float>( - "Z", component, result_domain, 0.0f); - - for (const int i : IndexRange(attribute_result->size())) { - const float x = attribute_x[i]; - const float y = attribute_y[i]; - const float z = attribute_z[i]; - attribute_result->set(i, {x, y, z}); - } - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - combine_attributes(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - combine_attributes(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - combine_attributes(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_combine_xyz_cc - -void register_node_type_geo_attribute_combine_xyz() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_combine_xyz_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, - GEO_NODE_LEGACY_ATTRIBUTE_COMBINE_XYZ, - "Attribute Combine XYZ", - NODE_CLASS_ATTRIBUTE); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - node_type_storage( - &ntype, "NodeAttributeCombineXYZ", node_free_standard_storage, node_copy_standard_storage); - - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_compare.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_compare.cc deleted file mode 100644 index 2136a07e58e..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_compare.cc +++ /dev/null @@ -1,345 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "NOD_math_functions.hh" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_compare_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("A")); - b.add_input<decl::Float>(N_("A"), "A_001"); - b.add_input<decl::Vector>(N_("A"), "A_002"); - b.add_input<decl::Color>(N_("A"), "A_003").default_value({0.5, 0.5, 0.5, 1.0}); - b.add_input<decl::String>(N_("B")); - b.add_input<decl::Float>(N_("B"), "B_001"); - b.add_input<decl::Vector>(N_("B"), "B_002"); - b.add_input<decl::Color>(N_("B"), "B_003").default_value({0.5, 0.5, 0.5, 1.0}); - b.add_input<decl::Float>(N_("Threshold")).default_value(0.01f).min(0.0f); - b.add_input<decl::String>(N_("Result")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "input_type_a", 0, IFACE_("A"), ICON_NONE); - uiItemR(layout, ptr, "input_type_b", 0, IFACE_("B"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeAttributeCompare *data = MEM_cnew<NodeAttributeCompare>(__func__); - data->operation = NODE_COMPARE_GREATER_THAN; - data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - node->storage = data; -} - -static bool operation_tests_equality(const NodeAttributeCompare &node_storage) -{ - return ELEM(node_storage.operation, NODE_COMPARE_EQUAL, NODE_COMPARE_NOT_EQUAL); -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeAttributeCompare *node_storage = (NodeAttributeCompare *)node->storage; - update_attribute_input_socket_availabilities( - *ntree, *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a); - update_attribute_input_socket_availabilities( - *ntree, *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b); - - bNodeSocket *socket_threshold = (bNodeSocket *)BLI_findlink(&node->inputs, 9); - nodeSetSocketAvailability(ntree, socket_threshold, operation_tests_equality(*node_storage)); -} - -static void do_math_operation(const VArray<float> &input_a, - const VArray<float> &input_b, - const NodeCompareOperation operation, - MutableSpan<bool> span_result) -{ - const int size = input_a.size(); - - if (try_dispatch_float_math_fl_fl_to_bool( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - for (const int i : IndexRange(size)) { - const float a = input_a[i]; - const float b = input_b[i]; - const bool out = math_function(a, b); - span_result[i] = out; - } - })) { - return; - } - - /* The operation is not supported by this node currently. */ - BLI_assert(false); -} - -static void do_equal_operation_float(const VArray<float> &input_a, - const VArray<float> &input_b, - const float threshold, - MutableSpan<bool> span_result) -{ - const int size = input_a.size(); - for (const int i : IndexRange(size)) { - const float a = input_a[i]; - const float b = input_b[i]; - span_result[i] = compare_ff(a, b, threshold); - } -} - -static void do_equal_operation_float3(const VArray<float3> &input_a, - const VArray<float3> &input_b, - const float threshold, - MutableSpan<bool> span_result) -{ - const float threshold_squared = pow2f(threshold); - const int size = input_a.size(); - for (const int i : IndexRange(size)) { - const float3 a = input_a[i]; - const float3 b = input_b[i]; - span_result[i] = len_squared_v3v3(a, b) < threshold_squared; - } -} - -static void do_equal_operation_color4f(const VArray<ColorGeometry4f> &input_a, - const VArray<ColorGeometry4f> &input_b, - const float threshold, - MutableSpan<bool> span_result) -{ - const float threshold_squared = pow2f(threshold); - const int size = input_a.size(); - for (const int i : IndexRange(size)) { - const ColorGeometry4f a = input_a[i]; - const ColorGeometry4f b = input_b[i]; - span_result[i] = len_squared_v4v4(a, b) < threshold_squared; - } -} - -static void do_equal_operation_bool(const VArray<bool> &input_a, - const VArray<bool> &input_b, - const float UNUSED(threshold), - MutableSpan<bool> span_result) -{ - const int size = input_a.size(); - for (const int i : IndexRange(size)) { - const bool a = input_a[i]; - const bool b = input_b[i]; - span_result[i] = a == b; - } -} - -static void do_not_equal_operation_float(const VArray<float> &input_a, - const VArray<float> &input_b, - const float threshold, - MutableSpan<bool> span_result) -{ - const int size = input_a.size(); - for (const int i : IndexRange(size)) { - const float a = input_a[i]; - const float b = input_b[i]; - span_result[i] = !compare_ff(a, b, threshold); - } -} - -static void do_not_equal_operation_float3(const VArray<float3> &input_a, - const VArray<float3> &input_b, - const float threshold, - MutableSpan<bool> span_result) -{ - const float threshold_squared = pow2f(threshold); - const int size = input_a.size(); - for (const int i : IndexRange(size)) { - const float3 a = input_a[i]; - const float3 b = input_b[i]; - span_result[i] = len_squared_v3v3(a, b) >= threshold_squared; - } -} - -static void do_not_equal_operation_color4f(const VArray<ColorGeometry4f> &input_a, - const VArray<ColorGeometry4f> &input_b, - const float threshold, - MutableSpan<bool> span_result) -{ - const float threshold_squared = pow2f(threshold); - const int size = input_a.size(); - for (const int i : IndexRange(size)) { - const ColorGeometry4f a = input_a[i]; - const ColorGeometry4f b = input_b[i]; - span_result[i] = len_squared_v4v4(a, b) >= threshold_squared; - } -} - -static void do_not_equal_operation_bool(const VArray<bool> &input_a, - const VArray<bool> &input_b, - const float UNUSED(threshold), - MutableSpan<bool> span_result) -{ - const int size = input_a.size(); - for (const int i : IndexRange(size)) { - const bool a = input_a[i]; - const bool b = input_b[i]; - span_result[i] = a != b; - } -} - -static CustomDataType get_data_type(GeometryComponent &component, - const GeoNodeExecParams ¶ms, - const NodeAttributeCompare &node_storage) -{ - if (operation_tests_equality(node_storage)) { - /* Convert the input attributes to the same data type for the equality tests. Use the higher - * complexity attribute type, otherwise information necessary to the comparison may be lost. */ - return bke::attribute_data_type_highest_complexity({ - params.get_input_attribute_data_type("A", component, CD_PROP_FLOAT), - params.get_input_attribute_data_type("B", component, CD_PROP_FLOAT), - }); - } - - /* Use float compare for every operation besides equality. */ - return CD_PROP_FLOAT; -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - const GeoNodeExecParams ¶ms, - StringRef result_name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - - /* Otherwise use the highest priority domain from existing input attributes, or the default. */ - return params.get_highest_priority_input_domain({"A", "B"}, component, ATTR_DOMAIN_POINT); -} - -static void attribute_compare_calc(GeometryComponent &component, const GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - NodeAttributeCompare *node_storage = (NodeAttributeCompare *)node.storage; - const NodeCompareOperation operation = static_cast<NodeCompareOperation>( - node_storage->operation); - const std::string result_name = params.get_input<std::string>("Result"); - - const AttributeDomain result_domain = get_result_domain(component, params, result_name); - - OutputAttribute_Typed<bool> attribute_result = component.attribute_try_get_for_output_only<bool>( - result_name, result_domain); - if (!attribute_result) { - return; - } - - const CustomDataType input_data_type = get_data_type(component, params, *node_storage); - - GVArray attribute_a = params.get_input_attribute( - "A", component, result_domain, input_data_type, nullptr); - GVArray attribute_b = params.get_input_attribute( - "B", component, result_domain, input_data_type, nullptr); - - if (!attribute_a || !attribute_b) { - /* Attribute wasn't found. */ - return; - } - - MutableSpan<bool> result_span = attribute_result.as_span(); - - /* Use specific types for correct equality operations, but for other operations we use implicit - * conversions and float comparison. In other words, the comparison is not element-wise. */ - if (operation_tests_equality(*node_storage)) { - const float threshold = params.get_input<float>("Threshold"); - if (operation == NODE_COMPARE_EQUAL) { - if (input_data_type == CD_PROP_FLOAT) { - do_equal_operation_float( - attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span); - } - else if (input_data_type == CD_PROP_FLOAT3) { - do_equal_operation_float3( - attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span); - } - else if (input_data_type == CD_PROP_COLOR) { - do_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(), - attribute_b.typed<ColorGeometry4f>(), - threshold, - result_span); - } - else if (input_data_type == CD_PROP_BOOL) { - do_equal_operation_bool( - attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span); - } - } - else if (operation == NODE_COMPARE_NOT_EQUAL) { - if (input_data_type == CD_PROP_FLOAT) { - do_not_equal_operation_float( - attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span); - } - else if (input_data_type == CD_PROP_FLOAT3) { - do_not_equal_operation_float3( - attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span); - } - else if (input_data_type == CD_PROP_COLOR) { - do_not_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(), - attribute_b.typed<ColorGeometry4f>(), - threshold, - result_span); - } - else if (input_data_type == CD_PROP_BOOL) { - do_not_equal_operation_bool( - attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span); - } - } - } - else { - do_math_operation( - attribute_a.typed<float>(), attribute_b.typed<float>(), operation, result_span); - } - - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - attribute_compare_calc(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - attribute_compare_calc(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - attribute_compare_calc(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_compare_cc - -void register_node_type_geo_attribute_compare() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_compare_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_COMPARE, "Attribute Compare", NODE_CLASS_ATTRIBUTE); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - node_type_update(&ntype, file_ns::node_update); - node_type_storage( - &ntype, "NodeAttributeCompare", node_free_standard_storage, node_copy_standard_storage); - node_type_init(&ntype, file_ns::node_init); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_convert.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_convert.cc deleted file mode 100644 index 5ded4efd4f7..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_convert.cc +++ /dev/null @@ -1,179 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_convert_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Attribute")); - b.add_input<decl::String>(N_("Result")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "domain", 0, nullptr, ICON_NONE); - uiItemR(layout, ptr, "data_type", 0, IFACE_("Type"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeAttributeConvert *data = MEM_cnew<NodeAttributeConvert>(__func__); - - data->data_type = CD_AUTO_FROM_NAME; - data->domain = ATTR_DOMAIN_AUTO; - node->storage = data; -} - -static AttributeMetaData get_result_domain_and_type(const GeometryComponent &component, - const StringRef source_name, - const StringRef result_name) -{ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return *result_info; - } - std::optional<AttributeMetaData> source_info = component.attribute_get_meta_data(source_name); - if (source_info) { - return *source_info; - } - /* The node won't do anything in this case, but we still have to return a value. */ - return AttributeMetaData{ATTR_DOMAIN_POINT, CD_PROP_BOOL}; -} - -static bool conversion_can_be_skipped(const GeometryComponent &component, - const StringRef source_name, - const StringRef result_name, - const AttributeDomain result_domain, - const CustomDataType result_type) -{ - if (source_name != result_name) { - return false; - } - std::optional<AttributeMetaData> info = component.attribute_get_meta_data(result_name); - if (!info) { - return false; - } - if (info->domain != result_domain) { - return false; - } - if (info->data_type != result_type) { - return false; - } - return true; -} - -static void attribute_convert_calc(GeometryComponent &component, - const GeoNodeExecParams ¶ms, - const StringRef source_name, - const StringRef result_name, - const CustomDataType data_type, - const AttributeDomain domain) -{ - const AttributeMetaData auto_info = get_result_domain_and_type( - component, source_name, result_name); - const AttributeDomain result_domain = (domain == ATTR_DOMAIN_AUTO) ? auto_info.domain : domain; - const CustomDataType result_type = (data_type == CD_AUTO_FROM_NAME) ? auto_info.data_type : - data_type; - - if (conversion_can_be_skipped(component, source_name, result_name, result_domain, result_type)) { - return; - } - - GVArray source_attribute = component.attribute_try_get_for_read( - source_name, result_domain, result_type); - if (!source_attribute) { - params.error_message_add(NodeWarningType::Error, - TIP_("No attribute with name \"") + source_name + "\""); - return; - } - - OutputAttribute result_attribute = component.attribute_try_get_for_output_only( - result_name, result_domain, result_type); - if (!result_attribute) { - return; - } - - GVArray_GSpan source_span{source_attribute}; - GMutableSpan result_span = result_attribute.as_span(); - - BLI_assert(source_span.size() == result_span.size()); - - const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(result_type); - BLI_assert(cpp_type != nullptr); - - cpp_type->copy_assign_n(source_span.data(), result_span.data(), result_span.size()); - result_attribute.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - const std::string result_name = params.extract_input<std::string>("Result"); - const std::string source_name = params.extract_input<std::string>("Attribute"); - const NodeAttributeConvert &node_storage = *(const NodeAttributeConvert *)params.node().storage; - const CustomDataType data_type = static_cast<CustomDataType>(node_storage.data_type); - const AttributeDomain domain = static_cast<AttributeDomain>(node_storage.domain); - - if (result_name.empty()) { - params.set_default_remaining_outputs(); - return; - } - - if (geometry_set.has<MeshComponent>()) { - attribute_convert_calc(geometry_set.get_component_for_write<MeshComponent>(), - params, - source_name, - result_name, - data_type, - domain); - } - if (geometry_set.has<PointCloudComponent>()) { - attribute_convert_calc(geometry_set.get_component_for_write<PointCloudComponent>(), - params, - source_name, - result_name, - data_type, - domain); - } - if (geometry_set.has<CurveComponent>()) { - attribute_convert_calc(geometry_set.get_component_for_write<CurveComponent>(), - params, - source_name, - result_name, - data_type, - domain); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_convert_cc - -void register_node_type_geo_attribute_convert() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_convert_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_CONVERT, "Attribute Convert", NODE_CLASS_ATTRIBUTE); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - node_type_init(&ntype, file_ns::node_init); - node_type_storage( - &ntype, "NodeAttributeConvert", node_free_standard_storage, node_copy_standard_storage); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_curve_map.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_curve_map.cc deleted file mode 100644 index 800587e2157..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_curve_map.cc +++ /dev/null @@ -1,208 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_blenlib.h" -#include "BLI_task.hh" - -#include "BKE_colortools.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_curve_map_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Attribute")); - b.add_input<decl::String>(N_("Result")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); - bNode *node = (bNode *)ptr->data; - NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)node->storage; - switch (data->data_type) { - case CD_PROP_FLOAT: - uiTemplateCurveMapping(layout, ptr, "curve_vec", 0, false, false, false, false); - break; - case CD_PROP_FLOAT3: - uiTemplateCurveMapping(layout, ptr, "curve_vec", 'v', false, false, false, false); - break; - case CD_PROP_COLOR: - uiTemplateCurveMapping(layout, ptr, "curve_rgb", 'c', false, false, false, false); - break; - } -} - -static void node_free_storage(bNode *node) -{ - if (node->storage) { - NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)node->storage; - BKE_curvemapping_free(data->curve_vec); - BKE_curvemapping_free(data->curve_rgb); - MEM_freeN(node->storage); - } -} - -static void node_copy_storage(bNodeTree *UNUSED(dest_ntree), - bNode *dest_node, - const bNode *src_node) -{ - dest_node->storage = MEM_dupallocN(src_node->storage); - NodeAttributeCurveMap *src_data = (NodeAttributeCurveMap *)src_node->storage; - NodeAttributeCurveMap *dest_data = (NodeAttributeCurveMap *)dest_node->storage; - dest_data->curve_vec = BKE_curvemapping_copy(src_data->curve_vec); - dest_data->curve_rgb = BKE_curvemapping_copy(src_data->curve_rgb); -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeAttributeCurveMap *data = MEM_cnew<NodeAttributeCurveMap>(__func__); - - data->data_type = CD_PROP_FLOAT; - data->curve_vec = BKE_curvemapping_add(4, -1.0f, -1.0f, 1.0f, 1.0f); - data->curve_vec->cur = 3; - data->curve_rgb = BKE_curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); - node->storage = data; -} - -static void node_update(bNodeTree *UNUSED(ntree), bNode *node) -{ - /* Set the active curve when data type is changed. */ - NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)node->storage; - if (data->data_type == CD_PROP_FLOAT) { - data->curve_vec->cur = 3; - } - else if (data->data_type == CD_PROP_FLOAT3) { - data->curve_vec->cur = 0; - } -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - StringRef input_name, - StringRef result_name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - /* Otherwise use the input attribute's domain if it exists. */ - std::optional<AttributeMetaData> input_info = component.attribute_get_meta_data(input_name); - if (input_info) { - return input_info->domain; - } - - return ATTR_DOMAIN_POINT; -} - -static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryComponent &component) -{ - const bNode &bnode = params.node(); - NodeAttributeCurveMap &node_storage = *(NodeAttributeCurveMap *)bnode.storage; - const std::string result_name = params.get_input<std::string>("Result"); - const std::string input_name = params.get_input<std::string>("Attribute"); - - const CustomDataType result_type = (CustomDataType)node_storage.data_type; - const AttributeDomain result_domain = get_result_domain(component, input_name, result_name); - - OutputAttribute attribute_result = component.attribute_try_get_for_output_only( - result_name, result_domain, result_type); - if (!attribute_result) { - return; - } - - switch (result_type) { - case CD_PROP_FLOAT: { - const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec; - VArray<float> attribute_in = component.attribute_get_for_read<float>( - input_name, result_domain, float(0.0f)); - MutableSpan<float> results = attribute_result.as_span<float>(); - threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - results[i] = BKE_curvemapping_evaluateF(cumap, 3, attribute_in[i]); - } - }); - break; - } - case CD_PROP_FLOAT3: { - const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec; - VArray<float3> attribute_in = component.attribute_get_for_read<float3>( - input_name, result_domain, float3(0.0f)); - MutableSpan<float3> results = attribute_result.as_span<float3>(); - threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - BKE_curvemapping_evaluate3F(cumap, results[i], attribute_in[i]); - } - }); - break; - } - case CD_PROP_COLOR: { - const CurveMapping *cumap = (CurveMapping *)node_storage.curve_rgb; - VArray<ColorGeometry4f> attribute_in = component.attribute_get_for_read<ColorGeometry4f>( - input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f)); - MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>(); - threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - BKE_curvemapping_evaluateRGBF(cumap, results[i], attribute_in[i]); - } - }); - break; - } - default: { - BLI_assert_unreachable(); - break; - } - } - - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - const bNode &bnode = params.node(); - NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)bnode.storage; - BKE_curvemapping_init(data->curve_vec); - BKE_curvemapping_init(data->curve_rgb); - - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<MeshComponent>()); - } - if (geometry_set.has<PointCloudComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<PointCloudComponent>()); - } - if (geometry_set.has<CurveComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<CurveComponent>()); - } - - params.set_output("Geometry", std::move(geometry_set)); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_curve_map_cc - -void register_node_type_geo_attribute_curve_map() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_curve_map_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_CURVE_MAP, "Attribute Curve Map", NODE_CLASS_ATTRIBUTE); - node_type_update(&ntype, file_ns::node_update); - node_type_init(&ntype, file_ns::node_init); - node_type_size_preset(&ntype, NODE_SIZE_LARGE); - node_type_storage( - &ntype, "NodeAttributeCurveMap", file_ns::node_free_storage, file_ns::node_copy_storage); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_fill.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_fill.cc deleted file mode 100644 index 21fe8e12e65..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_fill.cc +++ /dev/null @@ -1,151 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_fill_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Attribute")).is_attribute_name(); - b.add_input<decl::Vector>(N_("Value"), "Value"); - b.add_input<decl::Float>(N_("Value"), "Value_001"); - b.add_input<decl::Color>(N_("Value"), "Value_002"); - b.add_input<decl::Bool>(N_("Value"), "Value_003"); - b.add_input<decl::Int>(N_("Value"), "Value_004"); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "domain", 0, "", ICON_NONE); - uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - node->custom1 = CD_PROP_FLOAT; - node->custom2 = ATTR_DOMAIN_AUTO; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - bNodeSocket *socket_value_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 2); - bNodeSocket *socket_value_float = socket_value_vector->next; - bNodeSocket *socket_value_color4f = socket_value_float->next; - bNodeSocket *socket_value_boolean = socket_value_color4f->next; - bNodeSocket *socket_value_int32 = socket_value_boolean->next; - - const CustomDataType data_type = static_cast<CustomDataType>(node->custom1); - - nodeSetSocketAvailability(ntree, socket_value_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, socket_value_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, socket_value_color4f, data_type == CD_PROP_COLOR); - nodeSetSocketAvailability(ntree, socket_value_boolean, data_type == CD_PROP_BOOL); - nodeSetSocketAvailability(ntree, socket_value_int32, data_type == CD_PROP_INT32); -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, const StringRef name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(name); - if (result_info) { - return result_info->domain; - } - return ATTR_DOMAIN_POINT; -} - -static void fill_attribute(GeometryComponent &component, const GeoNodeExecParams ¶ms) -{ - const std::string attribute_name = params.get_input<std::string>("Attribute"); - if (attribute_name.empty()) { - return; - } - - const bNode &node = params.node(); - const CustomDataType data_type = static_cast<CustomDataType>(node.custom1); - const AttributeDomain domain = static_cast<AttributeDomain>(node.custom2); - const AttributeDomain result_domain = (domain == ATTR_DOMAIN_AUTO) ? - get_result_domain(component, attribute_name) : - domain; - - OutputAttribute attribute = component.attribute_try_get_for_output_only( - attribute_name, result_domain, data_type); - if (!attribute) { - return; - } - - switch (data_type) { - case CD_PROP_FLOAT: { - const float value = params.get_input<float>("Value_001"); - attribute->fill(&value); - break; - } - case CD_PROP_FLOAT3: { - const float3 value = params.get_input<float3>("Value"); - attribute->fill(&value); - break; - } - case CD_PROP_COLOR: { - const ColorGeometry4f value = params.get_input<ColorGeometry4f>("Value_002"); - attribute->fill(&value); - break; - } - case CD_PROP_BOOL: { - const bool value = params.get_input<bool>("Value_003"); - attribute->fill(&value); - break; - } - case CD_PROP_INT32: { - const int value = params.get_input<int>("Value_004"); - attribute->fill(&value); - break; - } - default: - break; - } - - attribute.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - fill_attribute(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - fill_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - fill_attribute(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_fill_cc - -void register_node_type_geo_attribute_fill() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_fill_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_FILL, "Attribute Fill", NODE_CLASS_ATTRIBUTE); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - ntype.declare = file_ns::node_declare; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_map_range.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_map_range.cc deleted file mode 100644 index 05440b09442..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_map_range.cc +++ /dev/null @@ -1,422 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_math_base_safe.h" -#include "BLI_task.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_map_range_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Attribute")); - b.add_input<decl::String>(N_("Result")); - b.add_input<decl::Float>(N_("From Min")); - b.add_input<decl::Float>(N_("From Max")).default_value(1.0f); - b.add_input<decl::Float>(N_("To Min")); - b.add_input<decl::Float>(N_("To Max")).default_value(1.0f); - b.add_input<decl::Float>(N_("Steps")).default_value(4.0f); - b.add_input<decl::Vector>(N_("From Min"), "From Min_001"); - b.add_input<decl::Vector>(N_("From Max"), "From Max_001").default_value({1.0f, 1.0f, 1.0f}); - b.add_input<decl::Vector>(N_("To Min"), "To Min_001"); - b.add_input<decl::Vector>(N_("To Max"), "To Max_001").default_value({1.0f, 1.0f, 1.0f}); - b.add_input<decl::Vector>(N_("Steps"), "Steps_001").default_value({4.0f, 4.0f, 4.0f}); - b.add_input<decl::Bool>(N_("Clamp")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void fn_attribute_map_range_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "interpolation_type", 0, "", ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeAttributeMapRange *data = MEM_cnew<NodeAttributeMapRange>(__func__); - data->data_type = CD_PROP_FLOAT; - data->interpolation_type = NODE_MAP_RANGE_LINEAR; - - node->storage = data; -} -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node->storage; - - bNodeSocket *sock_from_min_float = (bNodeSocket *)BLI_findlink(&node->inputs, 3); - bNodeSocket *sock_from_max_float = sock_from_min_float->next; - bNodeSocket *sock_to_min_float = sock_from_max_float->next; - bNodeSocket *sock_to_max_float = sock_to_min_float->next; - bNodeSocket *sock_steps_float = sock_to_max_float->next; - - bNodeSocket *sock_from_min_vector = sock_steps_float->next; - bNodeSocket *sock_from_max_vector = sock_from_min_vector->next; - bNodeSocket *sock_to_min_vector = sock_from_max_vector->next; - bNodeSocket *sock_to_max_vector = sock_to_min_vector->next; - bNodeSocket *sock_steps_vector = sock_to_max_vector->next; - - bNodeSocket *sock_clamp = sock_steps_vector->next; - - const CustomDataType data_type = static_cast<CustomDataType>(node_storage.data_type); - - nodeSetSocketAvailability(ntree, - sock_clamp, - node_storage.interpolation_type == NODE_MAP_RANGE_LINEAR || - node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED); - - nodeSetSocketAvailability(ntree, sock_from_min_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, sock_from_max_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, sock_to_min_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, sock_to_max_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, - sock_steps_float, - data_type == CD_PROP_FLOAT && - node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED); - - nodeSetSocketAvailability(ntree, sock_from_min_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, sock_from_max_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, sock_to_min_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, sock_to_max_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, - sock_steps_vector, - data_type == CD_PROP_FLOAT3 && - node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED); -} - -static float map_linear(const float value, - const float min_from, - const float max_from, - const float min_to, - const float max_to) -{ - /* First we calculate a fraction that measures how far along - * the [min_from, max_from] interval the value lies. - * - * value - * min_from [------>|------------------------] max_from - * factor (e.g. 0.25) - * - * Then to find where the value is mapped, we add the same fraction - * of the [min_to, max_to] interval to min_to. - * - * min_to [--->|-----------] max_to - * v - * min_to + (max_to - min_to) * factor - */ - const float factor = safe_divide(value - min_from, max_from - min_from); - return min_to + factor * (max_to - min_to); -} - -static float map_stepped(const float value, - const float min_from, - const float max_from, - const float min_to, - const float max_to, - const float steps) -{ - /* First the factor is calculated here in the same way as for the linear mapping. - * - * Then the factor is mapped to multiples of 1.0 / steps. - * This is best understood with a few examples. Assume steps == 3. - * ____________________________________ - * | factor | * 4.0 | floor() | / 3.0 | - * |--------|-------|---------|-------| - * | 0.0 | 0.0 | 0.0 | 0.0 | - * | 0.1 | 0.4 | 0.0 | 0.0 | - * | 0.25 | 1.0 | 1.0 | 0.333 | - * | 0.45 | 1.8 | 1.0 | 0.333 | - * | 0.5 | 2.0 | 2.0 | 0.666 | - * | 0.55 | 2.2 | 2.0 | 0.666 | - * | 0.999 | 3.999 | 3.0 | 1.0 | - * | 1.0 | 4.0 | 4.0 | 1.333 | - * ------------------------------------ - * Note that the factor is not always mapped the closest multiple of 1.0 /steps. - */ - const float factor = safe_divide(value - min_from, max_from - min_from); - const float factor_mapped = safe_divide(floorf(factor * (steps + 1.0f)), steps); - return min_to + factor_mapped * (max_to - min_to); -} - -static float smoothstep_polynomial(float x) -{ - /* This polynomial is only meant to be used for the [0, 1] range. */ - return (3.0f - 2.0f * x) * (x * x); -} - -static float map_smoothstep(const float value, - const float min_from, - const float max_from, - const float min_to, - const float max_to) -{ - const float factor = safe_divide(value - min_from, max_from - min_from); - const float factor_clamped = std::clamp(factor, 0.0f, 1.0f); - const float factor_mapped = smoothstep_polynomial(factor_clamped); - return min_to + factor_mapped * (max_to - min_to); -} - -static float smootherstep_polynomial(float x) -{ - /* This polynomial is only meant to be used for the [0, 1] range. */ - return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f); -} - -static float map_smootherstep(const float value, - const float min_from, - const float max_from, - const float min_to, - const float max_to) -{ - const float factor = safe_divide(value - min_from, max_from - min_from); - const float factor_clamped = std::clamp(factor, 0.0f, 1.0f); - const float factor_mapped = smootherstep_polynomial(factor_clamped); - return min_to + factor_mapped * (max_to - min_to); -} - -static void map_range_float(const VArray<float> &attribute_input, - MutableSpan<float> results, - const GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node.storage; - const int interpolation_type = node_storage.interpolation_type; - const float min_from = params.get_input<float>("From Min"); - const float max_from = params.get_input<float>("From Max"); - const float min_to = params.get_input<float>("To Min"); - const float max_to = params.get_input<float>("To Max"); - - VArray_Span<float> span{attribute_input}; - - switch (interpolation_type) { - case NODE_MAP_RANGE_LINEAR: { - threading::parallel_for(span.index_range(), 2048, [&](IndexRange range) { - for (const int i : range) { - results[i] = map_linear(span[i], min_from, max_from, min_to, max_to); - } - }); - break; - } - case NODE_MAP_RANGE_STEPPED: { - const float steps = params.get_input<float>("Steps"); - threading::parallel_for(span.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - results[i] = map_stepped(span[i], min_from, max_from, min_to, max_to, steps); - } - }); - break; - } - case NODE_MAP_RANGE_SMOOTHSTEP: { - threading::parallel_for(span.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - results[i] = map_smoothstep(span[i], min_from, max_from, min_to, max_to); - } - }); - break; - } - case NODE_MAP_RANGE_SMOOTHERSTEP: { - threading::parallel_for(span.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - results[i] = map_smootherstep(span[i], min_from, max_from, min_to, max_to); - } - }); - break; - } - } - - if (ELEM(interpolation_type, NODE_MAP_RANGE_LINEAR, NODE_MAP_RANGE_STEPPED) && - params.get_input<bool>("Clamp")) { - /* Users can specify min_to > max_to, but clamping expects min < max. */ - const float clamp_min = min_to < max_to ? min_to : max_to; - const float clamp_max = min_to < max_to ? max_to : min_to; - - threading::parallel_for(results.index_range(), 2048, [&](IndexRange range) { - for (const int i : range) { - results[i] = std::clamp(results[i], clamp_min, clamp_max); - } - }); - } -} - -static void map_range_float3(const VArray<float3> &attribute_input, - const MutableSpan<float3> results, - const GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node.storage; - const int interpolation_type = node_storage.interpolation_type; - const float3 min_from = params.get_input<float3>("From Min_001"); - const float3 max_from = params.get_input<float3>("From Max_001"); - const float3 min_to = params.get_input<float3>("To Min_001"); - const float3 max_to = params.get_input<float3>("To Max_001"); - - VArray_Span<float3> span{attribute_input}; - - switch (interpolation_type) { - case NODE_MAP_RANGE_LINEAR: { - threading::parallel_for(span.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - results[i].x = map_linear(span[i].x, min_from.x, max_from.x, min_to.x, max_to.x); - results[i].y = map_linear(span[i].y, min_from.y, max_from.y, min_to.y, max_to.y); - results[i].z = map_linear(span[i].z, min_from.z, max_from.z, min_to.z, max_to.z); - } - }); - break; - } - case NODE_MAP_RANGE_STEPPED: { - const float3 steps = params.get_input<float3>("Steps_001"); - threading::parallel_for(span.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - results[i].x = map_stepped( - span[i].x, min_from.x, max_from.x, min_to.x, max_to.x, steps.x); - results[i].y = map_stepped( - span[i].y, min_from.y, max_from.y, min_to.y, max_to.y, steps.y); - results[i].z = map_stepped( - span[i].z, min_from.z, max_from.z, min_to.z, max_to.z, steps.z); - } - }); - break; - } - case NODE_MAP_RANGE_SMOOTHSTEP: { - threading::parallel_for(span.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - results[i].x = map_smoothstep(span[i].x, min_from.x, max_from.x, min_to.x, max_to.x); - results[i].y = map_smoothstep(span[i].y, min_from.y, max_from.y, min_to.y, max_to.y); - results[i].z = map_smoothstep(span[i].z, min_from.z, max_from.z, min_to.z, max_to.z); - } - }); - break; - } - case NODE_MAP_RANGE_SMOOTHERSTEP: { - threading::parallel_for(span.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - results[i].x = map_smootherstep(span[i].x, min_from.x, max_from.x, min_to.x, max_to.x); - results[i].y = map_smootherstep(span[i].y, min_from.y, max_from.y, min_to.y, max_to.y); - results[i].z = map_smootherstep(span[i].z, min_from.z, max_from.z, min_to.z, max_to.z); - } - }); - break; - } - } - - if (ELEM(interpolation_type, NODE_MAP_RANGE_LINEAR, NODE_MAP_RANGE_STEPPED) && - params.get_input<bool>("Clamp")) { - /* Users can specify min_to > max_to, but clamping expects min < max. */ - float3 clamp_min; - float3 clamp_max; - clamp_min.x = min_to.x < max_to.x ? min_to.x : max_to.x; - clamp_max.x = min_to.x < max_to.x ? max_to.x : min_to.x; - clamp_min.y = min_to.y < max_to.y ? min_to.y : max_to.y; - clamp_max.y = min_to.y < max_to.y ? max_to.y : min_to.y; - clamp_min.z = min_to.z < max_to.z ? min_to.z : max_to.z; - clamp_max.z = min_to.z < max_to.z ? max_to.z : min_to.z; - - for (int i : results.index_range()) { - clamp_v3_v3v3(results[i], clamp_min, clamp_max); - } - } -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - StringRef source_name, - StringRef result_name) -{ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - std::optional<AttributeMetaData> source_info = component.attribute_get_meta_data(source_name); - if (source_info) { - return source_info->domain; - } - return ATTR_DOMAIN_POINT; -} - -static void map_range_attribute(GeometryComponent &component, const GeoNodeExecParams ¶ms) -{ - const std::string input_name = params.get_input<std::string>("Attribute"); - const std::string result_name = params.get_input<std::string>("Result"); - - if (input_name.empty() || result_name.empty()) { - return; - } - - const bNode &node = params.node(); - NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node.storage; - const CustomDataType data_type = static_cast<CustomDataType>(node_storage.data_type); - - const AttributeDomain domain = get_result_domain(component, input_name, result_name); - - GVArray attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type); - - if (!attribute_input) { - params.error_message_add(NodeWarningType::Error, - TIP_("No attribute with name \"") + input_name + "\""); - return; - } - - OutputAttribute attribute_result = component.attribute_try_get_for_output_only( - result_name, domain, data_type); - if (!attribute_result) { - params.error_message_add(NodeWarningType::Error, - TIP_("Could not find or create attribute with name \"") + - result_name + "\""); - return; - } - - switch (data_type) { - case CD_PROP_FLOAT: { - map_range_float(attribute_input.typed<float>(), attribute_result.as_span<float>(), params); - break; - } - case CD_PROP_FLOAT3: { - map_range_float3( - attribute_input.typed<float3>(), attribute_result.as_span<float3>(), params); - break; - } - default: - BLI_assert_unreachable(); - } - - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - if (geometry_set.has<MeshComponent>()) { - map_range_attribute(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - map_range_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - map_range_attribute(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_map_range_cc - -void register_node_type_geo_attribute_map_range() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_map_range_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_MAP_RANGE, "Attribute Map Range", NODE_CLASS_ATTRIBUTE); - ntype.geometry_node_execute = file_ns::node_geo_exec; - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - node_type_storage( - &ntype, "NodeAttributeMapRange", node_free_standard_storage, node_copy_standard_storage); - ntype.declare = file_ns::node_declare; - ntype.draw_buttons = file_ns::fn_attribute_map_range_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_math.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_math.cc deleted file mode 100644 index 9e909ec749b..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_math.cc +++ /dev/null @@ -1,308 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_task.hh" - -#include "RNA_enum_types.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "NOD_math_functions.hh" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_math_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("A")); - b.add_input<decl::Float>(N_("A"), "A_001"); - b.add_input<decl::String>(N_("B")); - b.add_input<decl::Float>(N_("B"), "B_001"); - b.add_input<decl::String>(N_("C")); - b.add_input<decl::Float>(N_("C"), "C_001"); - b.add_input<decl::String>(N_("Result")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static bool operation_use_input_c(const NodeMathOperation operation) -{ - return ELEM(operation, - NODE_MATH_MULTIPLY_ADD, - NODE_MATH_SMOOTH_MIN, - NODE_MATH_SMOOTH_MAX, - NODE_MATH_WRAP, - NODE_MATH_COMPARE); -} - -static bool operation_use_input_b(const NodeMathOperation operation) -{ - switch (operation) { - case NODE_MATH_ADD: - case NODE_MATH_SUBTRACT: - case NODE_MATH_MULTIPLY: - case NODE_MATH_DIVIDE: - case NODE_MATH_POWER: - case NODE_MATH_LOGARITHM: - case NODE_MATH_MINIMUM: - case NODE_MATH_MAXIMUM: - case NODE_MATH_LESS_THAN: - case NODE_MATH_GREATER_THAN: - case NODE_MATH_MODULO: - case NODE_MATH_ARCTAN2: - case NODE_MATH_SNAP: - case NODE_MATH_WRAP: - case NODE_MATH_COMPARE: - case NODE_MATH_MULTIPLY_ADD: - case NODE_MATH_PINGPONG: - case NODE_MATH_SMOOTH_MIN: - case NODE_MATH_SMOOTH_MAX: - return true; - case NODE_MATH_SINE: - case NODE_MATH_COSINE: - case NODE_MATH_TANGENT: - case NODE_MATH_ARCSINE: - case NODE_MATH_ARCCOSINE: - case NODE_MATH_ARCTANGENT: - case NODE_MATH_ROUND: - case NODE_MATH_ABSOLUTE: - case NODE_MATH_FLOOR: - case NODE_MATH_CEIL: - case NODE_MATH_FRACTION: - case NODE_MATH_SQRT: - case NODE_MATH_INV_SQRT: - case NODE_MATH_SIGN: - case NODE_MATH_EXPONENT: - case NODE_MATH_RADIANS: - case NODE_MATH_DEGREES: - case NODE_MATH_SINH: - case NODE_MATH_COSH: - case NODE_MATH_TANH: - case NODE_MATH_TRUNC: - return false; - } - BLI_assert(false); - return false; -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - bNode *node = (bNode *)ptr->data; - NodeAttributeMath *node_storage = (NodeAttributeMath *)node->storage; - NodeMathOperation operation = (NodeMathOperation)node_storage->operation; - - uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); - - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "input_type_a", 0, IFACE_("A"), ICON_NONE); - if (operation_use_input_b(operation)) { - uiItemR(layout, ptr, "input_type_b", 0, IFACE_("B"), ICON_NONE); - } - if (operation_use_input_c(operation)) { - uiItemR(layout, ptr, "input_type_c", 0, IFACE_("C"), ICON_NONE); - } -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeAttributeMath *data = MEM_cnew<NodeAttributeMath>(__func__); - - data->operation = NODE_MATH_ADD; - data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - data->input_type_c = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - node->storage = data; -} - -static void geo_node_math_label(const bNodeTree *UNUSED(ntree), - const bNode *node, - char *label, - int maxlen) -{ - NodeAttributeMath &node_storage = *(NodeAttributeMath *)node->storage; - const char *name; - bool enum_label = RNA_enum_name(rna_enum_node_math_items, node_storage.operation, &name); - if (!enum_label) { - name = "Unknown"; - } - BLI_strncpy(label, IFACE_(name), maxlen); -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeAttributeMath &node_storage = *(NodeAttributeMath *)node->storage; - NodeMathOperation operation = static_cast<NodeMathOperation>(node_storage.operation); - - update_attribute_input_socket_availabilities( - *ntree, *node, "A", (GeometryNodeAttributeInputMode)node_storage.input_type_a); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "B", - (GeometryNodeAttributeInputMode)node_storage.input_type_b, - operation_use_input_b(operation)); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "C", - (GeometryNodeAttributeInputMode)node_storage.input_type_c, - operation_use_input_c(operation)); -} - -static void do_math_operation(const VArray<float> &span_a, - const VArray<float> &span_b, - const VArray<float> &span_c, - MutableSpan<float> span_result, - const NodeMathOperation operation) -{ - bool success = try_dispatch_float_math_fl_fl_fl_to_fl( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(span_result.size()), 512, [&](IndexRange range) { - for (const int i : range) { - span_result[i] = math_function(span_a[i], span_b[i], span_c[i]); - } - }); - }); - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static void do_math_operation(const VArray<float> &span_a, - const VArray<float> &span_b, - MutableSpan<float> span_result, - const NodeMathOperation operation) -{ - bool success = try_dispatch_float_math_fl_fl_to_fl( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(span_result.size()), 1024, [&](IndexRange range) { - for (const int i : range) { - span_result[i] = math_function(span_a[i], span_b[i]); - } - }); - }); - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static void do_math_operation(const VArray<float> &span_input, - MutableSpan<float> span_result, - const NodeMathOperation operation) -{ - bool success = try_dispatch_float_math_fl_to_fl( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(span_result.size()), 1024, [&](IndexRange range) { - for (const int i : range) { - span_result[i] = math_function(span_input[i]); - } - }); - }); - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - const GeoNodeExecParams ¶ms, - const NodeMathOperation operation, - StringRef result_name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - - /* Otherwise use the highest priority domain from existing input attributes, or the default. */ - const AttributeDomain default_domain = ATTR_DOMAIN_POINT; - if (operation_use_input_b(operation)) { - if (operation_use_input_c(operation)) { - return params.get_highest_priority_input_domain({"A", "B", "C"}, component, default_domain); - } - return params.get_highest_priority_input_domain({"A", "B"}, component, default_domain); - } - return params.get_highest_priority_input_domain({"A"}, component, default_domain); -} - -static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - const NodeAttributeMath *node_storage = (const NodeAttributeMath *)node.storage; - const NodeMathOperation operation = static_cast<NodeMathOperation>(node_storage->operation); - const std::string result_name = params.get_input<std::string>("Result"); - - /* The result type of this node is always float. */ - const AttributeDomain result_domain = get_result_domain( - component, params, operation, result_name); - - OutputAttribute_Typed<float> attribute_result = - component.attribute_try_get_for_output_only<float>(result_name, result_domain); - if (!attribute_result) { - return; - } - - VArray<float> attribute_a = params.get_input_attribute<float>( - "A", component, result_domain, 0.0f); - - MutableSpan<float> result_span = attribute_result.as_span(); - - /* Note that passing the data with `get_internal_span<float>()` works - * because the attributes were accessed with #CD_PROP_FLOAT. */ - if (operation_use_input_b(operation)) { - VArray<float> attribute_b = params.get_input_attribute<float>( - "B", component, result_domain, 0.0f); - if (operation_use_input_c(operation)) { - VArray<float> attribute_c = params.get_input_attribute<float>( - "C", component, result_domain, 0.0f); - do_math_operation(attribute_a, attribute_b, attribute_c, result_span, operation); - } - else { - do_math_operation(attribute_a, attribute_b, result_span, operation); - } - } - else { - do_math_operation(attribute_a, result_span, operation); - } - - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - attribute_math_calc(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - attribute_math_calc(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - attribute_math_calc(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_math_cc - -void register_node_type_geo_attribute_math() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_math_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_MATH, "Attribute Math", NODE_CLASS_ATTRIBUTE); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - ntype.labelfunc = file_ns::geo_node_math_label; - node_type_update(&ntype, file_ns::node_update); - node_type_init(&ntype, file_ns::node_init); - node_type_storage( - &ntype, "NodeAttributeMath", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_mix.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_mix.cc deleted file mode 100644 index aab33e1ef01..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_mix.cc +++ /dev/null @@ -1,245 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_task.hh" - -#include "BKE_material.h" - -#include "DNA_material_types.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_mix_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Factor")); - b.add_input<decl::Float>(N_("Factor"), "Factor_001") - .default_value(0.5f) - .min(0.0f) - .max(1.0f) - .subtype(PROP_FACTOR); - b.add_input<decl::String>(N_("A")); - b.add_input<decl::Float>(N_("A"), "A_001"); - b.add_input<decl::Vector>(N_("A"), "A_002"); - b.add_input<decl::Color>(N_("A"), "A_003").default_value({0.5f, 0.5f, 0.5f, 1.0f}); - b.add_input<decl::String>(N_("B")); - b.add_input<decl::Float>(N_("B"), "B_001"); - b.add_input<decl::Vector>(N_("B"), "B_002"); - b.add_input<decl::Color>(N_("B"), "B_003").default_value({0.5f, 0.5f, 0.5f, 1.0f}); - b.add_input<decl::String>(N_("Result")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE); - uiLayout *col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "input_type_factor", 0, IFACE_("Factor"), ICON_NONE); - uiItemR(col, ptr, "input_type_a", 0, IFACE_("A"), ICON_NONE); - uiItemR(col, ptr, "input_type_b", 0, IFACE_("B"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeAttributeMix *data = MEM_cnew<NodeAttributeMix>("attribute mix node"); - data->blend_type = MA_RAMP_BLEND; - data->input_type_factor = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeAttributeMix *node_storage = (NodeAttributeMix *)node->storage; - update_attribute_input_socket_availabilities( - *ntree, *node, "Factor", (GeometryNodeAttributeInputMode)node_storage->input_type_factor); - update_attribute_input_socket_availabilities( - *ntree, *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a); - update_attribute_input_socket_availabilities( - *ntree, *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b); -} - -static void do_mix_operation_float(const int blend_mode, - const VArray<float> &factors, - const VArray<float> &inputs_a, - const VArray<float> &inputs_b, - VMutableArray<float> &results) -{ - const int size = results.size(); - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float factor = factors[i]; - float3 a{inputs_a[i]}; - const float3 b{inputs_b[i]}; - ramp_blend(blend_mode, a, factor, b); - const float result = a.x; - results.set(i, result); - } - }); -} - -static void do_mix_operation_float3(const int blend_mode, - const VArray<float> &factors, - const VArray<float3> &inputs_a, - const VArray<float3> &inputs_b, - VMutableArray<float3> &results) -{ - const int size = results.size(); - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float factor = factors[i]; - float3 a = inputs_a[i]; - const float3 b = inputs_b[i]; - ramp_blend(blend_mode, a, factor, b); - results.set(i, a); - } - }); -} - -static void do_mix_operation_color4f(const int blend_mode, - const VArray<float> &factors, - const VArray<ColorGeometry4f> &inputs_a, - const VArray<ColorGeometry4f> &inputs_b, - VMutableArray<ColorGeometry4f> &results) -{ - const int size = results.size(); - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float factor = factors[i]; - ColorGeometry4f a = inputs_a[i]; - const ColorGeometry4f b = inputs_b[i]; - ramp_blend(blend_mode, a, factor, b); - results.set(i, a); - } - }); -} - -static void do_mix_operation(const CustomDataType result_type, - int blend_mode, - const VArray<float> &attribute_factor, - const GVArray &attribute_a, - const GVArray &attribute_b, - GVMutableArray &attribute_result) -{ - if (result_type == CD_PROP_FLOAT) { - VMutableArray<float> result = attribute_result.typed<float>(); - do_mix_operation_float(blend_mode, - attribute_factor, - attribute_a.typed<float>(), - attribute_b.typed<float>(), - result); - } - else if (result_type == CD_PROP_FLOAT3) { - VMutableArray<float3> result = attribute_result.typed<float3>(); - do_mix_operation_float3(blend_mode, - attribute_factor, - attribute_a.typed<float3>(), - attribute_b.typed<float3>(), - result); - } - else if (result_type == CD_PROP_COLOR) { - VMutableArray<ColorGeometry4f> result = attribute_result.typed<ColorGeometry4f>(); - do_mix_operation_color4f(blend_mode, - attribute_factor, - attribute_a.typed<ColorGeometry4f>(), - attribute_b.typed<ColorGeometry4f>(), - result); - } -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - const GeoNodeExecParams ¶ms, - StringRef result_name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - - /* Otherwise use the highest priority domain from existing input attributes, or the default. */ - return params.get_highest_priority_input_domain({"A", "B"}, component, ATTR_DOMAIN_POINT); -} - -static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - const NodeAttributeMix *node_storage = (const NodeAttributeMix *)node.storage; - const std::string result_name = params.get_input<std::string>("Result"); - - /* Use the highest complexity data type among the inputs and outputs, that way the node will - * never "remove information". Use CD_PROP_BOOL as the lowest complexity data type, but in any - * real situation it won't be returned. */ - const CustomDataType result_type = bke::attribute_data_type_highest_complexity({ - params.get_input_attribute_data_type("A", component, CD_PROP_BOOL), - params.get_input_attribute_data_type("B", component, CD_PROP_BOOL), - params.get_input_attribute_data_type("Result", component, CD_PROP_BOOL), - }); - - const AttributeDomain result_domain = get_result_domain(component, params, result_name); - - OutputAttribute attribute_result = component.attribute_try_get_for_output_only( - result_name, result_domain, result_type); - if (!attribute_result) { - return; - } - - VArray<float> attribute_factor = params.get_input_attribute<float>( - "Factor", component, result_domain, 0.5f); - GVArray attribute_a = params.get_input_attribute( - "A", component, result_domain, result_type, nullptr); - GVArray attribute_b = params.get_input_attribute( - "B", component, result_domain, result_type, nullptr); - - do_mix_operation(result_type, - node_storage->blend_type, - attribute_factor, - attribute_a, - attribute_b, - attribute_result.varray()); - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - attribute_mix_calc(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - attribute_mix_calc(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - attribute_mix_calc(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_mix_cc - -void register_node_type_geo_attribute_mix() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_mix_cc; - - static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_LEGACY_ATTRIBUTE_MIX, "Attribute Mix", NODE_CLASS_ATTRIBUTE); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - ntype.declare = file_ns::node_declare; - ntype.draw_buttons = file_ns::node_layout; - node_type_storage( - &ntype, "NodeAttributeMix", node_free_standard_storage, node_copy_standard_storage); - ntype.geometry_node_execute = file_ns::node_geo_exec; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_proximity.cc deleted file mode 100644 index a3af6200ab8..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_proximity.cc +++ /dev/null @@ -1,237 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_task.hh" -#include "BLI_timeit.hh" - -#include "DNA_mesh_types.h" - -#include "BKE_bvhutils.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_proximity_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Geometry>(N_("Target")); - b.add_input<decl::String>(N_("Distance")); - b.add_input<decl::String>(N_("Position")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "target_geometry_element", 0, "", ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeGeometryAttributeProximity *node_storage = MEM_cnew<NodeGeometryAttributeProximity>( - __func__); - - node_storage->target_geometry_element = GEO_NODE_PROXIMITY_TARGET_FACES; - node->storage = node_storage; -} - -static void calculate_mesh_proximity(const VArray<float3> &positions, - const Mesh &mesh, - const GeometryNodeAttributeProximityTargetType type, - MutableSpan<float> r_distances, - MutableSpan<float3> r_locations) -{ - BVHTreeFromMesh bvh_data; - switch (type) { - case GEO_NODE_PROXIMITY_TARGET_POINTS: - BKE_bvhtree_from_mesh_get(&bvh_data, &mesh, BVHTREE_FROM_VERTS, 2); - break; - case GEO_NODE_PROXIMITY_TARGET_EDGES: - BKE_bvhtree_from_mesh_get(&bvh_data, &mesh, BVHTREE_FROM_EDGES, 2); - break; - case GEO_NODE_PROXIMITY_TARGET_FACES: - BKE_bvhtree_from_mesh_get(&bvh_data, &mesh, BVHTREE_FROM_LOOPTRI, 2); - break; - } - - if (bvh_data.tree == nullptr) { - return; - } - - threading::parallel_for(positions.index_range(), 512, [&](IndexRange range) { - BVHTreeNearest nearest; - copy_v3_fl(nearest.co, FLT_MAX); - nearest.index = -1; - - for (int i : range) { - /* Use the distance to the last found point as upper bound to speedup the bvh lookup. */ - nearest.dist_sq = math::distance_squared(float3(nearest.co), positions[i]); - - BLI_bvhtree_find_nearest( - bvh_data.tree, positions[i], &nearest, bvh_data.nearest_callback, &bvh_data); - - if (nearest.dist_sq < r_distances[i]) { - r_distances[i] = nearest.dist_sq; - if (!r_locations.is_empty()) { - r_locations[i] = nearest.co; - } - } - } - }); - - free_bvhtree_from_mesh(&bvh_data); -} - -static void calculate_pointcloud_proximity(const VArray<float3> &positions, - const PointCloud &pointcloud, - MutableSpan<float> r_distances, - MutableSpan<float3> r_locations) -{ - BVHTreeFromPointCloud bvh_data; - BKE_bvhtree_from_pointcloud_get(&bvh_data, &pointcloud, 2); - if (bvh_data.tree == nullptr) { - return; - } - - threading::parallel_for(positions.index_range(), 512, [&](IndexRange range) { - BVHTreeNearest nearest; - copy_v3_fl(nearest.co, FLT_MAX); - nearest.index = -1; - - for (int i : range) { - /* Use the distance to the closest point in the mesh to speedup the pointcloud bvh lookup. - * This is ok because we only need to find the closest point in the pointcloud if it's - * closer than the mesh. */ - nearest.dist_sq = r_distances[i]; - - BLI_bvhtree_find_nearest( - bvh_data.tree, positions[i], &nearest, bvh_data.nearest_callback, &bvh_data); - - if (nearest.dist_sq < r_distances[i]) { - r_distances[i] = nearest.dist_sq; - if (!r_locations.is_empty()) { - r_locations[i] = nearest.co; - } - } - } - }); - - free_bvhtree_from_pointcloud(&bvh_data); -} - -static void attribute_calc_proximity(GeometryComponent &component, - GeometrySet &target, - GeoNodeExecParams ¶ms) -{ - const std::string distance_name = params.get_input<std::string>("Distance"); - OutputAttribute_Typed<float> distance_attribute = - component.attribute_try_get_for_output_only<float>(distance_name, ATTR_DOMAIN_POINT); - - const std::string location_name = params.get_input<std::string>("Position"); - OutputAttribute_Typed<float3> location_attribute = - component.attribute_try_get_for_output_only<float3>(location_name, ATTR_DOMAIN_POINT); - - ReadAttributeLookup position_attribute = component.attribute_try_get_for_read("position"); - if (!position_attribute || (!distance_attribute && !location_attribute)) { - return; - } - VArray<float3> positions = position_attribute.varray.typed<float3>(); - const NodeGeometryAttributeProximity &storage = - *(const NodeGeometryAttributeProximity *)params.node().storage; - - Array<float> distances_internal; - MutableSpan<float> distances; - if (distance_attribute) { - distances = distance_attribute.as_span(); - } - else { - /* Theoretically it would be possible to avoid using the distance array when it's not required - * and there is only one component. However, this only adds an allocation and a single float - * comparison per vertex, so it's likely not worth it. */ - distances_internal.reinitialize(positions.size()); - distances = distances_internal; - } - distances.fill(FLT_MAX); - MutableSpan<float3> locations = location_attribute ? location_attribute.as_span() : - MutableSpan<float3>(); - - if (target.has_mesh()) { - calculate_mesh_proximity( - positions, - *target.get_mesh_for_read(), - static_cast<GeometryNodeAttributeProximityTargetType>(storage.target_geometry_element), - distances, - locations); - } - - if (target.has_pointcloud() && - storage.target_geometry_element == GEO_NODE_PROXIMITY_TARGET_POINTS) { - calculate_pointcloud_proximity( - positions, *target.get_pointcloud_for_read(), distances, locations); - } - - if (distance_attribute) { - /* Squared distances are used above to speed up comparisons, - * so do the square roots now if necessary for the output attribute. */ - threading::parallel_for(distances.index_range(), 2048, [&](IndexRange range) { - for (const int i : range) { - distances[i] = std::sqrt(distances[i]); - } - }); - distance_attribute.save(); - } - if (location_attribute) { - location_attribute.save(); - } -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - GeometrySet geometry_set_target = params.extract_input<GeometrySet>("Target"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - /* This isn't required. This node should be rewritten to handle instances - * for the target geometry set. However, the generic BVH API complicates this. */ - geometry_set_target = geometry::realize_instances_legacy(geometry_set_target); - - if (geometry_set.has<MeshComponent>()) { - attribute_calc_proximity( - geometry_set.get_component_for_write<MeshComponent>(), geometry_set_target, params); - } - if (geometry_set.has<PointCloudComponent>()) { - attribute_calc_proximity( - geometry_set.get_component_for_write<PointCloudComponent>(), geometry_set_target, params); - } - if (geometry_set.has<CurveComponent>()) { - attribute_calc_proximity( - geometry_set.get_component_for_write<CurveComponent>(), geometry_set_target, params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_proximity_cc - -void register_node_type_geo_legacy_attribute_proximity() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_proximity_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_PROXIMITY, "Attribute Proximity", NODE_CLASS_ATTRIBUTE); - node_type_init(&ntype, file_ns::node_init); - node_type_storage(&ntype, - "NodeGeometryAttributeProximity", - node_free_standard_storage, - node_copy_standard_storage); - - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_randomize.cc deleted file mode 100644 index 6a306229b8c..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_randomize.cc +++ /dev/null @@ -1,333 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_hash.h" -#include "BLI_rand.hh" -#include "BLI_task.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes { - -Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &component, - const AttributeDomain domain) -{ - const int domain_size = component.attribute_domain_size(domain); - - /* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */ - GVArray hash_attribute = component.attribute_try_get_for_read("id", domain); - Array<uint32_t> hashes(domain_size); - if (hash_attribute) { - BLI_assert(hashes.size() == hash_attribute.size()); - const CPPType &cpp_type = hash_attribute.type(); - BLI_assert(cpp_type.is_hashable()); - GVArray_GSpan items{hash_attribute}; - threading::parallel_for(hashes.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - hashes[i] = cpp_type.hash(items[i]); - } - }); - } - else { - /* If there is no "id" attribute for per-point variation, just create it here. */ - RandomNumberGenerator rng(0); - for (const int i : hashes.index_range()) { - hashes[i] = rng.get_uint32(); - } - } - - return hashes; -} - -} // namespace blender::nodes - -namespace blender::nodes::node_geo_legacy_attribute_randomize_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Attribute")); - b.add_input<decl::Vector>(N_("Min")); - b.add_input<decl::Vector>(N_("Max")).default_value({1.0f, 1.0f, 1.0f}); - b.add_input<decl::Float>(N_("Min"), "Min_001"); - b.add_input<decl::Float>(N_("Max"), "Max_001").default_value(1.0f); - b.add_input<decl::Int>(N_("Min"), "Min_002").min(-100000).max(100000); - b.add_input<decl::Int>(N_("Max"), "Max_002").default_value(100).min(-100000).max(100000); - b.add_input<decl::Int>(N_("Seed")).min(-10000).max(10000); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeAttributeRandomize *data = MEM_cnew<NodeAttributeRandomize>(__func__); - data->data_type = CD_PROP_FLOAT; - data->domain = ATTR_DOMAIN_POINT; - data->operation = GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - bNodeSocket *sock_min_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 2); - bNodeSocket *sock_max_vector = sock_min_vector->next; - bNodeSocket *sock_min_float = sock_max_vector->next; - bNodeSocket *sock_max_float = sock_min_float->next; - bNodeSocket *sock_min_int = sock_max_float->next; - bNodeSocket *sock_max_int = sock_min_int->next; - - const NodeAttributeRandomize &storage = *(const NodeAttributeRandomize *)node->storage; - const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type); - nodeSetSocketAvailability(ntree, sock_min_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, sock_max_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, sock_min_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, sock_max_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, sock_min_int, data_type == CD_PROP_INT32); - nodeSetSocketAvailability(ntree, sock_max_int, data_type == CD_PROP_INT32); -} - -template<typename T> -T random_value_in_range(const uint32_t id, const uint32_t seed, const T min, const T max); - -template<> -inline float random_value_in_range(const uint32_t id, - const uint32_t seed, - const float min, - const float max) -{ - return BLI_hash_int_2d_to_float(id, seed) * (max - min) + min; -} - -template<> -inline int random_value_in_range(const uint32_t id, - const uint32_t seed, - const int min, - const int max) -{ - return round_fl_to_int( - random_value_in_range<float>(id, seed, static_cast<float>(min), static_cast<float>(max))); -} - -template<> -inline float3 random_value_in_range(const uint32_t id, - const uint32_t seed, - const float3 min, - const float3 max) -{ - const float x = BLI_hash_int_3d_to_float(seed, id, 435109); - const float y = BLI_hash_int_3d_to_float(seed, id, 380867); - const float z = BLI_hash_int_3d_to_float(seed, id, 1059217); - - return float3(x, y, z) * (max - min) + min; -} - -template<typename T> -static void randomize_attribute(MutableSpan<T> span, - const T min, - const T max, - Span<uint32_t> ids, - const uint32_t seed, - const GeometryNodeAttributeRandomizeMode operation) -{ - /* The operations could be templated too, but it doesn't make the code much shorter. */ - switch (operation) { - case GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE: - threading::parallel_for(span.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - const T random_value = random_value_in_range<T>(ids[i], seed, min, max); - span[i] = random_value; - } - }); - break; - case GEO_NODE_ATTRIBUTE_RANDOMIZE_ADD: - threading::parallel_for(span.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - const T random_value = random_value_in_range<T>(ids[i], seed, min, max); - span[i] = span[i] + random_value; - } - }); - break; - case GEO_NODE_ATTRIBUTE_RANDOMIZE_SUBTRACT: - threading::parallel_for(span.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - const T random_value = random_value_in_range<T>(ids[i], seed, min, max); - span[i] = span[i] - random_value; - } - }); - break; - case GEO_NODE_ATTRIBUTE_RANDOMIZE_MULTIPLY: - threading::parallel_for(span.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - const T random_value = random_value_in_range<T>(ids[i], seed, min, max); - span[i] = span[i] * random_value; - } - }); - break; - default: - BLI_assert(false); - break; - } -} - -static void randomize_attribute_bool(MutableSpan<bool> span, - Span<uint32_t> ids, - const uint32_t seed, - const GeometryNodeAttributeRandomizeMode operation) -{ - BLI_assert(operation == GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE); - UNUSED_VARS_NDEBUG(operation); - threading::parallel_for(span.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - const bool random_value = BLI_hash_int_2d_to_float(ids[i], seed) > 0.5f; - span[i] = random_value; - } - }); -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - const GeoNodeExecParams ¶ms, - const StringRef name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(name); - if (result_info) { - return result_info->domain; - } - - /* Otherwise use the input domain chosen in the interface. */ - const bNode &node = params.node(); - return static_cast<AttributeDomain>(node.custom2); -} - -static void randomize_attribute_on_component(GeometryComponent &component, - const GeoNodeExecParams ¶ms, - StringRef attribute_name, - const CustomDataType data_type, - const GeometryNodeAttributeRandomizeMode operation, - const int seed) -{ - /* If the node is not in "replace / create" mode and the attribute - * doesn't already exist, don't do the operation. */ - if (operation != GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE) { - if (!component.attribute_exists(attribute_name)) { - params.error_message_add(NodeWarningType::Error, - TIP_("No attribute with name \"") + attribute_name + "\""); - return; - } - } - - const AttributeDomain domain = get_result_domain(component, params, attribute_name); - - OutputAttribute attribute = component.attribute_try_get_for_output( - attribute_name, domain, data_type); - if (!attribute) { - return; - } - - GMutableSpan span = attribute.as_span(); - - Array<uint32_t> hashes = get_geometry_element_ids_as_uints(component, domain); - - switch (data_type) { - case CD_PROP_FLOAT3: { - const float3 min = params.get_input<float3>("Min"); - const float3 max = params.get_input<float3>("Max"); - randomize_attribute<float3>(span.typed<float3>(), min, max, hashes, seed, operation); - break; - } - case CD_PROP_FLOAT: { - const float min = params.get_input<float>("Min_001"); - const float max = params.get_input<float>("Max_001"); - randomize_attribute<float>(span.typed<float>(), min, max, hashes, seed, operation); - break; - } - case CD_PROP_BOOL: { - randomize_attribute_bool(span.typed<bool>(), hashes, seed, operation); - break; - } - case CD_PROP_INT32: { - const int min = params.get_input<int>("Min_002"); - const int max = params.get_input<int>("Max_002"); - randomize_attribute<int>(span.typed<int>(), min, max, hashes, seed, operation); - break; - } - default: { - BLI_assert(false); - break; - } - } - - attribute.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - const std::string attribute_name = params.get_input<std::string>("Attribute"); - if (attribute_name.empty()) { - params.set_default_remaining_outputs(); - return; - } - const int seed = params.get_input<int>("Seed"); - const NodeAttributeRandomize &storage = *(const NodeAttributeRandomize *)params.node().storage; - const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type); - const GeometryNodeAttributeRandomizeMode operation = - static_cast<GeometryNodeAttributeRandomizeMode>(storage.operation); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - randomize_attribute_on_component(geometry_set.get_component_for_write<MeshComponent>(), - params, - attribute_name, - data_type, - operation, - seed); - } - if (geometry_set.has<PointCloudComponent>()) { - randomize_attribute_on_component(geometry_set.get_component_for_write<PointCloudComponent>(), - params, - attribute_name, - data_type, - operation, - seed); - } - if (geometry_set.has<CurveComponent>()) { - randomize_attribute_on_component(geometry_set.get_component_for_write<CurveComponent>(), - params, - attribute_name, - data_type, - operation, - seed); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_randomize_cc - -void register_node_type_geo_legacy_attribute_randomize() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_randomize_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_RANDOMIZE, "Attribute Randomize", NODE_CLASS_ATTRIBUTE); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - node_type_storage( - &ntype, "NodeAttributeRandomize", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_remove.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_remove.cc deleted file mode 100644 index cc7118fd305..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_remove.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_remove_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Attribute")).multi_input(); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void remove_attribute(GeometryComponent &component, - GeoNodeExecParams ¶ms, - Span<std::string> attribute_names) -{ - for (std::string attribute_name : attribute_names) { - if (attribute_name.empty()) { - continue; - } - - if (!component.attribute_try_delete(attribute_name)) { - params.error_message_add(NodeWarningType::Error, - TIP_("Cannot delete attribute with name \"") + attribute_name + - "\""); - } - } -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - Vector<std::string> attribute_names = params.extract_multi_input<std::string>("Attribute"); - - for (const GeometryComponentType type : {GEO_COMPONENT_TYPE_MESH, - GEO_COMPONENT_TYPE_POINT_CLOUD, - GEO_COMPONENT_TYPE_CURVE, - GEO_COMPONENT_TYPE_INSTANCES}) { - if (geometry_set.has(type)) { - remove_attribute(geometry_set.get_component_for_write(type), params, attribute_names); - } - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_remove_cc - -void register_node_type_geo_legacy_attribute_remove() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_remove_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_REMOVE, "Attribute Remove", NODE_CLASS_ATTRIBUTE); - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.declare = file_ns::node_declare; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_sample_texture.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_sample_texture.cc deleted file mode 100644 index 42719d4bf1a..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_sample_texture.cc +++ /dev/null @@ -1,124 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_compiler_attrs.h" -#include "BLI_task.hh" - -#include "DNA_texture_types.h" - -#include "BKE_texture.h" - -#include "RE_texture.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_sample_texture_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Texture>(N_("Texture")).hide_label(); - b.add_input<decl::String>(N_("Mapping")); - b.add_input<decl::String>(N_("Result")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - const StringRef result_name, - const StringRef map_name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - - /* Otherwise use the name of the map attribute. */ - std::optional<AttributeMetaData> map_info = component.attribute_get_meta_data(map_name); - if (map_info) { - return map_info->domain; - } - - /* The node won't execute in this case, but we still have to return a value. */ - return ATTR_DOMAIN_POINT; -} - -static void execute_on_component(GeometryComponent &component, const GeoNodeExecParams ¶ms) -{ - Tex *texture = params.get_input<Tex *>("Texture"); - if (texture == nullptr) { - return; - } - - const std::string result_attribute_name = params.get_input<std::string>("Result"); - const std::string mapping_name = params.get_input<std::string>("Mapping"); - if (!component.attribute_exists(mapping_name)) { - return; - } - - const AttributeDomain result_domain = get_result_domain( - component, result_attribute_name, mapping_name); - - OutputAttribute_Typed<ColorGeometry4f> attribute_out = - component.attribute_try_get_for_output_only<ColorGeometry4f>(result_attribute_name, - result_domain); - if (!attribute_out) { - return; - } - - VArray<float3> mapping_attribute = component.attribute_get_for_read<float3>( - mapping_name, result_domain, {0, 0, 0}); - - MutableSpan<ColorGeometry4f> colors = attribute_out.as_span(); - threading::parallel_for(IndexRange(mapping_attribute.size()), 128, [&](IndexRange range) { - for (const int i : range) { - TexResult texture_result = {0}; - const float3 position = mapping_attribute[i]; - /* For legacy reasons we have to map [0, 1] to [-1, 1] to support uv mappings. */ - const float3 remapped_position = position * 2.0f - float3(1.0f); - BKE_texture_get_value(nullptr, texture, remapped_position, &texture_result, false); - copy_v4_v4(colors[i], texture_result.trgba); - } - }); - - attribute_out.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - execute_on_component(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - execute_on_component(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - execute_on_component(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_sample_texture_cc - -void register_node_type_geo_sample_texture() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_sample_texture_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, - GEO_NODE_LEGACY_ATTRIBUTE_SAMPLE_TEXTURE, - "Attribute Sample Texture", - NODE_CLASS_ATTRIBUTE); - node_type_size_preset(&ntype, NODE_SIZE_LARGE); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_separate_xyz.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_separate_xyz.cc deleted file mode 100644 index 85ffbf6679b..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_separate_xyz.cc +++ /dev/null @@ -1,157 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_separate_xyz_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Vector")); - b.add_input<decl::Vector>(N_("Vector"), "Vector_001"); - b.add_input<decl::String>(N_("Result X")); - b.add_input<decl::String>(N_("Result Y")); - b.add_input<decl::String>(N_("Result Z")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "input_type", 0, IFACE_("Type"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeAttributeSeparateXYZ *data = MEM_cnew<NodeAttributeSeparateXYZ>(__func__); - data->input_type = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeAttributeSeparateXYZ *node_storage = (NodeAttributeSeparateXYZ *)node->storage; - update_attribute_input_socket_availabilities( - *ntree, *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type); -} - -static void extract_input(const int index, const Span<float3> &input, MutableSpan<float> result) -{ - for (const int i : result.index_range()) { - /* Get the component of the float3. (0: X, 1: Y, 2: Z). */ - const float component = input[i][index]; - result[i] = component; - } -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - const GeoNodeExecParams ¶ms, - const StringRef name_x, - const StringRef name_y, - const StringRef name_z) -{ - /* Use the highest priority domain from any existing attribute outputs. */ - Vector<AttributeDomain, 3> output_domains; - std::optional<AttributeMetaData> info_x = component.attribute_get_meta_data(name_x); - std::optional<AttributeMetaData> info_y = component.attribute_get_meta_data(name_y); - std::optional<AttributeMetaData> info_z = component.attribute_get_meta_data(name_z); - if (info_x) { - output_domains.append(info_x->domain); - } - if (info_y) { - output_domains.append(info_y->domain); - } - if (info_z) { - output_domains.append(info_z->domain); - } - if (output_domains.size() > 0) { - return bke::attribute_domain_highest_priority(output_domains); - } - - /* Otherwise use the domain of the input attribute, or the default. */ - return params.get_highest_priority_input_domain({"Vector"}, component, ATTR_DOMAIN_POINT); -} - -static void separate_attribute(GeometryComponent &component, const GeoNodeExecParams ¶ms) -{ - const std::string result_name_x = params.get_input<std::string>("Result X"); - const std::string result_name_y = params.get_input<std::string>("Result Y"); - const std::string result_name_z = params.get_input<std::string>("Result Z"); - if (result_name_x.empty() && result_name_y.empty() && result_name_z.empty()) { - return; - } - - /* The node is only for float3 to float conversions. */ - const AttributeDomain result_domain = get_result_domain( - component, params, result_name_x, result_name_y, result_name_z); - - VArray<float3> attribute_input = params.get_input_attribute<float3>( - "Vector", component, result_domain, {0, 0, 0}); - VArray_Span<float3> input_span{attribute_input}; - - OutputAttribute_Typed<float> attribute_result_x = - component.attribute_try_get_for_output_only<float>(result_name_x, result_domain); - OutputAttribute_Typed<float> attribute_result_y = - component.attribute_try_get_for_output_only<float>(result_name_y, result_domain); - OutputAttribute_Typed<float> attribute_result_z = - component.attribute_try_get_for_output_only<float>(result_name_z, result_domain); - - /* Only extract the components for the outputs with a given attribute. */ - if (attribute_result_x) { - extract_input(0, input_span, attribute_result_x.as_span()); - attribute_result_x.save(); - } - if (attribute_result_y) { - extract_input(1, input_span, attribute_result_y.as_span()); - attribute_result_y.save(); - } - if (attribute_result_z) { - extract_input(2, input_span, attribute_result_z.as_span()); - attribute_result_z.save(); - } -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - separate_attribute(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - separate_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - separate_attribute(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_separate_xyz_cc - -void register_node_type_geo_attribute_separate_xyz() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_separate_xyz_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, - GEO_NODE_LEGACY_ATTRIBUTE_SEPARATE_XYZ, - "Attribute Separate XYZ", - NODE_CLASS_ATTRIBUTE); - ntype.declare = file_ns::node_declare; - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - node_type_storage( - &ntype, "NodeAttributeSeparateXYZ", node_free_standard_storage, node_copy_standard_storage); - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_transfer.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_transfer.cc deleted file mode 100644 index 802feb88ce2..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_transfer.cc +++ /dev/null @@ -1,515 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_kdopbvh.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_pointcloud_types.h" - -#include "BKE_bvhutils.h" -#include "BKE_mesh_runtime.h" -#include "BKE_mesh_sample.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_transfer_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Geometry>(N_("Source Geometry")); - b.add_input<decl::String>(N_("Source")); - b.add_input<decl::String>(N_("Destination")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "domain", 0, IFACE_("Domain"), ICON_NONE); - uiItemR(layout, ptr, "mapping", 0, IFACE_("Mapping"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryAttributeTransfer *data = MEM_cnew<NodeGeometryAttributeTransfer>(__func__); - data->domain = ATTR_DOMAIN_AUTO; - node->storage = data; -} - -static void get_result_domain_and_data_type(const GeometrySet &src_geometry, - const GeometryComponent &dst_component, - const StringRef attribute_name, - CustomDataType *r_data_type, - AttributeDomain *r_domain) -{ - Vector<CustomDataType> data_types; - Vector<AttributeDomain> domains; - - const PointCloudComponent *pointcloud_component = - src_geometry.get_component_for_read<PointCloudComponent>(); - if (pointcloud_component != nullptr) { - std::optional<AttributeMetaData> meta_data = pointcloud_component->attribute_get_meta_data( - attribute_name); - if (meta_data.has_value()) { - data_types.append(meta_data->data_type); - domains.append(meta_data->domain); - } - } - - const MeshComponent *mesh_component = src_geometry.get_component_for_read<MeshComponent>(); - if (mesh_component != nullptr) { - std::optional<AttributeMetaData> meta_data = mesh_component->attribute_get_meta_data( - attribute_name); - if (meta_data.has_value()) { - data_types.append(meta_data->data_type); - domains.append(meta_data->domain); - } - } - - *r_data_type = bke::attribute_data_type_highest_complexity(data_types); - - if (dst_component.type() == GEO_COMPONENT_TYPE_POINT_CLOUD) { - *r_domain = ATTR_DOMAIN_POINT; - } - else { - *r_domain = bke::attribute_domain_highest_priority(domains); - } -} - -static void get_closest_in_bvhtree(BVHTreeFromMesh &tree_data, - const VArray<float3> &positions, - const MutableSpan<int> r_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(positions.size() == r_indices.size() || r_indices.is_empty()); - BLI_assert(positions.size() == r_distances_sq.size() || r_distances_sq.is_empty()); - BLI_assert(positions.size() == r_positions.size() || r_positions.is_empty()); - - for (const int i : positions.index_range()) { - BVHTreeNearest nearest; - nearest.dist_sq = FLT_MAX; - const float3 position = positions[i]; - BLI_bvhtree_find_nearest( - tree_data.tree, position, &nearest, tree_data.nearest_callback, &tree_data); - if (!r_indices.is_empty()) { - r_indices[i] = nearest.index; - } - if (!r_distances_sq.is_empty()) { - r_distances_sq[i] = nearest.dist_sq; - } - if (!r_positions.is_empty()) { - r_positions[i] = nearest.co; - } - } -} - -static void get_closest_pointcloud_points(const PointCloud &pointcloud, - const VArray<float3> &positions, - const MutableSpan<int> r_indices, - const MutableSpan<float> r_distances_sq) -{ - BLI_assert(positions.size() == r_indices.size()); - BLI_assert(pointcloud.totpoint > 0); - - BVHTreeFromPointCloud tree_data; - BKE_bvhtree_from_pointcloud_get(&tree_data, &pointcloud, 2); - - for (const int i : positions.index_range()) { - BVHTreeNearest nearest; - nearest.dist_sq = FLT_MAX; - const float3 position = positions[i]; - BLI_bvhtree_find_nearest( - tree_data.tree, position, &nearest, tree_data.nearest_callback, &tree_data); - r_indices[i] = nearest.index; - r_distances_sq[i] = nearest.dist_sq; - } - - free_bvhtree_from_pointcloud(&tree_data); -} - -static void get_closest_mesh_points(const Mesh &mesh, - const VArray<float3> &positions, - const MutableSpan<int> r_point_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(mesh.totvert > 0); - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_VERTS, 2); - get_closest_in_bvhtree(tree_data, positions, r_point_indices, r_distances_sq, r_positions); - free_bvhtree_from_mesh(&tree_data); -} - -static void get_closest_mesh_edges(const Mesh &mesh, - const VArray<float3> &positions, - const MutableSpan<int> r_edge_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(mesh.totedge > 0); - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_EDGES, 2); - get_closest_in_bvhtree(tree_data, positions, r_edge_indices, r_distances_sq, r_positions); - free_bvhtree_from_mesh(&tree_data); -} - -static void get_closest_mesh_looptris(const Mesh &mesh, - const VArray<float3> &positions, - const MutableSpan<int> r_looptri_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(mesh.totpoly > 0); - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_LOOPTRI, 2); - get_closest_in_bvhtree(tree_data, positions, r_looptri_indices, r_distances_sq, r_positions); - free_bvhtree_from_mesh(&tree_data); -} - -static void get_closest_mesh_polygons(const Mesh &mesh, - const VArray<float3> &positions, - const MutableSpan<int> r_poly_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(mesh.totpoly > 0); - - Array<int> looptri_indices(positions.size()); - get_closest_mesh_looptris(mesh, positions, looptri_indices, r_distances_sq, r_positions); - - const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), - BKE_mesh_runtime_looptri_len(&mesh)}; - for (const int i : positions.index_range()) { - const MLoopTri &looptri = looptris[looptri_indices[i]]; - r_poly_indices[i] = looptri.poly; - } -} - -/* The closest corner is defined to be the closest corner on the closest face. */ -static void get_closest_mesh_corners(const Mesh &mesh, - const VArray<float3> &positions, - const MutableSpan<int> r_corner_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(mesh.totloop > 0); - Array<int> poly_indices(positions.size()); - get_closest_mesh_polygons(mesh, positions, poly_indices, {}, {}); - - for (const int i : positions.index_range()) { - const float3 position = positions[i]; - const int poly_index = poly_indices[i]; - const MPoly &poly = mesh.mpoly[poly_index]; - - /* Find the closest vertex in the polygon. */ - float min_distance_sq = FLT_MAX; - const MVert *closest_mvert; - int closest_loop_index = 0; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = mesh.mloop[loop_index]; - const int vertex_index = loop.v; - const MVert &mvert = mesh.mvert[vertex_index]; - const float distance_sq = math::distance_squared(position, float3(mvert.co)); - if (distance_sq < min_distance_sq) { - min_distance_sq = distance_sq; - closest_loop_index = loop_index; - closest_mvert = &mvert; - } - } - if (!r_corner_indices.is_empty()) { - r_corner_indices[i] = closest_loop_index; - } - if (!r_positions.is_empty()) { - r_positions[i] = closest_mvert->co; - } - if (!r_distances_sq.is_empty()) { - r_distances_sq[i] = min_distance_sq; - } - } -} - -static void transfer_attribute_nearest_face_interpolated(const GeometrySet &src_geometry, - GeometryComponent &dst_component, - const VArray<float3> &dst_positions, - const AttributeDomain dst_domain, - const CustomDataType data_type, - const StringRef src_name, - const StringRef dst_name) -{ - const int tot_samples = dst_positions.size(); - const MeshComponent *component = src_geometry.get_component_for_read<MeshComponent>(); - if (component == nullptr) { - return; - } - const Mesh *mesh = component->get_for_read(); - if (mesh == nullptr) { - return; - } - if (mesh->totpoly == 0) { - return; - } - - ReadAttributeLookup src_attribute = component->attribute_try_get_for_read(src_name, data_type); - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - dst_name, dst_domain, data_type); - if (!src_attribute || !dst_attribute) { - return; - } - - /* Find closest points on the mesh surface. */ - Array<int> looptri_indices(tot_samples); - Array<float3> positions(tot_samples); - get_closest_mesh_looptris(*mesh, dst_positions, looptri_indices, {}, positions); - - bke::mesh_surface_sample::MeshAttributeInterpolator interp( - mesh, IndexMask(tot_samples), positions, looptri_indices); - interp.sample_attribute( - src_attribute, dst_attribute, bke::mesh_surface_sample::eAttributeMapMode::INTERPOLATED); - - dst_attribute.save(); -} - -static void transfer_attribute_nearest(const GeometrySet &src_geometry, - GeometryComponent &dst_component, - const VArray<float3> &dst_positions, - const AttributeDomain dst_domain, - const CustomDataType data_type, - const StringRef src_name, - const StringRef dst_name) -{ - const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type); - - /* Get pointcloud data from geometry. */ - const PointCloudComponent *pointcloud_component = - src_geometry.get_component_for_read<PointCloudComponent>(); - const PointCloud *pointcloud = pointcloud_component ? pointcloud_component->get_for_read() : - nullptr; - - /* Get mesh data from geometry. */ - const MeshComponent *mesh_component = src_geometry.get_component_for_read<MeshComponent>(); - const Mesh *mesh = mesh_component ? mesh_component->get_for_read() : nullptr; - - const int tot_samples = dst_positions.size(); - - Array<int> pointcloud_indices; - Array<float> pointcloud_distances_sq; - bool use_pointcloud = false; - - /* Depending on where what domain the source attribute lives, these indices are either vertex, - * corner, edge or polygon indices. */ - Array<int> mesh_indices; - Array<float> mesh_distances_sq; - bool use_mesh = false; - - /* If there is a pointcloud, find the closest points. */ - if (pointcloud != nullptr && pointcloud->totpoint > 0) { - if (pointcloud_component->attribute_exists(src_name)) { - use_pointcloud = true; - pointcloud_indices.reinitialize(tot_samples); - pointcloud_distances_sq.reinitialize(tot_samples); - get_closest_pointcloud_points( - *pointcloud, dst_positions, pointcloud_indices, pointcloud_distances_sq); - } - } - - /* If there is a mesh, find the closest mesh elements. */ - if (mesh != nullptr) { - ReadAttributeLookup src_attribute = mesh_component->attribute_try_get_for_read(src_name); - if (src_attribute) { - switch (src_attribute.domain) { - case ATTR_DOMAIN_POINT: { - if (mesh->totvert > 0) { - use_mesh = true; - mesh_indices.reinitialize(tot_samples); - mesh_distances_sq.reinitialize(tot_samples); - get_closest_mesh_points(*mesh, dst_positions, mesh_indices, mesh_distances_sq, {}); - } - break; - } - case ATTR_DOMAIN_EDGE: { - if (mesh->totedge > 0) { - use_mesh = true; - mesh_indices.reinitialize(tot_samples); - mesh_distances_sq.reinitialize(tot_samples); - get_closest_mesh_edges(*mesh, dst_positions, mesh_indices, mesh_distances_sq, {}); - } - break; - } - case ATTR_DOMAIN_FACE: { - if (mesh->totpoly > 0) { - use_mesh = true; - mesh_indices.reinitialize(tot_samples); - mesh_distances_sq.reinitialize(tot_samples); - get_closest_mesh_polygons(*mesh, dst_positions, mesh_indices, mesh_distances_sq, {}); - } - break; - } - case ATTR_DOMAIN_CORNER: { - if (mesh->totloop > 0) { - use_mesh = true; - mesh_indices.reinitialize(tot_samples); - mesh_distances_sq.reinitialize(tot_samples); - get_closest_mesh_corners(*mesh, dst_positions, mesh_indices, mesh_distances_sq, {}); - } - break; - } - default: { - break; - } - } - } - } - - if (!use_pointcloud && !use_mesh) { - return; - } - - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - dst_name, dst_domain, data_type); - if (!dst_attribute) { - return; - } - - /* Create a buffer for intermediate values. */ - BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); - - if (use_mesh && use_pointcloud) { - /* When there is a mesh and a pointcloud, we still have to check whether a pointcloud point or - * a mesh element is closer to every point. */ - ReadAttributeLookup pointcloud_src_attribute = - pointcloud_component->attribute_try_get_for_read(src_name, data_type); - ReadAttributeLookup mesh_src_attribute = mesh_component->attribute_try_get_for_read(src_name, - data_type); - for (const int i : IndexRange(tot_samples)) { - if (pointcloud_distances_sq[i] < mesh_distances_sq[i]) { - /* Point cloud point is closer. */ - const int index = pointcloud_indices[i]; - pointcloud_src_attribute.varray.get(index, buffer); - dst_attribute->set_by_relocate(i, buffer); - } - else { - /* Mesh element is closer. */ - const int index = mesh_indices[i]; - mesh_src_attribute.varray.get(index, buffer); - dst_attribute->set_by_relocate(i, buffer); - } - } - } - else if (use_pointcloud) { - /* The source geometry only has a pointcloud. */ - ReadAttributeLookup src_attribute = pointcloud_component->attribute_try_get_for_read( - src_name, data_type); - for (const int i : IndexRange(tot_samples)) { - const int index = pointcloud_indices[i]; - src_attribute.varray.get(index, buffer); - dst_attribute->set_by_relocate(i, buffer); - } - } - else if (use_mesh) { - /* The source geometry only has a mesh. */ - ReadAttributeLookup src_attribute = mesh_component->attribute_try_get_for_read(src_name, - data_type); - for (const int i : IndexRange(tot_samples)) { - const int index = mesh_indices[i]; - src_attribute.varray.get(index, buffer); - dst_attribute->set_by_relocate(i, buffer); - } - } - - dst_attribute.save(); -} - -static void transfer_attribute(const GeoNodeExecParams ¶ms, - const GeometrySet &src_geometry, - GeometryComponent &dst_component, - const StringRef src_name, - const StringRef dst_name) -{ - const NodeGeometryAttributeTransfer &storage = - *(const NodeGeometryAttributeTransfer *)params.node().storage; - const GeometryNodeAttributeTransferMapMode mapping = (GeometryNodeAttributeTransferMapMode) - storage.mapping; - const AttributeDomain input_domain = (AttributeDomain)storage.domain; - - CustomDataType data_type; - AttributeDomain auto_domain; - get_result_domain_and_data_type(src_geometry, dst_component, src_name, &data_type, &auto_domain); - const AttributeDomain dst_domain = (input_domain == ATTR_DOMAIN_AUTO) ? auto_domain : - input_domain; - - VArray<float3> dst_positions = dst_component.attribute_get_for_read<float3>( - "position", dst_domain, {0, 0, 0}); - - switch (mapping) { - case GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED: { - transfer_attribute_nearest_face_interpolated( - src_geometry, dst_component, dst_positions, dst_domain, data_type, src_name, dst_name); - break; - } - case GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER_NEAREST: { - transfer_attribute_nearest( - src_geometry, dst_component, dst_positions, dst_domain, data_type, src_name, dst_name); - break; - } - } -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet dst_geometry_set = params.extract_input<GeometrySet>("Geometry"); - GeometrySet src_geometry_set = params.extract_input<GeometrySet>("Source Geometry"); - const std::string src_attribute_name = params.extract_input<std::string>("Source"); - const std::string dst_attribute_name = params.extract_input<std::string>("Destination"); - - if (src_attribute_name.empty() || dst_attribute_name.empty()) { - params.set_default_remaining_outputs(); - return; - } - - dst_geometry_set = geometry::realize_instances_legacy(dst_geometry_set); - src_geometry_set = geometry::realize_instances_legacy(src_geometry_set); - - if (dst_geometry_set.has<MeshComponent>()) { - transfer_attribute(params, - src_geometry_set, - dst_geometry_set.get_component_for_write<MeshComponent>(), - src_attribute_name, - dst_attribute_name); - } - if (dst_geometry_set.has<PointCloudComponent>()) { - transfer_attribute(params, - src_geometry_set, - dst_geometry_set.get_component_for_write<PointCloudComponent>(), - src_attribute_name, - dst_attribute_name); - } - - params.set_output("Geometry", dst_geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_transfer_cc - -void register_node_type_geo_legacy_attribute_transfer() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_transfer_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER, "Attribute Transfer", NODE_CLASS_ATTRIBUTE); - node_type_init(&ntype, file_ns::node_init); - node_type_storage(&ntype, - "NodeGeometryAttributeTransfer", - node_free_standard_storage, - node_copy_standard_storage); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_math.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_math.cc deleted file mode 100644 index 83ece031dd2..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_math.cc +++ /dev/null @@ -1,559 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_math_base_safe.h" -#include "BLI_task.hh" - -#include "RNA_enum_types.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "NOD_math_functions.hh" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_attribute_vector_math_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("A")); - b.add_input<decl::Vector>(N_("A"), "A_001"); - b.add_input<decl::String>(N_("B")); - b.add_input<decl::Vector>(N_("B"), "B_001"); - b.add_input<decl::Float>(N_("B"), "B_002"); - b.add_input<decl::String>(N_("C")); - b.add_input<decl::Vector>(N_("C"), "C_001"); - b.add_input<decl::Float>(N_("C"), "C_002"); - b.add_input<decl::String>(N_("Result")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static bool operation_use_input_b(const NodeVectorMathOperation operation) -{ - return !ELEM(operation, - NODE_VECTOR_MATH_NORMALIZE, - NODE_VECTOR_MATH_FLOOR, - NODE_VECTOR_MATH_CEIL, - NODE_VECTOR_MATH_FRACTION, - NODE_VECTOR_MATH_ABSOLUTE, - NODE_VECTOR_MATH_SINE, - NODE_VECTOR_MATH_COSINE, - NODE_VECTOR_MATH_TANGENT, - NODE_VECTOR_MATH_LENGTH); -} - -static bool operation_use_input_c(const NodeVectorMathOperation operation) -{ - return ELEM(operation, - NODE_VECTOR_MATH_WRAP, - NODE_VECTOR_MATH_REFRACT, - NODE_VECTOR_MATH_FACEFORWARD, - NODE_VECTOR_MATH_MULTIPLY_ADD); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - bNode *node = (bNode *)ptr->data; - const NodeAttributeVectorMath &node_storage = *(NodeAttributeVectorMath *)node->storage; - const NodeVectorMathOperation operation = (const NodeVectorMathOperation)node_storage.operation; - - uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); - - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "input_type_a", 0, IFACE_("A"), ICON_NONE); - if (operation_use_input_b(operation)) { - uiItemR(layout, ptr, "input_type_b", 0, IFACE_("B"), ICON_NONE); - } - if (operation_use_input_c(operation)) { - uiItemR(layout, ptr, "input_type_c", 0, IFACE_("C"), ICON_NONE); - } -} - -static CustomDataType operation_get_read_type_b(const NodeVectorMathOperation operation) -{ - if (operation == NODE_VECTOR_MATH_SCALE) { - return CD_PROP_FLOAT; - } - return CD_PROP_FLOAT3; -} - -static CustomDataType operation_get_read_type_c(const NodeVectorMathOperation operation) -{ - if (operation == NODE_VECTOR_MATH_REFRACT) { - return CD_PROP_FLOAT; - } - return CD_PROP_FLOAT3; -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeAttributeVectorMath *data = MEM_cnew<NodeAttributeVectorMath>(__func__); - - data->operation = NODE_VECTOR_MATH_ADD; - data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - node->storage = data; -} - -static CustomDataType operation_get_result_type(const NodeVectorMathOperation operation) -{ - switch (operation) { - case NODE_VECTOR_MATH_ADD: - case NODE_VECTOR_MATH_SUBTRACT: - case NODE_VECTOR_MATH_MULTIPLY: - case NODE_VECTOR_MATH_DIVIDE: - case NODE_VECTOR_MATH_CROSS_PRODUCT: - case NODE_VECTOR_MATH_PROJECT: - case NODE_VECTOR_MATH_REFLECT: - case NODE_VECTOR_MATH_SCALE: - case NODE_VECTOR_MATH_NORMALIZE: - case NODE_VECTOR_MATH_SNAP: - case NODE_VECTOR_MATH_FLOOR: - case NODE_VECTOR_MATH_CEIL: - case NODE_VECTOR_MATH_MODULO: - case NODE_VECTOR_MATH_FRACTION: - case NODE_VECTOR_MATH_ABSOLUTE: - case NODE_VECTOR_MATH_MINIMUM: - case NODE_VECTOR_MATH_MAXIMUM: - case NODE_VECTOR_MATH_WRAP: - case NODE_VECTOR_MATH_SINE: - case NODE_VECTOR_MATH_COSINE: - case NODE_VECTOR_MATH_TANGENT: - case NODE_VECTOR_MATH_REFRACT: - case NODE_VECTOR_MATH_FACEFORWARD: - case NODE_VECTOR_MATH_MULTIPLY_ADD: - return CD_PROP_FLOAT3; - case NODE_VECTOR_MATH_DOT_PRODUCT: - case NODE_VECTOR_MATH_DISTANCE: - case NODE_VECTOR_MATH_LENGTH: - return CD_PROP_FLOAT; - } - - BLI_assert(false); - return CD_PROP_FLOAT3; -} - -static void geo_node_vector_math_label(const bNodeTree *UNUSED(ntree), - const bNode *node, - char *label, - int maxlen) -{ - NodeAttributeMath &node_storage = *(NodeAttributeMath *)node->storage; - const char *name; - bool enum_label = RNA_enum_name(rna_enum_node_vec_math_items, node_storage.operation, &name); - if (!enum_label) { - name = "Unknown"; - } - BLI_snprintf(label, maxlen, IFACE_("Vector %s"), IFACE_(name)); -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - const NodeAttributeVectorMath *node_storage = (NodeAttributeVectorMath *)node->storage; - const NodeVectorMathOperation operation = (const NodeVectorMathOperation)node_storage->operation; - - update_attribute_input_socket_availabilities( - *ntree, *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "B", - (GeometryNodeAttributeInputMode)node_storage->input_type_b, - operation_use_input_b(operation)); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "C", - (GeometryNodeAttributeInputMode)node_storage->input_type_c, - operation_use_input_c(operation)); -} - -static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a, - const VArray<float3> &input_b, - const VMutableArray<float3> &result, - const NodeVectorMathOperation operation) -{ - const int size = input_a.size(); - - VArray_Span<float3> span_a{input_a}; - VArray_Span<float3> span_b{input_b}; - VMutableArray_Span<float3> span_result{result, false}; - - bool success = try_dispatch_float_math_fl3_fl3_to_fl3( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float3 a = span_a[i]; - const float3 b = span_b[i]; - const float3 out = math_function(a, b); - span_result[i] = out; - } - }); - }); - - span_result.save(); - - /* The operation is not supported by this node currently. */ - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a, - const VArray<float3> &input_b, - const VArray<float3> &input_c, - const VMutableArray<float3> &result, - const NodeVectorMathOperation operation) -{ - const int size = input_a.size(); - - VArray_Span<float3> span_a{input_a}; - VArray_Span<float3> span_b{input_b}; - VArray_Span<float3> span_c{input_c}; - VMutableArray_Span<float3> span_result{result}; - - bool success = try_dispatch_float_math_fl3_fl3_fl3_to_fl3( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float3 a = span_a[i]; - const float3 b = span_b[i]; - const float3 c = span_c[i]; - const float3 out = math_function(a, b, c); - span_result[i] = out; - } - }); - }); - - span_result.save(); - - /* The operation is not supported by this node currently. */ - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a, - const VArray<float3> &input_b, - const VArray<float> &input_c, - const VMutableArray<float3> &result, - const NodeVectorMathOperation operation) -{ - const int size = input_a.size(); - - VArray_Span<float3> span_a{input_a}; - VArray_Span<float3> span_b{input_b}; - VArray_Span<float> span_c{input_c}; - VMutableArray_Span<float3> span_result{result, false}; - - bool success = try_dispatch_float_math_fl3_fl3_fl_to_fl3( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float3 a = span_a[i]; - const float3 b = span_b[i]; - const float c = span_c[i]; - const float3 out = math_function(a, b, c); - span_result[i] = out; - } - }); - }); - - span_result.save(); - - /* The operation is not supported by this node currently. */ - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a, - const VArray<float3> &input_b, - const VMutableArray<float> &result, - const NodeVectorMathOperation operation) -{ - const int size = input_a.size(); - - VArray_Span<float3> span_a{input_a}; - VArray_Span<float3> span_b{input_b}; - VMutableArray_Span<float> span_result{result, false}; - - bool success = try_dispatch_float_math_fl3_fl3_to_fl( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float3 a = span_a[i]; - const float3 b = span_b[i]; - const float out = math_function(a, b); - span_result[i] = out; - } - }); - }); - - span_result.save(); - - /* The operation is not supported by this node currently. */ - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a, - const VArray<float> &input_b, - const VMutableArray<float3> &result, - const NodeVectorMathOperation operation) -{ - const int size = input_a.size(); - - VArray_Span<float3> span_a{input_a}; - VArray_Span<float> span_b{input_b}; - VMutableArray_Span<float3> span_result{result, false}; - - bool success = try_dispatch_float_math_fl3_fl_to_fl3( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float3 a = span_a[i]; - const float b = span_b[i]; - const float3 out = math_function(a, b); - span_result[i] = out; - } - }); - }); - - span_result.save(); - - /* The operation is not supported by this node currently. */ - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a, - const VMutableArray<float3> &result, - const NodeVectorMathOperation operation) -{ - const int size = input_a.size(); - - VArray_Span<float3> span_a{input_a}; - VMutableArray_Span<float3> span_result{result, false}; - - bool success = try_dispatch_float_math_fl3_to_fl3( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float3 in = span_a[i]; - const float3 out = math_function(in); - span_result[i] = out; - } - }); - }); - - span_result.save(); - - /* The operation is not supported by this node currently. */ - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static void do_math_operation_fl3_to_fl(const VArray<float3> &input_a, - const VMutableArray<float> &result, - const NodeVectorMathOperation operation) -{ - const int size = input_a.size(); - - VArray_Span<float3> span_a{input_a}; - VMutableArray_Span<float> span_result{result, false}; - - bool success = try_dispatch_float_math_fl3_to_fl( - operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - threading::parallel_for(IndexRange(size), 512, [&](IndexRange range) { - for (const int i : range) { - const float3 in = span_a[i]; - const float out = math_function(in); - span_result[i] = out; - } - }); - }); - - span_result.save(); - - /* The operation is not supported by this node currently. */ - BLI_assert(success); - UNUSED_VARS_NDEBUG(success); -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - const GeoNodeExecParams ¶ms, - const NodeVectorMathOperation operation, - StringRef result_name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); - if (result_info) { - return result_info->domain; - } - - /* Otherwise use the highest priority domain from existing input attributes, or the default. */ - const AttributeDomain default_domain = ATTR_DOMAIN_POINT; - if (operation_use_input_b(operation)) { - if (operation_use_input_c(operation)) { - return params.get_highest_priority_input_domain({"A", "B", "C"}, component, default_domain); - } - return params.get_highest_priority_input_domain({"A", "B"}, component, default_domain); - } - return params.get_highest_priority_input_domain({"A"}, component, default_domain); -} - -static void attribute_vector_math_calc(GeometryComponent &component, - const GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - const NodeAttributeVectorMath *node_storage = (const NodeAttributeVectorMath *)node.storage; - const NodeVectorMathOperation operation = (NodeVectorMathOperation)node_storage->operation; - const std::string result_name = params.get_input<std::string>("Result"); - - /* The number and type of the input attribute depend on the operation. */ - const CustomDataType read_type_a = CD_PROP_FLOAT3; - const bool use_input_b = operation_use_input_b(operation); - const CustomDataType read_type_b = operation_get_read_type_b(operation); - const bool use_input_c = operation_use_input_c(operation); - const CustomDataType read_type_c = operation_get_read_type_c(operation); - - /* The result domain is always point for now. */ - const CustomDataType result_type = operation_get_result_type(operation); - const AttributeDomain result_domain = get_result_domain( - component, params, operation, result_name); - - GVArray attribute_a = params.get_input_attribute( - "A", component, result_domain, read_type_a, nullptr); - if (!attribute_a) { - return; - } - GVArray attribute_b; - GVArray attribute_c; - if (use_input_b) { - attribute_b = params.get_input_attribute("B", component, result_domain, read_type_b, nullptr); - if (!attribute_b) { - return; - } - } - if (use_input_c) { - attribute_c = params.get_input_attribute("C", component, result_domain, read_type_c, nullptr); - if (!attribute_c) { - return; - } - } - - /* Get result attribute first, in case it has to overwrite one of the existing attributes. */ - OutputAttribute attribute_result = component.attribute_try_get_for_output_only( - result_name, result_domain, result_type); - if (!attribute_result) { - return; - } - - switch (operation) { - case NODE_VECTOR_MATH_ADD: - case NODE_VECTOR_MATH_SUBTRACT: - case NODE_VECTOR_MATH_MULTIPLY: - case NODE_VECTOR_MATH_DIVIDE: - case NODE_VECTOR_MATH_CROSS_PRODUCT: - case NODE_VECTOR_MATH_PROJECT: - case NODE_VECTOR_MATH_REFLECT: - case NODE_VECTOR_MATH_SNAP: - case NODE_VECTOR_MATH_MODULO: - case NODE_VECTOR_MATH_MINIMUM: - case NODE_VECTOR_MATH_MAXIMUM: - do_math_operation_fl3_fl3_to_fl3(attribute_a.typed<float3>(), - attribute_b.typed<float3>(), - attribute_result.varray().typed<float3>(), - operation); - break; - case NODE_VECTOR_MATH_DOT_PRODUCT: - case NODE_VECTOR_MATH_DISTANCE: - do_math_operation_fl3_fl3_to_fl(attribute_a.typed<float3>(), - attribute_b.typed<float3>(), - attribute_result.varray().typed<float>(), - operation); - break; - case NODE_VECTOR_MATH_LENGTH: - do_math_operation_fl3_to_fl( - attribute_a.typed<float3>(), attribute_result.varray().typed<float>(), operation); - break; - case NODE_VECTOR_MATH_SCALE: - do_math_operation_fl3_fl_to_fl3(attribute_a.typed<float3>(), - attribute_b.typed<float>(), - attribute_result.varray().typed<float3>(), - operation); - break; - case NODE_VECTOR_MATH_NORMALIZE: - case NODE_VECTOR_MATH_FLOOR: - case NODE_VECTOR_MATH_CEIL: - case NODE_VECTOR_MATH_FRACTION: - case NODE_VECTOR_MATH_ABSOLUTE: - case NODE_VECTOR_MATH_SINE: - case NODE_VECTOR_MATH_COSINE: - case NODE_VECTOR_MATH_TANGENT: - do_math_operation_fl3_to_fl3( - attribute_a.typed<float3>(), attribute_result.varray().typed<float3>(), operation); - break; - case NODE_VECTOR_MATH_WRAP: - case NODE_VECTOR_MATH_FACEFORWARD: - case NODE_VECTOR_MATH_MULTIPLY_ADD: - do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a.typed<float3>(), - attribute_b.typed<float3>(), - attribute_c.typed<float3>(), - attribute_result.varray().typed<float3>(), - operation); - break; - case NODE_VECTOR_MATH_REFRACT: - do_math_operation_fl3_fl3_fl_to_fl3(attribute_a.typed<float3>(), - attribute_b.typed<float3>(), - attribute_c.typed<float>(), - attribute_result.varray().typed<float3>(), - operation); - break; - } - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - attribute_vector_math_calc(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - attribute_vector_math_calc(geometry_set.get_component_for_write<PointCloudComponent>(), - params); - } - if (geometry_set.has<CurveComponent>()) { - attribute_vector_math_calc(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_vector_math_cc - -void register_node_type_geo_attribute_vector_math() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_vector_math_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, - GEO_NODE_LEGACY_ATTRIBUTE_VECTOR_MATH, - "Attribute Vector Math", - NODE_CLASS_ATTRIBUTE); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - ntype.labelfunc = file_ns::geo_node_vector_math_label; - node_type_update(&ntype, file_ns::node_update); - node_type_init(&ntype, file_ns::node_init); - node_type_storage( - &ntype, "NodeAttributeVectorMath", node_free_standard_storage, node_copy_standard_storage); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_rotate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_rotate.cc deleted file mode 100644 index ccf1bdb0a19..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_rotate.cc +++ /dev/null @@ -1,335 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "node_geometry_util.hh" - -#include "BLI_task.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -namespace blender::nodes::node_geo_legacy_attribute_vector_rotate_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Vector")); - b.add_input<decl::Vector>(N_("Vector"), "Vector_001").min(0.0f).max(1.0f).hide_value(); - b.add_input<decl::String>(N_("Center")); - b.add_input<decl::Vector>(N_("Center"), "Center_001").subtype(PROP_XYZ); - b.add_input<decl::String>(N_("Axis")); - b.add_input<decl::Vector>(N_("Axis"), "Axis_001").min(-1.0f).max(1.0f).subtype(PROP_XYZ); - b.add_input<decl::String>(N_("Angle")); - b.add_input<decl::Float>(N_("Angle"), "Angle_001").subtype(PROP_ANGLE); - b.add_input<decl::String>(N_("Rotation")); - b.add_input<decl::Vector>(N_("Rotation"), "Rotation_001").subtype(PROP_EULER); - b.add_input<decl::Bool>(N_("Invert")); - b.add_input<decl::String>(N_("Result")); - - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - bNode *node = (bNode *)ptr->data; - const NodeAttributeVectorRotate &node_storage = *(NodeAttributeVectorRotate *)node->storage; - const GeometryNodeAttributeVectorRotateMode mode = (const GeometryNodeAttributeVectorRotateMode) - node_storage.mode; - - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiLayout *column = uiLayoutColumn(layout, false); - - uiItemR(column, ptr, "rotation_mode", 0, "", ICON_NONE); - - uiItemR(column, ptr, "input_type_vector", 0, IFACE_("Vector"), ICON_NONE); - uiItemR(column, ptr, "input_type_center", 0, IFACE_("Center"), ICON_NONE); - if (mode == GEO_NODE_VECTOR_ROTATE_TYPE_AXIS) { - uiItemR(column, ptr, "input_type_axis", 0, IFACE_("Axis"), ICON_NONE); - } - if (mode != GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) { - uiItemR(column, ptr, "input_type_angle", 0, IFACE_("Angle"), ICON_NONE); - } - if (mode == GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) { - uiItemR(column, ptr, "input_type_rotation", 0, IFACE_("Rotation"), ICON_NONE); - } -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - const NodeAttributeVectorRotate *node_storage = (NodeAttributeVectorRotate *)node->storage; - const GeometryNodeAttributeVectorRotateMode mode = (const GeometryNodeAttributeVectorRotateMode) - node_storage->mode; - - update_attribute_input_socket_availabilities( - *ntree, *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type_vector); - update_attribute_input_socket_availabilities( - *ntree, *node, "Center", (GeometryNodeAttributeInputMode)node_storage->input_type_center); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "Axis", - (GeometryNodeAttributeInputMode)node_storage->input_type_axis, - (mode == GEO_NODE_VECTOR_ROTATE_TYPE_AXIS)); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "Angle", - (GeometryNodeAttributeInputMode)node_storage->input_type_angle, - (mode != GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ)); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "Rotation", - (GeometryNodeAttributeInputMode)node_storage->input_type_rotation, - (mode == GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ)); -} - -static float3 vector_rotate_around_axis(const float3 vector, - const float3 center, - const float3 axis, - const float angle) -{ - float3 result = vector - center; - float mat[3][3]; - axis_angle_to_mat3(mat, axis, angle); - mul_m3_v3(mat, result); - return result + center; -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeAttributeVectorRotate *node_storage = MEM_cnew<NodeAttributeVectorRotate>(__func__); - - node_storage->mode = GEO_NODE_VECTOR_ROTATE_TYPE_AXIS; - node_storage->input_type_vector = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - node_storage->input_type_center = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - node_storage->input_type_axis = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - node_storage->input_type_angle = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - node_storage->input_type_rotation = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - - node->storage = node_storage; -} - -static float3 vector_rotate_euler(const float3 vector, - const float3 center, - const float3 rotation, - const bool invert) -{ - float mat[3][3]; - float3 result = vector - center; - eul_to_mat3(mat, rotation); - if (invert) { - invert_m3(mat); - } - mul_m3_v3(mat, result); - return result + center; -} - -static void do_vector_rotate_around_axis(const VArray<float3> &vector, - const VArray<float3> ¢er, - const VArray<float3> &axis, - const VArray<float> &angle, - MutableSpan<float3> results, - const bool invert) -{ - VArray_Span<float3> span_vector{vector}; - VArray_Span<float3> span_center{center}; - VArray_Span<float3> span_axis{axis}; - VArray_Span<float> span_angle{angle}; - - threading::parallel_for(IndexRange(results.size()), 1024, [&](IndexRange range) { - for (const int i : range) { - float angle = (invert) ? -span_angle[i] : span_angle[i]; - results[i] = vector_rotate_around_axis(span_vector[i], span_center[i], span_axis[i], angle); - } - }); -} - -static void do_vector_rotate_around_fixed_axis(const VArray<float3> &vector, - const VArray<float3> ¢er, - const float3 axis, - const VArray<float> &angle, - MutableSpan<float3> results, - const bool invert) -{ - VArray_Span<float3> span_vector{vector}; - VArray_Span<float3> span_center{center}; - VArray_Span<float> span_angle{angle}; - - threading::parallel_for(IndexRange(results.size()), 1024, [&](IndexRange range) { - for (const int i : range) { - float angle = (invert) ? -span_angle[i] : span_angle[i]; - results[i] = vector_rotate_around_axis(span_vector[i], span_center[i], axis, angle); - } - }); -} - -static void do_vector_rotate_euler(const VArray<float3> &vector, - const VArray<float3> ¢er, - const VArray<float3> &rotation, - MutableSpan<float3> results, - const bool invert) -{ - VArray_Span<float3> span_vector{vector}; - VArray_Span<float3> span_center{center}; - VArray_Span<float3> span_rotation{rotation}; - - threading::parallel_for(IndexRange(results.size()), 1024, [&](IndexRange range) { - for (const int i : range) { - results[i] = vector_rotate_euler(span_vector[i], span_center[i], span_rotation[i], invert); - } - }); -} - -static AttributeDomain get_result_domain(const GeometryComponent &component, - const GeoNodeExecParams ¶ms, - StringRef result_name) -{ - /* Use the domain of the result attribute if it already exists. */ - std::optional<AttributeMetaData> meta_data = component.attribute_get_meta_data(result_name); - if (meta_data) { - return meta_data->domain; - } - - /* Otherwise use the highest priority domain from existing input attributes, or the default. */ - const AttributeDomain default_domain = ATTR_DOMAIN_POINT; - return params.get_highest_priority_input_domain({"Vector", "Center"}, component, default_domain); -} - -static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryComponent &component) -{ - const bNode &node = params.node(); - const NodeAttributeVectorRotate *node_storage = (const NodeAttributeVectorRotate *)node.storage; - const GeometryNodeAttributeVectorRotateMode mode = (GeometryNodeAttributeVectorRotateMode) - node_storage->mode; - const std::string result_name = params.get_input<std::string>("Result"); - const AttributeDomain result_domain = get_result_domain(component, params, result_name); - const bool invert = params.get_input<bool>("Invert"); - - GVArray attribute_vector = params.get_input_attribute( - "Vector", component, result_domain, CD_PROP_FLOAT3, nullptr); - if (!attribute_vector) { - return; - } - GVArray attribute_center = params.get_input_attribute( - "Center", component, result_domain, CD_PROP_FLOAT3, nullptr); - if (!attribute_center) { - return; - } - - OutputAttribute attribute_result = component.attribute_try_get_for_output_only( - result_name, result_domain, CD_PROP_FLOAT3); - if (!attribute_result) { - return; - } - - if (mode == GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) { - GVArray attribute_rotation = params.get_input_attribute( - "Rotation", component, result_domain, CD_PROP_FLOAT3, nullptr); - if (!attribute_rotation) { - return; - } - do_vector_rotate_euler(attribute_vector.typed<float3>(), - attribute_center.typed<float3>(), - attribute_rotation.typed<float3>(), - attribute_result.as_span<float3>(), - invert); - attribute_result.save(); - return; - } - - GVArray attribute_angle = params.get_input_attribute( - "Angle", component, result_domain, CD_PROP_FLOAT, nullptr); - if (!attribute_angle) { - return; - } - - switch (mode) { - case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS: { - GVArray attribute_axis = params.get_input_attribute( - "Axis", component, result_domain, CD_PROP_FLOAT3, nullptr); - if (!attribute_axis) { - return; - } - do_vector_rotate_around_axis(attribute_vector.typed<float3>(), - attribute_center.typed<float3>(), - attribute_axis.typed<float3>(), - attribute_angle.typed<float>(), - attribute_result.as_span<float3>(), - invert); - } break; - case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_X: - do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(), - attribute_center.typed<float3>(), - float3(1.0f, 0.0f, 0.0f), - attribute_angle.typed<float>(), - attribute_result.as_span<float3>(), - invert); - break; - case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Y: - do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(), - attribute_center.typed<float3>(), - float3(0.0f, 1.0f, 0.0f), - attribute_angle.typed<float>(), - attribute_result.as_span<float3>(), - invert); - - break; - case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Z: - do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(), - attribute_center.typed<float3>(), - float3(0.0f, 0.0f, 1.0f), - attribute_angle.typed<float>(), - attribute_result.as_span<float3>(), - invert); - - break; - case GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: - /* Euler is handled before other modes to avoid processing the unavailable angle socket. */ - BLI_assert_unreachable(); - break; - } - attribute_result.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<MeshComponent>()); - } - if (geometry_set.has<PointCloudComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<PointCloudComponent>()); - } - if (geometry_set.has<CurveComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<CurveComponent>()); - } - - params.set_output("Geometry", std::move(geometry_set)); -} - -} // namespace blender::nodes::node_geo_legacy_attribute_vector_rotate_cc - -void register_node_type_geo_attribute_vector_rotate() -{ - namespace file_ns = blender::nodes::node_geo_legacy_attribute_vector_rotate_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, - GEO_NODE_LEGACY_ATTRIBUTE_VECTOR_ROTATE, - "Attribute Vector Rotate", - NODE_CLASS_ATTRIBUTE); - node_type_update(&ntype, file_ns::node_update); - node_type_init(&ntype, file_ns::node_init); - node_type_size(&ntype, 165, 100, 600); - node_type_storage( - &ntype, "NodeAttributeVectorRotate", node_free_standard_storage, node_copy_standard_storage); - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - ntype.declare = file_ns::node_declare; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc deleted file mode 100644 index 0980c2d6e72..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc +++ /dev/null @@ -1,207 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_task.hh" -#include "BLI_timeit.hh" - -#include "BKE_pointcloud.h" -#include "BKE_spline.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_curve_endpoints_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_output<decl::Geometry>(N_("Start Points")); - b.add_output<decl::Geometry>(N_("End Points")); -} - -/** - * Evaluate splines in parallel to speed up the rest of the node's execution. - */ -static void evaluate_splines(Span<SplinePtr> splines) -{ - threading::parallel_for_each(splines, [](const SplinePtr &spline) { - /* These functions fill the corresponding caches on each spline. */ - spline->evaluated_positions(); - spline->evaluated_tangents(); - spline->evaluated_normals(); - spline->evaluated_lengths(); - }); -} - -/** - * \note Use attributes from the curve component rather than the attribute data directly on the - * attribute storage to allow reading the virtual spline attributes like "cyclic" and "resolution". - */ -static void copy_spline_domain_attributes(const CurveComponent &curve_component, - Span<int> offsets, - PointCloudComponent &points) -{ - curve_component.attribute_foreach( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - if (meta_data.domain != ATTR_DOMAIN_CURVE) { - return true; - } - GVArray spline_attribute = curve_component.attribute_get_for_read( - attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type); - - OutputAttribute result_attribute = points.attribute_try_get_for_output_only( - attribute_id, ATTR_DOMAIN_POINT, meta_data.data_type); - GMutableSpan result = result_attribute.as_span(); - - /* Only copy the attributes of splines in the offsets. */ - for (const int i : offsets.index_range()) { - spline_attribute.get(offsets[i], result[i]); - } - - result_attribute.save(); - return true; - }); -} - -/** - * Get the offsets for the splines whose endpoints we want to output. - * Filter those which are cyclic, or that evaluate to empty. - * Could be easily adapted to include a selection argument to support attribute selection. - */ -static blender::Vector<int> get_endpoint_spline_offsets(Span<SplinePtr> splines) -{ - blender::Vector<int> spline_offsets; - spline_offsets.reserve(splines.size()); - - for (const int i : splines.index_range()) { - if (!(splines[i]->is_cyclic() || splines[i]->evaluated_points_size() == 0)) { - spline_offsets.append(i); - } - } - - return spline_offsets; -} - -/** - * Copy the endpoint attributes from the correct positions at the splines at the offsets to - * the start and end attributes. - */ -static void copy_endpoint_attributes(Span<SplinePtr> splines, - Span<int> offsets, - CurveToPointsResults &start_data, - CurveToPointsResults &end_data) -{ - threading::parallel_for(offsets.index_range(), 64, [&](IndexRange range) { - for (const int i : range) { - const Spline &spline = *splines[offsets[i]]; - - /* Copy the start and end point data over. */ - start_data.positions[i] = spline.evaluated_positions().first(); - start_data.tangents[i] = spline.evaluated_tangents().first(); - start_data.normals[i] = spline.evaluated_normals().first(); - start_data.radii[i] = spline.radii().first(); - start_data.tilts[i] = spline.tilts().first(); - - end_data.positions[i] = spline.evaluated_positions().last(); - end_data.tangents[i] = spline.evaluated_tangents().last(); - end_data.normals[i] = spline.evaluated_normals().last(); - end_data.radii[i] = spline.radii().last(); - end_data.tilts[i] = spline.tilts().last(); - - /* Copy the point attribute data over. */ - for (const auto item : start_data.point_attributes.items()) { - const AttributeIDRef attribute_id = item.key; - GMutableSpan point_span = item.value; - - BLI_assert(spline.attributes.get_for_read(attribute_id)); - GSpan spline_span = *spline.attributes.get_for_read(attribute_id); - spline_span.type().copy_assign(spline_span[0], point_span[i]); - } - - for (const auto item : end_data.point_attributes.items()) { - const AttributeIDRef attribute_id = item.key; - GMutableSpan point_span = item.value; - - BLI_assert(spline.attributes.get_for_read(attribute_id)); - GSpan spline_span = *spline.attributes.get_for_read(attribute_id); - spline_span.type().copy_assign(spline_span[spline.size() - 1], point_span[i]); - } - } - }); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (!geometry_set.has_curves()) { - params.set_default_remaining_outputs(); - return; - } - - const CurveComponent &curve_component = *geometry_set.get_component_for_read<CurveComponent>(); - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read()); - const Span<SplinePtr> splines = curve->splines(); - curve->assert_valid_point_attributes(); - - evaluate_splines(splines); - - const Vector<int> offsets = get_endpoint_spline_offsets(splines); - const int total_size = offsets.size(); - - if (total_size == 0) { - params.set_default_remaining_outputs(); - return; - } - - GeometrySet start_result = GeometrySet::create_with_pointcloud( - BKE_pointcloud_new_nomain(total_size)); - GeometrySet end_result = GeometrySet::create_with_pointcloud( - BKE_pointcloud_new_nomain(total_size)); - PointCloudComponent &start_point_component = - start_result.get_component_for_write<PointCloudComponent>(); - PointCloudComponent &end_point_component = - end_result.get_component_for_write<PointCloudComponent>(); - - CurveToPointsResults start_attributes = curve_to_points_create_result_attributes( - start_point_component, *curve); - CurveToPointsResults end_attributes = curve_to_points_create_result_attributes( - end_point_component, *curve); - - copy_endpoint_attributes(splines, offsets.as_span(), start_attributes, end_attributes); - copy_spline_domain_attributes(curve_component, offsets.as_span(), start_point_component); - curve_create_default_rotation_attribute( - start_attributes.tangents, start_attributes.normals, start_attributes.rotations); - curve_create_default_rotation_attribute( - end_attributes.tangents, end_attributes.normals, end_attributes.rotations); - - /* The default radius is way too large for points, divide by 10. */ - for (float &radius : start_attributes.radii) { - radius *= 0.1f; - } - for (float &radius : end_attributes.radii) { - radius *= 0.1f; - } - - params.set_output("Start Points", std::move(start_result)); - params.set_output("End Points", std::move(end_result)); -} - -} // namespace blender::nodes::node_geo_legacy_curve_endpoints_cc - -void register_node_type_geo_legacy_curve_endpoints() -{ - namespace file_ns = blender::nodes::node_geo_legacy_curve_endpoints_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_CURVE_ENDPOINTS, "Curve Endpoints", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc deleted file mode 100644 index 2c801642bd7..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_task.hh" - -#include "BKE_spline.hh" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_curve_reverse_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Curve")); - b.add_input<decl::String>(N_("Selection")); - b.add_output<decl::Geometry>(N_("Curve")); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); - geometry_set = geometry::realize_instances_legacy(geometry_set); - if (!geometry_set.has_curves()) { - params.set_output("Curve", geometry_set); - return; - } - - /* Retrieve data for write access so we can avoid new allocations for the reversed data. */ - CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>(); - std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read()); - MutableSpan<SplinePtr> splines = curve->splines(); - - const std::string selection_name = params.extract_input<std::string>("Selection"); - VArray<bool> selection = curve_component.attribute_get_for_read( - selection_name, ATTR_DOMAIN_CURVE, true); - - threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { - for (const int i : range) { - if (selection[i]) { - splines[i]->reverse(); - } - } - }); - - geometry_set.replace_curves(curve_eval_to_curves(*curve)); - - params.set_output("Curve", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_curve_reverse_cc - -void register_node_type_geo_legacy_curve_reverse() -{ - namespace file_ns = blender::nodes::node_geo_legacy_curve_reverse_cc; - - static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_LEGACY_CURVE_REVERSE, "Curve Reverse", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc deleted file mode 100644 index 729ccca5f04..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc +++ /dev/null @@ -1,126 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_task.hh" - -#include "BKE_spline.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_curve_select_by_handle_type_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Selection")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); - uiItemR(layout, ptr, "handle_type", 0, "", ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryCurveSelectHandles *data = MEM_cnew<NodeGeometryCurveSelectHandles>(__func__); - - data->handle_type = GEO_NODE_CURVE_HANDLE_AUTO; - data->mode = GEO_NODE_CURVE_HANDLE_LEFT | GEO_NODE_CURVE_HANDLE_RIGHT; - node->storage = data; -} - -static HandleType handle_type_from_input_type(const GeometryNodeCurveHandleType type) -{ - switch (type) { - case GEO_NODE_CURVE_HANDLE_AUTO: - return BEZIER_HANDLE_AUTO; - case GEO_NODE_CURVE_HANDLE_ALIGN: - return BEZIER_HANDLE_ALIGN; - case GEO_NODE_CURVE_HANDLE_FREE: - return BEZIER_HANDLE_FREE; - case GEO_NODE_CURVE_HANDLE_VECTOR: - return BEZIER_HANDLE_VECTOR; - } - BLI_assert_unreachable(); - return BEZIER_HANDLE_AUTO; -} - -static void select_curve_by_handle_type(const CurveEval &curve, - const HandleType type, - const GeometryNodeCurveHandleMode mode, - const MutableSpan<bool> r_selection) -{ - const Array<int> offsets = curve.control_point_offsets(); - Span<SplinePtr> splines = curve.splines(); - threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { - for (const int i_spline : range) { - const Spline &spline = *splines[i_spline]; - if (spline.type() == CURVE_TYPE_BEZIER) { - const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(spline); - Span<int8_t> types_left = bezier_spline.handle_types_left(); - Span<int8_t> types_right = bezier_spline.handle_types_right(); - for (const int i_point : IndexRange(bezier_spline.size())) { - r_selection[offsets[i_spline] + i_point] = (mode & GEO_NODE_CURVE_HANDLE_LEFT && - types_left[i_point] == type) || - (mode & GEO_NODE_CURVE_HANDLE_RIGHT && - types_right[i_point] == type); - } - } - else { - r_selection.slice(offsets[i_spline], offsets[i_spline + 1]).fill(false); - } - } - }); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - const NodeGeometryCurveSelectHandles *storage = - (const NodeGeometryCurveSelectHandles *)params.node().storage; - const HandleType handle_type = handle_type_from_input_type( - (GeometryNodeCurveHandleType)storage->handle_type); - const GeometryNodeCurveHandleMode mode = (GeometryNodeCurveHandleMode)storage->mode; - - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - geometry_set = geometry::realize_instances_legacy(geometry_set); - - CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>(); - if (curve_component.has_curves()) { - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read()); - const std::string selection_name = params.extract_input<std::string>("Selection"); - OutputAttribute_Typed<bool> selection = - curve_component.attribute_try_get_for_output_only<bool>(selection_name, ATTR_DOMAIN_POINT); - if (selection) { - select_curve_by_handle_type(*curve, handle_type, mode, selection.as_span()); - selection.save(); - } - } - - params.set_output("Geometry", std::move(geometry_set)); -} - -} // namespace blender::nodes::node_geo_legacy_curve_select_by_handle_type_cc - -void register_node_type_geo_legacy_select_by_handle_type() -{ - namespace file_ns = blender::nodes::node_geo_legacy_curve_select_by_handle_type_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_CURVE_SELECT_HANDLES, "Select by Handle Type", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - node_type_init(&ntype, file_ns::node_init); - node_type_storage(&ntype, - "NodeGeometryCurveSelectHandles", - node_free_standard_storage, - node_copy_standard_storage); - ntype.draw_buttons = file_ns::node_layout; - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc deleted file mode 100644 index 56e9068882b..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc +++ /dev/null @@ -1,131 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BKE_spline.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_curve_set_handles_cc { - -static void node_decalre(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Curve")); - b.add_input<decl::String>(N_("Selection")); - b.add_output<decl::Geometry>(N_("Curve")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); - uiItemR(layout, ptr, "handle_type", 0, "", ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryCurveSetHandles *data = MEM_cnew<NodeGeometryCurveSetHandles>(__func__); - - data->handle_type = GEO_NODE_CURVE_HANDLE_AUTO; - data->mode = GEO_NODE_CURVE_HANDLE_LEFT | GEO_NODE_CURVE_HANDLE_RIGHT; - node->storage = data; -} - -static HandleType handle_type_from_input_type(GeometryNodeCurveHandleType type) -{ - switch (type) { - case GEO_NODE_CURVE_HANDLE_AUTO: - return BEZIER_HANDLE_AUTO; - case GEO_NODE_CURVE_HANDLE_ALIGN: - return BEZIER_HANDLE_ALIGN; - case GEO_NODE_CURVE_HANDLE_FREE: - return BEZIER_HANDLE_FREE; - case GEO_NODE_CURVE_HANDLE_VECTOR: - return BEZIER_HANDLE_VECTOR; - } - BLI_assert_unreachable(); - return BEZIER_HANDLE_AUTO; -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - const NodeGeometryCurveSetHandles *node_storage = - (NodeGeometryCurveSetHandles *)params.node().storage; - const GeometryNodeCurveHandleType type = (GeometryNodeCurveHandleType)node_storage->handle_type; - const GeometryNodeCurveHandleMode mode = (GeometryNodeCurveHandleMode)node_storage->mode; - - GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); - geometry_set = geometry::realize_instances_legacy(geometry_set); - if (!geometry_set.has_curves()) { - params.set_output("Curve", geometry_set); - return; - } - - /* Retrieve data for write access so we can avoid new allocations for the handles data. */ - CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>(); - std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read()); - MutableSpan<SplinePtr> splines = curve->splines(); - - const std::string selection_name = params.extract_input<std::string>("Selection"); - VArray<bool> selection = curve_component.attribute_get_for_read( - selection_name, ATTR_DOMAIN_POINT, true); - - const HandleType new_handle_type = handle_type_from_input_type(type); - int point_index = 0; - bool has_bezier_spline = false; - for (SplinePtr &spline : splines) { - if (spline->type() != CURVE_TYPE_BEZIER) { - point_index += spline->positions().size(); - continue; - } - - BezierSpline &bezier_spline = static_cast<BezierSpline &>(*spline); - if (ELEM(new_handle_type, BEZIER_HANDLE_FREE, BEZIER_HANDLE_ALIGN)) { - /* In this case the automatically calculated handle types need to be "baked", because - * they're possibly changing from a type that is calculated automatically to a type that - * is positioned manually. */ - bezier_spline.ensure_auto_handles(); - } - has_bezier_spline = true; - for (int i_point : IndexRange(bezier_spline.size())) { - if (selection[point_index]) { - if (mode & GEO_NODE_CURVE_HANDLE_LEFT) { - bezier_spline.handle_types_left()[i_point] = new_handle_type; - } - if (mode & GEO_NODE_CURVE_HANDLE_RIGHT) { - bezier_spline.handle_types_right()[i_point] = new_handle_type; - } - } - point_index++; - } - bezier_spline.mark_cache_invalid(); - } - - geometry_set.replace_curves(curve_eval_to_curves(*curve)); - - if (!has_bezier_spline) { - params.error_message_add(NodeWarningType::Info, TIP_("No Bezier splines in input curve")); - } - - params.set_output("Curve", geometry_set); -} -} // namespace blender::nodes::node_geo_legacy_curve_set_handles_cc - -void register_node_type_geo_legacy_curve_set_handles() -{ - namespace file_ns = blender::nodes::node_geo_legacy_curve_set_handles_cc; - - static bNodeType ntype; - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_CURVE_SET_HANDLES, "Set Handle Type", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_decalre; - ntype.geometry_node_execute = file_ns::node_geo_exec; - node_type_init(&ntype, file_ns::node_init); - node_type_storage(&ntype, - "NodeGeometryCurveSetHandles", - node_free_standard_storage, - node_copy_standard_storage); - ntype.draw_buttons = file_ns::node_layout; - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc deleted file mode 100644 index 002c42c4c82..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc +++ /dev/null @@ -1,294 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BKE_spline.hh" - -#include "BLI_task.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_curve_spline_type_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Curve")); - b.add_input<decl::String>(N_("Selection")); - b.add_output<decl::Geometry>(N_("Curve")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "spline_type", 0, "", ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryCurveSplineType *data = MEM_cnew<NodeGeometryCurveSplineType>(__func__); - - data->spline_type = GEO_NODE_SPLINE_TYPE_POLY; - node->storage = data; -} - -template<class T> -static void scale_input_assign(const Span<T> input, - const int scale, - const int offset, - const MutableSpan<T> r_output) -{ - for (const int i : IndexRange(r_output.size())) { - r_output[i] = input[i * scale + offset]; - } -} - -template<class T> -static void scale_output_assign(const Span<T> input, - const int scale, - const int offset, - const MutableSpan<T> &r_output) -{ - for (const int i : IndexRange(input.size())) { - r_output[i * scale + offset] = input[i]; - } -} - -template<typename CopyFn> -static void copy_attributes(const Spline &input_spline, Spline &output_spline, CopyFn copy_fn) -{ - input_spline.attributes.foreach_attribute( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - std::optional<GSpan> src = input_spline.attributes.get_for_read(attribute_id); - BLI_assert(src); - if (!output_spline.attributes.create(attribute_id, meta_data.data_type)) { - BLI_assert_unreachable(); - return false; - } - std::optional<GMutableSpan> dst = output_spline.attributes.get_for_write(attribute_id); - if (!dst) { - BLI_assert_unreachable(); - return false; - } - - copy_fn(*src, *dst); - - return true; - }, - ATTR_DOMAIN_POINT); -} - -static SplinePtr convert_to_poly_spline(const Spline &input) -{ - std::unique_ptr<PolySpline> output = std::make_unique<PolySpline>(); - output->resize(input.positions().size()); - output->positions().copy_from(input.positions()); - output->radii().copy_from(input.radii()); - output->tilts().copy_from(input.tilts()); - Spline::copy_base_settings(input, *output); - output->attributes = input.attributes; - return output; -} - -static SplinePtr poly_to_nurbs(const Spline &input) -{ - std::unique_ptr<NURBSpline> output = std::make_unique<NURBSpline>(); - output->resize(input.positions().size()); - output->positions().copy_from(input.positions()); - output->radii().copy_from(input.radii()); - output->tilts().copy_from(input.tilts()); - output->weights().fill(1.0f); - output->set_resolution(12); - output->set_order(4); - Spline::copy_base_settings(input, *output); - output->knots_mode = NURBS_KNOT_MODE_BEZIER; - output->attributes = input.attributes; - return output; -} - -static SplinePtr bezier_to_nurbs(const Spline &input) -{ - const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(input); - std::unique_ptr<NURBSpline> output = std::make_unique<NURBSpline>(); - output->resize(input.size() * 3); - - scale_output_assign(bezier_spline.handle_positions_left(), 3, 0, output->positions()); - scale_output_assign(input.radii(), 3, 0, output->radii()); - scale_output_assign(input.tilts(), 3, 0, output->tilts()); - - scale_output_assign(bezier_spline.positions(), 3, 1, output->positions()); - scale_output_assign(input.radii(), 3, 1, output->radii()); - scale_output_assign(input.tilts(), 3, 1, output->tilts()); - - scale_output_assign(bezier_spline.handle_positions_right(), 3, 2, output->positions()); - scale_output_assign(input.radii(), 3, 2, output->radii()); - scale_output_assign(input.tilts(), 3, 2, output->tilts()); - - Spline::copy_base_settings(input, *output); - output->weights().fill(1.0f); - output->set_resolution(12); - output->set_order(4); - output->set_cyclic(input.is_cyclic()); - output->knots_mode = NURBS_KNOT_MODE_BEZIER; - output->attributes.reallocate(output->size()); - copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) { - attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { - using T = decltype(dummy); - scale_output_assign<T>(src.typed<T>(), 3, 0, dst.typed<T>()); - scale_output_assign<T>(src.typed<T>(), 3, 1, dst.typed<T>()); - scale_output_assign<T>(src.typed<T>(), 3, 2, dst.typed<T>()); - }); - }); - return output; -} - -static SplinePtr poly_to_bezier(const Spline &input) -{ - std::unique_ptr<BezierSpline> output = std::make_unique<BezierSpline>(); - output->resize(input.size()); - output->positions().copy_from(input.positions()); - output->radii().copy_from(input.radii()); - output->tilts().copy_from(input.tilts()); - output->handle_types_left().fill(BEZIER_HANDLE_VECTOR); - output->handle_types_right().fill(BEZIER_HANDLE_VECTOR); - output->set_resolution(12); - Spline::copy_base_settings(input, *output); - output->attributes = input.attributes; - return output; -} - -static SplinePtr nurbs_to_bezier(const Spline &input) -{ - const NURBSpline &nurbs_spline = static_cast<const NURBSpline &>(input); - std::unique_ptr<BezierSpline> output = std::make_unique<BezierSpline>(); - output->resize(input.size() / 3); - scale_input_assign<float3>(input.positions(), 3, 1, output->positions()); - scale_input_assign<float3>(input.positions(), 3, 0, output->handle_positions_left()); - scale_input_assign<float3>(input.positions(), 3, 2, output->handle_positions_right()); - scale_input_assign<float>(input.radii(), 3, 2, output->radii()); - scale_input_assign<float>(input.tilts(), 3, 2, output->tilts()); - output->handle_types_left().fill(BEZIER_HANDLE_ALIGN); - output->handle_types_right().fill(BEZIER_HANDLE_ALIGN); - output->set_resolution(nurbs_spline.resolution()); - Spline::copy_base_settings(input, *output); - output->attributes.reallocate(output->size()); - copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) { - attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { - using T = decltype(dummy); - scale_input_assign<T>(src.typed<T>(), 3, 1, dst.typed<T>()); - }); - }); - return output; -} - -static SplinePtr convert_to_bezier(const Spline &input, GeoNodeExecParams params) -{ - switch (input.type()) { - case CURVE_TYPE_BEZIER: - return input.copy(); - case CURVE_TYPE_POLY: - return poly_to_bezier(input); - case CURVE_TYPE_NURBS: - if (input.size() < 6) { - params.error_message_add( - NodeWarningType::Info, - TIP_("NURBS must have minimum of 6 points for Bezier Conversion")); - return input.copy(); - } - else { - if (input.size() % 3 != 0) { - params.error_message_add(NodeWarningType::Info, - TIP_("NURBS must have multiples of 3 points for full Bezier " - "conversion, curve truncated")); - } - return nurbs_to_bezier(input); - } - case CURVE_TYPE_CATMULL_ROM: { - BLI_assert_unreachable(); - return {}; - } - } - BLI_assert_unreachable(); - return {}; -} - -static SplinePtr convert_to_nurbs(const Spline &input) -{ - switch (input.type()) { - case CURVE_TYPE_NURBS: - return input.copy(); - case CURVE_TYPE_BEZIER: - return bezier_to_nurbs(input); - case CURVE_TYPE_POLY: - return poly_to_nurbs(input); - case CURVE_TYPE_CATMULL_ROM: - BLI_assert_unreachable(); - return {}; - } - BLI_assert_unreachable(); - return {}; -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - const NodeGeometryCurveSplineType *storage = - (const NodeGeometryCurveSplineType *)params.node().storage; - const GeometryNodeSplineType output_type = (const GeometryNodeSplineType)storage->spline_type; - - GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); - geometry_set = geometry::realize_instances_legacy(geometry_set); - if (!geometry_set.has_curves()) { - params.set_output("Curve", geometry_set); - return; - } - - const CurveComponent *curve_component = geometry_set.get_component_for_read<CurveComponent>(); - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component->get_for_read()); - - const std::string selection_name = params.extract_input<std::string>("Selection"); - VArray<bool> selection = curve_component->attribute_get_for_read( - selection_name, ATTR_DOMAIN_CURVE, true); - - std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>(); - for (const int i : curve->splines().index_range()) { - if (selection[i]) { - switch (output_type) { - case GEO_NODE_SPLINE_TYPE_POLY: - new_curve->add_spline(convert_to_poly_spline(*curve->splines()[i])); - break; - case GEO_NODE_SPLINE_TYPE_BEZIER: - new_curve->add_spline(convert_to_bezier(*curve->splines()[i], params)); - break; - case GEO_NODE_SPLINE_TYPE_NURBS: - new_curve->add_spline(convert_to_nurbs(*curve->splines()[i])); - break; - } - } - else { - new_curve->add_spline(curve->splines()[i]->copy()); - } - } - - new_curve->attributes = curve->attributes; - params.set_output("Curve", GeometrySet::create_with_curves(curve_eval_to_curves(*new_curve))); -} - -} // namespace blender::nodes::node_geo_legacy_curve_spline_type_cc - -void register_node_type_geo_legacy_curve_spline_type() -{ - namespace file_ns = blender::nodes::node_geo_legacy_curve_spline_type_cc; - - static bNodeType ntype; - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_CURVE_SPLINE_TYPE, "Set Spline Type", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - node_type_init(&ntype, file_ns::node_init); - node_type_storage(&ntype, - "NodeGeometryCurveSplineType", - node_free_standard_storage, - node_copy_standard_storage); - ntype.draw_buttons = file_ns::node_layout; - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc deleted file mode 100644 index 03f7aec8838..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc +++ /dev/null @@ -1,384 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_task.hh" -#include "BLI_timeit.hh" - -#include "BKE_attribute_math.hh" -#include "BKE_spline.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_curve_subdivide_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Cuts")); - b.add_input<decl::Int>(N_("Cuts"), "Cuts_001").default_value(1).min(0).max(1000); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "cuts_type", 0, IFACE_("Cuts"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryCurveSubdivide *data = MEM_cnew<NodeGeometryCurveSubdivide>(__func__); - - data->cuts_type = GEO_NODE_ATTRIBUTE_INPUT_INTEGER; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeGeometryPointTranslate &node_storage = *(NodeGeometryPointTranslate *)node->storage; - - update_attribute_input_socket_availabilities( - *ntree, *node, "Cuts", (GeometryNodeAttributeInputMode)node_storage.input_type); -} - -static Array<int> get_subdivided_offsets(const Spline &spline, - const VArray<int> &cuts, - const int spline_offset) -{ - Array<int> offsets(spline.segments_size() + 1); - int offset = 0; - for (const int i : IndexRange(spline.segments_size())) { - offsets[i] = offset; - offset = offset + std::max(cuts[spline_offset + i], 0) + 1; - } - offsets.last() = offset; - return offsets; -} - -template<typename T> -static void subdivide_attribute(Span<T> src, - const Span<int> offsets, - const bool is_cyclic, - MutableSpan<T> dst) -{ - const int src_size = src.size(); - threading::parallel_for(IndexRange(src_size - 1), 1024, [&](IndexRange range) { - for (const int i : range) { - const int cuts = offsets[i + 1] - offsets[i]; - dst[offsets[i]] = src[i]; - const float factor_delta = 1.0f / (cuts + 1.0f); - for (const int cut : IndexRange(cuts)) { - const float factor = (cut + 1) * factor_delta; - dst[offsets[i] + cut] = attribute_math::mix2(factor, src[i], src[i + 1]); - } - } - }); - - if (is_cyclic) { - const int i = src_size - 1; - const int cuts = offsets[i + 1] - offsets[i]; - dst[offsets[i]] = src.last(); - const float factor_delta = 1.0f / (cuts + 1.0f); - for (const int cut : IndexRange(cuts)) { - const float factor = (cut + 1) * factor_delta; - dst[offsets[i] + cut] = attribute_math::mix2(factor, src.last(), src.first()); - } - } - else { - dst.last() = src.last(); - } -} - -/** - * In order to generate a Bezier spline with the same shape as the input spline, apply the - * De Casteljau algorithm iteratively for the provided number of cuts, constantly updating the - * previous result point's right handle and the left handle at the end of the segment. - * - * \note Non-vector segments in the result spline are given free handles. This could possibly be - * improved with another pass that sets handles to aligned where possible, but currently that does - * not provide much benefit for the increased complexity. - */ -static void subdivide_bezier_segment(const BezierSpline &src, - const int index, - const int offset, - const int result_size, - Span<float3> src_positions, - Span<float3> src_handles_left, - Span<float3> src_handles_right, - MutableSpan<float3> dst_positions, - MutableSpan<float3> dst_handles_left, - MutableSpan<float3> dst_handles_right, - MutableSpan<int8_t> dst_type_left, - MutableSpan<int8_t> dst_type_right) -{ - const bool is_last_cyclic_segment = index == (src.size() - 1); - const int next_index = is_last_cyclic_segment ? 0 : index + 1; - - /* The first point in the segment is always copied. */ - dst_positions[offset] = src_positions[index]; - - if (src.segment_is_vector(index)) { - if (is_last_cyclic_segment) { - dst_type_left.first() = BEZIER_HANDLE_VECTOR; - } - dst_type_left.slice(offset + 1, result_size).fill(BEZIER_HANDLE_VECTOR); - dst_type_right.slice(offset, result_size).fill(BEZIER_HANDLE_VECTOR); - - const float factor_delta = 1.0f / result_size; - for (const int cut : IndexRange(result_size)) { - const float factor = cut * factor_delta; - dst_positions[offset + cut] = attribute_math::mix2( - factor, src_positions[index], src_positions[next_index]); - } - } - else { - if (is_last_cyclic_segment) { - dst_type_left.first() = BEZIER_HANDLE_FREE; - } - dst_type_left.slice(offset + 1, result_size).fill(BEZIER_HANDLE_FREE); - dst_type_right.slice(offset, result_size).fill(BEZIER_HANDLE_FREE); - - const int i_segment_last = is_last_cyclic_segment ? 0 : offset + result_size; - - /* Create a Bezier segment to update iteratively for every subdivision - * and references to the meaningful values for ease of use. */ - BezierSpline temp; - temp.resize(2); - float3 &segment_start = temp.positions().first(); - float3 &segment_end = temp.positions().last(); - float3 &handle_prev = temp.handle_positions_right().first(); - float3 &handle_next = temp.handle_positions_left().last(); - segment_start = src_positions[index]; - segment_end = src_positions[next_index]; - handle_prev = src_handles_right[index]; - handle_next = src_handles_left[next_index]; - - for (const int cut : IndexRange(result_size - 1)) { - const float parameter = 1.0f / (result_size - cut); - const BezierSpline::InsertResult insert = temp.calculate_segment_insertion(0, 1, parameter); - - /* Copy relevant temporary data to the result. */ - dst_handles_right[offset + cut] = insert.handle_prev; - dst_handles_left[offset + cut + 1] = insert.left_handle; - dst_positions[offset + cut + 1] = insert.position; - - /* Update the segment to prepare it for the next subdivision. */ - segment_start = insert.position; - handle_prev = insert.right_handle; - handle_next = insert.handle_next; - } - - /* Copy the handles for the last segment from the temporary spline. */ - dst_handles_right[offset + result_size - 1] = handle_prev; - dst_handles_left[i_segment_last] = handle_next; - } -} - -static void subdivide_bezier_spline(const BezierSpline &src, - const Span<int> offsets, - BezierSpline &dst) -{ - Span<float3> src_positions = src.positions(); - Span<float3> src_handles_left = src.handle_positions_left(); - Span<float3> src_handles_right = src.handle_positions_right(); - MutableSpan<float3> dst_positions = dst.positions(); - MutableSpan<float3> dst_handles_left = dst.handle_positions_left(); - MutableSpan<float3> dst_handles_right = dst.handle_positions_right(); - MutableSpan<int8_t> dst_type_left = dst.handle_types_left(); - MutableSpan<int8_t> dst_type_right = dst.handle_types_right(); - - threading::parallel_for(IndexRange(src.size() - 1), 512, [&](IndexRange range) { - for (const int i : range) { - subdivide_bezier_segment(src, - i, - offsets[i], - offsets[i + 1] - offsets[i], - src_positions, - src_handles_left, - src_handles_right, - dst_positions, - dst_handles_left, - dst_handles_right, - dst_type_left, - dst_type_right); - } - }); - - if (src.is_cyclic()) { - const int i_last = src.size() - 1; - subdivide_bezier_segment(src, - i_last, - offsets[i_last], - offsets.last() - offsets[i_last], - src_positions, - src_handles_left, - src_handles_right, - dst_positions, - dst_handles_left, - dst_handles_right, - dst_type_left, - dst_type_right); - } - else { - dst_positions.last() = src_positions.last(); - } -} - -static void subdivide_builtin_attributes(const Spline &src_spline, - const Span<int> offsets, - Spline &dst_spline) -{ - const bool is_cyclic = src_spline.is_cyclic(); - subdivide_attribute<float>(src_spline.radii(), offsets, is_cyclic, dst_spline.radii()); - subdivide_attribute<float>(src_spline.tilts(), offsets, is_cyclic, dst_spline.tilts()); - switch (src_spline.type()) { - case CURVE_TYPE_POLY: { - const PolySpline &src = static_cast<const PolySpline &>(src_spline); - PolySpline &dst = static_cast<PolySpline &>(dst_spline); - subdivide_attribute<float3>(src.positions(), offsets, is_cyclic, dst.positions()); - break; - } - case CURVE_TYPE_BEZIER: { - const BezierSpline &src = static_cast<const BezierSpline &>(src_spline); - BezierSpline &dst = static_cast<BezierSpline &>(dst_spline); - subdivide_bezier_spline(src, offsets, dst); - dst.mark_cache_invalid(); - break; - } - case CURVE_TYPE_NURBS: { - const NURBSpline &src = static_cast<const NURBSpline &>(src_spline); - NURBSpline &dst = static_cast<NURBSpline &>(dst_spline); - subdivide_attribute<float3>(src.positions(), offsets, is_cyclic, dst.positions()); - subdivide_attribute<float>(src.weights(), offsets, is_cyclic, dst.weights()); - break; - } - case CURVE_TYPE_CATMULL_ROM: { - BLI_assert_unreachable(); - break; - } - } -} - -static void subdivide_dynamic_attributes(const Spline &src_spline, - const Span<int> offsets, - Spline &dst_spline) -{ - const bool is_cyclic = src_spline.is_cyclic(); - src_spline.attributes.foreach_attribute( - [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - std::optional<GSpan> src = src_spline.attributes.get_for_read(attribute_id); - BLI_assert(src); - - if (!dst_spline.attributes.create(attribute_id, meta_data.data_type)) { - /* Since the source spline of the same type had the attribute, adding it should work. */ - BLI_assert_unreachable(); - } - - std::optional<GMutableSpan> dst = dst_spline.attributes.get_for_write(attribute_id); - BLI_assert(dst); - - attribute_math::convert_to_static_type(dst->type(), [&](auto dummy) { - using T = decltype(dummy); - subdivide_attribute<T>(src->typed<T>(), offsets, is_cyclic, dst->typed<T>()); - }); - return true; - }, - ATTR_DOMAIN_POINT); -} - -static SplinePtr subdivide_spline(const Spline &spline, - const VArray<int> &cuts, - const int spline_offset) -{ - if (spline.size() <= 1) { - return spline.copy(); - } - - /* Since we expect to access each value many times, it should be worth it to make sure count - * of cuts is a real span (especially considering the note below). Using the offset at each - * point facilitates subdividing in parallel later. */ - Array<int> offsets = get_subdivided_offsets(spline, cuts, spline_offset); - const int result_size = offsets.last() + int(!spline.is_cyclic()); - SplinePtr new_spline = spline.copy_only_settings(); - new_spline->resize(result_size); - subdivide_builtin_attributes(spline, offsets, *new_spline); - subdivide_dynamic_attributes(spline, offsets, *new_spline); - return new_spline; -} - -/** - * \note Passing the virtual array for the entire spline is possibly quite inefficient here when - * the attribute was on the point domain and stored separately for each spline already, and it - * prevents some other optimizations like skipping splines with a single attribute value of < 1. - * However, it allows the node to access builtin attribute easily, so it the makes most sense this - * way until the attribute API is refactored. - */ -static std::unique_ptr<CurveEval> subdivide_curve(const CurveEval &input_curve, - const VArray<int> &cuts) -{ - const Array<int> control_point_offsets = input_curve.control_point_offsets(); - const Span<SplinePtr> input_splines = input_curve.splines(); - - std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>(); - output_curve->resize(input_splines.size()); - output_curve->attributes = input_curve.attributes; - MutableSpan<SplinePtr> output_splines = output_curve->splines(); - - threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) { - for (const int i : range) { - output_splines[i] = subdivide_spline(*input_splines[i], cuts, control_point_offsets[i]); - } - }); - - return output_curve; -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (!geometry_set.has_curves()) { - params.set_output("Geometry", geometry_set); - return; - } - - const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>(); - VArray<int> cuts = params.get_input_attribute<int>("Cuts", component, ATTR_DOMAIN_POINT, 0); - if (cuts.is_single() && cuts.get_internal_single() < 1) { - params.set_output("Geometry", geometry_set); - return; - } - - std::unique_ptr<CurveEval> output_curve = subdivide_curve( - *curves_to_curve_eval(*component.get_for_read()), cuts); - - params.set_output("Geometry", - GeometrySet::create_with_curves(curve_eval_to_curves(*output_curve))); -} - -} // namespace blender::nodes::node_geo_legacy_curve_subdivide_cc - -void register_node_type_geo_legacy_curve_subdivide() -{ - namespace file_ns = blender::nodes::node_geo_legacy_curve_subdivide_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_CURVE_SUBDIVIDE, "Curve Subdivide", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.draw_buttons = file_ns::node_layout; - node_type_storage(&ntype, - "NodeGeometryCurveSubdivide", - node_free_standard_storage, - node_copy_standard_storage); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - ntype.geometry_node_execute = file_ns::node_geo_exec; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc deleted file mode 100644 index f8fcc3cc363..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc +++ /dev/null @@ -1,351 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_array.hh" -#include "BLI_task.hh" -#include "BLI_timeit.hh" - -#include "BKE_pointcloud.h" -#include "BKE_spline.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes { - -static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &points, - const AttributeIDRef &attribute_id, - const CustomDataType data_type) -{ - points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault()); - WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id); - BLI_assert(attribute); - return attribute.varray.get_internal_span(); -} - -template<typename T> -static MutableSpan<T> create_attribute_and_retrieve_span(PointCloudComponent &points, - const AttributeIDRef &attribute_id) -{ - GMutableSpan attribute = create_attribute_and_retrieve_span( - points, attribute_id, bke::cpp_type_to_custom_data_type(CPPType::get<T>())); - return attribute.typed<T>(); -} - -CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points, - const CurveEval &curve) -{ - CurveToPointsResults attributes; - - attributes.result_size = points.attribute_domain_size(ATTR_DOMAIN_POINT); - - attributes.positions = create_attribute_and_retrieve_span<float3>(points, "position"); - attributes.radii = create_attribute_and_retrieve_span<float>(points, "radius"); - attributes.tilts = create_attribute_and_retrieve_span<float>(points, "tilt"); - - /* Because of the invariants of the curve component, we use the attributes of the - * first spline as a representative for the attribute meta data all splines. */ - curve.splines().first()->attributes.foreach_attribute( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - attributes.point_attributes.add_new( - attribute_id, - create_attribute_and_retrieve_span(points, attribute_id, meta_data.data_type)); - return true; - }, - ATTR_DOMAIN_POINT); - - attributes.tangents = create_attribute_and_retrieve_span<float3>(points, "tangent"); - attributes.normals = create_attribute_and_retrieve_span<float3>(points, "normal"); - attributes.rotations = create_attribute_and_retrieve_span<float3>(points, "rotation"); - - return attributes; -} - -} // namespace blender::nodes - -namespace blender::nodes::node_geo_legacy_curve_to_points_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Int>(N_("Count")).default_value(10).min(2).max(100000); - b.add_input<decl::Float>(N_("Length")).default_value(0.1f).min(0.001f).subtype(PROP_DISTANCE); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "mode", 0, "", ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryCurveToPoints *data = MEM_cnew<NodeGeometryCurveToPoints>(__func__); - - data->mode = GEO_NODE_CURVE_RESAMPLE_COUNT; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeGeometryCurveToPoints &node_storage = *(NodeGeometryCurveToPoints *)node->storage; - const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode; - - bNodeSocket *count_socket = ((bNodeSocket *)node->inputs.first)->next; - bNodeSocket *length_socket = count_socket->next; - - nodeSetSocketAvailability(ntree, count_socket, mode == GEO_NODE_CURVE_RESAMPLE_COUNT); - nodeSetSocketAvailability(ntree, length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH); -} - -/** - * Evaluate splines in parallel to speed up the rest of the node's execution. - */ -static void evaluate_splines(Span<SplinePtr> splines) -{ - threading::parallel_for_each(splines, [](const SplinePtr &spline) { - /* These functions fill the corresponding caches on each spline. */ - spline->evaluated_positions(); - spline->evaluated_tangents(); - spline->evaluated_normals(); - spline->evaluated_lengths(); - }); -} - -static Array<int> calculate_spline_point_offsets(GeoNodeExecParams ¶ms, - const GeometryNodeCurveResampleMode mode, - const CurveEval &curve, - const Span<SplinePtr> splines) -{ - const int size = curve.splines().size(); - switch (mode) { - case GEO_NODE_CURVE_RESAMPLE_COUNT: { - const int count = params.extract_input<int>("Count"); - if (count < 1) { - return {0}; - } - Array<int> offsets(size + 1); - for (const int i : offsets.index_range()) { - offsets[i] = count * i; - } - return offsets; - } - case GEO_NODE_CURVE_RESAMPLE_LENGTH: { - /* Don't allow asymptotic count increase for low resolution values. */ - const float resolution = std::max(params.extract_input<float>("Length"), 0.0001f); - Array<int> offsets(size + 1); - int offset = 0; - for (const int i : IndexRange(size)) { - offsets[i] = offset; - offset += splines[i]->length() / resolution + 1; - } - offsets.last() = offset; - return offsets; - } - case GEO_NODE_CURVE_RESAMPLE_EVALUATED: { - return curve.evaluated_point_offsets(); - } - } - BLI_assert_unreachable(); - return {0}; -} - -/** - * TODO: For non-poly splines, this has double copies that could be avoided as part - * of a general look at optimizing uses of #Spline::interpolate_to_evaluated. - */ -static void copy_evaluated_point_attributes(Span<SplinePtr> splines, - Span<int> offsets, - CurveToPointsResults &data) -{ - threading::parallel_for(splines.index_range(), 64, [&](IndexRange range) { - for (const int i : range) { - const Spline &spline = *splines[i]; - const int offset = offsets[i]; - const int size = offsets[i + 1] - offsets[i]; - - data.positions.slice(offset, size).copy_from(spline.evaluated_positions()); - spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size)); - spline.interpolate_to_evaluated(spline.tilts()).materialize(data.tilts.slice(offset, size)); - - for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) { - const AttributeIDRef attribute_id = item.key; - GMutableSpan point_span = item.value; - - BLI_assert(spline.attributes.get_for_read(attribute_id)); - GSpan spline_span = *spline.attributes.get_for_read(attribute_id); - - spline.interpolate_to_evaluated(spline_span) - .materialize(point_span.slice(offset, size).data()); - } - - data.tangents.slice(offset, size).copy_from(spline.evaluated_tangents()); - data.normals.slice(offset, size).copy_from(spline.evaluated_normals()); - } - }); -} - -static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines, - Span<int> offsets, - CurveToPointsResults &data) -{ - threading::parallel_for(splines.index_range(), 64, [&](IndexRange range) { - for (const int i : range) { - const Spline &spline = *splines[i]; - const int offset = offsets[i]; - const int size = offsets[i + 1] - offsets[i]; - if (size == 0) { - continue; - } - - const Array<float> uniform_samples = spline.sample_uniform_index_factors(size); - - spline.sample_with_index_factors<float3>( - spline.evaluated_positions(), uniform_samples, data.positions.slice(offset, size)); - - spline.sample_with_index_factors<float>(spline.interpolate_to_evaluated(spline.radii()), - uniform_samples, - data.radii.slice(offset, size)); - - spline.sample_with_index_factors<float>(spline.interpolate_to_evaluated(spline.tilts()), - uniform_samples, - data.tilts.slice(offset, size)); - - for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) { - const AttributeIDRef attribute_id = item.key; - GMutableSpan point_span = item.value; - - BLI_assert(spline.attributes.get_for_read(attribute_id)); - GSpan spline_span = *spline.attributes.get_for_read(attribute_id); - - spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span), - uniform_samples, - point_span.slice(offset, size)); - } - - spline.sample_with_index_factors<float3>( - spline.evaluated_tangents(), uniform_samples, data.tangents.slice(offset, size)); - for (float3 &tangent : data.tangents) { - tangent = math::normalize(tangent); - } - - spline.sample_with_index_factors<float3>( - spline.evaluated_normals(), uniform_samples, data.normals.slice(offset, size)); - for (float3 &normals : data.normals) { - normals = math::normalize(normals); - } - } - }); -} - -/** - * \note Use attributes from the curve component rather than the attribute data directly on the - * attribute storage to allow reading the virtual spline attributes like "cyclic" and "resolution". - */ -static void copy_spline_domain_attributes(const CurveComponent &curve_component, - Span<int> offsets, - PointCloudComponent &points) -{ - curve_component.attribute_foreach( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - if (meta_data.domain != ATTR_DOMAIN_CURVE) { - return true; - } - GVArray spline_attribute = curve_component.attribute_get_for_read( - attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type); - const CPPType &type = spline_attribute.type(); - - OutputAttribute result_attribute = points.attribute_try_get_for_output_only( - attribute_id, ATTR_DOMAIN_POINT, meta_data.data_type); - GMutableSpan result = result_attribute.as_span(); - - for (const int i : spline_attribute.index_range()) { - const int offset = offsets[i]; - const int size = offsets[i + 1] - offsets[i]; - if (size != 0) { - BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); - spline_attribute.get(i, buffer); - type.fill_assign_n(buffer, result[offset], size); - } - } - - result_attribute.save(); - return true; - }); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - NodeGeometryCurveToPoints &node_storage = *(NodeGeometryCurveToPoints *)params.node().storage; - const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode; - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (!geometry_set.has_curves()) { - params.set_output("Geometry", GeometrySet()); - return; - } - - const CurveComponent &curve_component = *geometry_set.get_component_for_read<CurveComponent>(); - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read()); - const Span<SplinePtr> splines = curve->splines(); - curve->assert_valid_point_attributes(); - - evaluate_splines(splines); - - const Array<int> offsets = calculate_spline_point_offsets(params, mode, *curve, splines); - const int total_size = offsets.last(); - if (total_size == 0) { - params.set_output("Geometry", GeometrySet()); - return; - } - - GeometrySet result = GeometrySet::create_with_pointcloud(BKE_pointcloud_new_nomain(total_size)); - PointCloudComponent &point_component = result.get_component_for_write<PointCloudComponent>(); - - CurveToPointsResults new_attributes = curve_to_points_create_result_attributes(point_component, - *curve); - switch (mode) { - case GEO_NODE_CURVE_RESAMPLE_COUNT: - case GEO_NODE_CURVE_RESAMPLE_LENGTH: - copy_uniform_sample_point_attributes(splines, offsets, new_attributes); - break; - case GEO_NODE_CURVE_RESAMPLE_EVALUATED: - copy_evaluated_point_attributes(splines, offsets, new_attributes); - break; - } - - copy_spline_domain_attributes(curve_component, offsets, point_component); - curve_create_default_rotation_attribute( - new_attributes.tangents, new_attributes.normals, new_attributes.rotations); - - /* The default radius is way too large for points, divide by 10. */ - for (float &radius : new_attributes.radii) { - radius *= 0.1f; - } - - params.set_output("Geometry", std::move(result)); -} - -} // namespace blender::nodes::node_geo_legacy_curve_to_points_cc - -void register_node_type_geo_legacy_curve_to_points() -{ - namespace file_ns = blender::nodes::node_geo_legacy_curve_to_points_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_CURVE_TO_POINTS, "Curve to Points", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - node_type_storage( - &ntype, "NodeGeometryCurveToPoints", node_free_standard_storage, node_copy_standard_storage); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc deleted file mode 100644 index ca98d83c137..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc +++ /dev/null @@ -1,726 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_array.hh" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" - -#include "BKE_customdata.h" -#include "BKE_mesh.h" -#include "BKE_pointcloud.h" -#include "BKE_spline.hh" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_delete_geometry_cc { - -using blender::bke::CustomDataAttributes; - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Selection")); - b.add_input<decl::Bool>(N_("Invert")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -template<typename T> static void copy_data(Span<T> data, MutableSpan<T> r_data, IndexMask mask) -{ - for (const int i_out : mask.index_range()) { - r_data[i_out] = data[mask[i_out]]; - } -} - -static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span<int> vertex_map) -{ - BLI_assert(src_mesh.totvert == vertex_map.size()); - for (const int i_src : vertex_map.index_range()) { - const int i_dst = vertex_map[i_src]; - if (i_dst == -1) { - continue; - } - - const MVert &v_src = src_mesh.mvert[i_src]; - MVert &v_dst = dst_mesh.mvert[i_dst]; - - v_dst = v_src; - CustomData_copy_data(&src_mesh.vdata, &dst_mesh.vdata, i_src, i_dst, 1); - } -} - -static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span<int> vertex_map, - Span<int> edge_map) -{ - BLI_assert(src_mesh.totvert == vertex_map.size()); - BLI_assert(src_mesh.totedge == edge_map.size()); - for (const int i_src : IndexRange(src_mesh.totedge)) { - const int i_dst = edge_map[i_src]; - if (ELEM(i_dst, -1, -2)) { - continue; - } - - const MEdge &e_src = src_mesh.medge[i_src]; - MEdge &e_dst = dst_mesh.medge[i_dst]; - - CustomData_copy_data(&src_mesh.edata, &dst_mesh.edata, i_src, i_dst, 1); - e_dst = e_src; - e_dst.v1 = vertex_map[e_src.v1]; - e_dst.v2 = vertex_map[e_src.v2]; - } -} - -static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span<int> vertex_map, - Span<int> edge_map, - Span<int> masked_poly_indices, - Span<int> new_loop_starts) -{ - for (const int i_dst : masked_poly_indices.index_range()) { - const int i_src = masked_poly_indices[i_dst]; - - const MPoly &mp_src = src_mesh.mpoly[i_src]; - MPoly &mp_dst = dst_mesh.mpoly[i_dst]; - const int i_ml_src = mp_src.loopstart; - const int i_ml_dst = new_loop_starts[i_dst]; - - CustomData_copy_data(&src_mesh.pdata, &dst_mesh.pdata, i_src, i_dst, 1); - CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src, i_ml_dst, mp_src.totloop); - - const MLoop *ml_src = src_mesh.mloop + i_ml_src; - MLoop *ml_dst = dst_mesh.mloop + i_ml_dst; - - mp_dst = mp_src; - mp_dst.loopstart = i_ml_dst; - for (int i : IndexRange(mp_src.totloop)) { - ml_dst[i].v = vertex_map[ml_src[i].v]; - ml_dst[i].e = edge_map[ml_src[i].e]; - } - } -} - -static void spline_copy_builtin_attributes(const Spline &spline, - Spline &r_spline, - const IndexMask mask) -{ - copy_data(spline.positions(), r_spline.positions(), mask); - copy_data(spline.radii(), r_spline.radii(), mask); - copy_data(spline.tilts(), r_spline.tilts(), mask); - switch (spline.type()) { - case CURVE_TYPE_POLY: - break; - case CURVE_TYPE_BEZIER: { - const BezierSpline &src = static_cast<const BezierSpline &>(spline); - BezierSpline &dst = static_cast<BezierSpline &>(r_spline); - copy_data(src.handle_positions_left(), dst.handle_positions_left(), mask); - copy_data(src.handle_positions_right(), dst.handle_positions_right(), mask); - copy_data(src.handle_types_left(), dst.handle_types_left(), mask); - copy_data(src.handle_types_right(), dst.handle_types_right(), mask); - break; - } - case CURVE_TYPE_NURBS: { - const NURBSpline &src = static_cast<const NURBSpline &>(spline); - NURBSpline &dst = static_cast<NURBSpline &>(r_spline); - copy_data(src.weights(), dst.weights(), mask); - break; - } - case CURVE_TYPE_CATMULL_ROM: { - BLI_assert_unreachable(); - break; - } - } -} - -static void copy_dynamic_attributes(const CustomDataAttributes &src, - CustomDataAttributes &dst, - const IndexMask mask) -{ - src.foreach_attribute( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - std::optional<GSpan> src_attribute = src.get_for_read(attribute_id); - BLI_assert(src_attribute); - - if (!dst.create(attribute_id, meta_data.data_type)) { - /* Since the source spline of the same type had the attribute, adding it should work. - */ - BLI_assert_unreachable(); - } - - std::optional<GMutableSpan> new_attribute = dst.get_for_write(attribute_id); - BLI_assert(new_attribute); - - attribute_math::convert_to_static_type(new_attribute->type(), [&](auto dummy) { - using T = decltype(dummy); - copy_data(src_attribute->typed<T>(), new_attribute->typed<T>(), mask); - }); - return true; - }, - ATTR_DOMAIN_POINT); -} - -static SplinePtr spline_delete(const Spline &spline, const IndexMask mask) -{ - SplinePtr new_spline = spline.copy_only_settings(); - new_spline->resize(mask.size()); - - spline_copy_builtin_attributes(spline, *new_spline, mask); - copy_dynamic_attributes(spline.attributes, new_spline->attributes, mask); - - return new_spline; -} - -static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve, - const StringRef name, - const bool invert) -{ - Span<SplinePtr> input_splines = input_curve.splines(); - std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>(); - - /* Keep track of which splines were copied to the result to copy spline domain attributes. */ - Vector<int64_t> copied_splines; - - if (input_curve.attributes.get_for_read(name)) { - VArray<bool> selection = input_curve.attributes.get_for_read<bool>(name, false); - for (const int i : input_splines.index_range()) { - if (selection[i] == invert) { - output_curve->add_spline(input_splines[i]->copy()); - copied_splines.append(i); - } - } - } - else { - /* Reuse index vector for each spline. */ - Vector<int64_t> indices_to_copy; - - for (const int i : input_splines.index_range()) { - const Spline &spline = *input_splines[i]; - VArray<bool> selection = spline.attributes.get_for_read<bool>(name, false); - - indices_to_copy.clear(); - for (const int i_point : IndexRange(spline.size())) { - if (selection[i_point] == invert) { - indices_to_copy.append(i_point); - } - } - - /* Avoid creating an empty spline. */ - if (indices_to_copy.is_empty()) { - continue; - } - - SplinePtr new_spline = spline_delete(spline, IndexMask(indices_to_copy)); - output_curve->add_spline(std::move(new_spline)); - copied_splines.append(i); - } - } - - if (copied_splines.is_empty()) { - return {}; - } - - output_curve->attributes.reallocate(output_curve->splines().size()); - copy_dynamic_attributes( - input_curve.attributes, output_curve->attributes, IndexMask(copied_splines)); - - return output_curve; -} - -static void delete_curve_selection(const CurveComponent &in_component, - CurveComponent &r_component, - const StringRef selection_name, - const bool invert) -{ - std::unique_ptr<CurveEval> r_curve = curve_delete( - *curves_to_curve_eval(*in_component.get_for_read()), selection_name, invert); - if (r_curve) { - r_component.replace(curve_eval_to_curves(*r_curve)); - } - else { - r_component.clear(); - } -} - -static void delete_point_cloud_selection(const PointCloudComponent &in_component, - PointCloudComponent &out_component, - const StringRef selection_name, - const bool invert) -{ - const VArray<bool> selection_attribute = in_component.attribute_get_for_read<bool>( - selection_name, ATTR_DOMAIN_POINT, false); - VArray_Span<bool> selection{selection_attribute}; - - const int total = selection.count(invert); - if (total == 0) { - out_component.clear(); - return; - } - out_component.replace(BKE_pointcloud_new_nomain(total)); - - /* Invert the inversion, because this deletes the selected points instead of keeping them. */ - copy_point_attributes_based_on_mask(in_component, out_component, selection, !invert); -} - -static void compute_selected_vertices_from_vertex_selection(const VArray<bool> &vertex_selection, - const bool invert, - MutableSpan<int> r_vertex_map, - uint *r_num_selected_vertices) -{ - BLI_assert(vertex_selection.size() == r_vertex_map.size()); - - uint num_selected_vertices = 0; - for (const int i : r_vertex_map.index_range()) { - if (vertex_selection[i] != invert) { - r_vertex_map[i] = num_selected_vertices; - num_selected_vertices++; - } - else { - r_vertex_map[i] = -1; - } - } - - *r_num_selected_vertices = num_selected_vertices; -} - -static void compute_selected_edges_from_vertex_selection(const Mesh &mesh, - const VArray<bool> &vertex_selection, - const bool invert, - MutableSpan<int> r_edge_map, - uint *r_num_selected_edges) -{ - BLI_assert(mesh.totedge == r_edge_map.size()); - - uint num_selected_edges = 0; - for (const int i : IndexRange(mesh.totedge)) { - const MEdge &edge = mesh.medge[i]; - - /* Only add the edge if both vertices will be in the new mesh. */ - if (vertex_selection[edge.v1] != invert && vertex_selection[edge.v2] != invert) { - r_edge_map[i] = num_selected_edges; - num_selected_edges++; - } - else { - r_edge_map[i] = -1; - } - } - - *r_num_selected_edges = num_selected_edges; -} - -static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh, - const VArray<bool> &vertex_selection, - const bool invert, - Vector<int> &r_selected_poly_indices, - Vector<int> &r_loop_starts, - uint *r_num_selected_polys, - uint *r_num_selected_loops) -{ - BLI_assert(mesh.totvert == vertex_selection.size()); - - r_selected_poly_indices.reserve(mesh.totpoly); - r_loop_starts.reserve(mesh.totloop); - - uint num_selected_loops = 0; - for (const int i : IndexRange(mesh.totpoly)) { - const MPoly &poly_src = mesh.mpoly[i]; - - bool all_verts_in_selection = true; - Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); - for (const MLoop &loop : loops_src) { - if (vertex_selection[loop.v] == invert) { - all_verts_in_selection = false; - break; - } - } - - if (all_verts_in_selection) { - r_selected_poly_indices.append_unchecked(i); - r_loop_starts.append_unchecked(num_selected_loops); - num_selected_loops += poly_src.totloop; - } - } - - *r_num_selected_polys = r_selected_poly_indices.size(); - *r_num_selected_loops = num_selected_loops; -} - -/** - * Checks for every edge if it is in `edge_selection`. If it is, then the two vertices of the - * edge are kept along with the edge. - */ -static void compute_selected_vertices_and_edges_from_edge_selection( - const Mesh &mesh, - const VArray<bool> &edge_selection, - const bool invert, - MutableSpan<int> r_vertex_map, - MutableSpan<int> r_edge_map, - uint *r_num_selected_vertices, - uint *r_num_selected_edges) -{ - BLI_assert(mesh.totedge == edge_selection.size()); - - uint num_selected_edges = 0; - uint num_selected_vertices = 0; - for (const int i : IndexRange(mesh.totedge)) { - const MEdge &edge = mesh.medge[i]; - if (edge_selection[i] != invert) { - r_edge_map[i] = num_selected_edges; - num_selected_edges++; - if (r_vertex_map[edge.v1] == -1) { - r_vertex_map[edge.v1] = num_selected_vertices; - num_selected_vertices++; - } - if (r_vertex_map[edge.v2] == -1) { - r_vertex_map[edge.v2] = num_selected_vertices; - num_selected_vertices++; - } - } - else { - r_edge_map[i] = -1; - } - } - - *r_num_selected_vertices = num_selected_vertices; - *r_num_selected_edges = num_selected_edges; -} - -/** - * Checks for every polygon if all the edges are in `edge_selection`. If they are, then that - * polygon is kept. - */ -static void compute_selected_polygons_from_edge_selection(const Mesh &mesh, - const VArray<bool> &edge_selection, - const bool invert, - Vector<int> &r_selected_poly_indices, - Vector<int> &r_loop_starts, - uint *r_num_selected_polys, - uint *r_num_selected_loops) -{ - r_selected_poly_indices.reserve(mesh.totpoly); - r_loop_starts.reserve(mesh.totloop); - - uint num_selected_loops = 0; - for (const int i : IndexRange(mesh.totpoly)) { - const MPoly &poly_src = mesh.mpoly[i]; - - bool all_edges_in_selection = true; - Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); - for (const MLoop &loop : loops_src) { - if (edge_selection[loop.e] == invert) { - all_edges_in_selection = false; - break; - } - } - - if (all_edges_in_selection) { - r_selected_poly_indices.append_unchecked(i); - r_loop_starts.append_unchecked(num_selected_loops); - num_selected_loops += poly_src.totloop; - } - } - - *r_num_selected_polys = r_selected_poly_indices.size(); - *r_num_selected_loops = num_selected_loops; -} - -/** - * Checks for every vertex if it is in `vertex_selection`. The polygons and edges are kept if all - * vertices of that polygon or edge are in the selection. - */ -static void compute_selected_mesh_data_from_vertex_selection(const Mesh &mesh, - const VArray<bool> &vertex_selection, - const bool invert, - MutableSpan<int> r_vertex_map, - MutableSpan<int> r_edge_map, - Vector<int> &r_selected_poly_indices, - Vector<int> &r_loop_starts, - uint *r_num_selected_vertices, - uint *r_num_selected_edges, - uint *r_num_selected_polys, - uint *r_num_selected_loops) -{ - compute_selected_vertices_from_vertex_selection( - vertex_selection, invert, r_vertex_map, r_num_selected_vertices); - - compute_selected_edges_from_vertex_selection( - mesh, vertex_selection, invert, r_edge_map, r_num_selected_edges); - - compute_selected_polygons_from_vertex_selection(mesh, - vertex_selection, - invert, - r_selected_poly_indices, - r_loop_starts, - r_num_selected_polys, - r_num_selected_loops); -} - -/** - * Checks for every edge if it is in `edge_selection`. If it is, the vertices belonging to - * that edge are kept as well. The polygons are kept if all edges are in the selection. - */ -static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh, - const VArray<bool> &edge_selection, - const bool invert, - MutableSpan<int> r_vertex_map, - MutableSpan<int> r_edge_map, - Vector<int> &r_selected_poly_indices, - Vector<int> &r_loop_starts, - uint *r_num_selected_vertices, - uint *r_num_selected_edges, - uint *r_num_selected_polys, - uint *r_num_selected_loops) -{ - r_vertex_map.fill(-1); - compute_selected_vertices_and_edges_from_edge_selection(mesh, - edge_selection, - invert, - r_vertex_map, - r_edge_map, - r_num_selected_vertices, - r_num_selected_edges); - compute_selected_polygons_from_edge_selection(mesh, - edge_selection, - invert, - r_selected_poly_indices, - r_loop_starts, - r_num_selected_polys, - r_num_selected_loops); -} - -/** - * Checks for every polygon if it is in `poly_selection`. If it is, the edges and vertices - * belonging to that polygon are kept as well. - */ -static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, - const VArray<bool> &poly_selection, - const bool invert, - MutableSpan<int> r_vertex_map, - MutableSpan<int> r_edge_map, - Vector<int> &r_selected_poly_indices, - Vector<int> &r_loop_starts, - uint *r_num_selected_vertices, - uint *r_num_selected_edges, - uint *r_num_selected_polys, - uint *r_num_selected_loops) -{ - BLI_assert(mesh.totpoly == poly_selection.size()); - BLI_assert(mesh.totedge == r_edge_map.size()); - r_vertex_map.fill(-1); - r_edge_map.fill(-1); - - r_selected_poly_indices.reserve(mesh.totpoly); - r_loop_starts.reserve(mesh.totloop); - - uint num_selected_loops = 0; - uint num_selected_vertices = 0; - uint num_selected_edges = 0; - for (const int i : IndexRange(mesh.totpoly)) { - const MPoly &poly_src = mesh.mpoly[i]; - /* We keep this one. */ - if (poly_selection[i] != invert) { - r_selected_poly_indices.append_unchecked(i); - r_loop_starts.append_unchecked(num_selected_loops); - num_selected_loops += poly_src.totloop; - - /* Add the vertices and the edges. */ - Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); - for (const MLoop &loop : loops_src) { - /* Check first if it has not yet been added. */ - if (r_vertex_map[loop.v] == -1) { - r_vertex_map[loop.v] = num_selected_vertices; - num_selected_vertices++; - } - if (r_edge_map[loop.e] == -1) { - r_edge_map[loop.e] = num_selected_edges; - num_selected_edges++; - } - } - } - } - *r_num_selected_vertices = num_selected_vertices; - *r_num_selected_edges = num_selected_edges; - *r_num_selected_polys = r_selected_poly_indices.size(); - *r_num_selected_loops = num_selected_loops; -} - -using FillMapsFunction = void (*)(const Mesh &mesh, - const VArray<bool> &selection, - const bool invert, - MutableSpan<int> r_vertex_map, - MutableSpan<int> r_edge_map, - Vector<int> &r_selected_poly_indices, - Vector<int> &r_loop_starts, - uint *r_num_selected_vertices, - uint *r_num_selected_edges, - uint *r_num_selected_polys, - uint *r_num_selected_loops); - -/** - * Delete the parts of the mesh that are in the selection. The `fill_maps_function` - * depends on the selection type: vertices, edges or faces. - */ -static Mesh *delete_mesh_selection(const Mesh &mesh_in, - const VArray<bool> &selection, - const bool invert, - FillMapsFunction fill_maps_function) -{ - Array<int> vertex_map(mesh_in.totvert); - uint num_selected_vertices; - - Array<int> edge_map(mesh_in.totedge); - uint num_selected_edges; - - Vector<int> selected_poly_indices; - Vector<int> new_loop_starts; - uint num_selected_polys; - uint num_selected_loops; - - /* Fill all the maps based on the selection. We delete everything - * in the selection instead of keeping it, so we need to invert it. */ - fill_maps_function(mesh_in, - selection, - !invert, - vertex_map, - edge_map, - selected_poly_indices, - new_loop_starts, - &num_selected_vertices, - &num_selected_edges, - &num_selected_polys, - &num_selected_loops); - - Mesh *result = BKE_mesh_new_nomain_from_template(&mesh_in, - num_selected_vertices, - num_selected_edges, - 0, - num_selected_loops, - num_selected_polys); - - /* Copy the selected parts of the mesh over to the new mesh. */ - copy_masked_vertices_to_new_mesh(mesh_in, *result, vertex_map); - copy_masked_edges_to_new_mesh(mesh_in, *result, vertex_map, edge_map); - copy_masked_polys_to_new_mesh( - mesh_in, *result, vertex_map, edge_map, selected_poly_indices, new_loop_starts); - BKE_mesh_calc_edges_loose(result); - /* Tag to recalculate normals later. */ - BKE_mesh_normals_tag_dirty(result); - - return result; -} - -static AttributeDomain get_mesh_selection_domain(MeshComponent &component, const StringRef name) -{ - std::optional<AttributeMetaData> selection_attribute = component.attribute_get_meta_data(name); - if (!selection_attribute) { - /* The node will not do anything in this case, but this function must return something. */ - return ATTR_DOMAIN_POINT; - } - - /* Corners can't be deleted separately, so interpolate corner attributes - * to the face domain. Note that this choice is somewhat arbitrary. */ - if (selection_attribute->domain == ATTR_DOMAIN_CORNER) { - return ATTR_DOMAIN_FACE; - } - - return selection_attribute->domain; -} - -static void delete_mesh_selection(MeshComponent &component, - const Mesh &mesh_in, - const StringRef selection_name, - const bool invert) -{ - /* Figure out the best domain to use. */ - const AttributeDomain selection_domain = get_mesh_selection_domain(component, selection_name); - - /* This already checks if the attribute exists, and displays a warning in that case. */ - VArray<bool> selection = component.attribute_get_for_read<bool>( - selection_name, selection_domain, false); - - /* Check if there is anything to delete. */ - bool delete_nothing = true; - for (const int i : selection.index_range()) { - if (selection[i] != invert) { - delete_nothing = false; - break; - } - } - if (delete_nothing) { - return; - } - - Mesh *mesh_out; - switch (selection_domain) { - case ATTR_DOMAIN_POINT: - mesh_out = delete_mesh_selection( - mesh_in, selection, invert, compute_selected_mesh_data_from_vertex_selection); - break; - case ATTR_DOMAIN_EDGE: - mesh_out = delete_mesh_selection( - mesh_in, selection, invert, compute_selected_mesh_data_from_edge_selection); - break; - case ATTR_DOMAIN_FACE: - mesh_out = delete_mesh_selection( - mesh_in, selection, invert, compute_selected_mesh_data_from_poly_selection); - break; - default: - BLI_assert_unreachable(); - mesh_out = nullptr; - break; - } - component.replace(mesh_out); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - geometry_set = geometry::realize_instances_legacy(geometry_set); - - const bool invert = params.extract_input<bool>("Invert"); - const std::string selection_name = params.extract_input<std::string>("Selection"); - if (selection_name.empty()) { - params.set_output("Geometry", std::move(geometry_set)); - return; - } - - GeometrySet out_set(geometry_set); - if (geometry_set.has<PointCloudComponent>()) { - delete_point_cloud_selection(*geometry_set.get_component_for_read<PointCloudComponent>(), - out_set.get_component_for_write<PointCloudComponent>(), - selection_name, - invert); - } - if (geometry_set.has<MeshComponent>()) { - delete_mesh_selection(out_set.get_component_for_write<MeshComponent>(), - *geometry_set.get_mesh_for_read(), - selection_name, - invert); - } - if (geometry_set.has<CurveComponent>()) { - delete_curve_selection(*geometry_set.get_component_for_read<CurveComponent>(), - out_set.get_component_for_write<CurveComponent>(), - selection_name, - invert); - } - - params.set_output("Geometry", std::move(out_set)); -} - -} // namespace blender::nodes::node_geo_legacy_delete_geometry_cc - -void register_node_type_geo_legacy_delete_geometry() -{ - namespace file_ns = blender::nodes::node_geo_legacy_delete_geometry_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_DELETE_GEOMETRY, "Delete Geometry", NODE_CLASS_GEOMETRY); - - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_edge_split.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_edge_split.cc deleted file mode 100644 index 74fea7cef22..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_edge_split.cc +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "DNA_modifier_types.h" - -#include "node_geometry_util.hh" - -extern "C" { -Mesh *doEdgeSplit(const Mesh *mesh, EdgeSplitModifierData *emd); -} - -namespace blender::nodes::node_geo_legacy_edge_split_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Bool>(N_("Edge Angle")).default_value(true); - b.add_input<decl::Float>(N_("Angle")) - .default_value(DEG2RADF(30.0f)) - .min(0.0f) - .max(DEG2RADF(180.0f)) - .subtype(PROP_ANGLE); - b.add_input<decl::Bool>(N_("Sharp Edges")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (!geometry_set.has_mesh()) { - params.set_output("Geometry", std::move(geometry_set)); - return; - } - - const bool use_sharp_flag = params.extract_input<bool>("Sharp Edges"); - const bool use_edge_angle = params.extract_input<bool>("Edge Angle"); - - if (!use_edge_angle && !use_sharp_flag) { - params.set_output("Geometry", std::move(geometry_set)); - return; - } - - const float split_angle = params.extract_input<float>("Angle"); - const Mesh *mesh_in = geometry_set.get_mesh_for_read(); - - /* Use modifier struct to pass arguments to the modifier code. */ - EdgeSplitModifierData emd; - memset(&emd, 0, sizeof(EdgeSplitModifierData)); - emd.split_angle = split_angle; - if (use_edge_angle) { - emd.flags = MOD_EDGESPLIT_FROMANGLE; - } - if (use_sharp_flag) { - emd.flags |= MOD_EDGESPLIT_FROMFLAG; - } - - Mesh *mesh_out = doEdgeSplit(mesh_in, &emd); - geometry_set.replace_mesh(mesh_out); - - params.set_output("Geometry", std::move(geometry_set)); -} - -} // namespace blender::nodes::node_geo_legacy_edge_split_cc - -void register_node_type_geo_legacy_edge_split() -{ - namespace file_ns = blender::nodes::node_geo_legacy_edge_split_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, GEO_NODE_LEGACY_EDGE_SPLIT, "Edge Split", NODE_CLASS_GEOMETRY); - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.declare = file_ns::node_declare; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_material_assign.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_material_assign.cc deleted file mode 100644 index cb5f4044d6f..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_material_assign.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "node_geometry_util.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" - -#include "BKE_material.h" - -namespace blender::nodes::node_geo_legacy_material_assign_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Material>(N_("Material")).hide_label(true); - b.add_input<decl::String>(N_("Selection")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void assign_material_to_faces(Mesh &mesh, const VArray<bool> &face_mask, Material *material) -{ - int new_material_index = -1; - for (const int i : IndexRange(mesh.totcol)) { - Material *other_material = mesh.mat[i]; - if (other_material == material) { - new_material_index = i; - break; - } - } - if (new_material_index == -1) { - /* Append a new material index. */ - new_material_index = mesh.totcol; - BKE_id_material_eval_assign(&mesh.id, new_material_index + 1, material); - } - - mesh.mpoly = (MPoly *)CustomData_duplicate_referenced_layer(&mesh.pdata, CD_MPOLY, mesh.totpoly); - for (const int i : IndexRange(mesh.totpoly)) { - if (face_mask[i]) { - MPoly &poly = mesh.mpoly[i]; - poly.mat_nr = new_material_index; - } - } -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - Material *material = params.extract_input<Material *>("Material"); - const std::string mask_name = params.extract_input<std::string>("Selection"); - - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); - Mesh *mesh = mesh_component.get_for_write(); - if (mesh != nullptr) { - VArray<bool> face_mask = mesh_component.attribute_get_for_read<bool>( - mask_name, ATTR_DOMAIN_FACE, true); - assign_material_to_faces(*mesh, face_mask, material); - } - } - - params.set_output("Geometry", std::move(geometry_set)); -} - -} // namespace blender::nodes::node_geo_legacy_material_assign_cc - -void register_node_type_geo_legacy_material_assign() -{ - namespace file_ns = blender::nodes::node_geo_legacy_material_assign_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_MATERIAL_ASSIGN, "Material Assign", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc deleted file mode 100644 index 72cb540df4a..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "GEO_mesh_to_curve.hh" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_mesh_to_curve_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Mesh")); - b.add_input<decl::String>(N_("Selection")); - b.add_output<decl::Geometry>(N_("Curve")); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (!geometry_set.has_mesh()) { - params.set_default_remaining_outputs(); - return; - } - - const MeshComponent &component = *geometry_set.get_component_for_read<MeshComponent>(); - const std::string selection_name = params.extract_input<std::string>("Selection"); - if (!selection_name.empty() && !component.attribute_exists(selection_name)) { - params.error_message_add(NodeWarningType::Error, - TIP_("No attribute with name \"") + selection_name + "\""); - } - VArray<bool> selection = component.attribute_get_for_read<bool>( - selection_name, ATTR_DOMAIN_EDGE, true); - - Vector<int64_t> selected_edge_indices; - for (const int64_t i : IndexRange(component.attribute_domain_size(ATTR_DOMAIN_EDGE))) { - if (selection[i]) { - selected_edge_indices.append(i); - } - } - - if (selected_edge_indices.size() == 0) { - params.set_default_remaining_outputs(); - return; - } - - Curves *curves = geometry::mesh_to_curve_convert(component, IndexMask(selected_edge_indices)); - params.set_output("Curve", GeometrySet::create_with_curves(curves)); -} - -} // namespace blender::nodes::node_geo_legacy_mesh_to_curve_cc - -void register_node_type_geo_legacy_mesh_to_curve() -{ - namespace file_ns = blender::nodes::node_geo_legacy_mesh_to_curve_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, GEO_NODE_LEGACY_MESH_TO_CURVE, "Mesh to Curve", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_distribute.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_distribute.cc deleted file mode 100644 index f7cd0624b53..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_distribute.cc +++ /dev/null @@ -1,657 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_hash.h" -#include "BLI_kdtree.h" -#include "BLI_rand.hh" -#include "BLI_timeit.hh" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_pointcloud_types.h" - -#include "BKE_attribute_math.hh" -#include "BKE_bvhutils.h" -#include "BKE_geometry_set_instances.hh" -#include "BKE_mesh.h" -#include "BKE_mesh_runtime.h" -#include "BKE_mesh_sample.hh" -#include "BKE_pointcloud.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_point_distribute_cc { - -using blender::bke::GeometryInstanceGroup; - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Float>(N_("Distance Min")).min(0.0f).max(100000.0f).subtype(PROP_DISTANCE); - b.add_input<decl::Float>(N_("Density Max")) - .default_value(1.0f) - .min(0.0f) - .max(100000.0f) - .subtype(PROP_NONE); - b.add_input<decl::String>(N_("Density Attribute")); - b.add_input<decl::Int>(N_("Seed")).min(-10000).max(10000); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "distribute_method", 0, "", ICON_NONE); -} - -static void node_point_distribute_update(bNodeTree *ntree, bNode *node) -{ - bNodeSocket *sock_min_dist = (bNodeSocket *)BLI_findlink(&node->inputs, 1); - - nodeSetSocketAvailability( - ntree, sock_min_dist, ELEM(node->custom1, GEO_NODE_POINT_DISTRIBUTE_POISSON)); -} - -/** - * Use an arbitrary choice of axes for a usable rotation attribute directly out of this node. - */ -static float3 normal_to_euler_rotation(const float3 normal) -{ - float quat[4]; - vec_to_quat(quat, normal, OB_NEGZ, OB_POSY); - float3 rotation; - quat_to_eul(rotation, quat); - return rotation; -} - -static void sample_mesh_surface(const Mesh &mesh, - const float4x4 &transform, - const float base_density, - const VArray<float> *density_factors, - const int seed, - Vector<float3> &r_positions, - Vector<float3> &r_bary_coords, - Vector<int> &r_looptri_indices) -{ - const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), - BKE_mesh_runtime_looptri_len(&mesh)}; - - for (const int looptri_index : looptris.index_range()) { - const MLoopTri &looptri = looptris[looptri_index]; - const int v0_loop = looptri.tri[0]; - const int v1_loop = looptri.tri[1]; - const int v2_loop = looptri.tri[2]; - const int v0_index = mesh.mloop[v0_loop].v; - const int v1_index = mesh.mloop[v1_loop].v; - const int v2_index = mesh.mloop[v2_loop].v; - const float3 v0_pos = transform * float3(mesh.mvert[v0_index].co); - const float3 v1_pos = transform * float3(mesh.mvert[v1_index].co); - const float3 v2_pos = transform * float3(mesh.mvert[v2_index].co); - - float looptri_density_factor = 1.0f; - if (density_factors != nullptr) { - const float v0_density_factor = std::max(0.0f, (*density_factors)[v0_loop]); - const float v1_density_factor = std::max(0.0f, (*density_factors)[v1_loop]); - const float v2_density_factor = std::max(0.0f, (*density_factors)[v2_loop]); - looptri_density_factor = (v0_density_factor + v1_density_factor + v2_density_factor) / 3.0f; - } - const float area = area_tri_v3(v0_pos, v1_pos, v2_pos); - - const int looptri_seed = BLI_hash_int(looptri_index + seed); - RandomNumberGenerator looptri_rng(looptri_seed); - - const float points_amount_fl = area * base_density * looptri_density_factor; - const float add_point_probability = fractf(points_amount_fl); - const bool add_point = add_point_probability > looptri_rng.get_float(); - const int point_amount = (int)points_amount_fl + (int)add_point; - - for (int i = 0; i < point_amount; i++) { - const float3 bary_coord = looptri_rng.get_barycentric_coordinates(); - float3 point_pos; - interp_v3_v3v3v3(point_pos, v0_pos, v1_pos, v2_pos, bary_coord); - r_positions.append(point_pos); - r_bary_coords.append(bary_coord); - r_looptri_indices.append(looptri_index); - } - } -} - -BLI_NOINLINE static KDTree_3d *build_kdtree(Span<Vector<float3>> positions_all, - const int initial_points_len) -{ - KDTree_3d *kdtree = BLI_kdtree_3d_new(initial_points_len); - - int i_point = 0; - for (const Vector<float3> &positions : positions_all) { - for (const float3 position : positions) { - BLI_kdtree_3d_insert(kdtree, i_point, position); - i_point++; - } - } - BLI_kdtree_3d_balance(kdtree); - return kdtree; -} - -BLI_NOINLINE static void update_elimination_mask_for_close_points( - Span<Vector<float3>> positions_all, - Span<int> instance_start_offsets, - const float minimum_distance, - MutableSpan<bool> elimination_mask, - const int initial_points_len) -{ - if (minimum_distance <= 0.0f) { - return; - } - - KDTree_3d *kdtree = build_kdtree(positions_all, initial_points_len); - - /* The elimination mask is a flattened array for every point, - * so keep track of the index to it separately. */ - for (const int i_instance : positions_all.index_range()) { - Span<float3> positions = positions_all[i_instance]; - const int offset = instance_start_offsets[i_instance]; - - for (const int i : positions.index_range()) { - if (elimination_mask[offset + i]) { - continue; - } - - struct CallbackData { - int index; - MutableSpan<bool> elimination_mask; - } callback_data = {offset + i, elimination_mask}; - - BLI_kdtree_3d_range_search_cb( - kdtree, - positions[i], - minimum_distance, - [](void *user_data, int index, const float *UNUSED(co), float UNUSED(dist_sq)) { - CallbackData &callback_data = *static_cast<CallbackData *>(user_data); - if (index != callback_data.index) { - callback_data.elimination_mask[index] = true; - } - return true; - }, - &callback_data); - } - } - BLI_kdtree_3d_free(kdtree); -} - -BLI_NOINLINE static void update_elimination_mask_based_on_density_factors( - const Mesh &mesh, - const VArray<float> &density_factors, - Span<float3> bary_coords, - Span<int> looptri_indices, - MutableSpan<bool> elimination_mask) -{ - const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), - BKE_mesh_runtime_looptri_len(&mesh)}; - for (const int i : bary_coords.index_range()) { - if (elimination_mask[i]) { - continue; - } - - const MLoopTri &looptri = looptris[looptri_indices[i]]; - const float3 bary_coord = bary_coords[i]; - - const int v0_loop = looptri.tri[0]; - const int v1_loop = looptri.tri[1]; - const int v2_loop = looptri.tri[2]; - - const float v0_density_factor = std::max(0.0f, density_factors[v0_loop]); - const float v1_density_factor = std::max(0.0f, density_factors[v1_loop]); - const float v2_density_factor = std::max(0.0f, density_factors[v2_loop]); - - const float probablity = v0_density_factor * bary_coord.x + v1_density_factor * bary_coord.y + - v2_density_factor * bary_coord.z; - - const float hash = BLI_hash_int_01(bary_coord.hash()); - if (hash > probablity) { - elimination_mask[i] = true; - } - } -} - -BLI_NOINLINE static void eliminate_points_based_on_mask(Span<bool> elimination_mask, - Vector<float3> &positions, - Vector<float3> &bary_coords, - Vector<int> &looptri_indices) -{ - for (int i = positions.size() - 1; i >= 0; i--) { - if (elimination_mask[i]) { - positions.remove_and_reorder(i); - bary_coords.remove_and_reorder(i); - looptri_indices.remove_and_reorder(i); - } - } -} - -BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh, - Span<float3> bary_coords, - Span<int> looptri_indices, - const AttributeDomain source_domain, - const GVArray &source_data, - GMutableSpan output_data) -{ - switch (source_domain) { - case ATTR_DOMAIN_POINT: { - bke::mesh_surface_sample::sample_point_attribute(mesh, - looptri_indices, - bary_coords, - source_data, - IndexMask(output_data.size()), - output_data); - break; - } - case ATTR_DOMAIN_CORNER: { - bke::mesh_surface_sample::sample_corner_attribute(mesh, - looptri_indices, - bary_coords, - source_data, - IndexMask(output_data.size()), - output_data); - break; - } - case ATTR_DOMAIN_FACE: { - bke::mesh_surface_sample::sample_face_attribute( - mesh, looptri_indices, source_data, IndexMask(output_data.size()), output_data); - break; - } - default: { - /* Not supported currently. */ - return; - } - } -} - -BLI_NOINLINE static void interpolate_existing_attributes( - Span<GeometryInstanceGroup> set_groups, - Span<int> instance_start_offsets, - const Map<AttributeIDRef, AttributeKind> &attributes, - GeometryComponent &component, - Span<Vector<float3>> bary_coords_array, - Span<Vector<int>> looptri_indices_array) -{ - for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - const CustomDataType output_data_type = entry.value.data_type; - /* The output domain is always #ATTR_DOMAIN_POINT, since we are creating a point cloud. */ - OutputAttribute attribute_out = component.attribute_try_get_for_output_only( - attribute_id, ATTR_DOMAIN_POINT, output_data_type); - if (!attribute_out) { - continue; - } - - GMutableSpan out_span = attribute_out.as_span(); - - int i_instance = 0; - for (const GeometryInstanceGroup &set_group : set_groups) { - const GeometrySet &set = set_group.geometry_set; - const MeshComponent &source_component = *set.get_component_for_read<MeshComponent>(); - const Mesh &mesh = *source_component.get_for_read(); - - std::optional<AttributeMetaData> attribute_info = component.attribute_get_meta_data( - attribute_id); - if (!attribute_info) { - i_instance += set_group.transforms.size(); - continue; - } - - const AttributeDomain source_domain = attribute_info->domain; - GVArray source_attribute = source_component.attribute_get_for_read( - attribute_id, source_domain, output_data_type, nullptr); - if (!source_attribute) { - i_instance += set_group.transforms.size(); - continue; - } - - for ([[maybe_unused]] const int i_set_instance : set_group.transforms.index_range()) { - const int offset = instance_start_offsets[i_instance]; - Span<float3> bary_coords = bary_coords_array[i_instance]; - Span<int> looptri_indices = looptri_indices_array[i_instance]; - - GMutableSpan instance_span = out_span.slice(offset, bary_coords.size()); - interpolate_attribute( - mesh, bary_coords, looptri_indices, source_domain, source_attribute, instance_span); - - i_instance++; - } - - attribute_math::convert_to_static_type(output_data_type, [&](auto dummy) { - using T = decltype(dummy); - - VArray_Span source_span{source_attribute.typed<T>()}; - }); - } - - attribute_out.save(); - } -} - -BLI_NOINLINE static void compute_special_attributes(Span<GeometryInstanceGroup> sets, - Span<int> instance_start_offsets, - GeometryComponent &component, - Span<Vector<float3>> bary_coords_array, - Span<Vector<int>> looptri_indices_array) -{ - OutputAttribute_Typed<int> id_attribute = component.attribute_try_get_for_output_only<int>( - "id", ATTR_DOMAIN_POINT); - OutputAttribute_Typed<float3> normal_attribute = - component.attribute_try_get_for_output_only<float3>("normal", ATTR_DOMAIN_POINT); - OutputAttribute_Typed<float3> rotation_attribute = - component.attribute_try_get_for_output_only<float3>("rotation", ATTR_DOMAIN_POINT); - - MutableSpan<int> result_ids = id_attribute.as_span(); - MutableSpan<float3> result_normals = normal_attribute.as_span(); - MutableSpan<float3> result_rotations = rotation_attribute.as_span(); - - int i_instance = 0; - for (const GeometryInstanceGroup &set_group : sets) { - const GeometrySet &set = set_group.geometry_set; - const MeshComponent &component = *set.get_component_for_read<MeshComponent>(); - const Mesh &mesh = *component.get_for_read(); - const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), - BKE_mesh_runtime_looptri_len(&mesh)}; - - for (const float4x4 &transform : set_group.transforms) { - const int offset = instance_start_offsets[i_instance]; - - Span<float3> bary_coords = bary_coords_array[i_instance]; - Span<int> looptri_indices = looptri_indices_array[i_instance]; - MutableSpan<int> ids = result_ids.slice(offset, bary_coords.size()); - MutableSpan<float3> normals = result_normals.slice(offset, bary_coords.size()); - MutableSpan<float3> rotations = result_rotations.slice(offset, bary_coords.size()); - - /* Use one matrix multiplication per point instead of three (for each triangle corner). */ - float rotation_matrix[3][3]; - mat4_to_rot(rotation_matrix, transform.values); - - for (const int i : bary_coords.index_range()) { - const int looptri_index = looptri_indices[i]; - const MLoopTri &looptri = looptris[looptri_index]; - const float3 &bary_coord = bary_coords[i]; - - const int v0_index = mesh.mloop[looptri.tri[0]].v; - const int v1_index = mesh.mloop[looptri.tri[1]].v; - const int v2_index = mesh.mloop[looptri.tri[2]].v; - const float3 v0_pos = float3(mesh.mvert[v0_index].co); - const float3 v1_pos = float3(mesh.mvert[v1_index].co); - const float3 v2_pos = float3(mesh.mvert[v2_index].co); - - ids[i] = (int)(bary_coord.hash() + (uint64_t)looptri_index); - normal_tri_v3(normals[i], v0_pos, v1_pos, v2_pos); - mul_m3_v3(rotation_matrix, normals[i]); - rotations[i] = normal_to_euler_rotation(normals[i]); - } - - i_instance++; - } - } - - id_attribute.save(); - normal_attribute.save(); - rotation_attribute.save(); -} - -BLI_NOINLINE static void add_remaining_point_attributes( - Span<GeometryInstanceGroup> set_groups, - Span<int> instance_start_offsets, - const Map<AttributeIDRef, AttributeKind> &attributes, - GeometryComponent &component, - Span<Vector<float3>> bary_coords_array, - Span<Vector<int>> looptri_indices_array) -{ - interpolate_existing_attributes(set_groups, - instance_start_offsets, - attributes, - component, - bary_coords_array, - looptri_indices_array); - compute_special_attributes( - set_groups, instance_start_offsets, component, bary_coords_array, looptri_indices_array); -} - -static void distribute_points_random(Span<GeometryInstanceGroup> set_groups, - const StringRef density_attribute_name, - const float density, - const int seed, - MutableSpan<Vector<float3>> positions_all, - MutableSpan<Vector<float3>> bary_coords_all, - MutableSpan<Vector<int>> looptri_indices_all) -{ - /* If there is an attribute name, the default value for the densities should be zero so that - * points are only scattered where the attribute exists. Otherwise, just "ignore" the density - * factors. */ - const bool use_one_default = density_attribute_name.is_empty(); - - int i_instance = 0; - for (const GeometryInstanceGroup &set_group : set_groups) { - const GeometrySet &set = set_group.geometry_set; - const MeshComponent &component = *set.get_component_for_read<MeshComponent>(); - VArray<float> density_factors = component.attribute_get_for_read<float>( - density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f); - const Mesh &mesh = *component.get_for_read(); - for (const float4x4 &transform : set_group.transforms) { - Vector<float3> &positions = positions_all[i_instance]; - Vector<float3> &bary_coords = bary_coords_all[i_instance]; - Vector<int> &looptri_indices = looptri_indices_all[i_instance]; - sample_mesh_surface(mesh, - transform, - density, - &density_factors, - seed, - positions, - bary_coords, - looptri_indices); - i_instance++; - } - } -} - -static void distribute_points_poisson_disk(Span<GeometryInstanceGroup> set_groups, - const StringRef density_attribute_name, - const float density, - const int seed, - const float minimum_distance, - MutableSpan<Vector<float3>> positions_all, - MutableSpan<Vector<float3>> bary_coords_all, - MutableSpan<Vector<int>> looptri_indices_all) -{ - Array<int> instance_start_offsets(positions_all.size()); - int initial_points_len = 0; - int i_instance = 0; - for (const GeometryInstanceGroup &set_group : set_groups) { - const GeometrySet &set = set_group.geometry_set; - const MeshComponent &component = *set.get_component_for_read<MeshComponent>(); - const Mesh &mesh = *component.get_for_read(); - for (const float4x4 &transform : set_group.transforms) { - Vector<float3> &positions = positions_all[i_instance]; - Vector<float3> &bary_coords = bary_coords_all[i_instance]; - Vector<int> &looptri_indices = looptri_indices_all[i_instance]; - sample_mesh_surface( - mesh, transform, density, nullptr, seed, positions, bary_coords, looptri_indices); - - instance_start_offsets[i_instance] = initial_points_len; - initial_points_len += positions.size(); - i_instance++; - } - } - - /* If there is an attribute name, the default value for the densities should be zero so that - * points are only scattered where the attribute exists. Otherwise, just "ignore" the density - * factors. */ - const bool use_one_default = density_attribute_name.is_empty(); - - /* Unlike the other result arrays, the elimination mask in stored as a flat array for every - * point, in order to simplify culling points from the KDTree (which needs to know about all - * points at once). */ - Array<bool> elimination_mask(initial_points_len, false); - update_elimination_mask_for_close_points(positions_all, - instance_start_offsets, - minimum_distance, - elimination_mask, - initial_points_len); - - i_instance = 0; - for (const GeometryInstanceGroup &set_group : set_groups) { - const GeometrySet &set = set_group.geometry_set; - const MeshComponent &component = *set.get_component_for_read<MeshComponent>(); - const Mesh &mesh = *component.get_for_read(); - const VArray<float> density_factors = component.attribute_get_for_read<float>( - density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f); - - for ([[maybe_unused]] const int i_set_instance : set_group.transforms.index_range()) { - Vector<float3> &positions = positions_all[i_instance]; - Vector<float3> &bary_coords = bary_coords_all[i_instance]; - Vector<int> &looptri_indices = looptri_indices_all[i_instance]; - - const int offset = instance_start_offsets[i_instance]; - update_elimination_mask_based_on_density_factors( - mesh, - density_factors, - bary_coords, - looptri_indices, - elimination_mask.as_mutable_span().slice(offset, positions.size())); - - eliminate_points_based_on_mask(elimination_mask.as_span().slice(offset, positions.size()), - positions, - bary_coords, - looptri_indices); - - i_instance++; - } - } -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - const GeometryNodePointDistributeMode distribute_method = - static_cast<GeometryNodePointDistributeMode>(params.node().custom1); - - const int seed = params.get_input<int>("Seed") * 5383843; - const float density = params.extract_input<float>("Density Max"); - const std::string density_attribute_name = params.extract_input<std::string>( - "Density Attribute"); - - if (density <= 0.0f) { - params.set_default_remaining_outputs(); - return; - } - - Vector<GeometryInstanceGroup> set_groups; - geometry_set_gather_instances(geometry_set, set_groups); - if (set_groups.is_empty()) { - params.set_default_remaining_outputs(); - return; - } - - /* Remove any set inputs that don't contain a mesh, to avoid checking later on. */ - for (int i = set_groups.size() - 1; i >= 0; i--) { - const GeometrySet &set = set_groups[i].geometry_set; - if (!set.has_mesh()) { - set_groups.remove_and_reorder(i); - } - } - - if (set_groups.is_empty()) { - params.error_message_add(NodeWarningType::Error, TIP_("Input geometry must contain a mesh")); - params.set_default_remaining_outputs(); - return; - } - - int instances_len = 0; - for (GeometryInstanceGroup &set_group : set_groups) { - instances_len += set_group.transforms.size(); - } - - /* Store data per-instance in order to simplify attribute access after the scattering, - * and to make the point elimination simpler for the poisson disk mode. Note that some - * vectors will be empty if any instances don't contain mesh data. */ - Array<Vector<float3>> positions_all(instances_len); - Array<Vector<float3>> bary_coords_all(instances_len); - Array<Vector<int>> looptri_indices_all(instances_len); - - switch (distribute_method) { - case GEO_NODE_POINT_DISTRIBUTE_RANDOM: { - distribute_points_random(set_groups, - density_attribute_name, - density, - seed, - positions_all, - bary_coords_all, - looptri_indices_all); - break; - } - case GEO_NODE_POINT_DISTRIBUTE_POISSON: { - const float minimum_distance = params.extract_input<float>("Distance Min"); - distribute_points_poisson_disk(set_groups, - density_attribute_name, - density, - seed, - minimum_distance, - positions_all, - bary_coords_all, - looptri_indices_all); - break; - } - } - - int final_points_len = 0; - Array<int> instance_start_offsets(set_groups.size()); - for (const int i : positions_all.index_range()) { - Vector<float3> &positions = positions_all[i]; - instance_start_offsets[i] = final_points_len; - final_points_len += positions.size(); - } - - if (final_points_len == 0) { - params.set_default_remaining_outputs(); - return; - } - - PointCloud *pointcloud = BKE_pointcloud_new_nomain(final_points_len); - for (const int instance_index : positions_all.index_range()) { - const int offset = instance_start_offsets[instance_index]; - Span<float3> positions = positions_all[instance_index]; - memcpy(pointcloud->co + offset, positions.data(), sizeof(float3) * positions.size()); - } - - uninitialized_fill_n(pointcloud->radius, pointcloud->totpoint, 0.05f); - - GeometrySet geometry_set_out = GeometrySet::create_with_pointcloud(pointcloud); - PointCloudComponent &point_component = - geometry_set_out.get_component_for_write<PointCloudComponent>(); - - Map<AttributeIDRef, AttributeKind> attributes; - bke::geometry_set_gather_instances_attribute_info( - set_groups, {GEO_COMPONENT_TYPE_MESH}, {"position", "normal", "id"}, attributes); - add_remaining_point_attributes(set_groups, - instance_start_offsets, - attributes, - point_component, - bary_coords_all, - looptri_indices_all); - - params.set_output("Geometry", std::move(geometry_set_out)); -} - -} // namespace blender::nodes::node_geo_legacy_point_distribute_cc - -void register_node_type_geo_point_distribute() -{ - namespace file_ns = blender::nodes::node_geo_legacy_point_distribute_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_POINT_DISTRIBUTE, "Point Distribute", NODE_CLASS_GEOMETRY); - node_type_update(&ntype, file_ns::node_point_distribute_update); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_instance.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_instance.cc deleted file mode 100644 index 3d31773300d..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_instance.cc +++ /dev/null @@ -1,268 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "DNA_collection_types.h" - -#include "BLI_hash.h" -#include "BLI_task.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_point_instance_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Object>(N_("Object")).hide_label(); - b.add_input<decl::Collection>(N_("Collection")).hide_label(); - b.add_input<decl::Geometry>(N_("Instance Geometry")); - b.add_input<decl::Int>(N_("Seed")).min(-10000).max(10000); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "instance_type", 0, "", ICON_NONE); - if (RNA_enum_get(ptr, "instance_type") == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) { - uiItemR(layout, ptr, "use_whole_collection", 0, nullptr, ICON_NONE); - } -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryPointInstance *data = MEM_cnew<NodeGeometryPointInstance>(__func__); - data->instance_type = GEO_NODE_POINT_INSTANCE_TYPE_OBJECT; - data->flag |= GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - bNodeSocket *object_socket = (bNodeSocket *)BLI_findlink(&node->inputs, 1); - bNodeSocket *collection_socket = object_socket->next; - bNodeSocket *instance_geometry_socket = collection_socket->next; - bNodeSocket *seed_socket = instance_geometry_socket->next; - - NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node->storage; - GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)node_storage->instance_type; - const bool use_whole_collection = (node_storage->flag & - GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION) != 0; - - nodeSetSocketAvailability(ntree, object_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); - nodeSetSocketAvailability( - ntree, collection_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION); - nodeSetSocketAvailability( - ntree, instance_geometry_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY); - nodeSetSocketAvailability(ntree, - seed_socket, - type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION && - !use_whole_collection); -} - -static Vector<InstanceReference> get_instance_references__object(GeoNodeExecParams ¶ms) -{ - Object *object = params.extract_input<Object *>("Object"); - if (object == params.self_object()) { - return {}; - } - if (object != nullptr) { - return {*object}; - } - return {}; -} - -static Vector<InstanceReference> get_instance_references__collection(GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node.storage; - - Collection *collection = params.get_input<Collection *>("Collection"); - if (collection == nullptr) { - return {}; - } - - if (BLI_listbase_is_empty(&collection->children) && - BLI_listbase_is_empty(&collection->gobject)) { - params.error_message_add(NodeWarningType::Info, TIP_("Collection is empty")); - return {}; - } - - if (node_storage->flag & GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION) { - return {*collection}; - } - - Vector<InstanceReference> references; - /* Direct child objects are instanced as objects. */ - LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - references.append(*cob->ob); - } - /* Direct child collections are instanced as collections. */ - LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { - references.append(*child->collection); - } - - return references; -} - -static Vector<InstanceReference> get_instance_references__geometry(GeoNodeExecParams ¶ms) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Instance Geometry"); - geometry_set.ensure_owns_direct_data(); - return {std::move(geometry_set)}; -} - -static Vector<InstanceReference> get_instance_references(GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node.storage; - const GeometryNodePointInstanceType type = (GeometryNodePointInstanceType) - node_storage->instance_type; - - switch (type) { - case GEO_NODE_POINT_INSTANCE_TYPE_OBJECT: { - return get_instance_references__object(params); - } - case GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION: { - return get_instance_references__collection(params); - } - case GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY: { - return get_instance_references__geometry(params); - } - } - return {}; -} - -/** - * Add the instance references to the component as a separate step from actually creating the - * instances in order to avoid a map lookup for every transform. While this might add some - * unnecessary references if they are not chosen while adding transforms, in the common cases - * there are many more transforms than there are references, so that isn't likely. - */ -static Array<int> add_instance_references(InstancesComponent &instance_component, - Span<InstanceReference> possible_references) -{ - Array<int> possible_handles(possible_references.size()); - for (const int i : possible_references.index_range()) { - possible_handles[i] = instance_component.add_reference(possible_references[i]); - } - return possible_handles; -} - -static void add_instances_from_component(InstancesComponent &instances, - const GeometryComponent &src_geometry, - Span<int> possible_handles, - const GeoNodeExecParams ¶ms) -{ - const AttributeDomain domain = ATTR_DOMAIN_POINT; - - const int domain_size = src_geometry.attribute_domain_size(domain); - if (domain_size == 0) { - return; - } - - VArray<float3> positions = src_geometry.attribute_get_for_read<float3>( - "position", domain, {0, 0, 0}); - VArray<float3> rotations = src_geometry.attribute_get_for_read<float3>( - "rotation", domain, {0, 0, 0}); - VArray<float3> scales = src_geometry.attribute_get_for_read<float3>("scale", domain, {1, 1, 1}); - VArray<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1); - - /* The initial size of the component might be non-zero if there are two component types. */ - const int start_len = instances.instances_amount(); - instances.resize(start_len + domain_size); - MutableSpan<int> handles = instances.instance_reference_handles().slice(start_len, domain_size); - MutableSpan<float4x4> transforms = instances.instance_transforms().slice(start_len, domain_size); - OutputAttribute_Typed<int> instance_id_attribute = - instances.attribute_try_get_for_output_only<int>("id", ATTR_DOMAIN_INSTANCE); - MutableSpan<int> instance_ids = instance_id_attribute.as_span(); - - /* Skip all of the randomness handling if there is only a single possible instance - * (anything except for collection mode with "Whole Collection" turned off). */ - if (possible_handles.size() == 1) { - const int handle = possible_handles.first(); - threading::parallel_for(IndexRange(domain_size), 1024, [&](IndexRange range) { - for (const int i : range) { - handles[i] = handle; - transforms[i] = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]); - instance_ids[i] = id_attribute[i]; - } - }); - } - else { - const int seed = params.get_input<int>("Seed"); - Array<uint32_t> ids = get_geometry_element_ids_as_uints(src_geometry, ATTR_DOMAIN_POINT); - threading::parallel_for(IndexRange(domain_size), 1024, [&](IndexRange range) { - for (const int i : range) { - const int index = BLI_hash_int_2d(ids[i], seed) % possible_handles.size(); - const int handle = possible_handles[index]; - handles[i] = handle; - transforms[i] = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]); - instance_ids[i] = id_attribute[i]; - } - }); - } - - instance_id_attribute.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - GeometrySet geometry_set_out; - - /* TODO: This node should be able to instance on the input instances component - * rather than making the entire input geometry set real. */ - geometry_set = geometry::realize_instances_legacy(geometry_set); - - const Vector<InstanceReference> possible_references = get_instance_references(params); - if (possible_references.is_empty()) { - params.set_output("Geometry", std::move(geometry_set_out)); - return; - } - - InstancesComponent &instances = geometry_set_out.get_component_for_write<InstancesComponent>(); - Array<int> possible_handles = add_instance_references(instances, possible_references); - - if (geometry_set.has<MeshComponent>()) { - add_instances_from_component(instances, - *geometry_set.get_component_for_read<MeshComponent>(), - possible_handles, - params); - } - if (geometry_set.has<PointCloudComponent>()) { - add_instances_from_component(instances, - *geometry_set.get_component_for_read<PointCloudComponent>(), - possible_handles, - params); - } - if (geometry_set.has<CurveComponent>()) { - add_instances_from_component(instances, - *geometry_set.get_component_for_read<CurveComponent>(), - possible_handles, - params); - } - - params.set_output("Geometry", std::move(geometry_set_out)); -} - -} // namespace blender::nodes::node_geo_legacy_point_instance_cc - -void register_node_type_geo_point_instance() -{ - namespace file_ns = blender::nodes::node_geo_legacy_point_instance_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_POINT_INSTANCE, "Point Instance", NODE_CLASS_GEOMETRY); - node_type_init(&ntype, file_ns::node_init); - node_type_storage( - &ntype, "NodeGeometryPointInstance", node_free_standard_storage, node_copy_standard_storage); - ntype.declare = file_ns::node_declare; - ntype.draw_buttons = file_ns::node_layout; - node_type_update(&ntype, file_ns::node_update); - ntype.geometry_node_execute = file_ns::node_geo_exec; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_rotate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_rotate.cc deleted file mode 100644 index 2895c15cb8c..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_rotate.cc +++ /dev/null @@ -1,223 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_math_rotation.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_point_rotate_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Axis")); - b.add_input<decl::Vector>(N_("Axis"), "Axis_001") - .default_value({0.0, 0.0, 1.0}) - .subtype(PROP_XYZ); - b.add_input<decl::String>(N_("Angle")); - b.add_input<decl::Float>(N_("Angle"), "Angle_001").subtype(PROP_ANGLE); - b.add_input<decl::String>(N_("Rotation")); - b.add_input<decl::Vector>(N_("Rotation"), "Rotation_001").subtype(PROP_EULER); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - NodeGeometryRotatePoints *storage = (NodeGeometryRotatePoints *)((bNode *)ptr->data)->storage; - - uiItemR(layout, ptr, "type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); - uiItemR(layout, ptr, "space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); - - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - - uiLayout *col = uiLayoutColumn(layout, false); - if (storage->type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) { - uiItemR(col, ptr, "input_type_axis", 0, IFACE_("Axis"), ICON_NONE); - uiItemR(col, ptr, "input_type_angle", 0, IFACE_("Angle"), ICON_NONE); - } - else { - uiItemR(col, ptr, "input_type_rotation", 0, IFACE_("Rotation"), ICON_NONE); - } -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeGeometryRotatePoints *node_storage = MEM_cnew<NodeGeometryRotatePoints>(__func__); - - node_storage->type = GEO_NODE_POINT_ROTATE_TYPE_EULER; - node_storage->space = GEO_NODE_POINT_ROTATE_SPACE_OBJECT; - node_storage->input_type_axis = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - node_storage->input_type_angle = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - node_storage->input_type_rotation = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - - node->storage = node_storage; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeGeometryRotatePoints *node_storage = (NodeGeometryRotatePoints *)node->storage; - update_attribute_input_socket_availabilities( - *ntree, - *node, - "Axis", - (GeometryNodeAttributeInputMode)node_storage->input_type_axis, - node_storage->type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "Angle", - (GeometryNodeAttributeInputMode)node_storage->input_type_angle, - node_storage->type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "Rotation", - (GeometryNodeAttributeInputMode)node_storage->input_type_rotation, - node_storage->type == GEO_NODE_POINT_ROTATE_TYPE_EULER); -} - -static void point_rotate__axis_angle__object_space(const int domain_size, - const VArray<float3> &axis, - const VArray<float> &angles, - MutableSpan<float3> rotations) -{ - for (const int i : IndexRange(domain_size)) { - float old_rotation[3][3]; - eul_to_mat3(old_rotation, rotations[i]); - float rotation[3][3]; - axis_angle_to_mat3(rotation, axis[i], angles[i]); - float new_rotation[3][3]; - mul_m3_m3m3(new_rotation, rotation, old_rotation); - mat3_to_eul(rotations[i], new_rotation); - } -} - -static void point_rotate__axis_angle__point_space(const int domain_size, - const VArray<float3> &axis, - const VArray<float> &angles, - MutableSpan<float3> rotations) -{ - for (const int i : IndexRange(domain_size)) { - float old_rotation[3][3]; - eul_to_mat3(old_rotation, rotations[i]); - float rotation[3][3]; - axis_angle_to_mat3(rotation, axis[i], angles[i]); - float new_rotation[3][3]; - mul_m3_m3m3(new_rotation, old_rotation, rotation); - mat3_to_eul(rotations[i], new_rotation); - } -} - -static void point_rotate__euler__object_space(const int domain_size, - const VArray<float3> &eulers, - MutableSpan<float3> rotations) -{ - for (const int i : IndexRange(domain_size)) { - float old_rotation[3][3]; - eul_to_mat3(old_rotation, rotations[i]); - float rotation[3][3]; - eul_to_mat3(rotation, eulers[i]); - float new_rotation[3][3]; - mul_m3_m3m3(new_rotation, rotation, old_rotation); - mat3_to_eul(rotations[i], new_rotation); - } -} - -static void point_rotate__euler__point_space(const int domain_size, - const VArray<float3> &eulers, - MutableSpan<float3> rotations) -{ - for (const int i : IndexRange(domain_size)) { - float old_rotation[3][3]; - eul_to_mat3(old_rotation, rotations[i]); - float rotation[3][3]; - eul_to_mat3(rotation, eulers[i]); - float new_rotation[3][3]; - mul_m3_m3m3(new_rotation, old_rotation, rotation); - mat3_to_eul(rotations[i], new_rotation); - } -} - -static void point_rotate_on_component(GeometryComponent &component, - const GeoNodeExecParams ¶ms) -{ - const bNode &node = params.node(); - const NodeGeometryRotatePoints &storage = *(const NodeGeometryRotatePoints *)node.storage; - - OutputAttribute_Typed<float3> rotation_attribute = - component.attribute_try_get_for_output<float3>("rotation", ATTR_DOMAIN_POINT, {0, 0, 0}); - if (!rotation_attribute) { - return; - } - - MutableSpan<float3> rotations = rotation_attribute.as_span(); - const int domain_size = rotations.size(); - - if (storage.type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) { - VArray<float3> axis = params.get_input_attribute<float3>( - "Axis", component, ATTR_DOMAIN_POINT, {0, 0, 1}); - VArray<float> angles = params.get_input_attribute<float>( - "Angle", component, ATTR_DOMAIN_POINT, 0); - - if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) { - point_rotate__axis_angle__object_space(domain_size, axis, angles, rotations); - } - else { - point_rotate__axis_angle__point_space(domain_size, axis, angles, rotations); - } - } - else { - VArray<float3> eulers = params.get_input_attribute<float3>( - "Rotation", component, ATTR_DOMAIN_POINT, {0, 0, 0}); - - if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) { - point_rotate__euler__object_space(domain_size, eulers, rotations); - } - else { - point_rotate__euler__point_space(domain_size, eulers, rotations); - } - } - - rotation_attribute.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - point_rotate_on_component(geometry_set.get_component_for_write<MeshComponent>(), params); - } - if (geometry_set.has<PointCloudComponent>()) { - point_rotate_on_component(geometry_set.get_component_for_write<PointCloudComponent>(), params); - } - if (geometry_set.has<CurveComponent>()) { - point_rotate_on_component(geometry_set.get_component_for_write<CurveComponent>(), params); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_point_rotate_cc - -void register_node_type_geo_point_rotate() -{ - namespace file_ns = blender::nodes::node_geo_legacy_point_rotate_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, GEO_NODE_LEGACY_POINT_ROTATE, "Point Rotate", NODE_CLASS_GEOMETRY); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - node_type_storage( - &ntype, "NodeGeometryRotatePoints", node_free_standard_storage, node_copy_standard_storage); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_scale.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_scale.cc deleted file mode 100644 index b51ef22fb49..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_scale.cc +++ /dev/null @@ -1,126 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BKE_colorband.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_point_scale_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Factor")); - b.add_input<decl::Vector>(N_("Factor"), "Factor_001") - .default_value({1.0f, 1.0f, 1.0f}) - .subtype(PROP_XYZ); - b.add_input<decl::Float>(N_("Factor"), "Factor_002").default_value(1.0f).min(0.0f); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "input_type", 0, IFACE_("Type"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryPointScale *data = MEM_cnew<NodeGeometryPointScale>(__func__); - - data->input_type = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeGeometryPointScale &node_storage = *(NodeGeometryPointScale *)node->storage; - - update_attribute_input_socket_availabilities( - *ntree, *node, "Factor", (GeometryNodeAttributeInputMode)node_storage.input_type); -} - -static void execute_on_component(GeoNodeExecParams params, GeometryComponent &component) -{ - /* Note that scale doesn't necessarily need to be created with a vector type-- it could also use - * the highest complexity of the existing attribute's type (if it exists) and the data type used - * for the factor. But for it's simpler to simply always use float3, since that is usually - * expected anyway. */ - static const float3 scale_default = float3(1.0f); - OutputAttribute_Typed<float3> scale_attribute = component.attribute_try_get_for_output( - "scale", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, &scale_default); - if (!scale_attribute) { - return; - } - - const bNode &node = params.node(); - const NodeGeometryPointScale &node_storage = *(const NodeGeometryPointScale *)node.storage; - const GeometryNodeAttributeInputMode input_type = (GeometryNodeAttributeInputMode) - node_storage.input_type; - const CustomDataType data_type = (input_type == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) ? CD_PROP_FLOAT : - CD_PROP_FLOAT3; - - GVArray attribute = params.get_input_attribute( - "Factor", component, ATTR_DOMAIN_POINT, data_type, nullptr); - if (!attribute) { - return; - } - - MutableSpan<float3> scale_span = scale_attribute.as_span(); - if (data_type == CD_PROP_FLOAT) { - VArray<float> factors = attribute.typed<float>(); - for (const int i : scale_span.index_range()) { - scale_span[i] = scale_span[i] * factors[i]; - } - } - else if (data_type == CD_PROP_FLOAT3) { - VArray<float3> factors = attribute.typed<float3>(); - for (const int i : scale_span.index_range()) { - scale_span[i] = scale_span[i] * factors[i]; - } - } - - scale_attribute.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<MeshComponent>()); - } - if (geometry_set.has<PointCloudComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<PointCloudComponent>()); - } - if (geometry_set.has<CurveComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<CurveComponent>()); - } - - params.set_output("Geometry", std::move(geometry_set)); -} - -} // namespace blender::nodes::node_geo_legacy_point_scale_cc - -void register_node_type_geo_point_scale() -{ - namespace file_ns = blender::nodes::node_geo_legacy_point_scale_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, GEO_NODE_LEGACY_POINT_SCALE, "Point Scale", NODE_CLASS_GEOMETRY); - - ntype.declare = file_ns::node_declare; - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - node_type_storage( - &ntype, "NodeGeometryPointScale", node_free_standard_storage, node_copy_standard_storage); - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_separate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_separate.cc deleted file mode 100644 index 541be1933af..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_separate.cc +++ /dev/null @@ -1,165 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BKE_attribute_math.hh" -#include "BKE_mesh.h" -#include "BKE_pointcloud.h" - -#include "DNA_mesh_types.h" -#include "DNA_pointcloud_types.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes { - -template<typename T> -static void copy_data_based_on_mask(Span<T> data, - Span<bool> masks, - const bool invert, - MutableSpan<T> out_data) -{ - int offset = 0; - for (const int i : data.index_range()) { - if (masks[i] != invert) { - out_data[offset] = data[i]; - offset++; - } - } -} - -void copy_point_attributes_based_on_mask(const GeometryComponent &in_component, - GeometryComponent &result_component, - Span<bool> masks, - const bool invert) -{ - for (const AttributeIDRef &attribute_id : in_component.attribute_ids()) { - ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id); - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); - - /* Only copy point attributes. Theoretically this could interpolate attributes on other - * domains to the point domain, but that would conflict with attributes that are built-in - * on other domains, which causes creating the attributes to fail. */ - if (attribute.domain != ATTR_DOMAIN_POINT) { - continue; - } - - OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( - attribute_id, ATTR_DOMAIN_POINT, data_type); - - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { - using T = decltype(dummy); - VArray_Span span{attribute.varray.typed<T>()}; - MutableSpan<T> out_span = result_attribute.as_span<T>(); - copy_data_based_on_mask(span, masks, invert, out_span); - }); - - result_attribute.save(); - } -} - -} // namespace blender::nodes - -namespace blender::nodes::node_geo_legacy_point_separate_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Mask")); - b.add_output<decl::Geometry>(N_("Geometry 1")); - b.add_output<decl::Geometry>(N_("Geometry 2")); -} - -static void create_component_points(GeometryComponent &component, const int total) -{ - switch (component.type()) { - case GEO_COMPONENT_TYPE_MESH: - static_cast<MeshComponent &>(component).replace(BKE_mesh_new_nomain(total, 0, 0, 0, 0)); - break; - case GEO_COMPONENT_TYPE_POINT_CLOUD: - static_cast<PointCloudComponent &>(component).replace(BKE_pointcloud_new_nomain(total)); - break; - default: - BLI_assert(false); - break; - } -} - -static void separate_points_from_component(const GeometryComponent &in_component, - GeometryComponent &out_component, - const StringRef mask_name, - const bool invert) -{ - if (!in_component.attribute_domain_supported(ATTR_DOMAIN_POINT) || - in_component.attribute_domain_size(ATTR_DOMAIN_POINT) == 0) { - return; - } - - const VArray<bool> mask_attribute = in_component.attribute_get_for_read<bool>( - mask_name, ATTR_DOMAIN_POINT, false); - VArray_Span<bool> masks{mask_attribute}; - - const int total = masks.count(!invert); - if (total == 0) { - return; - } - - create_component_points(out_component, total); - - copy_point_attributes_based_on_mask(in_component, out_component, masks, invert); -} - -static GeometrySet separate_geometry_set(const GeometrySet &set_in, - const StringRef mask_name, - const bool invert) -{ - GeometrySet set_out; - for (const GeometryComponent *component : set_in.get_components_for_read()) { - if (component->type() == GEO_COMPONENT_TYPE_CURVE) { - /* Don't support the curve component for now, even though it has a point domain. */ - continue; - } - GeometryComponent &out_component = set_out.get_component_for_write(component->type()); - separate_points_from_component(*component, out_component, mask_name, invert); - } - return set_out; -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - bool wait_for_inputs = false; - wait_for_inputs |= params.lazy_require_input("Geometry"); - wait_for_inputs |= params.lazy_require_input("Mask"); - if (wait_for_inputs) { - return; - } - const std::string mask_attribute_name = params.get_input<std::string>("Mask"); - GeometrySet geometry_set = params.get_input<GeometrySet>("Geometry"); - - /* TODO: This is not necessary-- the input geometry set can be read only, - * but it must be rewritten to handle instance groups. */ - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (params.lazy_output_is_required("Geometry 1")) { - params.set_output("Geometry 1", - separate_geometry_set(geometry_set, mask_attribute_name, true)); - } - if (params.lazy_output_is_required("Geometry 2")) { - params.set_output("Geometry 2", - separate_geometry_set(geometry_set, mask_attribute_name, false)); - } -} - -} // namespace blender::nodes::node_geo_legacy_point_separate_cc - -void register_node_type_geo_point_separate() -{ - namespace file_ns = blender::nodes::node_geo_legacy_point_separate_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_POINT_SEPARATE, "Point Separate", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.geometry_node_execute_supports_laziness = true; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_translate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_translate.cc deleted file mode 100644 index c1486da3c2e..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_translate.cc +++ /dev/null @@ -1,97 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_point_translate_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Translation")); - b.add_input<decl::Vector>(N_("Translation"), "Translation_001").subtype(PROP_TRANSLATION); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "input_type", 0, IFACE_("Type"), ICON_NONE); -} - -static void execute_on_component(GeoNodeExecParams params, GeometryComponent &component) -{ - OutputAttribute_Typed<float3> position_attribute = - component.attribute_try_get_for_output<float3>("position", ATTR_DOMAIN_POINT, {0, 0, 0}); - if (!position_attribute) { - return; - } - VArray<float3> attribute = params.get_input_attribute<float3>( - "Translation", component, ATTR_DOMAIN_POINT, {0, 0, 0}); - - for (const int i : attribute.index_range()) { - position_attribute->set(i, position_attribute->get(i) + attribute[i]); - } - - position_attribute.save(); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<MeshComponent>()); - } - if (geometry_set.has<PointCloudComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<PointCloudComponent>()); - } - if (geometry_set.has<CurveComponent>()) { - execute_on_component(params, geometry_set.get_component_for_write<CurveComponent>()); - } - - params.set_output("Geometry", std::move(geometry_set)); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryPointTranslate *data = MEM_cnew<NodeGeometryPointTranslate>(__func__); - - data->input_type = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeGeometryPointTranslate &node_storage = *(NodeGeometryPointTranslate *)node->storage; - - update_attribute_input_socket_availabilities( - *ntree, *node, "Translation", (GeometryNodeAttributeInputMode)node_storage.input_type); -} - -} // namespace blender::nodes::node_geo_legacy_point_translate_cc - -void register_node_type_geo_point_translate() -{ - namespace file_ns = blender::nodes::node_geo_legacy_point_translate_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_POINT_TRANSLATE, "Point Translate", NODE_CLASS_GEOMETRY); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - node_type_storage(&ntype, - "NodeGeometryPointTranslate", - node_free_standard_storage, - node_copy_standard_storage); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_points_to_volume.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_points_to_volume.cc deleted file mode 100644 index c83571f1967..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_points_to_volume.cc +++ /dev/null @@ -1,266 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#ifdef WITH_OPENVDB -# include <openvdb/openvdb.h> -# include <openvdb/tools/LevelSetUtil.h> -# include <openvdb/tools/ParticlesToLevelSet.h> -#endif - -#include "node_geometry_util.hh" - -#include "BKE_lib_id.h" -#include "BKE_volume.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -namespace blender::nodes::node_geo_legacy_points_to_volume_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Float>(N_("Density")).default_value(1.0f).min(0.0f); - b.add_input<decl::Float>(N_("Voxel Size")).default_value(0.3f).min(0.01f).subtype(PROP_DISTANCE); - b.add_input<decl::Float>(N_("Voxel Amount")).default_value(64.0f).min(0.0f); - b.add_input<decl::String>(N_("Radius")); - b.add_input<decl::Float>(N_("Radius"), "Radius_001").default_value(0.5f).min(0.0f); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "resolution_mode", 0, IFACE_("Resolution"), ICON_NONE); - uiItemR(layout, ptr, "input_type_radius", 0, IFACE_("Radius"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeGeometryPointsToVolume *data = MEM_cnew<NodeGeometryPointsToVolume>(__func__); - data->resolution_mode = GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT; - data->input_type_radius = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - node->storage = data; - - bNodeSocket *radius_attribute_socket = nodeFindSocket(node, SOCK_IN, "Radius"); - bNodeSocketValueString *radius_attribute_socket_value = - (bNodeSocketValueString *)radius_attribute_socket->default_value; - STRNCPY(radius_attribute_socket_value->value, "radius"); -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeGeometryPointsToVolume *data = (NodeGeometryPointsToVolume *)node->storage; - bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size"); - bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount"); - nodeSetSocketAvailability(ntree, - voxel_amount_socket, - data->resolution_mode == - GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT); - nodeSetSocketAvailability(ntree, - voxel_size_socket, - data->resolution_mode == - GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE); - - update_attribute_input_socket_availabilities( - *ntree, *node, "Radius", (GeometryNodeAttributeInputMode)data->input_type_radius); -} - -#ifdef WITH_OPENVDB -namespace { -/* Implements the interface required by #openvdb::tools::ParticlesToLevelSet. */ -struct ParticleList { - using PosType = openvdb::Vec3R; - - Span<float3> positions; - Span<float> radii; - - size_t size() const - { - return (size_t)positions.size(); - } - - void getPos(size_t n, openvdb::Vec3R &xyz) const - { - xyz = &positions[n].x; - } - - void getPosRad(size_t n, openvdb::Vec3R &xyz, openvdb::Real &radius) const - { - xyz = &positions[n].x; - radius = radii[n]; - } -}; -} // namespace - -static openvdb::FloatGrid::Ptr generate_volume_from_points(const Span<float3> positions, - const Span<float> radii, - const float density) -{ - /* Create a new grid that will be filled. #ParticlesToLevelSet requires the background value to - * be positive. It will be set to zero later on. */ - openvdb::FloatGrid::Ptr new_grid = openvdb::FloatGrid::create(1.0f); - - /* Create a narrow-band level set grid based on the positions and radii. */ - openvdb::tools::ParticlesToLevelSet op{*new_grid}; - /* Don't ignore particles based on their radius. */ - op.setRmin(0.0f); - op.setRmax(FLT_MAX); - ParticleList particles{positions, radii}; - op.rasterizeSpheres(particles); - op.finalize(); - - /* Convert the level set to a fog volume. This also sets the background value to zero. Inside the - * fog there will be a density of 1. */ - openvdb::tools::sdfToFogVolume(*new_grid); - - /* Take the desired density into account. */ - openvdb::tools::foreach (new_grid->beginValueOn(), - [&](const openvdb::FloatGrid::ValueOnIter &iter) { - iter.modifyValue([&](float &value) { value *= density; }); - }); - return new_grid; -} - -static float compute_voxel_size(const GeoNodeExecParams ¶ms, - Span<float3> positions, - const float radius) -{ - const NodeGeometryPointsToVolume &storage = - *(const NodeGeometryPointsToVolume *)params.node().storage; - - if (storage.resolution_mode == GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE) { - return params.get_input<float>("Voxel Size"); - } - - if (positions.is_empty()) { - return 0.0f; - } - - float3 min, max; - INIT_MINMAX(min, max); - minmax_v3v3_v3_array(min, max, (float(*)[3])positions.data(), positions.size()); - - const float voxel_amount = params.get_input<float>("Voxel Amount"); - if (voxel_amount <= 1) { - return 0.0f; - } - - /* The voxel size adapts to the final size of the volume. */ - const float diagonal = math::distance(min, max); - const float extended_diagonal = diagonal + 2.0f * radius; - const float voxel_size = extended_diagonal / voxel_amount; - return voxel_size; -} - -static void gather_point_data_from_component(const GeoNodeExecParams ¶ms, - const GeometryComponent &component, - Vector<float3> &r_positions, - Vector<float> &r_radii) -{ - VArray<float3> positions = component.attribute_get_for_read<float3>( - "position", ATTR_DOMAIN_POINT, {0, 0, 0}); - VArray<float> radii = params.get_input_attribute<float>( - "Radius", component, ATTR_DOMAIN_POINT, 0.0f); - - for (const int i : positions.index_range()) { - r_positions.append(positions[i]); - r_radii.append(radii[i]); - } -} - -static void convert_to_grid_index_space(const float voxel_size, - MutableSpan<float3> positions, - MutableSpan<float> radii) -{ - const float voxel_size_inv = 1.0f / voxel_size; - for (const int i : positions.index_range()) { - positions[i] *= voxel_size_inv; - /* Better align generated grid with source points. */ - positions[i] -= float3(0.5f); - radii[i] *= voxel_size_inv; - } -} - -static void initialize_volume_component_from_points(const GeometrySet &geometry_set_in, - GeometrySet &geometry_set_out, - const GeoNodeExecParams ¶ms) -{ - Vector<float3> positions; - Vector<float> radii; - - if (geometry_set_in.has<MeshComponent>()) { - gather_point_data_from_component( - params, *geometry_set_in.get_component_for_read<MeshComponent>(), positions, radii); - } - if (geometry_set_in.has<PointCloudComponent>()) { - gather_point_data_from_component( - params, *geometry_set_in.get_component_for_read<PointCloudComponent>(), positions, radii); - } - if (geometry_set_in.has<CurveComponent>()) { - gather_point_data_from_component( - params, *geometry_set_in.get_component_for_read<CurveComponent>(), positions, radii); - } - - const float max_radius = *std::max_element(radii.begin(), radii.end()); - const float voxel_size = compute_voxel_size(params, positions, max_radius); - if (voxel_size == 0.0f || positions.is_empty()) { - return; - } - - Volume *volume = (Volume *)BKE_id_new_nomain(ID_VO, nullptr); - BKE_volume_init_grids(volume); - - VolumeGrid *c_density_grid = BKE_volume_grid_add(volume, "density", VOLUME_GRID_FLOAT); - openvdb::FloatGrid::Ptr density_grid = openvdb::gridPtrCast<openvdb::FloatGrid>( - BKE_volume_grid_openvdb_for_write(volume, c_density_grid, false)); - - const float density = params.get_input<float>("Density"); - convert_to_grid_index_space(voxel_size, positions, radii); - openvdb::FloatGrid::Ptr new_grid = generate_volume_from_points(positions, radii, density); - /* This merge is cheap, because the #density_grid is empty. */ - density_grid->merge(*new_grid); - density_grid->transform().postScale(voxel_size); - - VolumeComponent &volume_component = geometry_set_out.get_component_for_write<VolumeComponent>(); - volume_component.replace(volume); -} -#endif - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set_in = params.extract_input<GeometrySet>("Geometry"); - GeometrySet geometry_set_out; - - /* TODO: Read-only access to instances should be supported here, for now they are made real. */ - geometry_set_in = geometry::realize_instances_legacy(geometry_set_in); - -#ifdef WITH_OPENVDB - initialize_volume_component_from_points(geometry_set_in, geometry_set_out, params); -#endif - - params.set_output("Geometry", std::move(geometry_set_out)); -} - -} // namespace blender::nodes::node_geo_legacy_points_to_volume_cc - -void register_node_type_geo_legacy_points_to_volume() -{ - namespace file_ns = blender::nodes::node_geo_legacy_points_to_volume_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_POINTS_TO_VOLUME, "Points to Volume", NODE_CLASS_GEOMETRY); - node_type_storage(&ntype, - "NodeGeometryPointsToVolume", - node_free_standard_storage, - node_copy_standard_storage); - node_type_size(&ntype, 170, 120, 700); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_raycast.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_raycast.cc deleted file mode 100644 index 1420edcca0b..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_raycast.cc +++ /dev/null @@ -1,313 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "DNA_mesh_types.h" - -#include "BKE_bvhutils.h" -#include "BKE_mesh_sample.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_raycast_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Geometry>(N_("Target Geometry")); - b.add_input<decl::String>(N_("Ray Direction")); - b.add_input<decl::Vector>(N_("Ray Direction"), "Ray Direction_001") - .default_value({0.0f, 0.0f, 1.0f}); - b.add_input<decl::String>(N_("Ray Length")); - b.add_input<decl::Float>(N_("Ray Length"), "Ray Length_001") - .default_value(100.0f) - .min(0.0f) - .subtype(PROP_DISTANCE); - b.add_input<decl::String>(N_("Target Attribute")); - b.add_input<decl::String>(N_("Is Hit")); - b.add_input<decl::String>(N_("Hit Position")); - b.add_input<decl::String>(N_("Hit Normal")); - b.add_input<decl::String>(N_("Hit Distance")); - b.add_input<decl::String>(N_("Hit Attribute")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "mapping", 0, IFACE_("Mapping"), ICON_NONE); - uiItemR(layout, ptr, "input_type_ray_direction", 0, IFACE_("Ray Direction"), ICON_NONE); - uiItemR(layout, ptr, "input_type_ray_length", 0, IFACE_("Ray Length"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryRaycast *data = MEM_cnew<NodeGeometryRaycast>(__func__); - data->input_type_ray_direction = GEO_NODE_ATTRIBUTE_INPUT_VECTOR; - data->input_type_ray_length = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeGeometryRaycast *node_storage = (NodeGeometryRaycast *)node->storage; - update_attribute_input_socket_availabilities( - *ntree, - *node, - "Ray Direction", - (GeometryNodeAttributeInputMode)node_storage->input_type_ray_direction); - update_attribute_input_socket_availabilities( - *ntree, - *node, - "Ray Length", - (GeometryNodeAttributeInputMode)node_storage->input_type_ray_length); -} - -static void raycast_to_mesh(const Mesh &mesh, - const VArray<float3> &ray_origins, - const VArray<float3> &ray_directions, - const VArray<float> &ray_lengths, - const MutableSpan<bool> r_hit, - const MutableSpan<int> r_hit_indices, - const MutableSpan<float3> r_hit_positions, - const MutableSpan<float3> r_hit_normals, - const MutableSpan<float> r_hit_distances) -{ - BLI_assert(ray_origins.size() == ray_directions.size()); - BLI_assert(ray_origins.size() == ray_lengths.size()); - BLI_assert(ray_origins.size() == r_hit.size() || r_hit.is_empty()); - BLI_assert(ray_origins.size() == r_hit_indices.size() || r_hit_indices.is_empty()); - BLI_assert(ray_origins.size() == r_hit_positions.size() || r_hit_positions.is_empty()); - BLI_assert(ray_origins.size() == r_hit_normals.size() || r_hit_normals.is_empty()); - BLI_assert(ray_origins.size() == r_hit_distances.size() || r_hit_distances.is_empty()); - - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_LOOPTRI, 4); - if (tree_data.tree == nullptr) { - free_bvhtree_from_mesh(&tree_data); - return; - } - - for (const int i : ray_origins.index_range()) { - const float ray_length = ray_lengths[i]; - const float3 ray_origin = ray_origins[i]; - const float3 ray_direction = math::normalize(ray_directions[i]); - - BVHTreeRayHit hit; - hit.index = -1; - hit.dist = ray_length; - if (BLI_bvhtree_ray_cast(tree_data.tree, - ray_origin, - ray_direction, - 0.0f, - &hit, - tree_data.raycast_callback, - &tree_data) != -1) { - if (!r_hit.is_empty()) { - r_hit[i] = hit.index >= 0; - } - if (!r_hit_indices.is_empty()) { - /* Index should always be a valid looptri index, use 0 when hit failed. */ - r_hit_indices[i] = max_ii(hit.index, 0); - } - if (!r_hit_positions.is_empty()) { - r_hit_positions[i] = hit.co; - } - if (!r_hit_normals.is_empty()) { - r_hit_normals[i] = hit.no; - } - if (!r_hit_distances.is_empty()) { - r_hit_distances[i] = hit.dist; - } - } - else { - if (!r_hit.is_empty()) { - r_hit[i] = false; - } - if (!r_hit_indices.is_empty()) { - r_hit_indices[i] = 0; - } - if (!r_hit_positions.is_empty()) { - r_hit_positions[i] = float3(0.0f, 0.0f, 0.0f); - } - if (!r_hit_normals.is_empty()) { - r_hit_normals[i] = float3(0.0f, 0.0f, 0.0f); - } - if (!r_hit_distances.is_empty()) { - r_hit_distances[i] = ray_length; - } - } - } - - free_bvhtree_from_mesh(&tree_data); -} - -static bke::mesh_surface_sample::eAttributeMapMode get_map_mode( - GeometryNodeRaycastMapMode map_mode) -{ - switch (map_mode) { - case GEO_NODE_RAYCAST_INTERPOLATED: - return bke::mesh_surface_sample::eAttributeMapMode::INTERPOLATED; - default: - case GEO_NODE_RAYCAST_NEAREST: - return bke::mesh_surface_sample::eAttributeMapMode::NEAREST; - } -} - -static void raycast_from_points(const GeoNodeExecParams ¶ms, - const GeometrySet &target_geometry, - GeometryComponent &dst_component, - const StringRef hit_name, - const StringRef hit_position_name, - const StringRef hit_normal_name, - const StringRef hit_distance_name, - const Span<std::string> hit_attribute_names, - const Span<std::string> hit_attribute_output_names) -{ - BLI_assert(hit_attribute_names.size() == hit_attribute_output_names.size()); - - const MeshComponent *src_mesh_component = - target_geometry.get_component_for_read<MeshComponent>(); - if (src_mesh_component == nullptr) { - return; - } - const Mesh *src_mesh = src_mesh_component->get_for_read(); - if (src_mesh == nullptr) { - return; - } - if (src_mesh->totpoly == 0) { - return; - } - - const NodeGeometryRaycast &storage = *(const NodeGeometryRaycast *)params.node().storage; - bke::mesh_surface_sample::eAttributeMapMode map_mode = get_map_mode( - (GeometryNodeRaycastMapMode)storage.mapping); - const AttributeDomain result_domain = ATTR_DOMAIN_POINT; - - VArray<float3> ray_origins = dst_component.attribute_get_for_read<float3>( - "position", result_domain, {0, 0, 0}); - VArray<float3> ray_directions = params.get_input_attribute<float3>( - "Ray Direction", dst_component, result_domain, {0, 0, 0}); - VArray<float> ray_lengths = params.get_input_attribute<float>( - "Ray Length", dst_component, result_domain, 0); - - OutputAttribute_Typed<bool> hit_attribute = - dst_component.attribute_try_get_for_output_only<bool>(hit_name, result_domain); - OutputAttribute_Typed<float3> hit_position_attribute = - dst_component.attribute_try_get_for_output_only<float3>(hit_position_name, result_domain); - OutputAttribute_Typed<float3> hit_normal_attribute = - dst_component.attribute_try_get_for_output_only<float3>(hit_normal_name, result_domain); - OutputAttribute_Typed<float> hit_distance_attribute = - dst_component.attribute_try_get_for_output_only<float>(hit_distance_name, result_domain); - - /* Positions and looptri indices are always needed for interpolation, - * so create temporary arrays if no output attribute is given. */ - Array<int> hit_indices; - Array<float3> hit_positions_internal; - if (!hit_attribute_names.is_empty()) { - hit_indices.reinitialize(ray_origins.size()); - - if (!hit_position_attribute) { - hit_positions_internal.reinitialize(ray_origins.size()); - } - } - const MutableSpan<bool> is_hit = hit_attribute ? hit_attribute.as_span() : MutableSpan<bool>(); - const MutableSpan<float3> hit_positions = hit_position_attribute ? - hit_position_attribute.as_span() : - hit_positions_internal; - const MutableSpan<float3> hit_normals = hit_normal_attribute ? hit_normal_attribute.as_span() : - MutableSpan<float3>(); - const MutableSpan<float> hit_distances = hit_distance_attribute ? - hit_distance_attribute.as_span() : - MutableSpan<float>(); - - raycast_to_mesh(*src_mesh, - ray_origins, - ray_directions, - ray_lengths, - is_hit, - hit_indices, - hit_positions, - hit_normals, - hit_distances); - - hit_attribute.save(); - hit_position_attribute.save(); - hit_normal_attribute.save(); - hit_distance_attribute.save(); - - /* Custom interpolated attributes */ - bke::mesh_surface_sample::MeshAttributeInterpolator interp( - src_mesh, IndexMask(ray_origins.size()), hit_positions, hit_indices); - for (const int i : hit_attribute_names.index_range()) { - const std::optional<AttributeMetaData> meta_data = src_mesh_component->attribute_get_meta_data( - hit_attribute_names[i]); - if (meta_data) { - ReadAttributeLookup hit_attribute = src_mesh_component->attribute_try_get_for_read( - hit_attribute_names[i]); - OutputAttribute hit_attribute_output = dst_component.attribute_try_get_for_output_only( - hit_attribute_output_names[i], result_domain, meta_data->data_type); - - interp.sample_attribute(hit_attribute, hit_attribute_output, map_mode); - - hit_attribute_output.save(); - } - } -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - GeometrySet target_geometry_set = params.extract_input<GeometrySet>("Target Geometry"); - - const std::string hit_name = params.extract_input<std::string>("Is Hit"); - const std::string hit_position_name = params.extract_input<std::string>("Hit Position"); - const std::string hit_normal_name = params.extract_input<std::string>("Hit Normal"); - const std::string hit_distance_name = params.extract_input<std::string>("Hit Distance"); - - const Array<std::string> hit_names = {params.extract_input<std::string>("Target Attribute")}; - const Array<std::string> hit_output_names = {params.extract_input<std::string>("Hit Attribute")}; - - geometry_set = geometry::realize_instances_legacy(geometry_set); - target_geometry_set = geometry::realize_instances_legacy(target_geometry_set); - - static const Array<GeometryComponentType> types = { - GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE}; - for (const GeometryComponentType type : types) { - if (geometry_set.has(type)) { - raycast_from_points(params, - target_geometry_set, - geometry_set.get_component_for_write(type), - hit_name, - hit_position_name, - hit_normal_name, - hit_distance_name, - hit_names, - hit_output_names); - } - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes::node_geo_legacy_raycast_cc - -void register_node_type_geo_legacy_raycast() -{ - namespace file_ns = blender::nodes::node_geo_legacy_raycast_cc; - - static bNodeType ntype; - - geo_node_type_base(&ntype, GEO_NODE_LEGACY_RAYCAST, "Raycast", NODE_CLASS_GEOMETRY); - node_type_size_preset(&ntype, NODE_SIZE_LARGE); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - node_type_storage( - &ntype, "NodeGeometryRaycast", node_free_standard_storage, node_copy_standard_storage); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_select_by_material.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_select_by_material.cc deleted file mode 100644 index 150fd56abe3..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_select_by_material.cc +++ /dev/null @@ -1,80 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "node_geometry_util.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" - -#include "BLI_task.hh" - -#include "BKE_material.h" - -namespace blender::nodes::node_geo_legacy_select_by_material_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Material>(N_("Material")).hide_label(); - b.add_input<decl::String>(N_("Selection")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void select_mesh_by_material(const Mesh &mesh, - const Material *material, - const MutableSpan<bool> r_selection) -{ - BLI_assert(mesh.totpoly == r_selection.size()); - Vector<int> material_indices; - for (const int i : IndexRange(mesh.totcol)) { - if (mesh.mat[i] == material) { - material_indices.append(i); - } - } - threading::parallel_for(r_selection.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - r_selection[i] = material_indices.contains(mesh.mpoly[i].mat_nr); - } - }); -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - Material *material = params.extract_input<Material *>("Material"); - const std::string selection_name = params.extract_input<std::string>("Selection"); - - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (geometry_set.has<MeshComponent>()) { - MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); - const Mesh *mesh = mesh_component.get_for_read(); - if (mesh != nullptr) { - OutputAttribute_Typed<bool> selection = - mesh_component.attribute_try_get_for_output_only<bool>(selection_name, ATTR_DOMAIN_FACE); - if (selection) { - select_mesh_by_material(*mesh, material, selection.as_span()); - selection.save(); - } - } - } - - params.set_output("Geometry", std::move(geometry_set)); -} - -} // namespace blender::nodes::node_geo_legacy_select_by_material_cc - -void register_node_type_geo_legacy_select_by_material() -{ - namespace file_ns = blender::nodes::node_geo_legacy_select_by_material_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_SELECT_BY_MATERIAL, "Select by Material", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_subdivision_surface.cc deleted file mode 100644 index 9eef4b84c36..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_subdivision_surface.cc +++ /dev/null @@ -1,132 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BKE_mesh.h" -#include "BKE_subdiv.h" -#include "BKE_subdiv_mesh.h" - -#include "DNA_modifier_types.h" -#include "UI_interface.h" -#include "UI_resources.h" -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_legacy_subdivision_surface_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::Int>(N_("Level")).default_value(1).min(0).max(6); - b.add_input<decl::Bool>(N_("Use Creases")); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ -#ifdef WITH_OPENSUBDIV - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "uv_smooth", 0, nullptr, ICON_NONE); - uiItemR(layout, ptr, "boundary_smooth", 0, nullptr, ICON_NONE); -#else - UNUSED_VARS(layout, ptr); -#endif -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeGeometrySubdivisionSurface *data = MEM_cnew<NodeGeometrySubdivisionSurface>(__func__); - data->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES; - data->boundary_smooth = SUBSURF_BOUNDARY_SMOOTH_ALL; - node->storage = data; -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - - geometry_set = geometry::realize_instances_legacy(geometry_set); - - if (!geometry_set.has_mesh()) { - params.set_output("Geometry", geometry_set); - return; - } - -#ifndef WITH_OPENSUBDIV - params.error_message_add(NodeWarningType::Error, - TIP_("Disabled, Blender was compiled without OpenSubdiv")); -#else - const NodeGeometrySubdivisionSurface &storage = - *(const NodeGeometrySubdivisionSurface *)params.node().storage; - const int uv_smooth = storage.uv_smooth; - const int boundary_smooth = storage.boundary_smooth; - const int subdiv_level = clamp_i(params.extract_input<int>("Level"), 0, 30); - - /* Only process subdivision if level is greater than 0. */ - if (subdiv_level == 0) { - params.set_output("Geometry", std::move(geometry_set)); - return; - } - - const bool use_crease = params.extract_input<bool>("Use Creases"); - const Mesh *mesh_in = geometry_set.get_mesh_for_read(); - - /* Initialize mesh settings. */ - SubdivToMeshSettings mesh_settings; - mesh_settings.resolution = (1 << subdiv_level) + 1; - mesh_settings.use_optimal_display = false; - - /* Initialize subdivision settings. */ - SubdivSettings subdiv_settings; - subdiv_settings.is_simple = false; - subdiv_settings.is_adaptive = false; - subdiv_settings.use_creases = use_crease; - subdiv_settings.level = subdiv_level; - - subdiv_settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( - boundary_smooth); - subdiv_settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth( - uv_smooth); - - /* Apply subdivision to mesh. */ - Subdiv *subdiv = BKE_subdiv_update_from_mesh(nullptr, &subdiv_settings, mesh_in); - - /* In case of bad topology, skip to input mesh. */ - if (subdiv == nullptr) { - params.set_output("Geometry", std::move(geometry_set)); - return; - } - - Mesh *mesh_out = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh_in); - BKE_mesh_normals_tag_dirty(mesh_out); - - MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); - mesh_component.replace(mesh_out); - - // BKE_subdiv_stats_print(&subdiv->stats); - BKE_subdiv_free(subdiv); - -#endif - - params.set_output("Geometry", std::move(geometry_set)); -} - -} // namespace blender::nodes::node_geo_legacy_subdivision_surface_cc - -void register_node_type_geo_legacy_subdivision_surface() -{ - namespace file_ns = blender::nodes::node_geo_legacy_subdivision_surface_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_SUBDIVISION_SURFACE, "Subdivision Surface", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - node_type_init(&ntype, file_ns::node_init); - node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_storage(&ntype, - "NodeGeometrySubdivisionSurface", - node_free_standard_storage, - node_copy_standard_storage); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_volume_to_mesh.cc deleted file mode 100644 index 768932a7fe7..00000000000 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_volume_to_mesh.cc +++ /dev/null @@ -1,162 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "DEG_depsgraph_query.h" -#ifdef WITH_OPENVDB -# include <openvdb/tools/GridTransformer.h> -# include <openvdb/tools/VolumeToMesh.h> -#endif - -#include "node_geometry_util.hh" - -#include "BKE_lib_id.h" -#include "BKE_material.h" -#include "BKE_mesh.h" -#include "BKE_mesh_runtime.h" -#include "BKE_volume.h" -#include "BKE_volume_to_mesh.hh" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -namespace blender::nodes::node_geo_legacy_volume_to_mesh_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Geometry")); - b.add_input<decl::String>(N_("Density")); - b.add_input<decl::Float>(N_("Voxel Size")).default_value(0.3f).min(0.01f).subtype(PROP_DISTANCE); - b.add_input<decl::Float>(N_("Voxel Amount")).default_value(64.0f).min(0.0f); - b.add_input<decl::Float>(N_("Threshold")).default_value(0.1f).min(0.0f); - b.add_input<decl::Float>(N_("Adaptivity")).min(0.0f).max(1.0f).subtype(PROP_FACTOR); - b.add_output<decl::Geometry>(N_("Geometry")); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "resolution_mode", 0, IFACE_("Resolution"), ICON_NONE); -} - -static void node_init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeGeometryVolumeToMesh *data = MEM_cnew<NodeGeometryVolumeToMesh>(__func__); - data->resolution_mode = VOLUME_TO_MESH_RESOLUTION_MODE_GRID; - - bNodeSocket *grid_socket = nodeFindSocket(node, SOCK_IN, "Density"); - bNodeSocketValueString *grid_socket_value = (bNodeSocketValueString *)grid_socket->default_value; - STRNCPY(grid_socket_value->value, "density"); - - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - NodeGeometryVolumeToMesh *data = (NodeGeometryVolumeToMesh *)node->storage; - - bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size"); - bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount"); - nodeSetSocketAvailability(ntree, - voxel_amount_socket, - data->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT); - nodeSetSocketAvailability(ntree, - voxel_size_socket, - data->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE); -} - -#ifdef WITH_OPENVDB - -static void create_mesh_from_volume(GeometrySet &geometry_set_in, - GeometrySet &geometry_set_out, - GeoNodeExecParams ¶ms) -{ - if (!geometry_set_in.has<VolumeComponent>()) { - return; - } - - const NodeGeometryVolumeToMesh &storage = - *(const NodeGeometryVolumeToMesh *)params.node().storage; - - bke::VolumeToMeshResolution resolution; - resolution.mode = (VolumeToMeshResolutionMode)storage.resolution_mode; - if (resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT) { - resolution.settings.voxel_amount = params.get_input<float>("Voxel Amount"); - if (resolution.settings.voxel_amount <= 0.0f) { - return; - } - } - else if (resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE) { - resolution.settings.voxel_size = params.get_input<float>("Voxel Size"); - if (resolution.settings.voxel_size <= 0.0f) { - return; - } - } - - const VolumeComponent *component = geometry_set_in.get_component_for_read<VolumeComponent>(); - const Volume *volume = component->get_for_read(); - if (volume == nullptr) { - return; - } - - const Main *bmain = DEG_get_bmain(params.depsgraph()); - BKE_volume_load(volume, bmain); - - const std::string grid_name = params.get_input<std::string>("Density"); - const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, grid_name.c_str()); - if (volume_grid == nullptr) { - return; - } - - float threshold = params.get_input<float>("Threshold"); - float adaptivity = params.get_input<float>("Adaptivity"); - - const openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); - Mesh *mesh = bke::volume_to_mesh(*grid, resolution, threshold, adaptivity); - if (mesh == nullptr) { - return; - } - BKE_id_material_eval_ensure_default_slot(&mesh->id); - MeshComponent &dst_component = geometry_set_out.get_component_for_write<MeshComponent>(); - dst_component.replace(mesh); -} - -#endif /* WITH_OPENVDB */ - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set_in = params.extract_input<GeometrySet>("Geometry"); - GeometrySet geometry_set_out; - -#ifdef WITH_OPENVDB - create_mesh_from_volume(geometry_set_in, geometry_set_out, params); -#else - params.error_message_add(NodeWarningType::Error, - TIP_("Disabled, Blender was compiled without OpenVDB")); -#endif - - params.set_output("Geometry", geometry_set_out); -} - -} // namespace blender::nodes::node_geo_legacy_volume_to_mesh_cc - -void register_node_type_geo_legacy_volume_to_mesh() -{ - namespace file_ns = blender::nodes::node_geo_legacy_volume_to_mesh_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_VOLUME_TO_MESH, "Volume to Mesh", NODE_CLASS_GEOMETRY); - ntype.declare = file_ns::node_declare; - node_type_storage( - &ntype, "NodeGeometryVolumeToMesh", node_free_standard_storage, node_copy_standard_storage); - node_type_size(&ntype, 170, 120, 700); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc index 1eb18b2f910..5955fe1f3b1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc @@ -12,19 +12,6 @@ #include "node_geometry_util.hh" -namespace blender::nodes { -void curve_create_default_rotation_attribute(Span<float3> tangents, - Span<float3> normals, - MutableSpan<float3> rotations) -{ - threading::parallel_for(IndexRange(rotations.size()), 512, [&](IndexRange range) { - for (const int i : range) { - rotations[i] = - float4x4::from_normalized_axis_data({0, 0, 0}, normals[i], tangents[i]).to_euler(); - } - }); -} -} // namespace blender::nodes namespace blender::nodes::node_geo_curve_to_points_cc { @@ -76,6 +63,19 @@ static void node_update(bNodeTree *ntree, bNode *node) nodeSetSocketAvailability(ntree, length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH); } +static void curve_create_default_rotation_attribute(Span<float3> tangents, + Span<float3> normals, + MutableSpan<float3> rotations) +{ + threading::parallel_for(IndexRange(rotations.size()), 512, [&](IndexRange range) { + for (const int i : range) { + rotations[i] = + float4x4::from_normalized_axis_data({0, 0, 0}, normals[i], tangents[i]).to_euler(); + } + }); +} + + static Array<int> calculate_spline_point_offsets(GeoNodeExecParams ¶ms, const GeometryNodeCurveResampleMode mode, const CurveEval &curve, |