diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index d062b6c5c71..03f5a9903ef 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -416,16 +416,15 @@ void calc_action_range(const bAction *act, float *start, float *end) const bConstraintChannel *conchan; const IpoCurve *icu; float min=999999999.0f, max=-999999999.0; - int i; int foundvert=0; if(act) { for (chan=act->chanbase.first; chan; chan=chan->next) { if(chan->ipo) { for (icu=chan->ipo->curve.first; icu; icu=icu->next) { - for (i=0; itotvert; i++) { - min = MIN2 (min, icu->bezt[i].vec[1][0]); - max = MAX2 (max, icu->bezt[i].vec[1][0]); + if(icu->totvert) { + min= MIN2 (min, icu->bezt[0].vec[1][0]); + max= MAX2 (max, icu->bezt[icu->totvert-1].vec[1][0]); foundvert=1; } } @@ -433,9 +432,9 @@ void calc_action_range(const bAction *act, float *start, float *end) for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) { if(conchan->ipo) { for (icu=conchan->ipo->curve.first; icu; icu=icu->next) { - for (i=0; itotvert; i++){ - min = MIN2 (min, icu->bezt[i].vec[1][0]); - max = MAX2 (max, icu->bezt[i].vec[1][0]); + if(icu->totvert) { + min= MIN2 (min, icu->bezt[0].vec[1][0]); + max= MAX2 (max, icu->bezt[icu->totvert-1].vec[1][0]); foundvert=1; } } @@ -482,7 +481,7 @@ void extract_pose_from_action(bPose *pose, bAction *act, float ctime) /* Copy the data from the action into the pose */ for (pchan= pose->chanbase.first; pchan; pchan=pchan->next) { achan= get_action_channel(act, pchan->name); - pchan->flag= 0; + pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); if(achan) { ipo = achan->ipo; if (ipo) { @@ -499,21 +498,21 @@ void extract_pose_from_action(bPose *pose, bAction *act, float ctime) /* for do_all_pose_actions, clears the pose */ static void rest_pose(bPose *pose) { - bPoseChannel *chan; + bPoseChannel *pchan; int i; if (!pose) return; - for (chan=pose->chanbase.first; chan; chan=chan->next){ + for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){ for (i=0; i<3; i++){ - chan->loc[i]=0.0; - chan->quat[i+1]=0.0; - chan->size[i]=1.0; + pchan->loc[i]=0.0; + pchan->quat[i+1]=0.0; + pchan->size[i]=1.0; } - chan->quat[0]=1.0; + pchan->quat[0]=1.0; - chan->flag =0; + pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); } } @@ -716,6 +715,65 @@ static float nla_time(float cfra, float unit) return cfra; } +static float stridechannel_frame(bAction *act, int stride_axis, char *name, float pdist) +{ + bActionChannel *achan= get_action_channel(act, name); + + if(achan && achan->ipo) { + IpoCurve *icu= NULL; + float minx=0.0f, maxx=0.0f, miny=0.0f, maxy=0.0f; + int foundvert= 0; + + if(stride_axis==0) stride_axis= AC_LOC_X; + else if(stride_axis==1) stride_axis= AC_LOC_Y; + else stride_axis= AC_LOC_Z; + + /* calculate the min/max */ + for (icu=achan->ipo->curve.first; icu; icu=icu->next) { + if(icu->adrcode==stride_axis) { + if(icu->totvert>1) { + foundvert= 1; + minx= icu->bezt[0].vec[1][0]; + maxx= icu->bezt[icu->totvert-1].vec[1][0]; + + miny= icu->bezt[0].vec[1][1]; + maxy= icu->bezt[icu->totvert-1].vec[1][1]; + } + break; + } + } + + if(foundvert && miny!=maxy) { + float stridelen= fabs(maxy-miny), striptime; + float actiondist, step= 0.5, error, threshold=0.00001f*stridelen; + int max= 20; + + /* amount path moves object */ + pdist = (float)fmod (pdist, stridelen); + + /* wanted; the (0-1) factor that cancels out this distance, do simple newton-raphson */ + striptime= step; + do { + actiondist= eval_icu(icu, minx + striptime*(maxx-minx)) - miny; + + error= pdist - fabs(actiondist); + + step*=0.5f; + if(error > 0.0) + striptime += step; + else + striptime -= step; + + max--; + } + while( fabs(error) > threshold && max>0); + + return striptime; + } + } + return 0.0f; +} + /* ************** do the action ************ */ static void do_nla(Object *ob, int blocktype) @@ -772,12 +830,16 @@ static void do_nla(Object *ob, int blocktype) } pdist = ctime*cu->path->totdist; - if (strip->stridelen) - striptime = pdist / strip->stridelen; - else - striptime = 0; - - striptime = (float)fmod (striptime, 1.0); + if(strip->stridechannel[0]) + striptime= stridechannel_frame(strip->act, strip->stride_axis, strip->stridechannel, pdist); + else { + if (strip->stridelen) { + striptime = pdist / strip->stridelen; + striptime = (float)fmod (striptime, 1.0); + } + else + striptime = 0; + } frametime = (striptime * actlength) + strip->actstart; frametime= bsystem_time(ob, 0, frametime, 0.0); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index f8dbdddc5d1..217f7a33f12 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1278,7 +1278,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) if(data->weight != 0.0) IK_SolverAddGoal(solver, iktarget, goalpos, data->weight); - if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0)) + if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0) && (data->flag & CONSTRAINT_IK_AUTO)==0) IK_SolverAddGoalOrientation(solver, iktarget, goalrot, data->orientweight); } diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 1b04a43ae28..2ab13fe328a 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -265,6 +265,8 @@ static VFontData *vfont_get_data(VFont *vfont) struct TmpFont *tmpfnt = NULL; PackedFile *tpf; + if(vfont==NULL) return NULL; + // Try finding the font from font list tmpfnt = G.ttfdata.first; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index cc7ca11f81c..fe3ab612525 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -855,11 +855,11 @@ Object *copy_object(Object *ob) obn->soft= copy_softbody(ob->soft); /* NT copy fluid sim setting memory */ - if(ob->fluidsimSettings) ob->fluidsimSettings = MEM_dupallocN(ob->fluidsimSettings); - else ob->fluidsimSettings = NULL; + if(obn->fluidsimSettings) obn->fluidsimSettings = MEM_dupallocN(ob->fluidsimSettings); + else obn->fluidsimSettings = NULL; - ob->derivedDeform = NULL; - ob->derivedFinal = NULL; + obn->derivedDeform = NULL; + obn->derivedFinal = NULL; return obn; } diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index a725ff18138..88a3175ba1b 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -433,6 +433,7 @@ enum { #define B_ARMBUTS 2400 #define B_ARM_RECALCDATA 2301 +#define B_ARM_STRIDE 2302 /* *********************** */ #define B_CAMBUTS 2500 diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index fce02e2e394..2f60045e9ea 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -138,7 +138,8 @@ enum { POSE_HAS_IK = 0x0100, POSE_CHAIN = 0x0200, POSE_DONE = 0x0400, - POSE_KEY = 0x1000 + POSE_KEY = 0x1000, + POSE_STRIDE = 0x2000 }; /* PoseChannel constflag (constraint detection) */ @@ -147,6 +148,8 @@ enum { /* only used for drawing Posemode, not stored in channel */ #define PCHAN_HAS_ACTION 4 #define PCHAN_HAS_TARGET 8 + /* only for drawing Posemode too */ +#define PCHAN_HAS_STRIDE 16 /* PoseChannel->ikflag */ #define BONE_IK_NO_XDOF 1 diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 47ecccc1f1e..b31a803718e 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -77,7 +77,7 @@ typedef struct bArmature { int flag; int drawtype; int deformflag; - int res3; + short ghostep, pad; }bArmature; /* armature->flag */ diff --git a/source/blender/makesdna/DNA_nla_types.h b/source/blender/makesdna/DNA_nla_types.h index 4d5483f71d7..bf3d7820dae 100644 --- a/source/blender/makesdna/DNA_nla_types.h +++ b/source/blender/makesdna/DNA_nla_types.h @@ -38,9 +38,8 @@ struct Ipo; typedef struct bActionStrip { struct bActionStrip *next, *prev; - short flag; - short mode; - int reserved1; + short flag, mode; + short stride_axis, pad; /* axis 0=x, 1=y, 2=z */ struct Ipo *ipo; /* Blending ipo */ struct bAction *act; /* The action referenced by this strip */ @@ -51,6 +50,8 @@ typedef struct bActionStrip { float repeat; /* The number of times to repeat the action range */ float blendin, blendout; + + char stridechannel[32]; /* Instead of stridelen, it uses an action channel */ } bActionStrip; #define ACTSTRIPMODE_BLEND 0 @@ -64,5 +65,6 @@ typedef struct bActionStrip { #define ACTSTRIP_ACTIVE 0x10 #define ACTSTRIP_LOCK_ACTION 0x20 + #endif diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index fe93adf5dcb..a6babe376bb 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -62,6 +62,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" +#include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_radio_types.h" @@ -2523,14 +2524,52 @@ static void editing_panel_lattice_type(Object *ob, Lattice *lt) void do_armbuts(unsigned short event) { + Object *ob= OBACT; + switch(event) { case B_ARM_RECALCDATA: - DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 1); allqueue(REDRAWBUTSEDIT, 0); + break; + case B_ARM_STRIDE: + if(ob && ob->pose) { + bPoseChannel *pchan; + bActionStrip *strip; + + for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) + if(pchan->flag & POSE_STRIDE) + break; + + /* we put the stride bone name in the strips, for lookup of action channel */ + for (strip=ob->nlastrips.first; strip; strip=strip->next){ + if(strip->flag & ACTSTRIP_USESTRIDE) { + if(pchan) BLI_strncpy(strip->stridechannel, pchan->name, 32); + else strip->stridechannel[0]= 0; + } + } + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 1); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWBUTSEDIT, 0); + } + break; } } +static void validate_stridebutton_cb(void *pchanv, void *poin) +{ + Object *ob= OBACT; + bPoseChannel *pchan; + + if(ob && ob->pose) { + for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next){ + if(pchan!=pchanv) + pchan->flag &= ~POSE_STRIDE; + } + } +} + static int editbone_to_parnr (EditBone *bone) { EditBone *ebone; @@ -2681,8 +2720,9 @@ static void editing_panel_armature_type(Object *ob, bArmature *arm) uiDefButI(block, ROW, REDRAWVIEW3D, "B-Bone", 155, 100,70,20, &arm->drawtype, 0, ARM_B_BONE, 0, 0, "Draw bones as boxes, showing subdivision and b-splines"); uiDefButI(block, ROW, REDRAWVIEW3D, "Envelope", 225, 100,85,20, &arm->drawtype, 0, ARM_ENVELOPE, 0, 0, "Draw bones as extruded spheres, showing deformation influence volume"); - uiDefButBitI(block, TOG, ARM_DRAWAXES, REDRAWVIEW3D, "Draw Axes", 10, 80,150,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes"); - uiDefButBitI(block, TOG, ARM_DRAWNAMES, REDRAWVIEW3D, "Draw Names", 160,80,150,20, &arm->flag, 0, 0, 0, 0, "Draw bone names"); + uiDefButBitI(block, TOG, ARM_DRAWAXES, REDRAWVIEW3D, "Draw Axes", 10, 80,100,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes"); + uiDefButBitI(block, TOG, ARM_DRAWNAMES, REDRAWVIEW3D, "Draw Names", 110,80,100,20, &arm->flag, 0, 0, 0, 0, "Draw bone names"); + uiDefButS(block, NUM, REDRAWVIEW3D, "Ghost: ", 210,80,100,20, &arm->ghostep, 0.0f, 30.0f, 0, 0, "Draw Ghosts around current frame, for current Action"); uiBlockEndAlign(block); uiDefBut(block, LABEL, 0, "Deform Options", 10,60,150,20, 0, 0, 0, 0, 0, ""); @@ -2801,7 +2841,6 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm) uiDefButF(block, NUM,B_ARM_RECALCDATA, "Dist:", bx+107, by, 105, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance"); uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", bx+220, by, 110, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight"); - /* Segment, ease in/out buttons */ uiBlockBeginAlign(block); uiDefButS(block, NUM, B_ARM_RECALCDATA, "Segm: ", bx-10,by-19,117,19, &curBone->segments, 1.0, 32.0, 0.0, 0.0, "Subdivisions for B-bones"); @@ -2864,15 +2903,15 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm) by -= (zerodof)? 82: (zerolimit)? 122: 162; - uiBlockBeginAlign(block); uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stretch:", bx-10, by, 113, 19, &pchan->ikstretch, 0.0, 1.0, 1.0, 0.0, "Allow scaling of the bone for IK"); - uiBlockEndAlign(block); by -= 20; } else { - uiDefBut(block, LABEL, 0, "(DoF options only for IK chains)", bx-10,by-60, 300, 20, 0, 0, 0, 0, 0, ""); - + but= uiDefButBitS(block, TOG, POSE_STRIDE, B_ARM_STRIDE, "Stride Root", bx-10, by-60, 113, 19, &pchan->flag, 0.0, 0.0, 0, 0, "Set this PoseChannel to define the Stride distance"); + uiButSetFunc(but, validate_stridebutton_cb, pchan, NULL); + + uiDefBut(block, LABEL, 0, "(DoF only for IK chains)", bx+110,by-60, 190, 19, 0, 0, 0, 0, 0, ""); by -= 82; } diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index 471eb1e0612..a4dffaea7dd 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -43,6 +43,7 @@ #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_ID.h" +#include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -829,7 +830,8 @@ static void draw_line_bone(int armflag, int boneflag, int constflag, unsigned in if(armflag & ARM_POSEMODE) { /* inner part in background color or constraint */ if(constflag) { - if(constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0); + if(constflag & PCHAN_HAS_STRIDE) glColor3ub(0, 0, 200); + else if(constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0); else if(constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0); else if(constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120); else BIF_ThemeColor(TH_BONE_POSE); // PCHAN_HAS_ACTION @@ -967,10 +969,10 @@ static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsign else { // wire if (armflag & ARM_POSEMODE){ if(constflag) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80); + if(constflag & PCHAN_HAS_STRIDE) glColor4ub(0, 0, 200, 80); + else if(constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80); else if(constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80); else if(constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80); else BIF_ThemeColor4(TH_BONE_POSE); // PCHAN_HAS_ACTION @@ -1035,10 +1037,10 @@ static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned } else if (armflag & ARM_POSEMODE){ if(constflag) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80); + if(constflag & PCHAN_HAS_STRIDE) glColor4ub(0, 0, 200, 80); + else if(constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80); else if(constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80); else if(constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80); else BIF_ThemeColor4(TH_BONE_POSE); // PCHAN_HAS_ACTION @@ -1130,7 +1132,6 @@ static void draw_dof_ellipse(float ax, float az) int i, j, n=16; float x, z, px, pz; - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glDepthMask(0); @@ -1310,7 +1311,6 @@ static void draw_pose_channels(Base *base, int dt) /* and draw blended distances */ if(arm->flag & ARM_POSEMODE) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); //glShadeModel(GL_SMOOTH); @@ -1425,6 +1425,8 @@ static void draw_pose_channels(Base *base, int dt) constflag= pchan->constflag; if(pchan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) constflag |= PCHAN_HAS_ACTION; + if(pchan->flag & POSE_STRIDE) + constflag |= PCHAN_HAS_STRIDE; if(arm->drawtype==ARM_ENVELOPE) { if(dtzbuf) glEnable(GL_DEPTH_TEST); } } + } /* in editmode, we don't store the bone matrix... */ @@ -1532,7 +1535,6 @@ static void draw_ebones(Object *ob, int dt) Mat4Invert(imat, smat); /* and draw blended distances */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); //glShadeModel(GL_SMOOTH); @@ -1712,6 +1714,93 @@ static void draw_pose_paths(Object *ob) glPopMatrix(); } +/* object is supposed to be armature in posemode */ +static void draw_ghost_poses(Base *base) +{ + Object *ob= base->object; + bArmature *arm= ob->data; + bPose *posen, *poseo; + bActionStrip *strip; + float cur, start, end, stepsize, range, colfac, actframe; + int cfrao, maptime; + + /* pre conditions, get an action with sufficient frames */ + if(ob->action==NULL) + return; + + calc_action_range(ob->action, &start, &end); + if(start==end) + return; + + stepsize= 1.0f; + range= (float)(arm->ghostep); + + /* we only map time for armature when an active strip exists */ + for (strip=ob->nlastrips.first; strip; strip=strip->next) + if(strip->flag & ACTSTRIP_ACTIVE) + break; + + maptime= (strip!=NULL); + + /* store values */ + ob->flag &= ~OB_POSEMODE; + cfrao= CFRA; + if(maptime) actframe= get_action_frame(ob, (float)CFRA); + else actframe= CFRA; + + /* copy the pose */ + poseo= ob->pose; + copy_pose(&posen, ob->pose, 1); + ob->pose= posen; + armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ + + glEnable(GL_BLEND); + if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); + + /* draw from lowest blend to darkest */ + for(cur= 0.5f; cur= start && actframe+cur <= end) { + + if(maptime) CFRA= (int)get_action_frame_inv(ob, actframe+cur); + else CFRA= (int)(actframe+cur); + + if(CFRA!=cfrao) { + do_all_pose_actions(ob); + where_is_pose(ob); + draw_pose_channels(base, OB_WIRE); + } + } + /* only within action range */ + if(actframe-cur >= start && actframe-cur <= end) { + + if(maptime) CFRA= (int)get_action_frame_inv(ob, actframe-cur); + else CFRA= (int)(actframe-cur); + + if(CFRA!=cfrao) { + do_all_pose_actions(ob); + where_is_pose(ob); + draw_pose_channels(base, OB_WIRE); + } + } + } + glDisable(GL_BLEND); + if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); + + free_pose_channels(posen); + MEM_freeN(posen); + + CFRA= cfrao; + ob->pose= poseo; + armature_rebuild_pose(ob, ob->data); + + ob->flag |= OB_POSEMODE; +} + /* called from drawobject.c */ void draw_armature(Base *base, int dt) { @@ -1744,16 +1833,25 @@ void draw_armature(Base *base, int dt) if(ob->flag & OB_POSEMODE) arm->flag |= ARM_POSEMODE; } else if(ob->flag & OB_POSEMODE) { + /* only set once */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if(arm->ghostep) { + draw_ghost_poses(base); + } + if(ob==OBACT) arm->flag |= ARM_POSEMODE; else if(G.f & G_WEIGHTPAINT) arm->flag |= ARM_POSEMODE; draw_pose_paths(ob); - } + } + draw_pose_channels(base, dt); arm->flag &= ~ARM_POSEMODE; + BIF_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */ } } /* restore */ diff --git a/source/blender/src/drawnla.c b/source/blender/src/drawnla.c index b558750647b..007238224de 100644 --- a/source/blender/src/drawnla.c +++ b/source/blender/src/drawnla.c @@ -58,6 +58,7 @@ #include "MEM_guardedalloc.h" #include "BKE_action.h" +#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BSE_drawnla.h" @@ -148,6 +149,15 @@ static void draw_nla_channels(void) glRasterPos2f(x+32, y-4); BMF_DrawString(G.font, ob->action->id.name+2); + /* icon for active action (no strip mapping) */ + for (strip = ob->nlastrips.first; strip; strip=strip->next) + if(strip->flag & ACTSTRIP_ACTIVE) break; + if(strip==NULL) { + glEnable(GL_BLEND); + BIF_draw_icon_blended(x, y-8, ICON_DOT, TH_BACK, 0); + glDisable(GL_BLEND); + } + y-=NLACHANNELHEIGHT+NLACHANNELSKIP; } @@ -417,24 +427,8 @@ void do_nlabuts(unsigned short event) allqueue(REDRAWNLA, 0); break; case B_NLA_PANEL: - if (strip->endstart) - strip->end=strip->start; - - - if (strip->blendin>(strip->end-strip->start)) - strip->blendin = strip->end-strip->start; - - if (strip->blendout>(strip->end-strip->start)) - strip->blendout = strip->end-strip->start; - - if (strip->blendin > (strip->end-strip->start-strip->blendout)) - strip->blendin = (strip->end-strip->start-strip->blendout); - - if (strip->blendout > (strip->end-strip->start-strip->blendin)) - strip->blendout = (strip->end-strip->start-strip->blendin); - - update_for_newframe_muted(); + DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA); allqueue (REDRAWNLA, 0); allqueue (REDRAWVIEW3D, 0); break; @@ -463,39 +457,46 @@ static void nla_panel_properties(short cntrl) // NLA_HANDLER_PROPERTIES /* first labels, for simpler align code :) */ uiDefBut(block, LABEL, 0, "Timeline Range:", 10,180,300,19, 0, 0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Action Range:", 10,140,300,19, 0, 0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Blending:", 10,100,300,19, 0, 0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Options:", 10,60,300,19, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Blending:", 10,120,300,19, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Options:", 10,80,300,19, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Stride Support:", 10,40,300,19, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_REDR, "Strip Start:", 10,160,150,19, &strip->start, -1000.0, strip->end-1, 100, 0, "First frame in the timeline"); - uiDefButF(block, NUM, B_REDR, "Strip End:", 160,160,150,19, &strip->end, strip->start+1, MAXFRAMEF, 100, 0, "Last frame in the timeline"); + uiDefButF(block, NUM, B_NLA_PANEL, "Strip Start:", 10,160,150,19, &strip->start, -1000.0, strip->end-1, 100, 0, "First frame in the timeline"); + uiDefButF(block, NUM, B_NLA_PANEL, "Strip End:", 160,160,150,19, &strip->end, strip->start+1, MAXFRAMEF, 100, 0, "Last frame in the timeline"); - uiBlockBeginAlign(block); - uiDefIconButBitS(block, ICONTOG, ACTSTRIP_LOCK_ACTION, B_NLA_LOCK, ICON_UNLOCKED, 10,120,20,19, &(strip->flag), 0, 0, 0, 0, "Toggles Action end/start to be automatic mapped to strip duration"); + uiDefIconButBitS(block, ICONTOG, ACTSTRIP_LOCK_ACTION, B_NLA_LOCK, ICON_UNLOCKED, 10,140,20,19, &(strip->flag), 0, 0, 0, 0, "Toggles Action end/start to be automatic mapped to strip duration"); if(strip->flag & ACTSTRIP_LOCK_ACTION) { char str[40]; sprintf(str, "Action Start: %.2f", strip->actstart); - uiDefBut(block, LABEL, B_NOP, str, 30,120,140,19, NULL, 0.0, 0.0, 0, 0, "First frame of the action to map to the playrange"); + uiDefBut(block, LABEL, B_NOP, str, 30,140,140,19, NULL, 0.0, 0.0, 0, 0, "First frame of the action to map to the playrange"); sprintf(str, "Action End: %.2f", strip->actend); - uiDefBut(block, LABEL, B_NOP, str, 170,120,140,19, NULL, 0.0, 0.0, 0, 0, "Last frame of the action to map to the playrange"); + uiDefBut(block, LABEL, B_NOP, str, 170,140,140,19, NULL, 0.0, 0.0, 0, 0, "Last frame of the action to map to the playrange"); } else { - uiDefButF(block, NUM, B_REDR, "Action Start:", 30,120,140,19, &strip->actstart, -1000.0, strip->actend-1, 100, 0, "First frame of the action to map to the playrange"); - uiDefButF(block, NUM, B_REDR, "Action End:", 170,120,140,19, &strip->actend, strip->actstart+1, MAXFRAMEF, 100, 0, "Last frame of the action to map to the playrange"); + uiDefButF(block, NUM, B_NLA_PANEL, "Action Start:", 30,140,140,19, &strip->actstart, -1000.0, strip->actend-1, 100, 0, "First frame of the action to map to the playrange"); + uiDefButF(block, NUM, B_NLA_PANEL, "Action End:", 170,140,140,19, &strip->actend, strip->actstart+1, MAXFRAMEF, 100, 0, "Last frame of the action to map to the playrange"); } + uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_REDR, "Blendin:", 10,80,150,19, &strip->blendin, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-in"); - uiDefButF(block, NUM, B_REDR, "Blendout:", 160,80,150,19, &strip->blendout, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-out"); + uiDefButF(block, NUM, B_NLA_PANEL, "Blendin:", 10,100,150,19, &strip->blendin, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-in"); + uiDefButF(block, NUM, B_NLA_PANEL, "Blendout:", 160,100,150,19, &strip->blendout, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-out"); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_REDR, "Repeat:", 10,40,150,19, &strip->repeat, 0.0001, 1000.0f, 100, 0, "Number of times the action should repeat"); - uiDefButF(block, NUM, B_REDR, "Stride:", 160,40,150,19, &strip->stridelen, 0.0001, 1000.0, 100, 0, "Distance covered by one complete cycle of the action specified in the Action Range"); - + uiDefButF(block, NUM, B_NLA_PANEL, "Repeat:", 10,60,150,19, &strip->repeat, 0.001, 1000.0f, 100, 0, "Number of times the action should repeat"); + uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_NLA_PANEL, "Hold", 160,60,75,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip"); + uiDefButS(block, TOG, B_NLA_PANEL, "Add", 230,60,75,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode"); + uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_REDR, "Use Path", 10,0,100,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride"); - uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_REDR, "Hold", 110,0,100,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip"); - uiDefButS(block, TOG, B_REDR, "Add", 210,0,100,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode"); + uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_NLA_PANEL, "Use Path", 10,20,100,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride"); + uiDefButF(block, NUM, B_NLA_PANEL, "Stride:", 110,20,200,19, &strip->stridelen, 0.0001, 1000.0, 100, 0, "Distance covered by one complete cycle of the action specified in the Action Range"); + + uiDefButS(block, ROW, B_NLA_PANEL, "X", 10, 0, 33, 19, &strip->stride_axis, 1, 0, 0, 0, "Dominant axis for Stride Bone"); + uiDefButS(block, ROW, B_NLA_PANEL, "Y", 43, 0, 33, 19, &strip->stride_axis, 1, 1, 0, 0, "Dominant axis for Stride Bone"); + uiDefButS(block, ROW, B_NLA_PANEL, "Z", 76, 0, 34, 19, &strip->stride_axis, 1, 2, 0, 0, "Dominant axis for Stride Bone"); + + uiDefBut(block, TEX, B_NLA_PANEL, "Stride Bone:", 110, 0, 200, 19, strip->stridechannel, 1, 31, 0, 0, "Name of Bone used for stride"); + } static void nla_blockhandlers(ScrArea *sa) diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c index 00857d3c841..645ac37c1e1 100644 --- a/source/blender/src/editnla.c +++ b/source/blender/src/editnla.c @@ -456,6 +456,20 @@ static void set_active_strip(Object *ob, bActionStrip *act) } } +static void find_stridechannel(Object *ob, bActionStrip *strip) +{ + if(ob && ob->pose) { + bPoseChannel *pchan; + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) + if(pchan->flag & POSE_STRIDE) + break; + if(pchan) + BLI_strncpy(strip->stridechannel, pchan->name, 32); + else + strip->stridechannel[0]= 0; + } +} + static void convert_nla(short mval[2]) { bActionStrip *strip, *nstrip; @@ -522,8 +536,10 @@ static void convert_nla(short mval[2]) nstrip->start = nstrip->actstart; nstrip->end = nstrip->actend; nstrip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION; + + find_stridechannel(base->object, nstrip); set_active_strip(base->object, nstrip); - + nstrip->repeat = 1.0; BLI_addtail(&base->object->nlastrips, nstrip); @@ -576,6 +592,8 @@ static void add_nla_block(short event) strip->end= strip->start+100; strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION; + + find_stridechannel(nla_base->object, strip); set_active_strip(nla_base->object, strip); strip->repeat = 1.0; @@ -684,7 +702,7 @@ static void mouse_nlachannels(short mval[2]) Base *base; Object *ob=NULL; float x,y; - int click, obclick=0; + int click, obclick=0, actclick=0; int wsize; wsize = (count_nla_levels ()*(NLACHANNELHEIGHT+NLACHANNELSKIP)); @@ -709,7 +727,10 @@ static void mouse_nlachannels(short mval[2]) /* See if this is an action */ if (ob->action){ - if (click==0) break; + if (click==0) { + actclick= 1; + break; + } click--; } @@ -740,17 +761,18 @@ static void mouse_nlachannels(short mval[2]) if(base!=BASACT) set_active_base(base); - /* set action */ - if(strip) + if(actclick) /* de-activate all strips */ + set_active_strip(ob, NULL); + else if(strip) /* set action */ set_active_strip(ob, strip); /* override option for NLA */ - if(obclick && mval[0]<25) { + if(obclick && mval[0]<25) ob->nlaflag ^= OB_NLA_OVERRIDE; - ob->ctime= -1234567.0f; // eveil! - DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA); - } + ob->ctime= -1234567.0f; // eveil! + DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA); + allqueue(REDRAWIPO, 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWACTION, 0); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 8a23fe7059d..5f240aac776 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3092,18 +3092,20 @@ void make_duplilist_real() /* font duplis can have a totcol without material, we get them from parent * should be implemented better... */ - if(ob->mat==0) ob->totcol= 0; + if(ob->mat==NULL) ob->totcol= 0; basen= MEM_dupallocN(base); basen->flag &= ~OB_FROMDUPLI; BLI_addhead(&G.scene->base, basen); /* addhead: othwise eternal loop */ - ob->ipo= 0; /* make sure apply works */ - ob->parent= ob->track= 0; - ob->disp.first= ob->disp.last= 0; + ob->ipo= NULL; /* make sure apply works */ + ob->parent= ob->track= NULL; + ob->disp.first= ob->disp.last= NULL; ob->transflag &= ~OB_DUPLI; basen->object= copy_object(ob); + basen->object->flag &= ~OB_FROMDUPLI; apply_obmat(basen->object); + ob= ob->id.next; } @@ -3115,6 +3117,8 @@ void make_duplilist_real() base= base->next; } + DAG_scene_sort(G.scene); + allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWOOPS, 0); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 68d5352e4e5..9cb84b03949 100755 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -472,6 +472,7 @@ static void apply_targetless_ik(Object *ob) Mat4MulMat4(tmat, offs_bone, parchan->parent->bone->arm_mat); else Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat); + Mat4Invert(imat, tmat); } else {