Compare commits

...

11 Commits

Author SHA1 Message Date
576680aa57 Actually remove RNA wrapper of PoseBackup
This should have gone with the previous commit.
2023-01-02 15:41:17 +01:00
8d1cc1168c Refactor the pose backup API so the Python side doesn't need a pointer
Refactor the pose backup API so the Python side doesn't need a pointer to
a `PoseBackup` struct. That struct also doesn't need an RNA wrapper any
more. RNA now only exposes the functions to use the stored-on-object
pointer.
2023-01-02 15:40:39 +01:00
8cd19d848c Cleanup: RNA documentation improvements 2023-01-02 15:23:29 +01:00
b3586be0f4 Cleanup: update Object_Runtime::pose_backup documentation 2023-01-02 14:58:54 +01:00
846bb70cd8 Refactor: rename the DNA field from temp_pose_backup to pose_backup
Rename the pose backup DNA field from `temp_pose_backup` to `pose_backup`.
Having `temp_` in there doesn't mean much, so it's better to just remove
it.

No functional changes
2023-01-02 14:58:50 +01:00
e3324f97e3 Pose backup: clear pose backup when object is freed
Automatically clear any pose backup owned by the object when the object
is freed.
2023-01-02 14:49:59 +01:00
20e833f4f9 Merge remote-tracking branch 'origin/master' into temp-rbf-pose-blender 2023-01-02 14:47:58 +01:00
c82b0bd220 Let the Object own the pose backup data
Having the Object own the `PoseBackup*` makes it consistent with other
Blender code, and makes it easier to use the functionality from Python.

This isn't complete yet; for that a move from `editors` to `blenkernel`
is needed. That I'll do in the master branch.
2023-01-02 14:27:40 +01:00
1047772789 Add docstring for pose_backup_create
Document the `pose_backup_create()` function.

No functional changes.
2023-01-02 12:03:21 +01:00
18471f0053 Merge remote-tracking branch 'origin/master' into temp-rbf-pose-blender 2023-01-02 11:31:48 +01:00
08d75e464c WIP: expose some pose library functions to RNA
Expose `BKE_pose_apply_action_blend`, `ED_pose_backup_create_all_bones`,
and `ED_pose_backup_restore` to RNA to facilitate an RBF-based pose
blending prototype I'm working on.
2022-12-23 16:20:06 +01:00
5 changed files with 181 additions and 3 deletions

View File

@@ -21,16 +21,47 @@ extern "C" {
struct PoseBackup;
/**
* Create a backup of those bones that are animated in the given action.
* Create a backup of those bones that are selected AND animated in the given action.
*
* The backup is owned by the caller, and should be freed with `BKE_pose_backup_free()`.
*/
struct PoseBackup *BKE_pose_backup_create_selected_bones(
const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT;
/**
* Create a backup of those bones that are animated in the given action.
*
* The backup is owned by the caller, and should be freed with `BKE_pose_backup_free()`.
*/
struct PoseBackup *BKE_pose_backup_create_all_bones(
const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT;
bool BKE_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup);
void BKE_pose_backup_restore(const struct PoseBackup *pbd);
void BKE_pose_backup_free(struct PoseBackup *pbd);
/**
* Create a backup of those bones that are animated in the given action.
*
* The backup is owned by the Object, and there can be only one backup at a time.
* It should be freed with `BKE_pose_backup_clear(ob)`.
*/
void BKE_pose_backup_create_on_object(struct Object *ob, const struct bAction *action);
/**
* Restore the pose backup owned by this OBject.
*
* \return true on success, false if there was no pose backup to restore.
*
* \see #BKE_pose_backup_create_on_object
*/
bool BKE_pose_backup_restore_on_object(struct Object *ob);
/**
* Free the pose backup that was stored on this object's runtime data.
*/
void BKE_pose_backup_clear(struct Object *ob);
#ifdef __cplusplus
}
#endif

View File

@@ -117,6 +117,7 @@
#include "BKE_pbvh.h"
#include "BKE_pointcache.h"
#include "BKE_pointcloud.h"
#include "BKE_pose_backup.h"
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
#include "BKE_shader_fx.h"
@@ -1814,6 +1815,7 @@ void BKE_object_free_derived_caches(Object *ob)
}
BKE_object_to_mesh_clear(ob);
BKE_pose_backup_clear(ob);
BKE_object_to_curve_clear(ob);
BKE_object_free_curve_cache(ob);
@@ -5132,6 +5134,7 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int /*flag*/)
runtime->mesh_deform_eval = nullptr;
runtime->curve_cache = nullptr;
runtime->object_as_temp_mesh = nullptr;
runtime->pose_backup = nullptr;
runtime->object_as_temp_curve = nullptr;
runtime->geometry_set_eval = nullptr;

View File

@@ -38,6 +38,14 @@ struct PoseBackup {
ListBase /* PoseChannelBackup* */ backups;
};
/**
* Create a backup of the pose, for only those bones that are animated in the
* given Action. If `selected_bone_names` is not empty, the set of bones to back
* up is intersected with these bone names such that only the selected subset is
* backed up.
*
* The returned pointer is owned by the caller.
*/
static PoseBackup *pose_backup_create(const Object *ob,
const bAction *action,
const BoneNameSet &selected_bone_names)
@@ -127,3 +135,29 @@ void BKE_pose_backup_free(PoseBackup *pbd)
}
MEM_freeN(pbd);
}
void BKE_pose_backup_create_on_object(Object *ob, const bAction *action)
{
BKE_pose_backup_clear(ob);
PoseBackup *pose_backup = BKE_pose_backup_create_all_bones(ob, action);
ob->runtime.pose_backup = pose_backup;
}
bool BKE_pose_backup_restore_on_object(struct Object *ob)
{
if (ob->runtime.pose_backup == nullptr) {
return false;
}
BKE_pose_backup_restore(ob->runtime.pose_backup);
return true;
}
void BKE_pose_backup_clear(Object *ob)
{
if (ob->runtime.pose_backup == nullptr) {
return;
}
BKE_pose_backup_free(ob->runtime.pose_backup);
ob->runtime.pose_backup = nullptr;
}

