Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Susano Pinto <andresusanopinto@gmail.com>2009-09-28 17:05:03 +0400
committerAndre Susano Pinto <andresusanopinto@gmail.com>2009-09-28 17:05:03 +0400
commit04fdec2017461bc9f85b24a74782e6049c0f2df9 (patch)
tree067534fc2edf9b9efb956798c240072defd5bfbe /source/blender/editors/armature
parent82198721d6996d03df5d384fde2c155e998bc56e (diff)
parent8f07d27de729dbe7a6d8a861a87cd7179f601431 (diff)
svn merge -r 23207:23528 https://svn.blender.org/svnroot/bf-blender/trunk/blender
Diffstat (limited to 'source/blender/editors/armature')
-rw-r--r--source/blender/editors/armature/armature_intern.h8
-rw-r--r--source/blender/editors/armature/armature_ops.c32
-rw-r--r--source/blender/editors/armature/editarmature.c30
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c2
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c12
-rw-r--r--source/blender/editors/armature/meshlaplacian.c6
-rw-r--r--source/blender/editors/armature/poseSlide.c936
-rw-r--r--source/blender/editors/armature/poselib.c11
-rw-r--r--source/blender/editors/armature/poseobject.c188
9 files changed, 1019 insertions, 206 deletions
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index 0c8c0e8e644..6f5a5f44d87 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -118,12 +118,20 @@ void SKETCH_OT_select(struct wmOperatorType *ot);
/* ******************************************************* */
/* PoseLib */
+
void POSELIB_OT_pose_add(struct wmOperatorType *ot);
void POSELIB_OT_pose_remove(struct wmOperatorType *ot);
void POSELIB_OT_pose_rename(struct wmOperatorType *ot);
void POSELIB_OT_browse_interactive(struct wmOperatorType *ot);
/* ******************************************************* */
+/* Pose Sliding Tools */
+
+void POSE_OT_push(struct wmOperatorType *ot);
+void POSE_OT_relax(struct wmOperatorType *ot);
+void POSE_OT_breakdown(struct wmOperatorType *ot);
+
+/* ******************************************************* */
/* editarmature.c */
struct bArmature;
struct EditBone;
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index 389a0a5174a..fae0b093551 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -196,17 +196,23 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(POSELIB_OT_pose_remove);
WM_operatortype_append(POSELIB_OT_pose_rename);
+ /* POSE SLIDING */
+ WM_operatortype_append(POSE_OT_push);
+ WM_operatortype_append(POSE_OT_relax);
+ WM_operatortype_append(POSE_OT_breakdown);
+
/* TESTS */
WM_operatortype_append(ARMATURE_OT_test); // XXX temp test for context iterators... to be removed
}
void ED_keymap_armature(wmWindowManager *wm)
{
- ListBase *keymap;
+ wmKeyMap *keymap;
wmKeymapItem *kmi;
/* Armature ------------------------ */
- keymap= WM_keymap_listbase(wm, "Armature", 0, 0);
+ keymap= WM_keymap_find(wm, "Armature", 0, 0);
+ keymap->poll= ED_operator_editarmature;
/* only set in editmode armature, by space_view3d listener */
// WM_keymap_add_item(keymap, "ARMATURE_OT_hide", HKEY, KM_PRESS, 0, 0);
@@ -278,9 +284,22 @@ void ED_keymap_armature(wmWindowManager *wm)
WM_keymap_add_item(keymap, "SKETCH_OT_cancel_stroke", ESCKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ /* sketch poll checks mode */
+ WM_keymap_add_item(keymap, "SKETCH_OT_gesture", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "snap", 1);
+ WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "snap", 1);
+
/* Pose ------------------------ */
/* only set in posemode, by space_view3d listener */
- keymap= WM_keymap_listbase(wm, "Pose", 0, 0);
+ keymap= WM_keymap_find(wm, "Pose", 0, 0);
+ keymap->poll= ED_operator_posemode;
+
+ // XXX: set parent is object-based operator, but it should also be available here...
+ WM_keymap_add_item(keymap, "OBJECT_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, 0, 0);
kmi= WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
@@ -294,7 +313,6 @@ void ED_keymap_armature(wmWindowManager *wm)
WM_keymap_add_item(keymap, "POSE_OT_loc_clear", GKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "POSE_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0);
- // for now, we include hotkeys for copy/paste
WM_keymap_add_item(keymap, "POSE_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
kmi= WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
@@ -354,5 +372,11 @@ void ED_keymap_armature(wmWindowManager *wm)
WM_keymap_add_item(keymap, "POSELIB_OT_pose_add", LKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSELIB_OT_pose_remove", LKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "POSELIB_OT_pose_rename", LKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+
+ /* Pose -> Pose Sliding ------------- */
+ /* only set in posemode, by space_view3d listener */
+ WM_keymap_add_item(keymap, "POSE_OT_push", EKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "POSE_OT_relax", EKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "POSE_OT_breakdown", EKEY, KM_PRESS, KM_SHIFT, 0);
}
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
index 7d196d23c98..402715dbb02 100644
--- a/source/blender/editors/armature/editarmature.c
+++ b/source/blender/editors/armature/editarmature.c
@@ -1736,7 +1736,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op)
ED_armature_sync_selection(arm->edbo);
- WM_event_add_notifier(C, NC_OBJECT, obedit);
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
return OPERATOR_FINISHED;
}
@@ -2539,6 +2539,8 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, ListBase *edit
VECCOPY(channew->limitmax, chanold->limitmax);
VECCOPY(channew->stiffness, chanold->stiffness);
channew->ikstretch= chanold->ikstretch;
+ channew->ikrotweight= chanold->ikrotweight;
+ channew->iklinweight= chanold->iklinweight;
/* constraints */
listnew = &channew->constraints;
@@ -2630,6 +2632,9 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
/* copy transform locks */
channew->protectflag = chanold->protectflag;
+ /* copy rotation mode */
+ channew->rotmode = chanold->rotmode;
+
/* copy bone group */
channew->agrp_index= chanold->agrp_index;
@@ -2639,6 +2644,8 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
VECCOPY(channew->limitmax, chanold->limitmax);
VECCOPY(channew->stiffness, chanold->stiffness);
channew->ikstretch= chanold->ikstretch;
+ channew->ikrotweight= chanold->ikrotweight;
+ channew->iklinweight= chanold->iklinweight;
/* constraints */
listnew = &channew->constraints;
@@ -3441,7 +3448,8 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
else
VecAddf(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
- WM_event_add_notifier(C, NC_OBJECT, obedit);
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
return OPERATOR_FINISHED;
}
@@ -3930,7 +3938,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op)
ED_armature_sync_selection(arm->edbo);
/* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
return OPERATOR_FINISHED;
}
@@ -4330,7 +4338,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
}
/* in weightpaint we select the associated vertex group too */
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (OBACT && OBACT->mode & OB_MODE_WEIGHT_PAINT) {
if (nearBone->flag & BONE_ACTIVE) {
ED_vgroup_select_by_name(OBACT, nearBone->name);
DAG_id_flush_update(&OBACT->id, OB_RECALC_DATA);
@@ -4854,7 +4862,7 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
if (pchan->protectflag & OB_LOCK_ROT4D) {
/* perform clamping on a component by component basis */
if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
- pchan->quat[0]= (pchan->rotmode == PCHAN_ROT_AXISANGLE) ? 0.0f : 1.0f;
+ pchan->quat[0]= (pchan->rotmode == ROT_MODE_AXISANGLE) ? 0.0f : 1.0f;
if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
pchan->quat[1]= 0.0f;
if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
@@ -4866,11 +4874,11 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
/* perform clamping using euler form (3-components) */
float eul[3], oldeul[3], quat1[4];
- if (pchan->rotmode == PCHAN_ROT_QUAT) {
+ if (pchan->rotmode == ROT_MODE_QUAT) {
QUATCOPY(quat1, pchan->quat);
QuatToEul(pchan->quat, oldeul);
}
- else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
}
else {
@@ -4886,14 +4894,14 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
if (pchan->protectflag & OB_LOCK_ROTZ)
eul[2]= oldeul[2];
- if (pchan->rotmode == PCHAN_ROT_QUAT) {
+ if (pchan->rotmode == ROT_MODE_QUAT) {
EulToQuat(eul, pchan->quat);
/* quaternions flip w sign to accumulate rotations correctly */
if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
QuatMulf(pchan->quat, -1.0f);
}
}
- else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
}
else {
@@ -4902,11 +4910,11 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
}
}
else {
- if (pchan->rotmode == PCHAN_ROT_QUAT) {
+ if (pchan->rotmode == ROT_MODE_QUAT) {
pchan->quat[1]=pchan->quat[2]=pchan->quat[3]= 0.0f;
pchan->quat[0]= 1.0f;
}
- else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
/* by default, make rotation of 0 radians around y-axis (roll) */
pchan->quat[0]=pchan->quat[1]=pchan->quat[3]= 0.0f;
pchan->quat[2]= 1.0f;
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index 16e78f7c8d1..4d65059c4c6 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -2716,7 +2716,6 @@ static void finishRetarget(RigGraph *rigg)
static void adjustGraphs(bContext *C, RigGraph *rigg)
{
- Scene *scene = CTX_data_scene(C);
bArmature *arm= rigg->ob->data;
RigArc *arc;
@@ -2739,7 +2738,6 @@ static void adjustGraphs(bContext *C, RigGraph *rigg)
static void retargetGraphs(bContext *C, RigGraph *rigg)
{
- Scene *scene = CTX_data_scene(C);
bArmature *arm= rigg->ob->data;
ReebGraph *reebg = rigg->link_mesh;
RigNode *inode;
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index 79d3d7b1366..74876691dac 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -1814,7 +1814,7 @@ int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
- angle = VecAngle2(s1, s2);
+ angle = RAD2DEG(VecAngle2(s1, s2));
if (angle > 60 && angle < 120)
{
@@ -1932,7 +1932,7 @@ int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
- angle = VecAngle2(s1, s2);
+ angle = RAD2DEG(VecAngle2(s1, s2));
if (angle > 120)
{
@@ -2064,7 +2064,7 @@ int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p);
}
- angle = VecAngle2(start_v, end_v);
+ angle = RAD2DEG(VecAngle2(start_v, end_v));
if (angle > 120)
{
@@ -2618,7 +2618,7 @@ static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event)
sk_draw_stroke(C, sketch, sketch->active_stroke, dd, snap);
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -2644,7 +2644,7 @@ static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event)
sk_start_draw_gesture(sketch);
sk_draw_stroke(C, sketch, sketch->gesture, dd, snap);
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -2675,7 +2675,7 @@ static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short
retval = OPERATOR_CANCELLED;
break;
case LEFTMOUSE:
- if (event->val == 0)
+ if (event->val == KM_RELEASE)
{
if (gesture == 0)
{
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 436048f5427..82843a49851 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -177,9 +177,9 @@ static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3
t2= cotan_weight(v2, v3, v1);
t3= cotan_weight(v3, v1, v2);
- if(VecAngle3(v2, v1, v3) > 90) obtuse= 1;
- else if(VecAngle3(v1, v2, v3) > 90) obtuse= 2;
- else if(VecAngle3(v1, v3, v2) > 90) obtuse= 3;
+ if(RAD2DEG(VecAngle3(v2, v1, v3)) > 90) obtuse= 1;
+ else if(RAD2DEG(VecAngle3(v1, v2, v3)) > 90) obtuse= 2;
+ else if(RAD2DEG(VecAngle3(v1, v3, v2)) > 90) obtuse= 3;
if (obtuse > 0) {
area= AreaT3Dfl(v1, v2, v3);
diff --git a/source/blender/editors/armature/poseSlide.c b/source/blender/editors/armature/poseSlide.c
new file mode 100644
index 00000000000..c73208c54c2
--- /dev/null
+++ b/source/blender/editors/armature/poseSlide.c
@@ -0,0 +1,936 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009, Blender Foundation, Joshua Leung
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+#include "BLI_dlrbTree.h"
+
+#include "DNA_listBase.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_object.h"
+
+#include "BKE_global.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "BIF_gl.h"
+
+#include "ED_anim_api.h"
+#include "ED_armature.h"
+#include "ED_keyframes_draw.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+
+#include "armature_intern.h"
+
+/* **************************************************** */
+/* == POSE 'SLIDING' TOOLS ==
+ *
+ * A) Push & Relax, Breakdowner
+ * These tools provide the animator with various capabilities
+ * for interactively controlling the spacing of poses, but also
+ * for 'pushing' and/or 'relaxing' extremes as they see fit.
+ *
+ * B) Pose Sculpting
+ * This is yet to be implemented, but the idea here is to use
+ * sculpting techniques to make it easier to pose rigs by allowing
+ * rigs to be manipulated using a familiar paint-based interface.
+ */
+/* **************************************************** */
+/* A) Push & Relax, Breakdowner */
+
+/* Temporary data shared between these operators */
+typedef struct tPoseSlideOp {
+ Scene *scene; /* current scene */
+ ARegion *ar; /* region that we're operating in (needed for */
+ Object *ob; /* active object that Pose Info comes from */
+ bArmature *arm; /* armature for pose */
+
+ ListBase pfLinks; /* links between posechannels and f-curves */
+ DLRBT_Tree keys; /* binary tree for quicker searching for keyframes (when applicable) */
+
+ KeyingSet *ks_loc; /* builtin KeyingSet for keyframing locations */
+ KeyingSet *ks_rot; /* builtin KeyingSet for keyframing rotations */
+ KeyingSet *ks_scale;/* builtin KeyingSet for keyframing scale */
+
+ int cframe; /* current frame number */
+ int prevFrame; /* frame before current frame (blend-from) */
+ int nextFrame; /* frame after current frame (blend-to) */
+
+ int mode; /* sliding mode (ePoseSlide_Modes) */
+ int flag; // unused for now, but can later get used for storing runtime settings....
+
+ float percentage; /* 0-1 value for determining the influence of whatever is relevant */
+} tPoseSlideOp;
+
+/* Pose Sliding Modes */
+typedef enum ePoseSlide_Modes {
+ POSESLIDE_PUSH = 0, /* exaggerate the pose... */
+ POSESLIDE_RELAX, /* soften the pose... */
+ POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */
+} ePoseSlide_Modes;
+
+/* Temporary data linking PoseChannels with the F-Curves they affect */
+typedef struct tPChanFCurveLink {
+ struct tPChanFCurveLink *next, *prev;
+
+ ListBase fcurves; /* F-Curves for this PoseChannel */
+ bPoseChannel *pchan; /* Pose Channel which data is attached to */
+
+ char *pchan_path; /* RNA Path to this Pose Channel (needs to be freed when we're done) */
+
+ float oldloc[3]; /* transform values at start of operator (to be restored before each modal step) */
+ float oldrot[3];
+ float oldscale[3];
+ float oldquat[4];
+} tPChanFCurveLink;
+
+/* ------------------------------------ */
+
+/* operator init */
+static int pose_slide_init (bContext *C, wmOperator *op, short mode)
+{
+ tPoseSlideOp *pso;
+ bAction *act= NULL;
+
+ /* init slide-op data */
+ pso= op->customdata= MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp");
+
+ /* get info from context */
+ pso->scene= CTX_data_scene(C);
+ pso->ob= CTX_data_active_object(C);
+ pso->arm= (pso->ob)? pso->ob->data : NULL;
+ pso->ar= CTX_wm_region(C); /* only really needed when doing modal() */
+
+ pso->cframe= pso->scene->r.cfra;
+ pso->mode= mode;
+
+ /* set range info from property values - these may get overridden for the invoke() */
+ pso->percentage= RNA_float_get(op->ptr, "percentage");
+ pso->prevFrame= RNA_int_get(op->ptr, "prev_frame");
+ pso->nextFrame= RNA_int_get(op->ptr, "next_frame");
+
+ /* check the settings from the context */
+ if (ELEM4(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
+ return 0;
+ else
+ act= pso->ob->adt->action;
+
+ /* for each Pose-Channel which gets affected, get the F-Curves for that channel
+ * and set the relevant transform flags...
+ */
+ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans)
+ {
+ ListBase curves = {NULL, NULL};
+ int transFlags = action_get_item_transforms(act, pso->ob, pchan, &curves);
+
+ pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
+
+ /* check if any transforms found... */
+ if (transFlags) {
+ /* make new linkage data */
+ tPChanFCurveLink *pfl= MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
+ PointerRNA ptr;
+
+ pfl->fcurves= curves;
+ pfl->pchan= pchan;
+
+ /* get the RNA path to this pchan - this needs to be freed! */
+ RNA_pointer_create((ID *)pso->ob, &RNA_PoseChannel, pchan, &ptr);
+ pfl->pchan_path= RNA_path_from_ID_to_struct(&ptr);
+
+ /* add linkage data to operator data */
+ BLI_addtail(&pso->pfLinks, pfl);
+
+ /* set pchan's transform flags */
+ if (transFlags & ACT_TRANS_LOC)
+ pchan->flag |= POSE_LOC;
+ if (transFlags & ACT_TRANS_ROT)
+ pchan->flag |= POSE_ROT;
+ if (transFlags & ACT_TRANS_SCALE)
+ pchan->flag |= POSE_SIZE;
+
+ /* store current transforms */
+ VECCOPY(pfl->oldloc, pchan->loc);
+ VECCOPY(pfl->oldrot, pchan->eul);
+ VECCOPY(pfl->oldscale, pchan->size);
+ QUATCOPY(pfl->oldquat, pchan->quat);
+ }
+ }
+ CTX_DATA_END;
+
+ /* set depsgraph flags */
+ /* make sure the lock is set OK, unlock can be accidentally saved? */
+ pso->ob->pose->flag |= POSE_LOCKED;
+ pso->ob->pose->flag &= ~POSE_DO_UNLOCK;
+
+ /* do basic initialise of RB-BST used for finding keyframes, but leave the filling of it up
+ * to the caller of this (usually only invoke() will do it, to make things more efficient).
+ */
+ BLI_dlrbTree_init(&pso->keys);
+
+ /* get builtin KeyingSets */
+ pso->ks_loc= ANIM_builtin_keyingset_get_named(NULL, "Location");
+ pso->ks_rot= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
+ pso->ks_scale= ANIM_builtin_keyingset_get_named(NULL, "Scaling");
+
+ /* return status is whether we've got all the data we were requested to get */
+ return 1;
+}
+
+/* exiting the operator - free data */
+static void pose_slide_exit (bContext *C, wmOperator *op)
+{
+ tPoseSlideOp *pso= op->customdata;
+
+ /* if data exists, clear its data and exit */
+ if (pso) {
+ tPChanFCurveLink *pfl, *pfln=NULL;
+
+ /* free the temp pchan links and their data */
+ for (pfl= pso->pfLinks.first; pfl; pfl= pfln) {
+ pfln= pfl->next;
+
+ /* free list of F-Curve reference links */
+ BLI_freelistN(&pfl->fcurves);
+
+ /* free pchan RNA Path */
+ MEM_freeN(pfl->pchan_path);
+
+ /* free link itself */
+ BLI_freelinkN(&pso->pfLinks, pfl);
+ }
+
+ /* free RB-BST for keyframes (if it contained data) */
+ BLI_dlrbTree_free(&pso->keys);
+
+ /* free data itself */
+ MEM_freeN(pso);
+ }
+
+ /* cleanup */
+ op->customdata= NULL;
+}
+
+/* ------------------------------------ */
+
+/* helper for apply() / reset() - refresh the data */
+static void pose_slide_refresh (bContext *C, tPoseSlideOp *pso)
+{
+ /* old optimize trick... this enforces to bypass the depgraph
+ * - note: code copied from transform_generics.c -> recalcData()
+ */
+ // FIXME: shouldn't this use the builtin stuff?
+ if ((pso->arm->flag & ARM_DELAYDEFORM)==0)
+ DAG_id_flush_update(&pso->ob->id, OB_RECALC_DATA); /* sets recalc flags */
+ else
+ where_is_pose(pso->scene, pso->ob);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_POSE, pso->ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+}
+
+/* helper for apply() callabcks - find the next F-Curve with matching path... */
+static LinkData *find_next_fcurve_link (ListBase *fcuLinks, LinkData *prev, char *path)
+{
+ LinkData *first= (prev)? prev->next : (fcuLinks)? fcuLinks->first : NULL;
+ LinkData *ld;
+
+ /* check each link to see if the linked F-Curve has a matching path */
+ for (ld= first; ld; ld= ld->next) {
+ FCurve *fcu= (FCurve *)ld->data;
+
+ /* check if paths match */
+ if (strcmp(path, fcu->rna_path) == 0)
+ return ld;
+ }
+
+ /* none found */
+ return NULL;
+}
+
+/* helper for apply() - perform sliding for some 3-element vector */
+static void pose_slide_apply_vec3 (tPoseSlideOp *pso, tPChanFCurveLink *pfl, float vec[3], char *propName)
+{
+ LinkData *ld=NULL;
+ char *path=NULL;
+ float cframe;
+
+ /* get the path to use... */
+ path= BLI_sprintfN("%s.%s", pfl->pchan_path, propName);
+
+ /* get the current frame number */
+ cframe= (float)pso->cframe;
+
+ /* using this path, find each matching F-Curve for the variables we're interested in */
+ while ( (ld= find_next_fcurve_link(&pfl->fcurves, ld, path)) ) {
+ FCurve *fcu= (FCurve *)ld->data;
+ float sVal, eVal;
+ float w1, w2;
+ int ch;
+
+ /* get keyframe values for endpoint poses to blend with */
+ /* previous/start */
+ sVal= evaluate_fcurve(fcu, (float)pso->prevFrame);
+ /* next/end */
+ eVal= evaluate_fcurve(fcu, (float)pso->nextFrame);
+
+ /* get channel index */
+ ch= fcu->array_index;
+
+ /* calculate the relative weights of the endpoints */
+ if (pso->mode == POSESLIDE_BREAKDOWN) {
+ /* get weights from the percentage control */
+ w1= pso->percentage; /* this must come second */
+ w2= 1.0f - w1; /* this must come first */
+ }
+ else {
+ /* - these weights are derived from the relative distance of these
+ * poses from the current frame
+ * - they then get normalised so that they only sum up to 1
+ */
+ float wtot;
+
+ w1 = cframe - (float)pso->prevFrame;
+ w2 = (float)pso->nextFrame - cframe;
+
+ wtot = w1 + w2;
+ w1 = (w1/wtot);
+ w2 = (w2/wtot);
+ }
+
+ /* depending on the mode, calculate the new value
+ * - in all of these, the start+end values are multiplied by w2 and w1 (respectively),
+ * since multiplication in another order would decrease the value the current frame is closer to
+ */
+ switch (pso->mode) {
+ case POSESLIDE_PUSH: /* make the current pose more pronounced */
+ {
+ /* perform a weighted average here, favouring the middle pose
+ * - numerator should be larger than denominator to 'expand' the result
+ * - perform this weighting a number of times given by the percentage...
+ */
+ int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed
+
+ while (iters-- > 0) {
+ vec[ch]= ( -((sVal * w2) + (eVal * w1)) + (vec[ch] * 6.0f) ) / 5.0f;
+ }
+ }
+ break;
+
+ case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */
+ {
+ /* perform a weighted average here, favouring the middle pose
+ * - numerator should be smaller than denominator to 'relax' the result
+ * - perform this weighting a number of times given by the percentage...
+ */
+ int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed
+
+ while (iters-- > 0) {
+ vec[ch]= ( ((sVal * w2) + (eVal * w1)) + (vec[ch] * 5.0f) ) / 6.0f;
+ }
+ }
+ break;
+
+ case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */
+ {
+ /* perform simple linear interpolation - coefficient for start must come from pso->percentage... */
+ // TODO: make this use some kind of spline interpolation instead?
+ vec[ch]= ((sVal * w2) + (eVal * w1));
+ }
+ break;
+ }
+
+ }
+
+ /* free the temp path we got */
+ MEM_freeN(path);
+}
+
+/* helper for apply() - perform sliding for quaternion rotations (using quat blending) */
+static void pose_slide_apply_quat (tPoseSlideOp *pso, tPChanFCurveLink *pfl)
+{
+ FCurve *fcu_w=NULL, *fcu_x=NULL, *fcu_y=NULL, *fcu_z=NULL;
+ bPoseChannel *pchan= pfl->pchan;
+ LinkData *ld=NULL;
+ char *path=NULL;
+ float cframe;
+
+ /* get the path to use - this should be quaternion rotations only (needs care) */
+ path= BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation");
+
+ /* get the current frame number */
+ cframe= (float)pso->cframe;
+
+ /* using this path, find each matching F-Curve for the variables we're interested in */
+ while ( (ld= find_next_fcurve_link(&pfl->fcurves, ld, path)) ) {
+ FCurve *fcu= (FCurve *)ld->data;
+
+ /* assign this F-Curve to one of the relevant pointers... */
+ switch (fcu->array_index) {
+ case 3: /* z */
+ fcu_z= fcu;
+ break;
+ case 2: /* y */
+ fcu_y= fcu;
+ break;
+ case 1: /* x */
+ fcu_x= fcu;
+ break;
+ case 0: /* w */
+ fcu_w= fcu;
+ break;
+ }
+ }
+
+ /* only if all channels exist, proceed */
+ if (fcu_w && fcu_x && fcu_y && fcu_z) {
+ float quat_prev[4], quat_next[4];
+
+ /* get 2 quats */
+ quat_prev[0] = evaluate_fcurve(fcu_w, pso->prevFrame);
+ quat_prev[1] = evaluate_fcurve(fcu_x, pso->prevFrame);
+ quat_prev[2] = evaluate_fcurve(fcu_y, pso->prevFrame);
+ quat_prev[3] = evaluate_fcurve(fcu_z, pso->prevFrame);
+
+ quat_next[0] = evaluate_fcurve(fcu_w, pso->nextFrame);
+ quat_next[1] = evaluate_fcurve(fcu_x, pso->nextFrame);
+ quat_next[2] = evaluate_fcurve(fcu_y, pso->nextFrame);
+ quat_next[3] = evaluate_fcurve(fcu_z, pso->nextFrame);
+
+ /* perform blending */
+ if (pso->mode == POSESLIDE_BREAKDOWN) {
+ /* just perform the interpol between quat_prev and quat_next using pso->percentage as a guide */
+ QuatInterpol(pchan->quat, quat_prev, quat_next, pso->percentage);
+ }
+ else {
+ float quat_interp[4], quat_orig[4];
+ int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed
+
+ /* perform this blending several times until a satisfactory result is reached */
+ while (iters-- > 0) {
+ /* calculate the interpolation between the endpoints */
+ QuatInterpol(quat_interp, quat_prev, quat_next, (cframe-pso->prevFrame) / (pso->nextFrame-pso->prevFrame) );
+
+ /* make a copy of the original rotation */
+ QUATCOPY(quat_orig, pchan->quat);
+
+ /* tricky interpolations - mode-dependent blending between original and new */
+ if (pso->mode == POSESLIDE_RELAX) // xxx this was the original code, so should work fine
+ QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f);
+ else // I'm just guessing here...
+ QuatInterpol(pchan->quat, quat_orig, quat_interp, 6.0f/5.0f);
+ }
+ }
+ }
+
+ /* free the path now */
+ MEM_freeN(path);
+}
+
+/* apply() - perform the pose sliding based on weighting various poses */
+static void pose_slide_apply (bContext *C, wmOperator *op, tPoseSlideOp *pso)
+{
+ tPChanFCurveLink *pfl;
+
+ /* sanitise the frame ranges */
+ if (pso->prevFrame == pso->nextFrame) {
+ /* move out one step either side */
+ pso->prevFrame--;
+ pso->nextFrame++;
+ }
+
+ /* for each link, handle each set of transforms */
+ for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) {
+ /* valid transforms for each PoseChannel should have been noted already
+ * - sliding the pose should be a straightforward exercise for location+rotation,
+ * but rotations get more complicated since we may want to use quaternion blending
+ * for quaternions instead...
+ */
+ bPoseChannel *pchan= pfl->pchan;
+
+ if (pchan->flag & POSE_LOC) {
+ /* calculate these for the 'location' vector, and use location curves */
+ pose_slide_apply_vec3(pso, pfl, pchan->loc, "location");
+ }
+
+ if (pchan->flag & POSE_SIZE) {
+ /* calculate these for the 'scale' vector, and use scale curves */
+ pose_slide_apply_vec3(pso, pfl, pchan->size, "scale");
+ }
+
+ if (pchan->flag & POSE_ROT) {
+ /* everything depends on the rotation mode */
+ if (pchan->rotmode > 0) {
+ /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */
+ pose_slide_apply_vec3(pso, pfl, pchan->eul, "rotation_euler");
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ // TODO: need to figure out how to do this!
+ }
+ else {
+ /* quaternions - use quaternion blending */
+ pose_slide_apply_quat(pso, pfl);
+ }
+ }
+ }
+
+ /* depsgraph updates + redraws */
+ pose_slide_refresh(C, pso);
+}
+
+/* perform autokeyframing after changes were made + confirmed */
+static void pose_slide_autoKeyframe (bContext *C, tPoseSlideOp *pso)
+{
+ /* insert keyframes as necessary if autokeyframing */
+ if (autokeyframe_cfra_can_key(pso->scene, &pso->ob->id)) {
+ bCommonKeySrc cks;
+ ListBase dsources = {&cks, &cks};
+ tPChanFCurveLink *pfl;
+
+ /* init common-key-source for use by KeyingSets */
+ memset(&cks, 0, sizeof(bCommonKeySrc));
+ cks.id= &pso->ob->id;
+
+ /* iterate over each pose-channel affected, applying the changes */
+ for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) {
+ bPoseChannel *pchan= pfl->pchan;
+ /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
+ cks.pchan= pchan;
+
+ /* insert keyframes */
+ if (pchan->flag & POSE_LOC)
+ modify_keyframes(C, &dsources, NULL, pso->ks_loc, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
+ if (pchan->flag & POSE_ROT)
+ modify_keyframes(C, &dsources, NULL, pso->ks_rot, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
+ if (pchan->flag & POSE_SIZE)
+ modify_keyframes(C, &dsources, NULL, pso->ks_scale, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
+ }
+ }
+}
+
+/* reset changes made to current pose */
+static void pose_slide_reset (bContext *C, tPoseSlideOp *pso)
+{
+ tPChanFCurveLink *pfl;
+
+ /* iterate over each pose-channel affected, restoring all channels to their original values */
+ for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) {
+ bPoseChannel *pchan= pfl->pchan;
+
+ /* just copy all the values over regardless of whether they changed or not */
+ VECCOPY(pchan->loc, pfl->oldloc);
+ VECCOPY(pchan->eul, pfl->oldrot);
+ VECCOPY(pchan->size, pfl->oldscale);
+ QUATCOPY(pchan->quat, pfl->oldquat);
+ }
+}
+
+/* ------------------------------------ */
+
+/* common code for invoke() methods */
+static int pose_slide_invoke_common (bContext *C, wmOperator *op, tPoseSlideOp *pso)
+{
+ tPChanFCurveLink *pfl;
+ AnimData *adt= pso->ob->adt;
+ wmWindow *win= CTX_wm_window(C);
+
+ /* for each link, add all its keyframes to the search tree */
+ for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) {
+ LinkData *ld;
+
+ /* do this for each F-Curve */
+ for (ld= pfl->fcurves.first; ld; ld= ld->next) {
+ FCurve *fcu= (FCurve *)ld->data;
+ fcurve_to_keylist(adt, fcu, &pso->keys, NULL);
+ }
+ }
+
+ /* consolidate these keyframes, and figure out the nearest ones */
+ BLI_dlrbTree_linkedlist_sync(&pso->keys);
+
+ /* cancel if no keyframes found... */
+ if (pso->keys.root) {
+ ActKeyColumn *ak;
+
+ /* firstly, check if the current frame is a keyframe... */
+ ak= cfra_find_actkeycolumn(pso->keys.root, pso->cframe);
+
+ if (ak == NULL) {
+ /* current frame is not a keyframe, so search */
+ ActKeyColumn *pk= cfra_find_nearest_next_ak(pso->keys.root, pso->cframe, 0);
+ ActKeyColumn *nk= cfra_find_nearest_next_ak(pso->keys.root, pso->cframe, 1);
+
+ /* check if we found good keyframes */
+ if ((pk == nk) && (pk != NULL)) {
+ if (pk->cfra < pso->cframe)
+ nk= nk->next;
+ else if (nk->cfra > pso->cframe)
+ pk= pk->prev;
+ }
+
+ /* new set the frames */
+ /* prev frame */
+ pso->prevFrame= (pk)? (pk->cfra) : (pso->cframe - 1);
+ RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
+ /* next frame */
+ pso->nextFrame= (nk)? (nk->cfra) : (pso->cframe + 1);
+ RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
+ }
+ else {
+ /* current frame itself is a keyframe, so just take keyframes on either side */
+ /* prev frame */
+ pso->prevFrame= (ak->prev)? (ak->prev->cfra) : (pso->cframe - 1);
+ RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
+ /* next frame */
+ pso->nextFrame= (ak->next)? (ak->next->cfra) : (pso->cframe + 1);
+ RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between.");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* initial apply for operator... */
+ // TODO: need to calculate percentage for initial round too...
+ pose_slide_apply(C, op, pso);
+
+ /* depsgraph updates + redraws */
+ pose_slide_refresh(C, pso);
+
+ /* set cursor to indicate modal */
+ WM_cursor_modal(win, BC_EW_SCROLLCURSOR);
+
+ /* add a modal handler for this operator */
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* common code for modal() */
+static int pose_slide_modal (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ tPoseSlideOp *pso= op->customdata;
+ wmWindow *win= CTX_wm_window(C);
+
+ switch (evt->type) {
+ case LEFTMOUSE: /* confirm */
+ {
+ /* return to normal cursor */
+ WM_cursor_restore(win);
+
+ /* insert keyframes as required... */
+ pose_slide_autoKeyframe(C, pso);
+ pose_slide_exit(C, op);
+
+ /* done! */
+ return OPERATOR_FINISHED;
+ }
+
+ case ESCKEY: /* cancel */
+ case RIGHTMOUSE:
+ {
+ /* return to normal cursor */
+ WM_cursor_restore(win);
+
+ /* reset transforms back to original state */
+ pose_slide_reset(C, pso);
+
+ /* depsgraph updates + redraws */
+ pose_slide_refresh(C, pso);
+
+ /* clean up temp data */
+ pose_slide_exit(C, op);
+
+ /* cancelled! */
+ return OPERATOR_CANCELLED;
+ }
+
+ case MOUSEMOVE: /* calculate new position */
+ {
+ /* calculate percentage based on position of mouse (we only use x-axis for now.
+ * since this is more conveninent for users to do), and store new percentage value
+ */
+ pso->percentage= (evt->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
+ RNA_float_set(op->ptr, "percentage", pso->percentage);
+
+ /* reset transforms (to avoid accumulation errors) */
+ pose_slide_reset(C, pso);
+
+ /* apply... */
+ pose_slide_apply(C, op, pso);
+ }
+ break;
+
+ default: /* unhandled event (maybe it was some view manip? */
+ /* allow to pass through */
+ return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH;
+ }
+
+ /* still running... */
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* common code for cancel() */
+static int pose_slide_cancel (bContext *C, wmOperator *op)
+{
+ /* cleanup and done */
+ pose_slide_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+/* common code for exec() methods */
+static int pose_slide_exec_common (bContext *C, wmOperator *op, tPoseSlideOp *pso)
+{
+ /* settings should have been set up ok for applying, so just apply! */
+ pose_slide_apply(C, op, pso);
+
+ /* insert keyframes if needed */
+ pose_slide_autoKeyframe(C, pso);
+
+ /* cleanup and done */
+ pose_slide_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+/* common code for defining RNA properties */
+static void pose_slide_opdef_properties (wmOperatorType *ot)
+{
+ RNA_def_int(ot->srna, "prev_frame", 0, MINAFRAME, MAXFRAME, "Previous Keyframe", "Frame number of keyframe immediately before the current frame.", 0, 50);
+ RNA_def_int(ot->srna, "next_frame", 0, MINAFRAME, MAXFRAME, "Next Keyframe", "Frame number of keyframe immediately after the current frame.", 0, 50);
+ RNA_def_float_percentage(ot->srna, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Weighting factor for the sliding operation", 0.3, 0.7);
+}
+
+/* ------------------------------------ */
+
+/* invoke() - for 'push' mode */
+static int pose_slide_push_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ tPoseSlideOp *pso;
+
+ /* initialise data */
+ if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
+ pose_slide_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso= op->customdata;
+
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
+}
+
+/* exec() - for push */
+static int pose_slide_push_exec (bContext *C, wmOperator *op)
+{
+ tPoseSlideOp *pso;
+
+ /* initialise data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
+ pose_slide_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso= op->customdata;
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
+}
+
+void POSE_OT_push (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Push Pose";
+ ot->idname= "POSE_OT_push";
+ ot->description= "Exaggerate the current pose";
+
+ /* callbacks */
+ ot->exec= pose_slide_push_exec;
+ ot->invoke= pose_slide_push_invoke;
+ ot->modal= pose_slide_modal;
+ ot->cancel= pose_slide_cancel;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
+}
+
+/* ........................ */
+
+/* invoke() - for 'relax' mode */
+static int pose_slide_relax_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ tPoseSlideOp *pso;
+
+ /* initialise data */
+ if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
+ pose_slide_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso= op->customdata;
+
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
+}
+
+/* exec() - for relax */
+static int pose_slide_relax_exec (bContext *C, wmOperator *op)
+{
+ tPoseSlideOp *pso;
+
+ /* initialise data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
+ pose_slide_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso= op->customdata;
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
+}
+
+void POSE_OT_relax (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Relax Pose";
+ ot->idname= "POSE_OT_relax";
+ ot->description= "Make the current pose more similar to its surrounding ones.";
+
+ /* callbacks */
+ ot->exec= pose_slide_relax_exec;
+ ot->invoke= pose_slide_relax_invoke;
+ ot->modal= pose_slide_modal;
+ ot->cancel= pose_slide_cancel;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
+}
+
+/* ........................ */
+
+/* invoke() - for 'breakdown' mode */
+static int pose_slide_breakdown_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ tPoseSlideOp *pso;
+
+ /* initialise data */
+ if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
+ pose_slide_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso= op->customdata;
+
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
+}
+
+/* exec() - for breakdown */
+static int pose_slide_breakdown_exec (bContext *C, wmOperator *op)
+{
+ tPoseSlideOp *pso;
+
+ /* initialise data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
+ pose_slide_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso= op->customdata;
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
+}
+
+void POSE_OT_breakdown (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Pose Breakdowner";
+ ot->idname= "POSE_OT_breakdown";
+ ot->description= "Create a suitable breakdown pose on the current frame.";
+
+ /* callbacks */
+ ot->exec= pose_slide_breakdown_exec;
+ ot->invoke= pose_slide_breakdown_invoke;
+ ot->modal= pose_slide_modal;
+ ot->cancel= pose_slide_cancel;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
+}
+
+/* **************************************************** */
diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c
index c332a297e57..386cb6512a3 100644
--- a/source/blender/editors/armature/poselib.c
+++ b/source/blender/editors/armature/poselib.c
@@ -44,7 +44,6 @@
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
-#include "DNA_ipo_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_scene_types.h"
@@ -62,8 +61,6 @@
#include "BKE_report.h"
#include "BKE_utildefines.h"
-#include "PIL_time.h" /* sleep */
-
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_types.h"
@@ -470,6 +467,7 @@ static int poselib_remove_exec (bContext *C, wmOperator *op)
marker= BLI_findlink(&act->markers, RNA_int_get(op->ptr, "index"));
if (marker == NULL) {
BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose");
+ return OPERATOR_CANCELLED;
}
/* remove relevant keyframes */
@@ -536,6 +534,7 @@ static int poselib_rename_exec (bContext *C, wmOperator *op)
marker= BLI_findlink(&act->markers, RNA_int_get(op->ptr, "index"));
if (marker == NULL) {
BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose");
+ return OPERATOR_CANCELLED;
}
/* get new name */
@@ -769,6 +768,10 @@ static void poselib_keytag_pose (bContext *C, Scene *scene, tPoseLib_PreviewData
if (poselib_ks_locrotscale == NULL)
poselib_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
+ /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
+ cks.pchan= pchan;
+
+ /* now insert the keyframe */
modify_keyframes(C, &dsources, NULL, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA);
/* clear any unkeyed tags */
@@ -1411,7 +1414,7 @@ static int poselib_preview_invoke(bContext *C, wmOperator *op, wmEvent *event)
poselib_preview_apply(C, op);
/* add temp handler if we're running as a modal operator */
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index bab7111dbd7..d4b7aa149df 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -798,6 +798,8 @@ void pose_copy_menu(Scene *scene)
VECCOPY(pchan->limitmax, pchanact->limitmax);
VECCOPY(pchan->stiffness, pchanact->stiffness);
pchan->ikstretch= pchanact->ikstretch;
+ pchan->ikrotweight= pchanact->ikrotweight;
+ pchan->iklinweight= pchanact->iklinweight;
}
break;
case 8: /* Custom Bone Shape */
@@ -812,14 +814,14 @@ void pose_copy_menu(Scene *scene)
armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
- if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+ if (pchan->rotmode == ROT_MODE_AXISANGLE) {
float tmp_quat[4];
/* need to convert to quat first (in temp var)... */
Mat4ToQuat(delta_mat, tmp_quat);
QuatToAxisAngle(tmp_quat, &pchan->quat[1], &pchan->quat[0]);
}
- else if (pchan->rotmode == PCHAN_ROT_QUAT)
+ else if (pchan->rotmode == ROT_MODE_QUAT)
Mat4ToQuat(delta_mat, pchan->quat);
else
Mat4ToEulO(delta_mat, pchan->eul, pchan->rotmode);
@@ -1021,12 +1023,12 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
}
else if (pchan->rotmode > 0) {
/* quat/axis-angle to euler */
- if (chan->rotmode == PCHAN_ROT_AXISANGLE)
+ if (chan->rotmode == ROT_MODE_AXISANGLE)
AxisAngleToEulO(&chan->quat[1], chan->quat[0], pchan->eul, pchan->rotmode);
else
QuatToEulO(chan->quat, pchan->eul, pchan->rotmode);
}
- else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
/* quat/euler to axis angle */
if (chan->rotmode > 0)
EulOToAxisAngle(chan->eul, chan->rotmode, &pchan->quat[1], &pchan->quat[0]);
@@ -1050,7 +1052,7 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
pchan->eul[1] *= -1;
pchan->eul[2] *= -1;
}
- else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
float eul[3];
AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], eul, EULER_ORDER_DEFAULT);
@@ -1084,6 +1086,9 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
if (posePaste_ks_locrotscale == NULL)
posePaste_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
+ /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
+ cks.pchan= pchan;
+
modify_keyframes(C, &dsources, NULL, posePaste_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA);
/* clear any unkeyed tags */
@@ -1939,7 +1944,7 @@ static int armature_bone_layers_invoke (bContext *C, wmOperator *op, wmEvent *ev
/* Set the visible layers for the active armature (edit and pose modes) */
static int armature_bone_layers_exec (bContext *C, wmOperator *op)
{
- Object *ob= CTX_data_active_object(C);
+ Object *ob= CTX_data_edit_object(C);
bArmature *arm= (ob)? ob->data : NULL;
PointerRNA ptr;
int layers[16]; /* hardcoded for now - we can only have 16 armature layers, so this should be fine... */
@@ -1952,7 +1957,7 @@ static int armature_bone_layers_exec (bContext *C, wmOperator *op)
{
/* get pointer for pchan, and write flags this way */
RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr);
- RNA_boolean_set_array(&ptr, "layers", layers);
+ RNA_boolean_set_array(&ptr, "layer", layers);
}
CTX_DATA_END;
@@ -1983,175 +1988,6 @@ void ARMATURE_OT_bone_layers (wmOperatorType *ot)
/* ********************************************** */
-#if 0
-// XXX old sys
-/* for use with pose_relax only */
-static int pose_relax_icu(struct IpoCurve *icu, float framef, float *val, float *frame_prev, float *frame_next)
-{
- if (!icu) {
- return 0;
- }
- else {
- BezTriple *bezt = icu->bezt;
-
- BezTriple *bezt_prev=NULL, *bezt_next=NULL;
- float w1, w2, wtot;
- int i;
-
- for (i=0; i < icu->totvert; i++, bezt++) {
- if (bezt->vec[1][0] < framef - 0.5) {
- bezt_prev = bezt;
- } else {
- break;
- }
- }
-
- if (bezt_prev==NULL) return 0;
-
- /* advance to the next, dont need to advance i */
- bezt = bezt_prev+1;
-
- for (; i < icu->totvert; i++, bezt++) {
- if (bezt->vec[1][0] > framef + 0.5) {
- bezt_next = bezt;
- break;
- }
- }
-
- if (bezt_next==NULL) return 0;
-
- if (val) {
- w1 = framef - bezt_prev->vec[1][0];
- w2 = bezt_next->vec[1][0] - framef;
- wtot = w1 + w2;
- w1=w1/wtot;
- w2=w2/wtot;
-#if 0
- val = (bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1);
-#else
- /* apply the value with a hard coded 6th */
- *val = (((bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1)) + (*val * 5.0f)) / 6.0f;
-#endif
- }
-
- if (frame_prev) *frame_prev = bezt_prev->vec[1][0];
- if (frame_next) *frame_next = bezt_next->vec[1][0];
-
- return 1;
- }
-}
-#endif
-
-void pose_relax(Scene *scene)
-{
- Object *ob = OBACT;
- bPose *pose;
- bAction *act;
- bArmature *arm;
-
-// IpoCurve *icu_w, *icu_x, *icu_y, *icu_z;
-
- bPoseChannel *pchan;
-// bActionChannel *achan;
-// float framef = F_CFRA;
-// float frame_prev, frame_next;
-// float quat_prev[4], quat_next[4], quat_interp[4], quat_orig[4];
-
- int do_scale = 0;
- int do_loc = 0;
- int do_quat = 0;
- int flag = 0;
-// int do_x, do_y, do_z;
-
- if (!ob) return;
-
- pose = ob->pose;
- act = ob->action;
- arm = (bArmature *)ob->data;
-
- if (!pose || !act || !arm) return;
-
- for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) {
-
- pchan->bone->flag &= ~BONE_TRANSFORM;
-
- if (pchan->bone->layer & arm->layer) {
- if (pchan->bone->flag & BONE_SELECTED) {
- /* do we have an ipo curve? */
-#if 0 // XXX old animation system
- achan= get_action_channel(act, pchan->name);
-
- if (achan && achan->ipo) {
- /*calc_ipo(achan->ipo, ctime);*/
-
- do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_X), framef, &pchan->loc[0], NULL, NULL);
- do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Y), framef, &pchan->loc[1], NULL, NULL);
- do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Z), framef, &pchan->loc[2], NULL, NULL);
- do_loc += do_x + do_y + do_z;
-
- do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_X), framef, &pchan->size[0], NULL, NULL);
- do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Y), framef, &pchan->size[1], NULL, NULL);
- do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Z), framef, &pchan->size[2], NULL, NULL);
- do_scale += do_x + do_y + do_z;
-
- if( ((icu_w = find_ipocurve(achan->ipo, AC_QUAT_W))) &&
- ((icu_x = find_ipocurve(achan->ipo, AC_QUAT_X))) &&
- ((icu_y = find_ipocurve(achan->ipo, AC_QUAT_Y))) &&
- ((icu_z = find_ipocurve(achan->ipo, AC_QUAT_Z))) )
- {
- /* use the quatw keyframe as a basis for others */
- if (pose_relax_icu(icu_w, framef, NULL, &frame_prev, &frame_next)) {
- /* get 2 quats */
- quat_prev[0] = eval_icu(icu_w, frame_prev);
- quat_prev[1] = eval_icu(icu_x, frame_prev);
- quat_prev[2] = eval_icu(icu_y, frame_prev);
- quat_prev[3] = eval_icu(icu_z, frame_prev);
-
- quat_next[0] = eval_icu(icu_w, frame_next);
- quat_next[1] = eval_icu(icu_x, frame_next);
- quat_next[2] = eval_icu(icu_y, frame_next);
- quat_next[3] = eval_icu(icu_z, frame_next);
-
-#if 0
- /* apply the setting, completely smooth */
- QuatInterpol(pchan->quat, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) );
-#else
- /* tricky interpolation */
- QuatInterpol(quat_interp, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) );
- QUATCOPY(quat_orig, pchan->quat);
- QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f);
- /* done */
-#endif
- do_quat++;
- }
- }
-
- /* apply BONE_TRANSFORM tag so that autokeying will pick it up */
- pchan->bone->flag |= BONE_TRANSFORM;
- }
-
-#endif // XXX old animation system
- }
- }
- }
-
- ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
-
- /* do auto-keying */
- if (do_loc) flag |= TFM_TRANSLATION;
- if (do_scale) flag |= TFM_RESIZE;
- if (do_quat) flag |= TFM_ROTATION;
- autokeyframe_pose_cb_func(ob, flag, 0);
-
- /* clear BONE_TRANSFORM flags */
- for (pchan=pose->chanbase.first; pchan; pchan= pchan->next)
- pchan->bone->flag &= ~ BONE_TRANSFORM;
-
- /* do depsgraph flush */
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
- BIF_undo_push("Relax Pose");
-}
-
/* for use in insertkey, ensure rotation goes other way around */
void pose_flipquats(Scene *scene)
{