diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 4a7d34f1b69..82999a99ca8 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -572,6 +572,7 @@ geometry_node_categories = [ NodeItem("ShaderNodeMath"), NodeItem("FunctionNodeBooleanMath"), NodeItem("FunctionNodeFloatCompare"), + NodeItem("FunctionNodeFloatToInt"), NodeItem("GeometryNodeSwitch"), ]), GeometryNodeCategory("GEO_VECTOR", "Vector", items=[ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index a3387ab554e..d049510ef4d 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1457,6 +1457,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define FN_NODE_RANDOM_FLOAT 1206 #define FN_NODE_INPUT_VECTOR 1207 #define FN_NODE_INPUT_STRING 1208 +#define FN_NODE_FLOAT_TO_INT 1209 /** \} */ diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 293a1b2f69d..3345aff5db4 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -5105,6 +5105,7 @@ static void registerFunctionNodes() { register_node_type_fn_boolean_math(); register_node_type_fn_float_compare(); + register_node_type_fn_float_to_int(); register_node_type_fn_input_string(); register_node_type_fn_input_vector(); register_node_type_fn_random_float(); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 54bd792294f..f1ad41a4492 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1688,6 +1688,14 @@ typedef enum FloatCompareOperation { NODE_FLOAT_COMPARE_NOT_EQUAL = 5, } FloatCompareOperation; +/* Float to Int node operations. */ +typedef enum FloatToIntRoundingMode { + FN_NODE_FLOAT_TO_INT_ROUND = 0, + FN_NODE_FLOAT_TO_INT_FLOOR = 1, + FN_NODE_FLOAT_TO_INT_CEIL = 2, + FN_NODE_FLOAT_TO_INT_TRUNCATE = 3, +} FloatToIntRoundingMode; + /* Clamp node types. */ enum { NODE_CLAMP_MINMAX = 0, diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 71af69f77a1..c8010a0e1ae 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -204,6 +204,7 @@ extern const EnumPropertyItem rna_enum_node_vec_math_items[]; extern const EnumPropertyItem rna_enum_node_boolean_math_items[]; extern const EnumPropertyItem rna_enum_node_float_compare_items[]; extern const EnumPropertyItem rna_enum_node_filter_items[]; +extern const EnumPropertyItem rna_enum_node_float_to_int_items[]; extern const EnumPropertyItem rna_enum_node_map_range_items[]; extern const EnumPropertyItem rna_enum_node_clamp_items[]; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index d9e199e5eb2..93d5197f931 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -337,6 +337,31 @@ const EnumPropertyItem rna_enum_node_float_compare_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_node_float_to_int_items[] = { + {FN_NODE_FLOAT_TO_INT_ROUND, + "ROUND", + 0, + "Round", + "Round the float up or down to the nearest integer"}, + {FN_NODE_FLOAT_TO_INT_FLOOR, + "FLOOR", + 0, + "Floor", + "Round the float down to the next smallest integer"}, + {FN_NODE_FLOAT_TO_INT_CEIL, + "CEILING", + 0, + "Ceiling", + "Round the float up to the next largest integer"}, + {FN_NODE_FLOAT_TO_INT_TRUNCATE, + "TRUNCATE", + 0, + "Truncate", + "Round the float to the closest integer in the direction of zero (floor if positive; ceiling " + "if negative)"}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_node_map_range_items[] = { {NODE_MAP_RANGE_LINEAR, "LINEAR", @@ -4794,6 +4819,18 @@ static void def_float_compare(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_float_to_int(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "rounding_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_enum_node_float_to_int_items); + RNA_def_property_ui_text( + prop, "Rounding Mode", "Method used to convert the float to an integer"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_vector_math(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 49e40060c0f..4d3eee51a27 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -134,6 +134,7 @@ set(SRC function/nodes/node_fn_boolean_math.cc function/nodes/node_fn_float_compare.cc + function/nodes/node_fn_float_to_int.cc function/nodes/node_fn_input_string.cc function/nodes/node_fn_input_vector.cc function/nodes/node_fn_random_float.cc diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h index b31b5326d66..29f1a465491 100644 --- a/source/blender/nodes/NOD_function.h +++ b/source/blender/nodes/NOD_function.h @@ -22,6 +22,7 @@ extern "C" { void register_node_type_fn_boolean_math(void); void register_node_type_fn_float_compare(void); +void register_node_type_fn_float_to_int(void); void register_node_type_fn_input_string(void); void register_node_type_fn_input_vector(void); void register_node_type_fn_random_float(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 1d906033128..4fe0dc2f20a 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -263,6 +263,7 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DI DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "") DefNode(FunctionNode, FN_NODE_FLOAT_COMPARE, def_float_compare, "FLOAT_COMPARE", FloatCompare, "Float Compare", "") +DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "") DefNode(FunctionNode, FN_NODE_INPUT_STRING, def_fn_input_string, "INPUT_STRING", InputString, "String", "") DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR", InputVector, "Vector", "") DefNode(FunctionNode, FN_NODE_RANDOM_FLOAT, 0, "RANDOM_FLOAT", RandomFloat, "Random Float", "") diff --git a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc new file mode 100644 index 00000000000..5bc60509b54 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc @@ -0,0 +1,96 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "RNA_enum_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_function_util.hh" + +static bNodeSocketTemplate fn_node_float_to_int_in[] = { + {SOCK_FLOAT, N_("Float"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_float_to_int_out[] = { + {SOCK_INT, N_("Integer")}, + {-1, ""}, +}; + +static void fn_node_float_to_int_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "rounding_mode", 0, "", ICON_NONE); +} + +static void node_float_to_int_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen) +{ + const char *name; + bool enum_label = RNA_enum_name(rna_enum_node_float_to_int_items, node->custom1, &name); + if (!enum_label) { + name = "Unknown"; + } + BLI_strncpy(label, IFACE_(name), maxlen); +} + +static const blender::fn::MultiFunction &get_multi_function(bNode &bnode) +{ + static blender::fn::CustomMF_SI_SO round_fn{"Round", + [](float a) { return std::round(a); }}; + static blender::fn::CustomMF_SI_SO floor_fn{"Floor", + [](float a) { return (int)floor(a); }}; + static blender::fn::CustomMF_SI_SO ceil_fn{"Ceiling", + [](float a) { return (int)ceil(a); }}; + static blender::fn::CustomMF_SI_SO trunc_fn{"Truncate", + [](float a) { return (int)trunc(a); }}; + + switch (static_cast(bnode.custom1)) { + case FN_NODE_FLOAT_TO_INT_ROUND: + return round_fn; + case FN_NODE_FLOAT_TO_INT_FLOOR: + return floor_fn; + case FN_NODE_FLOAT_TO_INT_CEIL: + return ceil_fn; + case FN_NODE_FLOAT_TO_INT_TRUNCATE: + return trunc_fn; + } + + BLI_assert_unreachable(); + return blender::fn::dummy_multi_function; +} + +static void node_float_to_int_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + const blender::fn::MultiFunction &fn = get_multi_function(builder.bnode()); + builder.set_matching_fn(fn); +} + +void register_node_type_fn_float_to_int() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_FLOAT_TO_INT, "Float to Integer", NODE_CLASS_CONVERTOR, 0); + node_type_socket_templates(&ntype, fn_node_float_to_int_in, fn_node_float_to_int_out); + node_type_label(&ntype, node_float_to_int_label); + ntype.expand_in_mf_network = node_float_to_int_expand_in_mf_network; + ntype.draw_buttons = fn_node_float_to_int_layout; + nodeRegisterType(&ntype); +}