diff --git a/source/blender/bmesh/intern/bmesh_operator_api.hh b/source/blender/bmesh/intern/bmesh_operator_api.hh index 983cc3e3cfe..f36c924e404 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.hh +++ b/source/blender/bmesh/intern/bmesh_operator_api.hh @@ -12,6 +12,7 @@ #include "BLI_utildefines.h" #include +#include #include "bmesh_class.hh" @@ -239,6 +240,15 @@ union eBMOpSlotSubType_Union { eBMOpSlotSubType_Int intg; }; +enum eBMOpSlotFlag : uint8_t { + /** + * This flag is set when the operators value has been set. + * Use this so it's possible to have non-zero defaults for properties. + */ + BMO_OP_SLOT_FLAG_IS_SET = (1 << 0), +}; +ENUM_OPERATORS(eBMOpSlotFlag, BMO_OP_SLOT_FLAG_IS_SET) + struct BMO_FlagSet { int value; const char *identifier; @@ -252,8 +262,8 @@ struct BMOpSlot { eBMOpSlotType slot_type; eBMOpSlotSubType_Union slot_subtype; + eBMOpSlotFlag flag; int len; - // int flag; /* UNUSED */ // int index; /* index within slot array */ /* UNUSED */ union { int i; @@ -549,10 +559,16 @@ void BMO_op_flag_disable(BMesh *bm, BMOperator *op, int op_flag); void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float f); float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +std::optional BMO_slot_float_get_optional(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name); void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int i); int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +std::optional BMO_slot_int_get_optional(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name); void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, bool i); bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +std::optional BMO_slot_bool_get_optional(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name); /** * Return a copy of the element buffer. */ diff --git a/source/blender/bmesh/intern/bmesh_operators.cc b/source/blender/bmesh/intern/bmesh_operators.cc index d56a9b80f5a..d93dc25ac26 100644 --- a/source/blender/bmesh/intern/bmesh_operators.cc +++ b/source/blender/bmesh/intern/bmesh_operators.cc @@ -295,6 +295,8 @@ void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], else { slot_dst->data = slot_src->data; } + + slot_dst->flag = slot_src->flag; } /* @@ -312,6 +314,7 @@ void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_n } slot->data.f = f; + slot->flag |= BMO_OP_SLOT_FLAG_IS_SET; } void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) @@ -323,6 +326,7 @@ void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam } slot->data.i = i; + slot->flag |= BMO_OP_SLOT_FLAG_IS_SET; } void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i) @@ -334,6 +338,7 @@ void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na } slot->data.i = i; + slot->flag |= BMO_OP_SLOT_FLAG_IS_SET; } void BMO_slot_mat_set(BMOperator *op, @@ -362,6 +367,7 @@ void BMO_slot_mat_set(BMOperator *op, zero_m4(static_cast(slot->data.p)); } + slot->flag |= BMO_OP_SLOT_FLAG_IS_SET; } void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], @@ -409,6 +415,7 @@ void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam } slot->data.p = p; + slot->flag |= BMO_OP_SLOT_FLAG_IS_SET; } void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], @@ -422,31 +429,51 @@ void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], } copy_v3_v3(slot->data.vec, vec); + slot->flag |= BMO_OP_SLOT_FLAG_IS_SET; } float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) +{ + return BMO_slot_float_get_optional(slot_args, slot_name).value_or(0.0f); +} + +std::optional BMO_slot_float_get_optional(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); if (!(slot->slot_type == BMO_OP_SLOT_FLT)) { - return 0.0f; + return std::nullopt; + } + if ((slot->flag & BMO_OP_SLOT_FLAG_IS_SET) == 0) { + return std::nullopt; } return slot->data.f; } -int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) +std::optional BMO_slot_int_get_optional(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); if (!(slot->slot_type == BMO_OP_SLOT_INT)) { - return 0; + return std::nullopt; + } + if ((slot->flag & BMO_OP_SLOT_FLAG_IS_SET) == 0) { + return std::nullopt; } return slot->data.i; } -bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) +int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) +{ + return BMO_slot_int_get_optional(slot_args, slot_name).value_or(0); +} + +std::optional BMO_slot_bool_get_optional(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); @@ -456,6 +483,10 @@ bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na return slot->data.i; } +bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) +{ + return BMO_slot_bool_get_optional(slot_args, slot_name).value_or(false); +} void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len) { diff --git a/source/blender/bmesh/operators/bmo_dissolve.cc b/source/blender/bmesh/operators/bmo_dissolve.cc index f377a0dd269..b0ea5877f5a 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.cc +++ b/source/blender/bmesh/operators/bmo_dissolve.cc @@ -387,7 +387,9 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) * This lets the test ignore that tiny bit of math error so users won't notice. */ const float angle_epsilon = RAD2DEGF(0.0001f); - const float angle_threshold = BMO_slot_float_get(op->slots_in, "angle_threshold"); + /* When unset, don't limit dissolving vertices at all. */ + const float angle_threshold = + BMO_slot_float_get_optional(op->slots_in, "angle_threshold").value_or(M_PI); /* Use verts when told to... except, do *not* use verts when angle_threshold is 0.0. */ const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts") &&