Blender V5.0
rna_pose_api.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdlib>
10#include <cstring>
11#include <ctime>
12
13#include "RNA_define.hh"
14
15/* #include "BLI_sys_types.h" */
16
17#include "rna_internal.hh" /* own include */
18
19using namespace blender;
20
21#ifdef RNA_RUNTIME
22
23# include "BKE_animsys.h"
24# include "BKE_armature.hh"
25# include "BKE_context.hh"
26# include "BKE_pose_backup.h"
27
28# include "DNA_action_types.h"
29# include "DNA_anim_types.h"
30
31# include "BLI_ghash.h"
32# include "BLI_math_matrix.h"
33
34# include "ANIM_action.hh"
35# include "ANIM_pose.hh"
36
37static float rna_PoseBone_do_envelope(bPoseChannel *chan, const float vec[3])
38{
39 Bone *bone = chan->bone;
40
41 float scale = (bone->flag & BONE_MULT_VG_ENV) == BONE_MULT_VG_ENV ? bone->weight : 1.0f;
42
43 return distfactor_to_bone(vec,
44 chan->pose_head,
45 chan->pose_tail,
46 bone->rad_head * scale,
47 bone->rad_tail * scale,
48 bone->dist * scale);
49}
50
51static void rna_PoseBone_bbone_segment_index(
52 bPoseChannel *pchan, ReportList *reports, const float pt[3], int *r_index, float *r_blend_next)
53{
54 if (!pchan->bone || pchan->bone->segments <= 1) {
55 BKE_reportf(reports, RPT_ERROR, "Bone '%s' is not a B-Bone!", pchan->name);
56 return;
57 }
58 if (pchan->runtime.bbone_segments != pchan->bone->segments) {
59 BKE_reportf(reports,
61 "Bone '%s' has out of date B-Bone segment data - depsgraph update required!",
62 pchan->name);
63 return;
64 }
65
66 BKE_pchan_bbone_deform_segment_index(pchan, pt, r_index, r_blend_next);
67}
68
69static void rna_PoseBone_bbone_segment_matrix(
70 bPoseChannel *pchan, ReportList *reports, float mat_ret[16], int index, bool rest)
71{
72 if (!pchan->bone || pchan->bone->segments <= 1) {
73 BKE_reportf(reports, RPT_ERROR, "Bone '%s' is not a B-Bone!", pchan->name);
74 return;
75 }
76 if (pchan->runtime.bbone_segments != pchan->bone->segments) {
77 BKE_reportf(reports,
79 "Bone '%s' has out of date B-Bone segment data - depsgraph update required!",
80 pchan->name);
81 return;
82 }
83 if (index < 0 || index > pchan->runtime.bbone_segments) {
85 reports, RPT_ERROR, "Invalid index %d for B-Bone segments of '%s'!", index, pchan->name);
86 return;
87 }
88
89 if (rest) {
90 copy_m4_m4((float (*)[4])mat_ret, pchan->runtime.bbone_rest_mats[index].mat);
91 }
92 else {
93 copy_m4_m4((float (*)[4])mat_ret, pchan->runtime.bbone_pose_mats[index].mat);
94 }
95}
96
97static void rna_PoseBone_compute_bbone_handles(bPoseChannel *pchan,
98 ReportList *reports,
99 float ret_h1[3],
100 float *ret_roll1,
101 float ret_h2[3],
102 float *ret_roll2,
103 bool rest,
104 bool ease,
105 bool offsets)
106{
107 if (!pchan->bone || pchan->bone->segments <= 1) {
108 BKE_reportf(reports, RPT_ERROR, "Bone '%s' is not a B-Bone!", pchan->name);
109 return;
110 }
111
113
116 &params, ret_h1, ret_roll1, ret_h2, ret_roll2, ease || offsets, offsets);
117}
118
119static void rna_Pose_apply_pose_from_action(ID *pose_owner,
120 bContext *C,
121 bAction *action,
122 const float evaluation_time)
123{
124 BLI_assert(GS(pose_owner->name) == ID_OB);
125 Object *pose_owner_ob = (Object *)pose_owner;
126
127 AnimationEvalContext anim_eval_context = {CTX_data_depsgraph_pointer(C), evaluation_time};
128 animrig::pose_apply_action({pose_owner_ob}, action->wrap(), &anim_eval_context, 1.0);
129
130 /* Do NOT tag with ID_RECALC_ANIMATION, as that would overwrite the just-applied pose. */
133}
134
135static void rna_Pose_blend_pose_from_action(ID *pose_owner,
136 bContext *C,
137 bAction *action,
138 const float blend_factor,
139 const float evaluation_time)
140{
141 BLI_assert(GS(pose_owner->name) == ID_OB);
142 Object *pose_owner_ob = (Object *)pose_owner;
143
144 AnimationEvalContext anim_eval_context = {CTX_data_depsgraph_pointer(C), evaluation_time};
145 animrig::pose_apply_action({pose_owner_ob}, action->wrap(), &anim_eval_context, blend_factor);
146
147 /* Do NOT tag with ID_RECALC_ANIMATION, as that would overwrite the just-applied pose. */
150}
151
152static void rna_Pose_backup_create(ID *pose_owner, bAction *action)
153{
154 BLI_assert(GS(pose_owner->name) == ID_OB);
155 if (!action || action->wrap().slot_array_num == 0) {
156 /* A pose asset without slots has no data, this usually doesn't happen but can happen by
157 * tagging an empty action as a pose asset. */
158 return;
159 }
160 Object *pose_owner_ob = (Object *)pose_owner;
161 BKE_pose_backup_create_on_object(pose_owner_ob, action);
162}
163
164static bool rna_Pose_backup_restore(ID *pose_owner, bContext *C)
165{
166 BLI_assert(GS(pose_owner->name) == ID_OB);
167 Object *pose_owner_ob = (Object *)pose_owner;
168
169 const bool success = BKE_pose_backup_restore_on_object(pose_owner_ob);
170 if (!success) {
171 return false;
172 }
173
174 /* Do NOT tag with ID_RECALC_ANIMATION, as that would overwrite the just-applied pose. */
177
178 return true;
179}
180
181static void rna_Pose_backup_clear(ID *pose_owner)
182{
183 BLI_assert(GS(pose_owner->name) == ID_OB);
184 Object *pose_owner_ob = (Object *)pose_owner;
185
186 BKE_pose_backup_clear(pose_owner_ob);
187}
188
189#else
190
192{
193 FunctionRNA *func;
194 PropertyRNA *parm;
195
196 func = RNA_def_function(srna, "apply_pose_from_action", "rna_Pose_apply_pose_from_action");
199 func,
200 "Apply the given action to this pose by evaluating it at a specific time. Only updates the "
201 "pose of selected bones, or all bones if none are selected.");
202 parm = RNA_def_pointer(func, "action", "Action", "Action", "The Action containing the pose");
204 parm = RNA_def_float(func,
205 "evaluation_time",
206 0.0f,
207 -FLT_MAX,
208 FLT_MAX,
209 "Evaluation Time",
210 "Time at which the given action is evaluated to obtain the pose",
211 -FLT_MAX,
212 FLT_MAX);
213
214 func = RNA_def_function(srna, "blend_pose_from_action", "rna_Pose_blend_pose_from_action");
217 "Blend the given action into this pose by evaluating it at a "
218 "specific time. Only updates the "
219 "pose of selected bones, or all bones if none are selected.");
220 parm = RNA_def_pointer(func, "action", "Action", "Action", "The Action containing the pose");
222 RNA_def_float(func,
223 "blend_factor",
224 1.0f,
225 0.0f,
226 1.0f,
227 "Blend Factor",
228 "How much the given Action affects the final pose",
229 0.0f,
230 1.0f);
231 RNA_def_float(func,
232 "evaluation_time",
233 0.0f,
234 -FLT_MAX,
235 FLT_MAX,
236 "Evaluation Time",
237 "Time at which the given action is evaluated to obtain the pose",
238 -FLT_MAX,
239 FLT_MAX);
240
241 func = RNA_def_function(srna, "backup_create", "rna_Pose_backup_create");
243 func,
244 "Create a backup of the current pose. Only those bones that are animated in the Action are "
245 "backed up. The object owns the backup, and each object can have only one backup at a time. "
246 "When you no longer need it, it must be freed use ``backup_clear()``.");
248 parm = RNA_def_pointer(func,
249 "action",
250 "Action",
251 "Action",
252 "An Action with animation data for the bones. "
253 "Only the animated bones will be included in the backup.");
255
256 func = RNA_def_function(srna, "backup_restore", "rna_Pose_backup_restore");
259 func,
260 "Restore the previously made pose backup. "
261 "This can be called multiple times. See ``Pose.backup_create()`` for more info.");
262 /* return value */
263 parm = RNA_def_boolean(
264 func,
265 "success",
266 false,
267 "",
268 "``True`` when the backup was restored, ``False`` if there was no backup to restore");
269 RNA_def_function_return(func, parm);
270
271 func = RNA_def_function(srna, "backup_clear", "rna_Pose_backup_clear");
273 func, "Free a previously made pose backup. See ``Pose.backup_create()`` for more info.");
275}
276
278{
279 PropertyRNA *parm;
280 FunctionRNA *func;
281
282 func = RNA_def_function(srna, "evaluate_envelope", "rna_PoseBone_do_envelope");
283 RNA_def_function_ui_description(func, "Calculate bone envelope at given point");
284 parm = RNA_def_float_vector_xyz(func,
285 "point",
286 3,
287 nullptr,
288 -FLT_MAX,
289 FLT_MAX,
290 "Point",
291 "Position in 3d space to evaluate",
292 -FLT_MAX,
293 FLT_MAX);
295 /* return value */
296 parm = RNA_def_float(
297 func, "factor", 0, -FLT_MAX, FLT_MAX, "Factor", "Envelope factor", -FLT_MAX, FLT_MAX);
298 RNA_def_function_return(func, parm);
299
300 /* B-Bone segment index from point */
301 func = RNA_def_function(srna, "bbone_segment_index", "rna_PoseBone_bbone_segment_index");
304 func, "Retrieve the index and blend factor of the B-Bone segments based on vertex position");
305 parm = RNA_def_float_vector_xyz(func,
306 "point",
307 3,
308 nullptr,
309 -FLT_MAX,
310 FLT_MAX,
311 "Point",
312 "Vertex position in armature pose space",
313 -FLT_MAX,
314 FLT_MAX);
316 /* outputs */
317 parm = RNA_def_property(func, "index", PROP_INT, PROP_NONE);
318 RNA_def_property_ui_text(parm, "", "The index of the first segment joint affecting the point");
319 RNA_def_function_output(func, parm);
320 parm = RNA_def_property(func, "blend_next", PROP_FLOAT, PROP_NONE);
321 RNA_def_property_ui_text(parm, "", "The blend factor between the given and the following joint");
322 RNA_def_function_output(func, parm);
323
324 /* B-Bone segment matrices */
325 func = RNA_def_function(srna, "bbone_segment_matrix", "rna_PoseBone_bbone_segment_matrix");
327 func, "Retrieve the matrix of the joint between B-Bone segments if available");
329 parm = RNA_def_property(func, "matrix_return", PROP_FLOAT, PROP_MATRIX);
331 RNA_def_property_ui_text(parm, "", "The resulting matrix in bone local space");
332 RNA_def_function_output(func, parm);
333 parm = RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the segment endpoint", 0, 10000);
335 parm = RNA_def_boolean(func, "rest", false, "", "Return the rest pose matrix");
336
337 /* B-Bone custom handle positions */
338 func = RNA_def_function(srna, "compute_bbone_handles", "rna_PoseBone_compute_bbone_handles");
340 func, "Retrieve the vectors and rolls coming from B-Bone custom handles");
342 parm = RNA_def_property(func, "handle1", PROP_FLOAT, PROP_XYZ);
343 RNA_def_property_array(parm, 3);
345 parm, "", "The direction vector of the start handle in bone local space");
346 RNA_def_function_output(func, parm);
347 parm = RNA_def_float(
348 func, "roll1", 0, -FLT_MAX, FLT_MAX, "", "Roll of the start handle", -FLT_MAX, FLT_MAX);
349 RNA_def_function_output(func, parm);
350 parm = RNA_def_property(func, "handle2", PROP_FLOAT, PROP_XYZ);
351 RNA_def_property_array(parm, 3);
352 RNA_def_property_ui_text(parm, "", "The direction vector of the end handle in bone local space");
353 RNA_def_function_output(func, parm);
354 parm = RNA_def_float(
355 func, "roll2", 0, -FLT_MAX, FLT_MAX, "", "Roll of the end handle", -FLT_MAX, FLT_MAX);
356 RNA_def_function_output(func, parm);
357 parm = RNA_def_boolean(func, "rest", false, "", "Return the rest pose state");
358 parm = RNA_def_boolean(func, "ease", false, "", "Apply scale from ease values");
359 parm = RNA_def_boolean(
360 func, "offsets", false, "", "Apply roll and curve offsets from bone properties");
361}
362
363#endif
Functions and classes to work with Actions.
Functions to work with animation poses.
void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan, const float *co, int *r_index, float *r_blend_next)
void BKE_pchan_bbone_spline_params_get(bPoseChannel *pchan, bool rest, BBoneSplineParameters *param)
float distfactor_to_bone(const blender::float3 &position, const blender::float3 &head, const blender::float3 &tail, float radius_head, float radius_tail, float falloff_distance)
void BKE_pchan_bbone_handles_compute(const BBoneSplineParameters *param, float h1[3], float *r_roll1, float h2[3], float *r_roll2, bool ease, bool offsets)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
void BKE_pose_backup_create_on_object(struct Object *ob, const struct bAction *action)
void BKE_pose_backup_clear(struct Object *ob)
bool BKE_pose_backup_restore_on_object(struct Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_ERROR
Definition BKE_report.hh:39
#define BLI_assert(a)
Definition BLI_assert.h:46
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ ID_OB
@ BONE_MULT_VG_ENV
@ PARM_REQUIRED
Definition RNA_types.hh:545
@ FUNC_USE_REPORTS
Definition RNA_types.hh:914
@ FUNC_NO_SELF
Definition RNA_types.hh:907
@ FUNC_USE_CONTEXT
Definition RNA_types.hh:913
@ FUNC_USE_SELF_ID
Definition RNA_types.hh:889
@ PROP_FLOAT
Definition RNA_types.hh:164
@ PROP_INT
Definition RNA_types.hh:163
PropertyFlag
Definition RNA_types.hh:300
@ PROP_MATRIX
Definition RNA_types.hh:265
@ PROP_XYZ
Definition RNA_types.hh:269
@ PROP_NONE
Definition RNA_types.hh:233
#define C
Definition RandGen.cpp:29
#define ND_POSE
Definition WM_types.hh:458
#define NC_OBJECT
Definition WM_types.hh:379
#define GS(x)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void pose_apply_action(blender::Span< Object * > objects, Action &pose_action, const AnimationEvalContext *anim_eval_context, float blend_factor)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret)
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int length[])
PropertyRNA * RNA_def_float_vector_xyz(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
FunctionRNA * RNA_def_function(StructRNA *srna, const char *identifier, const char *call)
void RNA_def_property_array(PropertyRNA *prop, int length)
PropertyRNA * RNA_def_pointer(StructOrFunctionRNA *cont_, const char *identifier, const char *type, const char *ui_name, const char *ui_description)
void RNA_def_function_ui_description(FunctionRNA *func, const char *description)
const int rna_matrix_dimsize_4x4[]
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
void RNA_def_function_flag(FunctionRNA *func, int flag)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_function_output(FunctionRNA *, PropertyRNA *ret)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
void RNA_def_parameter_flags(PropertyRNA *prop, PropertyFlag flag_property, ParameterFlag flag_parameter)
void RNA_api_pose(StructRNA *srna)
void RNA_api_pose_channel(StructRNA *srna)
#define FLT_MAX
Definition stdcycles.h:14
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
float mat[4][4]
struct Mat4 * bbone_pose_mats
struct Mat4 * bbone_rest_mats
struct Bone * bone
struct bPoseChannel_Runtime runtime
void WM_event_add_notifier(const bContext *C, uint type, void *reference)