Use temp .blend file copybuffer for pose copy-paste

Uses similar way of storing temp data as object copy paste, just
uses different read entrypoint which does not modify current bmain.

This gives ability to easily copy-paste poses from one blender to
another one.

Hopefully doesn't introduce user-measurable differences.

Request from Peer here in the studio.

Reviewers: mont29

Reviewed By: mont29

Subscribers: hjalti, fsiddi

Differential Revision: https://developer.blender.org/D2229
This commit is contained in:
Sergey Sharybin 2016-09-14 17:50:11 +02:00
parent ec54a08d30
commit fe1342ab9b
5 changed files with 82 additions and 64 deletions

View File

@ -37,6 +37,7 @@ struct ID;
void BKE_copybuffer_begin(struct Main *bmain_src);
void BKE_copybuffer_tag_ID(struct ID *id);
bool BKE_copybuffer_save(struct Main *bmain_src, const char *filename, struct ReportList *reports);
bool BKE_copybuffer_read(struct Main *bmain_dst, const char *libname, struct ReportList *reports);
bool BKE_copybuffer_paste(struct bContext *C, const char *libname, const short flag, struct ReportList *reports);
#ifdef __cplusplus

View File

@ -85,6 +85,31 @@ bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *repo
return retval;
}
bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *reports)
{
BlendHandle *bh = BLO_blendhandle_from_file(libname, reports);
if (bh == NULL) {
/* Error reports will have been made by BLO_blendhandle_from_file(). */
return false;
}
/* Here appending/linking starts. */
Main *mainl = BLO_library_link_begin(bmain_dst, &bh, libname);
BLO_library_link_copypaste(mainl, bh);
BLO_library_link_end(mainl, &bh, 0, NULL, NULL);
/* Mark all library linked objects to be updated. */
BKE_main_lib_objects_recalc_all(bmain_dst);
IMB_colormanagement_check_file_config(bmain_dst);
/* Append, rather than linking. */
Library *lib = BLI_findstring(&bmain_dst->library, libname, offsetof(Library, filepath));
BKE_library_make_local(bmain_dst, lib, true, false);
/* Important we unset, otherwise these object wont
* link into other scenes from this blend file.
*/
BKE_main_id_tag_all(bmain_dst, LIB_TAG_PRE_EXISTING, false);
BLO_blendhandle_close(bh);
return true;
}
/**
* \return Success.
*/

View File

