Merge branch 'blender-v4.5-release'
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <optional>
|
||||
|
||||
#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<float> 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<int> 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<bool> BMO_slot_bool_get_optional(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
|
||||
const char *slot_name);
|
||||
/**
|
||||
* Return a copy of the element buffer.
|
||||
*/
|
||||
|
||||
@@ -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<float(*)[4]>(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<float> 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<int> 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<bool> 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<bool> 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)
|
||||
{
|
||||
|
||||
@@ -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") &&
|
||||
|
||||
@@ -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
|
||||
|
||||
31
tests/python/bl_pyapi_bmesh.py
Normal file
31
tests/python/bl_pyapi_bmesh.py
Normal file
@@ -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()
|
||||
Reference in New Issue
Block a user