== Action and NLA Editor Transform ==
I've refactored the Action and NLA Editor Transform tools to use the Transform System instead of setting up their own transform loops. This should have happened ages ago, but no-one got around to doing so. * There are still a few bugs left to iron out of a few features, but on the whole it should work as well as it used to. These are: the values which get displayed when working with NLA-scaled actions may not all be correct yet; and the Time-Slide tool in the Action Editor is currently kindof broken. * One of the main benefits of this work, is that it is now possible to use Numeric Input during Transforms. * Also, a bug that meant that it was not possible to negatively scale keyframes in the Action Editor has been resolved.
This commit is contained in:
@@ -55,6 +55,9 @@
|
||||
#define TFM_BONE_ENVELOPE 16
|
||||
#define TFM_CURVE_SHRINKFATTEN 17
|
||||
#define TFM_BONE_ROLL 18
|
||||
#define TFM_TIME_TRANSLATE 19
|
||||
#define TFM_TIME_SLIDE 20
|
||||
#define TFM_TIME_SCALE 21
|
||||
|
||||
/* TRANSFORM CONTEXTS */
|
||||
#define CTX_NONE 0
|
||||
|
||||
@@ -339,6 +339,15 @@ int BoneEnvelope(TransInfo *t, short mval[2]);
|
||||
void initBoneRoll(TransInfo *t);
|
||||
int BoneRoll(TransInfo *t, short mval[2]);
|
||||
|
||||
void initTimeTranslate(TransInfo *t);
|
||||
int TimeTranslate(TransInfo *t, short mval[2]);
|
||||
|
||||
void initTimeSlide(TransInfo *t);
|
||||
int TimeSlide(TransInfo *t, short mval[2]);
|
||||
|
||||
void initTimeScale(TransInfo *t);
|
||||
int TimeScale(TransInfo *t, short mval[2]);
|
||||
|
||||
/*********************** transform_conversions.c ********** */
|
||||
struct ListBase;
|
||||
void flushTransUVs(TransInfo *t);
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
#include "BIF_screen.h"
|
||||
#include "BIF_space.h"
|
||||
#include "BIF_toolbox.h"
|
||||
#include "BIF_transform.h"
|
||||
|
||||
#include "BSE_edit.h"
|
||||
#include "BSE_drawipo.h"
|
||||
@@ -186,19 +187,6 @@ static void remake_meshaction_ipos (Ipo *ipo)
|
||||
}
|
||||
}
|
||||
|
||||
static void meshkey_do_redraw (Key *key)
|
||||
{
|
||||
if(key->ipo)
|
||||
remake_meshaction_ipos(key->ipo);
|
||||
|
||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
|
||||
|
||||
allspace(REMAKEIPO, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWIPO, 0);
|
||||
allqueue(REDRAWNLA, 0);
|
||||
|
||||
}
|
||||
|
||||
/* **************************************************** */
|
||||
/* FILTER->EDIT STRUCTURES */
|
||||
@@ -737,361 +725,9 @@ void *get_action_context (short *datatype)
|
||||
/* **************************************************** */
|
||||
/* TRANSFORM TOOLS */
|
||||
|
||||
/* initialise the transform data - create transverts */
|
||||
static TransVert *transform_action_init (int *tvtot, float *minx, float *maxx)
|
||||
{
|
||||
ListBase act_data = {NULL, NULL};
|
||||
bActListElem *ale;
|
||||
TransVert *tv;
|
||||
void *data;
|
||||
short datatype;
|
||||
int filter;
|
||||
int count= 0;
|
||||
float min= 0, max= 0;
|
||||
int i;
|
||||
|
||||
/* initialise the values being passed by reference */
|
||||
*tvtot = *minx = *maxx = 0;
|
||||
|
||||
/* determine what type of data we are operating on */
|
||||
data = get_action_context(&datatype);
|
||||
if (data == NULL) return NULL;
|
||||
|
||||
/* filter data */
|
||||
filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
|
||||
actdata_filter(&act_data, filter, data, datatype);
|
||||
|
||||
/* loop 1: fully select ipo-keys and count how many BezTriples are selected */
|
||||
for (ale= act_data.first; ale; ale= ale->next)
|
||||
count += fullselect_ipo_keys(ale->key_data);
|
||||
|
||||
/* stop if trying to build list if nothing selected */
|
||||
if (count == 0) {
|
||||
/* cleanup temp list */
|
||||
BLI_freelistN(&act_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Build the transvert structure */
|
||||
tv = MEM_callocN (sizeof(TransVert) * count, "transVert");
|
||||
|
||||
/* loop 2: build transvert structure */
|
||||
for (ale= act_data.first; ale; ale= ale->next)
|
||||
*tvtot = add_trans_ipo_keys(ale->key_data, tv, *tvtot);
|
||||
|
||||
/* min max, only every other three */
|
||||
min= max= tv[1].loc[0];
|
||||
for (i=1; i<count; i+=3) {
|
||||
if(min>tv[i].loc[0]) min= tv[i].loc[0];
|
||||
if(max<tv[i].loc[0]) max= tv[i].loc[0];
|
||||
}
|
||||
*minx= min;
|
||||
*maxx= max;
|
||||
|
||||
/* cleanup temp list */
|
||||
BLI_freelistN(&act_data);
|
||||
|
||||
/* return created transverts */
|
||||
return tv;
|
||||
}
|
||||
|
||||
/* main transform loop for action editor
|
||||
* NOTE: yes, this is a very long function that really should be converted to
|
||||
* using the transform system proper
|
||||
*/
|
||||
static short transform_action_loop (TransVert *tv, int tvtot, char mode, short context, float minx, float maxx)
|
||||
{
|
||||
Object *ob= OBACT;
|
||||
float deltax, startx;
|
||||
float cenf[2];
|
||||
float sval[2], cval[2], lastcval[2]={0,0};
|
||||
float fac=0.0f, secf= ((float)G.scene->r.frs_sec);
|
||||
int loop=1, invert=0;
|
||||
int i;
|
||||
short cancel=0, firsttime=1;
|
||||
short mvals[2], mvalc[2], cent[2];
|
||||
char str[256];
|
||||
|
||||
/* Do the event loop */
|
||||
cent[0] = curarea->winx + (G.saction->v2d.hor.xmax)/2;
|
||||
cent[1] = curarea->winy + (G.saction->v2d.hor.ymax)/2;
|
||||
areamouseco_to_ipoco(G.v2d, cent, &cenf[0], &cenf[1]);
|
||||
|
||||
getmouseco_areawin (mvals);
|
||||
areamouseco_to_ipoco(G.v2d, mvals, &sval[0], &sval[1]);
|
||||
|
||||
if (NLA_ACTION_SCALED)
|
||||
sval[0]= get_action_frame(OBACT, sval[0]);
|
||||
|
||||
/* used for drawing */
|
||||
if (mode=='t') {
|
||||
G.saction->flag |= SACTION_MOVING;
|
||||
G.saction->timeslide= sval[0];
|
||||
}
|
||||
|
||||
startx=sval[0];
|
||||
while (loop) {
|
||||
if (mode=='t' && minx==maxx)
|
||||
break;
|
||||
|
||||
/* Get the input:
|
||||
* - If we're cancelling, reset transformations
|
||||
* - Else calc new transformation
|
||||
* Perform the transformations
|
||||
*/
|
||||
while (qtest()) {
|
||||
short val;
|
||||
unsigned short event= extern_qread(&val);
|
||||
|
||||
if (val) {
|
||||
switch (event) {
|
||||
case LEFTMOUSE:
|
||||
case SPACEKEY:
|
||||
case RETKEY:
|
||||
loop=0;
|
||||
break;
|
||||
case XKEY:
|
||||
break;
|
||||
case ESCKEY:
|
||||
case RIGHTMOUSE:
|
||||
cancel=1;
|
||||
loop=0;
|
||||
break;
|
||||
default:
|
||||
arrows_move_cursor(event);
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (cancel) {
|
||||
for (i=0; i<tvtot; i++) {
|
||||
tv[i].loc[0]=tv[i].oldloc[0];
|
||||
tv[i].loc[1]=tv[i].oldloc[1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
getmouseco_areawin (mvalc);
|
||||
areamouseco_to_ipoco(G.v2d, mvalc, &cval[0], &cval[1]);
|
||||
|
||||
if (NLA_ACTION_SCALED)
|
||||
cval[0]= get_action_frame(OBACT, cval[0]);
|
||||
|
||||
if (mode=='t')
|
||||
G.saction->timeslide= cval[0];
|
||||
|
||||
if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) {
|
||||
PIL_sleep_ms(1);
|
||||
}
|
||||
else {
|
||||
short autosnap= 0;
|
||||
|
||||
/* determine mode of keyframe snapping/autosnap */
|
||||
if (mode != 't') {
|
||||
switch (G.saction->autosnap) {
|
||||
case SACTSNAP_OFF:
|
||||
if (G.qual == LR_CTRLKEY)
|
||||
autosnap= SACTSNAP_STEP;
|
||||
else if (G.qual == LR_SHIFTKEY)
|
||||
autosnap= SACTSNAP_FRAME;
|
||||
else
|
||||
autosnap= SACTSNAP_OFF;
|
||||
break;
|
||||
case SACTSNAP_STEP:
|
||||
autosnap= (G.qual==LR_CTRLKEY)? SACTSNAP_OFF: SACTSNAP_STEP;
|
||||
break;
|
||||
case SACTSNAP_FRAME:
|
||||
autosnap= (G.qual==LR_SHIFTKEY)? SACTSNAP_OFF: SACTSNAP_FRAME;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<tvtot; i++) {
|
||||
tv[i].loc[0]=tv[i].oldloc[0];
|
||||
|
||||
switch (mode) {
|
||||
case 't':
|
||||
if( sval[0] > minx && sval[0] < maxx) {
|
||||
float timefac, cvalc= CLAMPIS(cval[0], minx, maxx);
|
||||
|
||||
/* left half */
|
||||
if(tv[i].oldloc[0] < sval[0]) {
|
||||
timefac= ( sval[0] - tv[i].oldloc[0])/(sval[0] - minx);
|
||||
tv[i].loc[0]= cvalc - timefac*( cvalc - minx);
|
||||
}
|
||||
else {
|
||||
timefac= (tv[i].oldloc[0] - sval[0])/(maxx - sval[0]);
|
||||
tv[i].loc[0]= cvalc + timefac*(maxx- cvalc);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
if (NLA_ACTION_SCALED && context==ACTCONT_ACTION) {
|
||||
deltax = get_action_frame_inv(OBACT, cval[0]);
|
||||
deltax -= get_action_frame_inv(OBACT, sval[0]);
|
||||
|
||||
if (autosnap == SACTSNAP_STEP) {
|
||||
if (G.saction->flag & SACTION_DRAWTIME)
|
||||
deltax= (float)( floor((deltax/secf) + 0.5f) * secf );
|
||||
else
|
||||
deltax= (float)( floor(deltax + 0.5f) );
|
||||
}
|
||||
|
||||
fac = get_action_frame_inv(OBACT, tv[i].loc[0]);
|
||||
fac += deltax;
|
||||
tv[i].loc[0] = get_action_frame(OBACT, fac);
|
||||
}
|
||||
else {
|
||||
deltax = cval[0] - sval[0];
|
||||
fac= deltax;
|
||||
|
||||
if (autosnap == SACTSNAP_STEP) {
|
||||
if (G.saction->flag & SACTION_DRAWTIME)
|
||||
fac= (float)( floor((deltax/secf) + 0.5f) * secf );
|
||||
else
|
||||
fac= (float)( floor(fac + 0.5f) );
|
||||
}
|
||||
|
||||
tv[i].loc[0]+=fac;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
startx=mvals[0]-(ACTWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
|
||||
deltax=mvalc[0]-(ACTWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
|
||||
fac= fabs(deltax/startx);
|
||||
|
||||
if (autosnap == SACTSNAP_STEP) {
|
||||
if (G.saction->flag & SACTION_DRAWTIME)
|
||||
fac= (float)( floor(fac/secf + 0.5f) * secf );
|
||||
else
|
||||
fac= (float)( floor(fac + 0.5f) );
|
||||
}
|
||||
|
||||
if (invert) {
|
||||
if (i % 03 == 0) {
|
||||
memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i+2].oldloc));
|
||||
}
|
||||
if (i % 03 == 2) {
|
||||
memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i-2].oldloc));
|
||||
}
|
||||
|
||||
fac *= -1;
|
||||
}
|
||||
startx= (G.scene->r.cfra);
|
||||
if (NLA_ACTION_SCALED && context==ACTCONT_ACTION)
|
||||
startx= get_action_frame(OBACT, startx);
|
||||
|
||||
tv[i].loc[0]-= startx;
|
||||
tv[i].loc[0]*=fac;
|
||||
tv[i].loc[0]+= startx;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* snap key to nearest frame? */
|
||||
if (autosnap == SACTSNAP_FRAME) {
|
||||
float snapval;
|
||||
|
||||
/* convert frame to nla-action time (if needed) */
|
||||
if (NLA_ACTION_SCALED && context==ACTCONT_ACTION)
|
||||
snapval= get_action_frame_inv(OBACT, tv[i].loc[0]);
|
||||
else
|
||||
snapval= tv[i].loc[0];
|
||||
|
||||
/* snap to nearest frame */
|
||||
if (G.saction->flag & SACTION_DRAWTIME)
|
||||
snapval= (float)( floor((snapval/secf) + 0.5f) * secf );
|
||||
else
|
||||
snapval= (float)( floor(snapval+0.5f) );
|
||||
|
||||
/* convert frame out of nla-action time */
|
||||
if (NLA_ACTION_SCALED && context==ACTCONT_ACTION)
|
||||
tv[i].loc[0]= get_action_frame(OBACT, snapval);
|
||||
else
|
||||
tv[i].loc[0]= snapval;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode=='s') {
|
||||
sprintf(str, "scaleX: %.3f", fac);
|
||||
headerprint(str);
|
||||
}
|
||||
else if (mode=='g') {
|
||||
if (NLA_ACTION_SCALED && context==ACTCONT_ACTION) {
|
||||
/* recalculate the delta based on 'visual' times */
|
||||
fac = get_action_frame_inv(OBACT, cval[0]);
|
||||
fac -= get_action_frame_inv(OBACT, sval[0]);
|
||||
}
|
||||
|
||||
if (autosnap == SACTSNAP_STEP) {
|
||||
if (G.saction->flag & SACTION_DRAWTIME)
|
||||
fac= floor(fac/secf + 0.5f);
|
||||
else
|
||||
fac= floor(fac + 0.5f);
|
||||
}
|
||||
else if (autosnap == SACTSNAP_FRAME) {
|
||||
if (G.saction->flag & SACTION_DRAWTIME)
|
||||
fac= fac / secf;
|
||||
}
|
||||
|
||||
sprintf(str, "deltaX: %.3f", fac);
|
||||
headerprint(str);
|
||||
}
|
||||
else if (mode=='t') {
|
||||
fac= 2.0*(cval[0]-sval[0])/(maxx-minx);
|
||||
CLAMP(fac, -1.0f, 1.0f);
|
||||
|
||||
sprintf(str, "TimeSlide: %.3f", fac);
|
||||
headerprint(str);
|
||||
}
|
||||
|
||||
if (G.saction->lock) {
|
||||
if (context == ACTCONT_ACTION) {
|
||||
if(ob) {
|
||||
ob->ctime= -1234567.0f;
|
||||
if(ob->pose || ob_get_key(ob))
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC);
|
||||
else
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
||||
}
|
||||
force_draw_plus(SPACE_VIEW3D, 0);
|
||||
}
|
||||
else if (context == ACTCONT_SHAPEKEY) {
|
||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA);
|
||||
allqueue (REDRAWVIEW3D, 0);
|
||||
allqueue (REDRAWACTION, 0);
|
||||
allqueue (REDRAWIPO, 0);
|
||||
allqueue(REDRAWNLA, 0);
|
||||
allqueue(REDRAWTIME, 0);
|
||||
force_draw_all(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
force_draw(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastcval[0]= cval[0];
|
||||
lastcval[1]= cval[1];
|
||||
firsttime= 0;
|
||||
}
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/* main call to start transforming keyframes */
|
||||
/* NOTE: someday, this should be integrated with the transform system
|
||||
* instead of relying on our own methods
|
||||
*/
|
||||
void transform_action_keys (int mode, int dummy)
|
||||
{
|
||||
Object *ob= OBACT;
|
||||
TransVert *tv;
|
||||
int tvtot= 0;
|
||||
short cancel;
|
||||
float minx, maxx;
|
||||
|
||||
void *data;
|
||||
short datatype;
|
||||
|
||||
@@ -1099,44 +735,26 @@ void transform_action_keys (int mode, int dummy)
|
||||
data = get_action_context(&datatype);
|
||||
if (data == NULL) return;
|
||||
|
||||
/* initialise transform */
|
||||
tv= transform_action_init(&tvtot, &minx, &maxx);
|
||||
if (tv == NULL) return;
|
||||
|
||||
/* do transform loop */
|
||||
cancel= transform_action_loop(tv, tvtot, mode, datatype, minx, maxx);
|
||||
|
||||
/* cleanup */
|
||||
if (datatype == ACTCONT_ACTION) {
|
||||
/* Update the curve */
|
||||
/* Depending on the lock status, draw necessary views */
|
||||
if(ob) {
|
||||
ob->ctime= -1234567.0f;
|
||||
|
||||
if(ob->pose || ob_get_key(ob))
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC);
|
||||
else
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
||||
switch (mode) {
|
||||
case 'g':
|
||||
{
|
||||
initTransform(TFM_TIME_TRANSLATE, CTX_NONE);
|
||||
Transform();
|
||||
}
|
||||
|
||||
remake_action_ipos((bAction *)data);
|
||||
|
||||
G.saction->flag &= ~SACTION_MOVING;
|
||||
|
||||
if (cancel==0) BIF_undo_push("Transform Action"); // does it have to be here?
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWNLA, 0);
|
||||
allqueue(REDRAWIPO, 0);
|
||||
allqueue(REDRAWTIME, 0);
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
initTransform(TFM_TIME_SCALE, CTX_NONE);
|
||||
Transform();
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
{
|
||||
initTransform(TFM_TIME_SLIDE, CTX_NONE);
|
||||
Transform();
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (datatype == ACTCONT_SHAPEKEY) {
|
||||
/* fix up the Ipocurves and redraw stuff */
|
||||
meshkey_do_redraw((Key *)data);
|
||||
if (cancel==0) BIF_undo_push("Transform Action");
|
||||
}
|
||||
|
||||
MEM_freeN(tv);
|
||||
}
|
||||
|
||||
/* ----------------------------------------- */
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
#include "BIF_toolbox.h"
|
||||
#include "BIF_editnla.h"
|
||||
#include "BIF_editaction.h"
|
||||
#include "BIF_transform.h"
|
||||
|
||||
#include "BSE_editipo.h"
|
||||
#include "BSE_editnla_types.h"
|
||||
@@ -975,291 +976,20 @@ static void recalc_all_ipos(void)
|
||||
|
||||
void transform_nlachannel_keys(int mode, int dummy)
|
||||
{
|
||||
Base *base;
|
||||
TransVert *tv;
|
||||
bActionChannel *chan;
|
||||
bActionStrip *strip;
|
||||
bConstraintChannel *conchan;
|
||||
float sval[2], cval[2], lastcval[2]= {0.0f, 0.0f};
|
||||
float fac=0.0F;
|
||||
float deltax, startx;
|
||||
int i;
|
||||
int loop=1;
|
||||
int tvtot=0;
|
||||
int invert=0, firsttime=1;
|
||||
short mvals[2], mvalc[2];
|
||||
short cancel=0;
|
||||
char str[256];
|
||||
|
||||
/* Ensure that partial selections result in beztriple selections */
|
||||
for (base=G.scene->base.first; base; base=base->next){
|
||||
/* Check object ipos */
|
||||
i= fullselect_ipo_keys(base->object->ipo);
|
||||
if(i) base->flag |= BA_HAS_RECALC_OB;
|
||||
tvtot+=i;
|
||||
|
||||
/* Check object constraint ipos */
|
||||
for(conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
|
||||
tvtot+=fullselect_ipo_keys(conchan->ipo);
|
||||
|
||||
/* skip actions and nlastrips if object is collapsed */
|
||||
if (base->object->nlaflag & OB_NLA_COLLAPSED)
|
||||
continue;
|
||||
|
||||
/* Check action ipos */
|
||||
if (base->object->action){
|
||||
/* exclude if strip is selected too */
|
||||
for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
|
||||
if (strip->flag & ACTSTRIP_SELECT)
|
||||
if(strip->act==base->object->action)
|
||||
break;
|
||||
}
|
||||
if(strip==NULL) {
|
||||
|
||||
for (chan=base->object->action->chanbase.first; chan; chan=chan->next) {
|
||||
if (EDITABLE_ACHAN(chan)) {
|
||||
i= fullselect_ipo_keys(chan->ipo);
|
||||
if(i) base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
|
||||
tvtot+=i;
|
||||
|
||||
/* Check action constraint ipos */
|
||||
if (EXPANDED_ACHAN(chan) && FILTER_CON_ACHAN(chan)) {
|
||||
for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) {
|
||||
if (EDITABLE_CONCHAN(conchan))
|
||||
tvtot+=fullselect_ipo_keys(conchan->ipo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (mode) {
|
||||
case 'g':
|
||||
{
|
||||
initTransform(TFM_TIME_TRANSLATE, CTX_NONE);
|
||||
Transform();
|
||||
}
|
||||
|
||||
/* Check nlastrips */
|
||||
for (strip=base->object->nlastrips.first; strip; strip=strip->next){
|
||||
if (strip->flag & ACTSTRIP_SELECT) {
|
||||
base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
|
||||
tvtot+=2;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
initTransform(TFM_TIME_SCALE, CTX_NONE);
|
||||
Transform();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* If nothing is selected, bail out */
|
||||
if (!tvtot)
|
||||
return;
|
||||
|
||||
|
||||
/* Build the transvert structure */
|
||||
tv = MEM_callocN (sizeof(TransVert) * tvtot, "transVert");
|
||||
tvtot=0;
|
||||
for (base=G.scene->base.first; base; base=base->next){
|
||||
/* Manipulate object ipos */
|
||||
tvtot=add_trans_ipo_keys(base->object->ipo, tv, tvtot);
|
||||
|
||||
/* Manipulate object constraint ipos */
|
||||
for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
|
||||
tvtot=add_trans_ipo_keys(conchan->ipo, tv, tvtot);
|
||||
|
||||
/* skip actions and nlastrips if object collapsed */
|
||||
if (base->object->nlaflag & OB_NLA_COLLAPSED)
|
||||
continue;
|
||||
|
||||
/* Manipulate action ipos */
|
||||
if (base->object->action){
|
||||
/* exclude if strip is selected too */
|
||||
for (strip=base->object->nlastrips.first; strip; strip=strip->next){
|
||||
if (strip->flag & ACTSTRIP_SELECT)
|
||||
if(strip->act==base->object->action)
|
||||
break;
|
||||
}
|
||||
|
||||
/* can include - no selected strip is action */
|
||||
if(strip==NULL) {
|
||||
for (chan=base->object->action->chanbase.first; chan; chan=chan->next){
|
||||
if (EDITABLE_ACHAN(chan)) {
|
||||
tvtot=add_trans_ipo_keys(chan->ipo, tv, tvtot);
|
||||
|
||||
/* Manipulate action constraint ipos */
|
||||
if (EXPANDED_ACHAN(chan) && FILTER_CON_ACHAN(chan)) {
|
||||
for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) {
|
||||
if (EDITABLE_CONCHAN(conchan))
|
||||
tvtot=add_trans_ipo_keys(conchan->ipo, tv, tvtot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Manipulate nlastrips */
|
||||
for (strip=base->object->nlastrips.first; strip; strip=strip->next){
|
||||
if (strip->flag & ACTSTRIP_SELECT){
|
||||
tv[tvtot+0].val=&strip->start;
|
||||
tv[tvtot+1].val=&strip->end;
|
||||
|
||||
tv[tvtot+0].oldval = strip->start;
|
||||
tv[tvtot+1].oldval = strip->end;
|
||||
|
||||
tvtot+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the event loop */
|
||||
// cent[0] = curarea->winx + (G.snla->v2d.hor.xmax)/2;
|
||||
// cent[1] = curarea->winy + (G.snla->v2d.hor.ymax)/2;
|
||||
|
||||
// areamouseco_to_ipoco(cent, &cenf[0], &cenf[1]);
|
||||
|
||||
getmouseco_areawin (mvals);
|
||||
areamouseco_to_ipoco(G.v2d, mvals, &sval[0], &sval[1]);
|
||||
|
||||
startx=sval[0];
|
||||
while (loop) {
|
||||
/* Get the input */
|
||||
/* If we're cancelling, reset transformations */
|
||||
/* Else calc new transformation */
|
||||
/* Perform the transformations */
|
||||
while (qtest()) {
|
||||
short val;
|
||||
unsigned short event= extern_qread(&val);
|
||||
|
||||
if (val) {
|
||||
switch (event) {
|
||||
case LEFTMOUSE:
|
||||
case SPACEKEY:
|
||||
case RETKEY:
|
||||
loop=0;
|
||||
break;
|
||||
case XKEY:
|
||||
break;
|
||||
case ESCKEY:
|
||||
case RIGHTMOUSE:
|
||||
cancel=1;
|
||||
loop=0;
|
||||
break;
|
||||
default:
|
||||
arrows_move_cursor(event);
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (cancel) {
|
||||
for (i=0; i<tvtot; i++) {
|
||||
if (tv[i].loc){
|
||||
tv[i].loc[0]=tv[i].oldloc[0];
|
||||
tv[i].loc[1]=tv[i].oldloc[1];
|
||||
}
|
||||
if (tv[i].val)
|
||||
tv[i].val[0]=tv[i].oldval;
|
||||
}
|
||||
}
|
||||
else {
|
||||
getmouseco_areawin (mvalc);
|
||||
areamouseco_to_ipoco(G.v2d, mvalc, &cval[0], &cval[1]);
|
||||
|
||||
if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) {
|
||||
PIL_sleep_ms(10);
|
||||
}
|
||||
else {
|
||||
for (i=0; i<tvtot; i++){
|
||||
if (tv[i].loc)
|
||||
tv[i].loc[0]=tv[i].oldloc[0];
|
||||
if (tv[i].val)
|
||||
tv[i].val[0]=tv[i].oldval;
|
||||
|
||||
switch (mode){
|
||||
case 'g':
|
||||
deltax = cval[0]-sval[0];
|
||||
fac= deltax;
|
||||
|
||||
apply_keyb_grid(&fac, 0.0F, 1.0F, 0.1F, U.flag & USER_AUTOGRABGRID);
|
||||
|
||||
if (tv[i].loc)
|
||||
tv[i].loc[0]+=fac;
|
||||
if (tv[i].val)
|
||||
tv[i].val[0]+=fac;
|
||||
break;
|
||||
case 's':
|
||||
startx=mvals[0]-(NLAWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
|
||||
deltax=mvalc[0]-(NLAWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
|
||||
fac= (float)fabs(deltax/startx);
|
||||
|
||||
apply_keyb_grid(&fac, 0.0F, 0.2F, 0.1F, U.flag & USER_AUTOSIZEGRID);
|
||||
|
||||
if (invert){
|
||||
if (i % 03 == 0){
|
||||
memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i+2].oldloc));
|
||||
}
|
||||
if (i % 03 == 2){
|
||||
memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i-2].oldloc));
|
||||
}
|
||||
|
||||
fac*=-1;
|
||||
}
|
||||
startx= (G.scene->r.cfra);
|
||||
|
||||
if (tv[i].loc){
|
||||
tv[i].loc[0]-= startx;
|
||||
tv[i].loc[0]*=fac;
|
||||
tv[i].loc[0]+= startx;
|
||||
}
|
||||
if (tv[i].val){
|
||||
tv[i].val[0]-= startx;
|
||||
tv[i].val[0]*=fac;
|
||||
tv[i].val[0]+= startx;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode=='s'){
|
||||
sprintf(str, "scaleX: %.3f", fac);
|
||||
headerprint(str);
|
||||
}
|
||||
else if (mode=='g'){
|
||||
sprintf(str, "deltaX: %.3f", fac);
|
||||
headerprint(str);
|
||||
}
|
||||
|
||||
if (G.snla->lock) {
|
||||
for (base=G.scene->base.first; base; base=base->next){
|
||||
if(base->flag & BA_HAS_RECALC_OB)
|
||||
base->object->recalc |= OB_RECALC_OB;
|
||||
if(base->flag & BA_HAS_RECALC_DATA)
|
||||
base->object->recalc |= OB_RECALC_DATA;
|
||||
|
||||
if(base->object->recalc) base->object->ctime= -1234567.0f; // eveil!
|
||||
}
|
||||
|
||||
DAG_scene_flush_update(G.scene, screen_view3d_layers());
|
||||
|
||||
force_draw_all(0);
|
||||
}
|
||||
else {
|
||||
force_draw(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastcval[0]= cval[0];
|
||||
lastcval[1]= cval[1];
|
||||
firsttime= 0;
|
||||
}
|
||||
|
||||
synchronize_action_strips();
|
||||
|
||||
/* cleanup */
|
||||
for (base=G.scene->base.first; base; base=base->next)
|
||||
base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA);
|
||||
|
||||
if(cancel==0) BIF_undo_push("Select all NLA");
|
||||
recalc_all_ipos(); // bad
|
||||
allqueue (REDRAWVIEW3D, 0);
|
||||
allqueue (REDRAWNLA, 0);
|
||||
allqueue (REDRAWIPO, 0);
|
||||
MEM_freeN (tv);
|
||||
}
|
||||
|
||||
void delete_nlachannel_keys(void)
|
||||
|
||||
@@ -597,10 +597,10 @@ static void do_action_keymenu_transformmenu(void *arg, int event)
|
||||
transform_action_keys('g', 0);
|
||||
break;
|
||||
case ACTMENU_KEY_TRANSFORM_SCALE:
|
||||
transform_action_keys ('s', 0);
|
||||
transform_action_keys('s', 0);
|
||||
break;
|
||||
case ACTMENU_KEY_TRANSFORM_SLIDE:
|
||||
transform_action_keys ('t', 0);
|
||||
transform_action_keys('t', 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_action_types.h" /* for some special action-editor settings */
|
||||
#include "DNA_ipo_types.h" /* some silly ipo flag */
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
@@ -75,11 +76,15 @@
|
||||
#include "BIF_editmesh.h"
|
||||
#include "BIF_editsima.h"
|
||||
#include "BIF_drawimage.h" /* uvco_to_areaco_noclip */
|
||||
#include "BIF_editaction.h"
|
||||
|
||||
#include "BKE_action.h" /* get_action_frame */
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_bad_level_calls.h"/* popmenu and error */
|
||||
|
||||
#include "BSE_drawipo.h"
|
||||
#include "BSE_editnla_types.h" /* for NLAWIDTH */
|
||||
#include "BSE_view.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
@@ -350,7 +355,7 @@ void convertDisplayNumToVec(float *num, float *vec)
|
||||
|
||||
static void viewRedrawForce(TransInfo *t)
|
||||
{
|
||||
if(t->spacetype==SPACE_VIEW3D)
|
||||
if(ELEM4(t->spacetype, SPACE_VIEW3D, SPACE_ACTION, SPACE_NLA, SPACE_IPO))
|
||||
force_draw(0);
|
||||
else if(t->spacetype==SPACE_IMAGE) {
|
||||
if(G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
|
||||
@@ -368,6 +373,14 @@ static void viewRedrawPost(TransInfo *t)
|
||||
allqueue(REDRAWIMAGE, 0);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
}
|
||||
else if(ELEM3(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) {
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWNLA, 0);
|
||||
allqueue(REDRAWIPO, 0);
|
||||
allqueue(REDRAWTIME, 0);
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
}
|
||||
|
||||
scrarea_queue_headredraw(curarea);
|
||||
}
|
||||
@@ -492,6 +505,12 @@ static char *transform_to_undostr(TransInfo *t)
|
||||
return "Bone Width";
|
||||
case TFM_BONE_ENVELOPE:
|
||||
return "Bone Envelope";
|
||||
case TFM_TIME_TRANSLATE:
|
||||
return "Translate Anim. Data";
|
||||
case TFM_TIME_SCALE:
|
||||
return "Scale Anim. Data";
|
||||
case TFM_TIME_SLIDE:
|
||||
return "Time Slide";
|
||||
}
|
||||
return "Transform";
|
||||
}
|
||||
@@ -884,6 +903,15 @@ void initTransform(int mode, int context) {
|
||||
case TFM_BONE_ROLL:
|
||||
initBoneRoll(&Trans);
|
||||
break;
|
||||
case TFM_TIME_TRANSLATE:
|
||||
initTimeTranslate(&Trans);
|
||||
break;
|
||||
case TFM_TIME_SLIDE:
|
||||
initTimeSlide(&Trans);
|
||||
break;
|
||||
case TFM_TIME_SCALE:
|
||||
initTimeScale(&Trans);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3191,6 +3219,477 @@ void Mirror(short mode)
|
||||
viewRedrawPost(&Trans);
|
||||
}
|
||||
|
||||
/* ************************** ANIM EDITORS - TRANSFORM TOOLS *************************** */
|
||||
|
||||
/* ---------------- Special Helpers for Various Settings ------------- */
|
||||
|
||||
/* This function returns the snapping 'mode' for Animation Editors only
|
||||
* We cannot use the standard snapping due to NLA-strip scaling complexities.
|
||||
*/
|
||||
static short getAnimEdit_SnapMode(TransInfo *t)
|
||||
{
|
||||
short autosnap= SACTSNAP_OFF;
|
||||
|
||||
/* currently, some of these are only for the action editor */
|
||||
if (t->spacetype == SPACE_ACTION && G.saction) {
|
||||
switch (G.saction->autosnap) {
|
||||
case SACTSNAP_OFF:
|
||||
if (G.qual == LR_CTRLKEY)
|
||||
autosnap= SACTSNAP_STEP;
|
||||
else if (G.qual == LR_SHIFTKEY)
|
||||
autosnap= SACTSNAP_FRAME;
|
||||
else
|
||||
autosnap= SACTSNAP_OFF;
|
||||
break;
|
||||
case SACTSNAP_STEP:
|
||||
autosnap= (G.qual==LR_CTRLKEY)? SACTSNAP_OFF: SACTSNAP_STEP;
|
||||
break;
|
||||
case SACTSNAP_FRAME:
|
||||
autosnap= (G.qual==LR_SHIFTKEY)? SACTSNAP_OFF: SACTSNAP_FRAME;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (G.qual == LR_CTRLKEY)
|
||||
autosnap= SACTSNAP_STEP;
|
||||
else if (G.qual == LR_SHIFTKEY)
|
||||
autosnap= SACTSNAP_FRAME;
|
||||
else
|
||||
autosnap= SACTSNAP_OFF;
|
||||
}
|
||||
|
||||
return autosnap;
|
||||
}
|
||||
|
||||
/* This function is used for testing if an Animation Editor is displaying
|
||||
* its data in frames or seconds (and the data needing to be edited as such).
|
||||
* Returns 1 if in seconds, 0 if in frames
|
||||
*/
|
||||
static short getAnimEdit_DrawTime(TransInfo *t)
|
||||
{
|
||||
short drawtime;
|
||||
|
||||
/* currently, some of these are only for the action editor */
|
||||
if (t->spacetype == SPACE_ACTION && G.saction) {
|
||||
if (G.saction->flag & SACTION_DRAWTIME)
|
||||
drawtime = 1;
|
||||
else
|
||||
drawtime = 0;
|
||||
}
|
||||
else {
|
||||
drawtime = 0;
|
||||
}
|
||||
|
||||
return drawtime;
|
||||
}
|
||||
|
||||
|
||||
/* This function is used by Animation Editor specific transform functions to do
|
||||
* the Snap Keyframe to Nearest Keyframe
|
||||
*/
|
||||
static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short autosnap)
|
||||
{
|
||||
/* snap key to nearest frame? */
|
||||
if (autosnap == SACTSNAP_FRAME) {
|
||||
short doTime= getAnimEdit_DrawTime(t);
|
||||
float secf= ((float)G.scene->r.frs_sec);
|
||||
float val;
|
||||
|
||||
/* convert frame to nla-action time (if needed) */
|
||||
if (ob)
|
||||
val= get_action_frame_inv(ob, *(td->val));
|
||||
else
|
||||
val= *(td->val);
|
||||
|
||||
/* do the snapping to nearest frame/second */
|
||||
if (doTime)
|
||||
val= (float)( floor((val/secf) + 0.5f) * secf );
|
||||
else
|
||||
val= (float)( floor(val+0.5f) );
|
||||
|
||||
/* convert frame out of nla-action time */
|
||||
if (ob)
|
||||
*(td->val)= get_action_frame(ob, val);
|
||||
else
|
||||
*(td->val)= val;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------- Translation ----------------------- */
|
||||
|
||||
void initTimeTranslate(TransInfo *t)
|
||||
{
|
||||
t->mode = TFM_TIME_TRANSLATE;
|
||||
t->transform = TimeTranslate;
|
||||
|
||||
/* num-input has max of (n-1) */
|
||||
t->idx_max = 0;
|
||||
t->num.flag = 0;
|
||||
t->num.idx_max = t->idx_max;
|
||||
|
||||
/* initialise snap like for everything else */
|
||||
t->snap[0] = 0.0f;
|
||||
t->snap[1] = t->snap[2] = 1.0f;
|
||||
}
|
||||
|
||||
static void headerTimeTranslate(TransInfo *t, char *str)
|
||||
{
|
||||
char tvec[60];
|
||||
|
||||
/* if numeric input is active, use results from that, otherwise apply snapping to result */
|
||||
if (hasNumInput(&t->num)) {
|
||||
outputNumInput(&(t->num), tvec);
|
||||
}
|
||||
else {
|
||||
short autosnap= getAnimEdit_SnapMode(t);
|
||||
short doTime = getAnimEdit_DrawTime(t);
|
||||
float secf= ((float)G.scene->r.frs_sec);
|
||||
float val= t->fac;
|
||||
|
||||
/* take into account scaling (for Action Editor only) */
|
||||
if ((t->spacetype == SPACE_ACTION) && (NLA_ACTION_SCALED)) {
|
||||
float cval, sval[2];
|
||||
|
||||
/* recalculate the delta based on 'visual' times */
|
||||
areamouseco_to_ipoco(G.v2d, t->imval, &sval[0], &sval[1]);
|
||||
cval= sval[0] + t->fac;
|
||||
|
||||
val = get_action_frame_inv(OBACT, cval);
|
||||
val -= get_action_frame_inv(OBACT, sval[0]);
|
||||
}
|
||||
|
||||
/* apply snapping + frame->seconds conversions */
|
||||
if (autosnap == SACTSNAP_STEP) {
|
||||
if (doTime)
|
||||
val= floor(val/secf + 0.5f);
|
||||
else
|
||||
val= floor(val + 0.5f);
|
||||
}
|
||||
else {
|
||||
if (doTime)
|
||||
val= val / secf;
|
||||
}
|
||||
|
||||
sprintf(&tvec[0], "%.4f", val);
|
||||
}
|
||||
|
||||
sprintf(str, "DeltaX: %s", &tvec[0]);
|
||||
}
|
||||
|
||||
static void applyTimeTranslate(TransInfo *t, float sval)
|
||||
{
|
||||
TransData *td = t->data;
|
||||
int i;
|
||||
|
||||
short doTime= getAnimEdit_DrawTime(t);
|
||||
float secf= ((float)G.scene->r.frs_sec);
|
||||
|
||||
short autosnap= getAnimEdit_SnapMode(t);
|
||||
float cval= sval + t->fac;
|
||||
|
||||
float deltax, val;
|
||||
|
||||
/* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
|
||||
for (i = 0 ; i < t->total; i++, td++) {
|
||||
/* it is assumed that td->ob is a pointer to the object,
|
||||
* whose active action is where this keyframe comes from
|
||||
*/
|
||||
Object *ob= td->ob;
|
||||
|
||||
/* check if any need to apply nla-scaling */
|
||||
if (ob) {
|
||||
deltax = get_action_frame_inv(ob, cval);
|
||||
deltax -= get_action_frame_inv(ob, sval);
|
||||
|
||||
if (autosnap == SACTSNAP_STEP) {
|
||||
if (doTime)
|
||||
deltax= (float)( floor((deltax/secf) + 0.5f) * secf );
|
||||
else
|
||||
deltax= (float)( floor(deltax + 0.5f) );
|
||||
}
|
||||
|
||||
val = get_action_frame_inv(ob, td->ival);
|
||||
val += deltax;
|
||||
*(td->val) = get_action_frame(ob, val);
|
||||
}
|
||||
else {
|
||||
deltax = val = t->fac;
|
||||
|
||||
if (autosnap == SACTSNAP_STEP) {
|
||||
if (doTime)
|
||||
val= (float)( floor((deltax/secf) + 0.5f) * secf );
|
||||
else
|
||||
val= (float)( floor(val + 0.5f) );
|
||||
}
|
||||
|
||||
*(td->val) = td->ival + val;
|
||||
}
|
||||
|
||||
/* apply snap-to-nearest-frame? */
|
||||
doAnimEdit_SnapFrame(t, td, ob, autosnap);
|
||||
}
|
||||
}
|
||||
|
||||
int TimeTranslate(TransInfo *t, short mval[2])
|
||||
{
|
||||
float cval[2], sval[2];
|
||||
char str[200];
|
||||
|
||||
/* calculate translation amount from mouse movement - in 'time-grid space' */
|
||||
areamouseco_to_ipoco(G.v2d, mval, &cval[0], &cval[1]);
|
||||
areamouseco_to_ipoco(G.v2d, t->imval, &sval[0], &sval[1]);
|
||||
|
||||
/* we only need to calculate effect for time (applyTimeTranslate only needs that) */
|
||||
t->fac= cval[0] - sval[0];
|
||||
|
||||
/* handle numeric-input stuff */
|
||||
t->vec[0] = t->fac;
|
||||
applyNumInput(&t->num, &t->vec[0]);
|
||||
t->fac = t->vec[0];
|
||||
headerTimeTranslate(t, str);
|
||||
|
||||
applyTimeTranslate(t, sval[0]);
|
||||
|
||||
recalcData(t);
|
||||
|
||||
headerprint(str);
|
||||
|
||||
viewRedrawForce(t);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ----------------- Time Slide ----------------------- */
|
||||
|
||||
void initTimeSlide(TransInfo *t)
|
||||
{
|
||||
/* this tool is only really available in the Action Editor... */
|
||||
if (t->spacetype == SPACE_ACTION) {
|
||||
/* set flag for drawing stuff*/
|
||||
G.saction->flag |= SACTION_MOVING;
|
||||
}
|
||||
|
||||
t->mode = TFM_TIME_SLIDE;
|
||||
t->transform = TimeSlide;
|
||||
t->flag |= T_FREE_CUSTOMDATA;
|
||||
|
||||
/* num-input has max of (n-1) */
|
||||
t->idx_max = 0;
|
||||
t->num.flag = 0;
|
||||
t->num.idx_max = t->idx_max;
|
||||
|
||||
/* initialise snap like for everything else */
|
||||
t->snap[0] = 0.0f;
|
||||
t->snap[1] = t->snap[2] = 1.0f;
|
||||
}
|
||||
|
||||
static void headerTimeSlide(TransInfo *t, float sval, char *str)
|
||||
{
|
||||
char tvec[60];
|
||||
|
||||
if (hasNumInput(&t->num)) {
|
||||
outputNumInput(&(t->num), tvec);
|
||||
}
|
||||
else {
|
||||
float minx= *((float *)(t->customData));
|
||||
float maxx= *((float *)(t->customData + 1));
|
||||
float cval= t->fac;
|
||||
float val;
|
||||
|
||||
val= 2.0*(cval-sval) / (maxx-minx);
|
||||
CLAMP(val, -1.0f, 1.0f);
|
||||
|
||||
sprintf(&tvec[0], "%.4f", val);
|
||||
}
|
||||
|
||||
sprintf(str, "TimeSlide: %s", &tvec[0]);
|
||||
}
|
||||
|
||||
static void applyTimeSlide(TransInfo *t, float sval)
|
||||
{
|
||||
TransData *td = t->data;
|
||||
int i;
|
||||
|
||||
float minx= *((float *)(t->customData));
|
||||
float maxx= *((float *)(t->customData + 1));
|
||||
|
||||
/* set value for drawing black line */
|
||||
if (t->spacetype == SPACE_ACTION) {
|
||||
G.saction->timeslide= t->fac;
|
||||
|
||||
if (NLA_ACTION_SCALED)
|
||||
sval= get_action_frame(OBACT, sval);
|
||||
}
|
||||
|
||||
/* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
|
||||
for (i = 0 ; i < t->total; i++, td++) {
|
||||
/* it is assumed that td->ob is a pointer to the object,
|
||||
* whose active action is where this keyframe comes from
|
||||
*/
|
||||
Object *ob= td->ob;
|
||||
float cval = t->fac;
|
||||
|
||||
/* apply scaling to necessary values */
|
||||
if (ob)
|
||||
cval= get_action_frame(ob, cval);
|
||||
|
||||
/* only apply to data if in range */
|
||||
if (sval > minx && sval < maxx) {
|
||||
float cvalc= CLAMPIS(cval, minx, maxx);
|
||||
float timefac;
|
||||
|
||||
/* left half? */
|
||||
if (td->ival < sval) {
|
||||
timefac= (sval - td->ival) / (sval - minx);
|
||||
*(td->val)= cvalc - timefac * (cvalc - minx);
|
||||
}
|
||||
else {
|
||||
timefac= (td->ival - sval) / (maxx - sval);
|
||||
*(td->val)= cvalc + timefac * (maxx - cvalc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int TimeSlide(TransInfo *t, short mval[2])
|
||||
{
|
||||
float cval[2], sval[2];
|
||||
char str[200];
|
||||
|
||||
/* calculate mouse co-ordinates */
|
||||
areamouseco_to_ipoco(G.v2d, mval, &cval[0], &cval[1]);
|
||||
areamouseco_to_ipoco(G.v2d, t->imval, &sval[0], &sval[1]);
|
||||
|
||||
/* calculate fake value to work with */
|
||||
t->fac= cval[0];
|
||||
|
||||
/* handle numeric-input stuff */
|
||||
t->vec[0] = t->fac;
|
||||
applyNumInput(&t->num, &t->vec[0]);
|
||||
t->fac = t->vec[0];
|
||||
headerTimeSlide(t, sval[0], str);
|
||||
|
||||
applyTimeSlide(t, sval[0]);
|
||||
|
||||
recalcData(t);
|
||||
|
||||
headerprint(str);
|
||||
|
||||
viewRedrawForce(t);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ----------------- Scaling ----------------------- */
|
||||
|
||||
void initTimeScale(TransInfo *t)
|
||||
{
|
||||
t->mode = TFM_TIME_SCALE;
|
||||
t->transform = TimeScale;
|
||||
|
||||
t->flag |= T_NULL_ONE;
|
||||
t->num.flag |= NUM_NULL_ONE;
|
||||
|
||||
/* num-input has max of (n-1) */
|
||||
t->idx_max = 0;
|
||||
t->num.flag = 0;
|
||||
t->num.idx_max = t->idx_max;
|
||||
|
||||
/* initialise snap like for everything else */
|
||||
t->snap[0] = 0.0f;
|
||||
t->snap[1] = t->snap[2] = 1.0f;
|
||||
}
|
||||
|
||||
static void headerTimeScale(TransInfo *t, char *str) {
|
||||
char tvec[60];
|
||||
|
||||
if (hasNumInput(&t->num))
|
||||
outputNumInput(&(t->num), tvec);
|
||||
else
|
||||
sprintf(&tvec[0], "%.4f", t->fac);
|
||||
|
||||
sprintf(str, "ScaleX: %s", &tvec[0]);
|
||||
}
|
||||
|
||||
static void applyTimeScale(TransInfo *t) {
|
||||
TransData *td = t->data;
|
||||
int i;
|
||||
|
||||
short autosnap= getAnimEdit_SnapMode(t);
|
||||
short doTime= getAnimEdit_DrawTime(t);
|
||||
float secf= ((float)G.scene->r.frs_sec);
|
||||
|
||||
|
||||
for (i = 0 ; i < t->total; i++, td++) {
|
||||
/* it is assumed that td->ob is a pointer to the object,
|
||||
* whose active action is where this keyframe comes from
|
||||
*/
|
||||
Object *ob= td->ob;
|
||||
float startx= CFRA;
|
||||
float fac= t->fac;
|
||||
|
||||
if (autosnap == SACTSNAP_STEP) {
|
||||
if (doTime)
|
||||
fac= (float)( floor(fac/secf + 0.5f) * secf );
|
||||
else
|
||||
fac= (float)( floor(fac + 0.5f) );
|
||||
}
|
||||
|
||||
/* check if any need to apply nla-scaling */
|
||||
if (ob)
|
||||
startx= get_action_frame(ob, startx);
|
||||
|
||||
/* now, calculate the new value */
|
||||
*(td->val) = td->ival - startx;
|
||||
*(td->val) *= fac;
|
||||
*(td->val) += startx;
|
||||
|
||||
/* apply snap-to-nearest-frame? */
|
||||
doAnimEdit_SnapFrame(t, td, ob, autosnap);
|
||||
}
|
||||
}
|
||||
|
||||
int TimeScale(TransInfo *t, short mval[2])
|
||||
{
|
||||
float cval, sval;
|
||||
float deltax, startx;
|
||||
float width= 0.0f;
|
||||
char str[200];
|
||||
|
||||
sval= t->imval[0];
|
||||
cval= mval[0];
|
||||
|
||||
switch (t->spacetype) {
|
||||
case SPACE_ACTION:
|
||||
width= ACTWIDTH;
|
||||
break;
|
||||
case SPACE_NLA:
|
||||
width= NLAWIDTH;
|
||||
break;
|
||||
}
|
||||
|
||||
/* calculate scaling factor */
|
||||
startx= sval-(width/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
|
||||
deltax= cval-(width/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
|
||||
t->fac = deltax / startx;
|
||||
|
||||
/* handle numeric-input stuff */
|
||||
t->vec[0] = t->fac;
|
||||
applyNumInput(&t->num, &t->vec[0]);
|
||||
t->fac = t->vec[0];
|
||||
headerTimeScale(t, str);
|
||||
|
||||
applyTimeScale(t);
|
||||
|
||||
recalcData(t);
|
||||
|
||||
headerprint(str);
|
||||
|
||||
viewRedrawForce(t);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ************************************ */
|
||||
|
||||
void BIF_TransformSetUndo(char *str)
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_meta_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_nla_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_scene_types.h"
|
||||
@@ -85,6 +86,8 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_ipo.h"
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mball.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
@@ -98,6 +101,7 @@
|
||||
#include "BIF_editconstraint.h"
|
||||
#include "BIF_editarmature.h"
|
||||
#include "BIF_editmesh.h"
|
||||
#include "BIF_editnla.h"
|
||||
#include "BIF_editsima.h"
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_poseobject.h"
|
||||
@@ -112,6 +116,7 @@
|
||||
#include "BSE_edit.h"
|
||||
#include "BSE_editipo.h"
|
||||
#include "BSE_editipo_types.h"
|
||||
#include "BSE_editaction_types.h"
|
||||
|
||||
#include "BDR_editobject.h" // reset_slowparents()
|
||||
#include "BDR_unwrapper.h"
|
||||
@@ -1982,6 +1987,256 @@ int clipUVTransform(TransInfo *t, float *vec, int resize)
|
||||
return (clipx || clipy);
|
||||
}
|
||||
|
||||
/* ********************* ACTION/NLA EDITOR ****************** */
|
||||
|
||||
|
||||
static void TimeToTransData(TransData *td, float *time, Object *ob)
|
||||
{
|
||||
/* memory is calloc'ed, so that should zero everything nicely for us */
|
||||
td->val = time;
|
||||
td->ival = *(time);
|
||||
|
||||
/* store the Object where this keyframe exists as a keyframe of the
|
||||
* active action as td->ob. Usually, this member is only used for constraints
|
||||
* drawing
|
||||
*/
|
||||
td->ob= ob;
|
||||
}
|
||||
|
||||
/* This function advances the address to which td points to, so it must return
|
||||
* the new address so that the next time new transform data is added, it doesn't
|
||||
* overwrite the existing ones... i.e. td = IpoToTransData(td, ipo, ob);
|
||||
*/
|
||||
static TransData *IpoToTransData(TransData *td, Ipo *ipo, Object *ob)
|
||||
{
|
||||
IpoCurve *icu;
|
||||
BezTriple *bezt;
|
||||
int i;
|
||||
|
||||
if (ipo == NULL)
|
||||
return td;
|
||||
|
||||
for (icu= ipo->curve.first; icu; icu= icu->next) {
|
||||
/* only add selected keyframes (for now, proportional edit is not enabled) */
|
||||
for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
|
||||
if (BEZSELECTED(bezt)) {
|
||||
/* each control point needs to be added separetely */
|
||||
TimeToTransData(td, bezt->vec[0], ob);
|
||||
td++;
|
||||
|
||||
TimeToTransData(td, bezt->vec[1], ob);
|
||||
td++;
|
||||
|
||||
TimeToTransData(td, bezt->vec[2], ob);
|
||||
td++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return td;
|
||||
}
|
||||
|
||||
static void createTransActionData(TransInfo *t)
|
||||
{
|
||||
TransData *td = NULL;
|
||||
Object *ob= NULL;
|
||||
|
||||
ListBase act_data = {NULL, NULL};
|
||||
bActListElem *ale;
|
||||
void *data;
|
||||
short datatype;
|
||||
int filter;
|
||||
|
||||
int count=0;
|
||||
|
||||
/* determine what type of data we are operating on */
|
||||
data = get_action_context(&datatype);
|
||||
if (data == NULL) return;
|
||||
|
||||
/* filter data */
|
||||
filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
|
||||
actdata_filter(&act_data, filter, data, datatype);
|
||||
|
||||
/* is the action scaled? if so, the it should belong to the active object */
|
||||
if (NLA_ACTION_SCALED)
|
||||
ob= OBACT;
|
||||
|
||||
/* loop 1: fully select ipo-keys and count how many BezTriples are selected */
|
||||
for (ale= act_data.first; ale; ale= ale->next)
|
||||
count += fullselect_ipo_keys(ale->key_data);
|
||||
|
||||
/* stop if trying to build list if nothing selected */
|
||||
if (count == 0) {
|
||||
/* cleanup temp list */
|
||||
BLI_freelistN(&act_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate memory for data */
|
||||
t->total= count;
|
||||
t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)");
|
||||
if (t->mode == TFM_TIME_SLIDE)
|
||||
t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max");
|
||||
|
||||
td= t->data;
|
||||
/* loop 2: build transdata array */
|
||||
for (ale= act_data.first; ale; ale= ale->next) {
|
||||
Ipo *ipo= (Ipo *)ale->key_data;
|
||||
|
||||
td= IpoToTransData(td, ipo, ob);
|
||||
}
|
||||
|
||||
/* check if we're supposed to be setting minx/maxx for TimeSlide */
|
||||
if (t->mode == TFM_TIME_SLIDE) {
|
||||
float min = 0, max = 0;
|
||||
int i;
|
||||
|
||||
td= (t->data + 1);
|
||||
for (i=1; i < count; i+=3, td+=3) {
|
||||
if (min > *(td->val)) min= *(td->val);
|
||||
if (max < *(td->val)) max= *(td->val);
|
||||
}
|
||||
|
||||
/* minx/maxx values used by TimeSlide are stored as a
|
||||
* calloced 2-float array in t->customData. This gets freed
|
||||
* in postTrans (T_FREE_CUSTOMDATA).
|
||||
*/
|
||||
*((float *)(t->customData)) = min;
|
||||
*((float *)(t->customData + 1)) = max;
|
||||
}
|
||||
|
||||
/* cleanup temp list */
|
||||
BLI_freelistN(&act_data);
|
||||
}
|
||||
|
||||
static void createTransNLAData(TransInfo *t)
|
||||
{
|
||||
Base *base;
|
||||
bActionStrip *strip;
|
||||
bActionChannel *achan;
|
||||
bConstraintChannel *conchan;
|
||||
|
||||
TransData *td = NULL;
|
||||
int count=0, i;
|
||||
|
||||
/* Ensure that partial selections result in beztriple selections */
|
||||
for (base=G.scene->base.first; base; base=base->next) {
|
||||
/* Check object ipos */
|
||||
i= fullselect_ipo_keys(base->object->ipo);
|
||||
if (i) base->flag |= BA_HAS_RECALC_OB;
|
||||
count += i;
|
||||
|
||||
/* Check object constraint ipos */
|
||||
for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
|
||||
count += fullselect_ipo_keys(conchan->ipo);
|
||||
|
||||
/* skip actions and nlastrips if object is collapsed */
|
||||
if (base->object->nlaflag & OB_NLA_COLLAPSED)
|
||||
continue;
|
||||
|
||||
/* Check action ipos */
|
||||
if (base->object->action) {
|
||||
/* exclude if strip is selected too */
|
||||
for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
|
||||
if (strip->flag & ACTSTRIP_SELECT)
|
||||
if (strip->act == base->object->action)
|
||||
break;
|
||||
}
|
||||
if (strip==NULL) {
|
||||
for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
|
||||
if (EDITABLE_ACHAN(achan)) {
|
||||
i= fullselect_ipo_keys(achan->ipo);
|
||||
if (i) base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
|
||||
count += i;
|
||||
|
||||
/* Check action constraint ipos */
|
||||
if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
|
||||
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
|
||||
if (EDITABLE_CONCHAN(conchan))
|
||||
count += fullselect_ipo_keys(conchan->ipo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check nlastrips */
|
||||
for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
|
||||
if (strip->flag & ACTSTRIP_SELECT) {
|
||||
base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
|
||||
count += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If nothing is selected, bail out */
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
/* allocate memory for data */
|
||||
t->total= count;
|
||||
t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (NLA Editor)");
|
||||
|
||||
/* build the transdata structure */
|
||||
td= t->data;
|
||||
for (base=G.scene->base.first; base; base=base->next) {
|
||||
/* Manipulate object ipos */
|
||||
/* - no scaling of keyframe times is allowed here */
|
||||
td= IpoToTransData(td, base->object->ipo, NULL);
|
||||
|
||||
/* Manipulate object constraint ipos */
|
||||
/* - no scaling of keyframe times is allowed here */
|
||||
for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
|
||||
td= IpoToTransData(td, conchan->ipo, NULL);
|
||||
|
||||
/* skip actions and nlastrips if object collapsed */
|
||||
if (base->object->nlaflag & OB_NLA_COLLAPSED)
|
||||
continue;
|
||||
|
||||
/* Manipulate action ipos */
|
||||
if (base->object->action) {
|
||||
/* exclude if strip that active action belongs to is selected too */
|
||||
for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
|
||||
if (strip->flag & ACTSTRIP_SELECT)
|
||||
if (strip->act == base->object->action)
|
||||
break;
|
||||
}
|
||||
|
||||
/* can include if no strip found */
|
||||
if (strip==NULL) {
|
||||
for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
|
||||
if (EDITABLE_ACHAN(achan)) {
|
||||
td= IpoToTransData(td, achan->ipo, base->object);
|
||||
|
||||
/* Manipulate action constraint ipos */
|
||||
if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
|
||||
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
|
||||
if (EDITABLE_CONCHAN(conchan))
|
||||
td= IpoToTransData(td, conchan->ipo, base->object);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Manipulate nlastrips */
|
||||
for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
|
||||
if (strip->flag & ACTSTRIP_SELECT) {
|
||||
/* first TransData is the start, second is the end */
|
||||
td->val = &strip->start;
|
||||
td->ival = strip->start;
|
||||
td++;
|
||||
|
||||
td->val = &strip->end;
|
||||
td->ival = strip->end;
|
||||
td++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* **************** IpoKey stuff, for Object TransData ********** */
|
||||
|
||||
/* storage of bezier triple. thats why -3 and +3! */
|
||||
@@ -2414,8 +2669,23 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik)
|
||||
}
|
||||
}
|
||||
|
||||
/* very bad call!!! - copied from editnla.c! */
|
||||
static void recalc_all_ipos(void)
|
||||
{
|
||||
Ipo *ipo;
|
||||
IpoCurve *icu;
|
||||
|
||||
/* Go to each ipo */
|
||||
for (ipo=G.main->ipo.first; ipo; ipo=ipo->id.next){
|
||||
for (icu = ipo->curve.first; icu; icu=icu->next){
|
||||
sort_time_ipocurve(icu);
|
||||
testhandles_ipocurve(icu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
|
||||
/* note; transdata has been freed already! */
|
||||
/* note: transdata has been freed already! */
|
||||
void special_aftertrans_update(TransInfo *t)
|
||||
{
|
||||
Object *ob;
|
||||
@@ -2423,7 +2693,56 @@ void special_aftertrans_update(TransInfo *t)
|
||||
int redrawipo=0;
|
||||
int cancelled= (t->state == TRANS_CANCEL);
|
||||
|
||||
if(G.obedit) {
|
||||
if(t->spacetype == SPACE_ACTION) {
|
||||
void *data;
|
||||
short datatype;
|
||||
|
||||
/* determine what type of data we are operating on */
|
||||
data = get_action_context(&datatype);
|
||||
if (data == NULL) return;
|
||||
ob = OBACT;
|
||||
|
||||
if (datatype == ACTCONT_ACTION) {
|
||||
/* Update the curve */
|
||||
/* Depending on the lock status, draw necessary views */
|
||||
if (ob) {
|
||||
ob->ctime= -1234567.0f;
|
||||
|
||||
if(ob->pose || ob_get_key(ob))
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC);
|
||||
else
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
||||
}
|
||||
|
||||
remake_action_ipos((bAction *)data);
|
||||
|
||||
G.saction->flag &= ~SACTION_MOVING;
|
||||
}
|
||||
else if (datatype == ACTCONT_SHAPEKEY) {
|
||||
/* fix up the Ipocurves and redraw stuff */
|
||||
Key *key= (Key *)data;
|
||||
if (key->ipo) {
|
||||
IpoCurve *icu;
|
||||
|
||||
for (icu = key->ipo->curve.first; icu; icu=icu->next) {
|
||||
sort_time_ipocurve(icu);
|
||||
testhandles_ipocurve(icu);
|
||||
}
|
||||
}
|
||||
|
||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
|
||||
}
|
||||
}
|
||||
else if(t->spacetype == SPACE_NLA) {
|
||||
synchronize_action_strips();
|
||||
|
||||
/* cleanup */
|
||||
for (base=G.scene->base.first; base; base=base->next)
|
||||
base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA);
|
||||
|
||||
recalc_all_ipos(); // bad
|
||||
}
|
||||
else if(G.obedit) {
|
||||
if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
|
||||
@@ -2657,6 +2976,14 @@ void createTransData(TransInfo *t)
|
||||
sort_trans_data_dist(t);
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_ACTION) {
|
||||
t->flag |= T_POINTS|T_2D_EDIT;
|
||||
createTransActionData(t);
|
||||
}
|
||||
else if (t->spacetype == SPACE_NLA) {
|
||||
t->flag |= T_POINTS|T_2D_EDIT;
|
||||
createTransNLAData(t);
|
||||
}
|
||||
else if (G.obedit) {
|
||||
t->ext = NULL;
|
||||
if (G.obedit->type == OB_MESH) {
|
||||
|
||||
@@ -54,8 +54,10 @@
|
||||
#include "BIF_resources.h"
|
||||
#include "BIF_mywindow.h"
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_editaction.h"
|
||||
#include "BIF_editarmature.h"
|
||||
#include "BIF_editmesh.h"
|
||||
#include "BIF_editnla.h"
|
||||
#include "BIF_editsima.h"
|
||||
#include "BIF_meshtools.h"
|
||||
#include "BIF_retopo.h"
|
||||
@@ -75,6 +77,7 @@
|
||||
#include "BKE_group.h"
|
||||
#include "BKE_ipo.h"
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
@@ -85,6 +88,7 @@
|
||||
#endif
|
||||
|
||||
#include "BSE_view.h"
|
||||
#include "BSE_editaction_types.h"
|
||||
#include "BDR_unwrapper.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
@@ -216,7 +220,46 @@ void recalcData(TransInfo *t)
|
||||
struct TransData *td;
|
||||
#endif
|
||||
|
||||
if (G.obedit) {
|
||||
if (t->spacetype == SPACE_ACTION) {
|
||||
Object *ob= OBACT;
|
||||
void *data;
|
||||
short context;
|
||||
|
||||
/* determine what type of data we are operating on */
|
||||
data = get_action_context(&context);
|
||||
if (data == NULL) return;
|
||||
|
||||
if (G.saction->lock) {
|
||||
if (context == ACTCONT_ACTION) {
|
||||
if(ob) {
|
||||
ob->ctime= -1234567.0f;
|
||||
if(ob->pose || ob_get_key(ob))
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC);
|
||||
else
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
||||
}
|
||||
}
|
||||
else if (context == ACTCONT_SHAPEKEY) {
|
||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_NLA) {
|
||||
if (G.snla->lock) {
|
||||
for (base=G.scene->base.first; base; base=base->next) {
|
||||
if (base->flag & BA_HAS_RECALC_OB)
|
||||
base->object->recalc |= OB_RECALC_OB;
|
||||
if (base->flag & BA_HAS_RECALC_DATA)
|
||||
base->object->recalc |= OB_RECALC_DATA;
|
||||
|
||||
if (base->object->recalc)
|
||||
base->object->ctime= -1234567.0f; // eveil!
|
||||
}
|
||||
|
||||
DAG_scene_flush_update(G.scene, screen_view3d_layers());
|
||||
}
|
||||
}
|
||||
else if (G.obedit) {
|
||||
if (G.obedit->type == OB_MESH) {
|
||||
if(t->spacetype==SPACE_IMAGE) {
|
||||
flushTransUVs(t);
|
||||
|
||||
Reference in New Issue
Block a user