diff --git a/doc/python_api/rst/info_quickstart.rst b/doc/python_api/rst/info_quickstart.rst index 4e7382b9dd6..d422bd9b656 100644 --- a/doc/python_api/rst/info_quickstart.rst +++ b/doc/python_api/rst/info_quickstart.rst @@ -447,9 +447,22 @@ Using low-level functions: .. code-block:: python obj = bpy.context.object - obj.animation_data_create() - obj.animation_data.action = bpy.data.actions.new(name="MyAction") - fcu_z = obj.animation_data.action.fcurves.new(data_path="location", index=2) + + # Create the action, with a slot for the object, a layer, and a keyframe strip: + action = bpy.data.actions.new(name="MyAction") + slot = action.slots.new(obj.id_type, obj.name) + strip = action.layers.new("MyLayer").strips.new(type='KEYFRAME') + + # Create a channelbag to hold the F-Curves for the slot: + channelbag = strip.channelbag(slot, ensure=True) + + # Create the F-Curve with two keyframes: + fcu_z = channelbag.fcurves.new(data_path="location", index=2) fcu_z.keyframe_points.add(2) fcu_z.keyframe_points[0].co = 10.0, 0.0 fcu_z.keyframe_points[1].co = 20.0, 1.0 + + # Assign the action and the slot to the object: + adt = obj.animation_data_create() + adt.action = action + adt.action_slot = slot diff --git a/source/blender/bmesh/intern/bmesh_operator_api.hh b/source/blender/bmesh/intern/bmesh_operator_api.hh index f36c924e404..983cc3e3cfe 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.hh +++ b/source/blender/bmesh/intern/bmesh_operator_api.hh @@ -12,7 +12,6 @@ #include "BLI_utildefines.h" #include -#include #include "bmesh_class.hh" @@ -240,15 +239,6 @@ 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; @@ -262,8 +252,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; @@ -559,16 +549,10 @@ 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 d93dc25ac26..d56a9b80f5a 100644 --- a/source/blender/bmesh/intern/bmesh_operators.cc +++ b/source/blender/bmesh/intern/bmesh_operators.cc @@ -295,8 +295,6 @@ 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; } /* @@ -314,7 +312,6 @@ 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) @@ -326,7 +323,6 @@ 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) @@ -338,7 +334,6 @@ 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, @@ -367,7 +362,6 @@ 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], @@ -415,7 +409,6 @@ 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], @@ -429,51 +422,31 @@ 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 std::nullopt; - } - if ((slot->flag & BMO_OP_SLOT_FLAG_IS_SET) == 0) { - return std::nullopt; + return 0.0f; } return slot->data.f; } -std::optional BMO_slot_int_get_optional(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) { 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 std::nullopt; - } - if ((slot->flag & BMO_OP_SLOT_FLAG_IS_SET) == 0) { - return std::nullopt; + return 0; } return slot->data.i; } -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) +bool BMO_slot_bool_get(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); @@ -483,10 +456,6 @@ std::optional BMO_slot_bool_get_optional(BMOpSlot slot_args[BMO_OP_MAX_SLO 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 b0ea5877f5a..f377a0dd269 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.cc +++ b/source/blender/bmesh/operators/bmo_dissolve.cc @@ -387,9 +387,7 @@ 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); - /* 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); + const float angle_threshold = BMO_slot_float_get(op->slots_in, "angle_threshold"); /* 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") && diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 44ff11f9b46..0c1240cb523 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -261,6 +261,11 @@ add_blender_test( --python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_text.py ) +add_blender_test( + script_pyapi_bmesh + --python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_bmesh.py +) + add_blender_test( script_pyapi_grease_pencil --python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_grease_pencil.py diff --git a/tests/python/bl_pyapi_bmesh.py b/tests/python/bl_pyapi_bmesh.py new file mode 100644 index 00000000000..3a7d4e4c5fe --- /dev/null +++ b/tests/python/bl_pyapi_bmesh.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2025 Blender Authors +# +# SPDX-License-Identifier: Apache-2.0 + +# ./blender.bin --background --python tests/python/bl_pyapi_bmesh.py -- --verbose +import bmesh +import unittest + + +class TestBMeshBasic(unittest.TestCase): + + def test_create_uvsphere(self): + bm = bmesh.new() + bmesh.ops.create_uvsphere( + bm, + u_segments=8, + v_segments=5, + radius=1.0, + ) + + self.assertEqual(len(bm.verts), 34) + self.assertEqual(len(bm.edges), 72) + self.assertEqual(len(bm.faces), 40) + + bm.free() + + +if __name__ == "__main__": + import sys + sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []) + unittest.main()