View File

@@ -192,6 +192,14 @@ typedef struct Object_Runtime {
*/
struct Mesh *object_as_temp_mesh;
/**
* Backup of the object's pose (might be a subset, i.e. not contain all bones).
*
* Created by `BKE_pose_backup_create_on_object()`. This memory is owned by the Object.
* It is freed along with the object, or when `BKE_pose_backup_clear()` is called.
*/
struct PoseBackup *pose_backup;
/**
* This is a curve representation of corresponding object.
* It created when Python calls `object.to_curve()`.
@@ -200,6 +208,7 @@ typedef struct Object_Runtime {
/** Runtime evaluated curve-specific data, not stored in the file. */
struct CurveCache *curve_cache;
void *_pad4;
unsigned short local_collections_bits;
short _pad2[3];

View File

@@ -25,6 +25,7 @@
# include "BKE_animsys.h"
# include "BKE_armature.h"
# include "BKE_context.h"
# include "BKE_pose_backup.h"
# include "DNA_action_types.h"
# include "DNA_anim_types.h"
@@ -108,6 +109,47 @@ static void rna_Pose_apply_pose_from_action(ID *pose_owner,
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pose_owner);
}
static void rna_Pose_blend_pose_from_action(ID *pose_owner,
bContext *C,
bAction *action,
const float blend_factor,
const float evaluation_time)
{
BLI_assert(GS(pose_owner->name) == ID_OB);
Object *pose_owner_ob = (Object *)pose_owner;
AnimationEvalContext anim_eval_context = {CTX_data_depsgraph_pointer(C), evaluation_time};
BKE_pose_apply_action_blend(pose_owner_ob, action, &anim_eval_context, blend_factor);
/* Do NOT tag with ID_RECALC_ANIMATION, as that would overwrite the just-applied pose. */
DEG_id_tag_update(pose_owner, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pose_owner);
}
static void rna_Pose_backup_create(ID *pose_owner, bAction *action)
{
BLI_assert(GS(pose_owner->name) == ID_OB);
Object *pose_owner_ob = (Object *)pose_owner;
BKE_pose_backup_create_on_object(pose_owner_ob, action);
}
static bool rna_Pose_backup_restore(ID *pose_owner)
{
BLI_assert(GS(pose_owner->name) == ID_OB);
Object *pose_owner_ob = (Object *)pose_owner;
return BKE_pose_backup_restore_on_object(pose_owner_ob);
}
static void rna_Pose_backup_clear(ID *pose_owner)
{
BLI_assert(GS(pose_owner->name) == ID_OB);
Object *pose_owner_ob = (Object *)pose_owner;
BKE_pose_backup_clear(pose_owner_ob);
}
#else
void RNA_api_pose(StructRNA *srna)
@@ -121,10 +163,8 @@ void RNA_api_pose(StructRNA *srna)
func,
"Apply the given action to this pose by evaluating it at a specific time. Only updates the "
"pose of selected bones, or all bones if none are selected.");
parm = RNA_def_pointer(func, "action", "Action", "Action", "The Action containing the pose");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_float(func,
"evaluation_time",
0.0f,
@@ -134,6 +174,67 @@ void RNA_api_pose(StructRNA *srna)
"Time at which the given action is evaluated to obtain the pose",
-FLT_MAX,
FLT_MAX);
func = RNA_def_function(srna, "blend_pose_from_action", "rna_Pose_blend_pose_from_action");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF | FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func,
"Blend the given action into this pose by evaluating it at a "
"specific time. Only updates the "
"pose of selected bones, or all bones if none are selected.");
parm = RNA_def_pointer(func, "action", "Action", "Action", "The Action containing the pose");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_float(func,
"blend_factor",
1.0f,
0.0f,
1.0f,
"Blend Factor",
"How much the given Action affects the final pose",
0.0f,
1.0f);
parm = RNA_def_float(func,
"evaluation_time",
0.0f,
-FLT_MAX,
FLT_MAX,
"Evaluation Time",
"Time at which the given action is evaluated to obtain the pose",
-FLT_MAX,
FLT_MAX);
func = RNA_def_function(srna, "backup_create", "rna_Pose_backup_create");
RNA_def_function_ui_description(
func,
"Create a backup of the current pose. Only those bones that are animated in the Action are "
"backed up. The object owns the backup, and each object can have only one backup at a time. "
"When you no longer need it, it must be freed use `backup_clear()`.");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
parm = RNA_def_pointer(func,
"action",
"Action",
"Action",
"An Action with animation data for the bones. Only the animated bones "
"will be included in the backup.");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
func = RNA_def_function(srna, "backup_restore", "rna_Pose_backup_restore");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
RNA_def_function_ui_description(func,
"Restore the previously made pose backup. This can be called "
"multiple times. See `Pose.backup_create()` for more info.");
/* return value */
parm = RNA_def_boolean(
func,
"success",
false,
"",
"`True` when the backup was restored, `False` if there was no backup to restore.");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "backup_clear", "rna_Pose_backup_clear");
RNA_def_function_ui_description(
func, "Free a previously made pose backup. See `Pose.backup_create()` for more info.");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
}
void RNA_api_pose_channel(StructRNA *srna)