@ -39,7 +39,9 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_appdir.h"
#include "BKE_armature.h"
#include "BKE_blender_copybuffer.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_depsgraph.h"
@ -248,30 +250,6 @@ void POSE_OT_visual_transform_apply(wmOperatorType *ot)
/* ********************************************** */
/* Copy/Paste */
/* Global copy/paste buffer for pose - cleared on start/end session + before every copy operation */
static bPose *g_posebuf = NULL;
void ED_clipboard_posebuf_free(void)
{
if (g_posebuf) {
bPoseChannel *pchan;
for (pchan = g_posebuf->chanbase.first; pchan; pchan = pchan->next) {
if (pchan->prop) {
IDP_FreeProperty(pchan->prop);
MEM_freeN(pchan->prop);
}
}
/* was copied without constraints */
BLI_freelistN(&g_posebuf->chanbase);
BKE_pose_channels_hash_free(g_posebuf);
MEM_freeN(g_posebuf);
}
g_posebuf = NULL;
}
/* This function is used to indicate that a bone is selected
* and needs to be included in copy buffer (used to be for inserting keys)
*/
@ -436,22 +414,24 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
static int pose_copy_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
/* sanity checking */
char str[FILE_MAX];
/* Sanity checking. */
if (ELEM(NULL, ob, ob->pose)) {
BKE_report(op->reports, RPT_ERROR, "No pose to copy");
return OPERATOR_CANCELLED;
}
/* free existing pose buffer */
ED_clipboard_posebuf_free();
/* sets chan->flag to POSE_KEY if bone selected, then copy those bones to the buffer */
set_pose_keys(ob);
BKE_pose_copy_data(&g_posebuf, ob->pose, 0);
/* Sets chan->flag to POSE_KEY if bone selected. */
set_pose_keys(ob);
/* Store the whole object to the copy buffer because pose can't be
* existing on it's own.
*/
BKE_copybuffer_begin(bmain);
BKE_copybuffer_tag_ID(&ob->id);
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer_pose.blend");
BKE_copybuffer_save(bmain, str, op->reports);
BKE_report(op->reports, RPT_INFO, "Copied pose to buffer");
return OPERATOR_FINISHED;
}
@ -479,44 +459,60 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
bPoseChannel *chan;
const bool flip = RNA_boolean_get(op->ptr, "flipped");
bool selOnly = RNA_boolean_get(op->ptr, "selected_mask");
/* get KeyingSet to use */
/* Get KeyingSet to use. */
KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
/* sanity checks */
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
if (g_posebuf == NULL) {
BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty");
/* Sanity checks. */
if (ELEM(NULL, ob, ob->pose)) {
return OPERATOR_CANCELLED;
}
/* if selOnly option is enabled, if user hasn't selected any bones,
* just go back to default behavior to be more in line with other pose tools
/* Read copy buffer .blend file. */
char str[FILE_MAX];
Main *tmp_bmain = BKE_main_new();
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer_pose.blend");
if (!BKE_copybuffer_read(tmp_bmain, str, op->reports)) {
BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty");
BKE_main_free(tmp_bmain);
return OPERATOR_CANCELLED;
}
/* Make sure data from this file is usable for pose paste. */
if (BLI_listbase_count_ex(&tmp_bmain->object, 2) != 1) {
BKE_report(op->reports, RPT_ERROR, "Copy buffer is not from pose mode");
BKE_main_free(tmp_bmain);
return OPERATOR_CANCELLED;
}
Object *object_from = tmp_bmain->object.first;
bPose *pose_from = object_from->pose;
if (pose_from == NULL) {
BKE_report(op->reports, RPT_ERROR, "Copy buffer has no pose");
BKE_main_free(tmp_bmain);
return OPERATOR_CANCELLED;
}
/* If selOnly option is enabled, if user hasn't selected any bones,
* just go back to default behavior to be more in line with other
* pose tools.
*/
if (selOnly) {
if (CTX_DATA_COUNT(C, selected_pose_bones) == 0)
selOnly = 0;
if (CTX_DATA_COUNT(C, selected_pose_bones) == 0) {
selOnly = false;
}
}
/* Safely merge all of the channels in the buffer pose into any existing pose */
for (chan = g_posebuf->chanbase.first; chan; chan = chan->next) {
/* Safely merge all of the channels in the buffer pose into any
* existing pose.
*/
for (chan = pose_from->chanbase.first; chan; chan = chan->next) {
if (chan->flag & POSE_KEY) {
/* try to perform paste on this bone */
/* Try to perform paste on this bone. */
bPoseChannel *pchan = pose_bone_do_paste(ob, chan, selOnly, flip);
if (pchan) {
/* keyframing tagging for successful paste */
if (pchan != NULL) {
/* Keyframing tagging for successful paste, */
ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
}
}
}
/* Update event for pose and deformation children */
BKE_main_free(tmp_bmain);
/* Update event for pose and deformation children. */
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* notifiers for updates */
/* Notifiers for updates, */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
return OPERATOR_FINISHED;

View File

@ -78,9 +78,6 @@ void undo_editmode_push(struct bContext *C, const char *name,
void undo_editmode_clear(void);
/* cut-paste buffer free */
void ED_clipboard_posebuf_free(void);
/* ************** XXX OLD CRUFT WARNING ************* */
void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert);

View File

@ -527,7 +527,6 @@ void WM_exit_ext(bContext *C, const bool do_python)
ANIM_fmodifiers_copybuf_free();
ED_gpencil_anim_copybuf_free();
ED_gpencil_strokes_copybuf_free();
ED_clipboard_posebuf_free();
BKE_node_clipboard_clear();
BLF_exit();