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:
-rw-r--r--source/blender/include/BSE_editipo.h2
-rw-r--r--source/blender/makesdna/DNA_action_types.h4
-rw-r--r--source/blender/src/editaction.c2
-rw-r--r--source/blender/src/editipo.c19
-rw-r--r--source/blender/src/header_action.c15
-rw-r--r--source/blender/src/poselib.c2
-rw-r--r--source/blender/src/transform_conversions.c105
7 files changed, 134 insertions, 15 deletions
diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h
index 11691cfbd23..99a7930ddb1 100644
--- a/source/blender/include/BSE_editipo.h
+++ b/source/blender/include/BSE_editipo.h
@@ -157,7 +157,7 @@ void mirror_ipo_keys(struct Ipo *ipo, short mirror_mode);
void setipotype_ipo(struct Ipo *ipo, int code);
void set_ipo_key_selection(struct Ipo *ipo, int sel);
int is_ipo_key_selected(struct Ipo *ipo);
-void delete_icu_key(struct IpoCurve *icu, int index);
+void delete_icu_key(struct IpoCurve *icu, int index, short do_recalc);
void delete_ipo_keys(struct Ipo *ipo);
int fullselect_ipo_keys(struct Ipo *ipo);
int add_trans_ipo_keys(struct Ipo *ipo, struct TransVert *tv, int tvtot);
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 977abaffeb4..15e88ea0b86 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -219,7 +219,9 @@ typedef enum SACTION_FLAG {
/* draw time in seconds instead of time in frames */
SACTION_DRAWTIME = (1<<2),
/* don't filter action channels according to visibility */
- SACTION_NOHIDE = (1<<3)
+ SACTION_NOHIDE = (1<<3),
+ /* don't kill overlapping keyframes after transform */
+ SACTION_NOTRANSKEYCULL = (1<<4)
} SACTION_FLAG;
/* SpaceAction AutoSnap Settings (also used by SpaceNLA) */
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c
index 2cc905f1147..94019cb02aa 100644
--- a/source/blender/src/editaction.c
+++ b/source/blender/src/editaction.c
@@ -1130,7 +1130,7 @@ void transform_action_keys (int mode, int dummy)
}
break;
}
-}
+}
/* ----------------------------------------- */
diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c
index b3ea3e1931c..fce7fab779d 100644
--- a/source/blender/src/editipo.c
+++ b/source/blender/src/editipo.c
@@ -2624,10 +2624,10 @@ void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, in
/* delete keyframe immediately before/after newly added */
switch (insert_mode) {
case KEYNEEDED_DELPREV:
- delete_icu_key(icu, icu->totvert-2);
+ delete_icu_key(icu, icu->totvert-2, 1);
break;
case KEYNEEDED_DELNEXT:
- delete_icu_key(icu, 1);
+ delete_icu_key(icu, 1, 1);
break;
}
}
@@ -5642,22 +5642,25 @@ void remake_object_ipos(Object *ob)
/* Only delete the nominated keyframe from provided ipo-curve.
* Not recommended to be used many times successively. For that
- * there is delete_ipo_keys(). */
-void delete_icu_key(IpoCurve *icu, int index)
+ * there is delete_ipo_keys().
+ */
+void delete_icu_key(IpoCurve *icu, int index, short do_recalc)
{
/* firstly check that index is valid */
if (index < 0)
index *= -1;
+ if (icu == NULL)
+ return;
if (index >= icu->totvert)
return;
- if (!icu) return;
/* Delete this key */
- memcpy (&icu->bezt[index], &icu->bezt[index+1], sizeof (BezTriple)*(icu->totvert-index-1));
+ memcpy(&icu->bezt[index], &icu->bezt[index+1], sizeof(BezTriple)*(icu->totvert-index-1));
icu->totvert--;
- /* recalc handles */
- calchandles_ipocurve(icu);
+ /* recalc handles - only if it won't cause problems */
+ if (do_recalc)
+ calchandles_ipocurve(icu);
}
void delete_ipo_keys(Ipo *ipo)
diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c
index f9a3fb08bd8..c48e646af4c 100644
--- a/source/blender/src/header_action.c
+++ b/source/blender/src/header_action.c
@@ -98,7 +98,8 @@ enum {
ACTMENU_VIEW_NOHIDE,
ACTMENU_VIEW_OPENLEVELS,
ACTMENU_VIEW_CLOSELEVELS,
- ACTMENU_VIEW_EXPANDALL
+ ACTMENU_VIEW_EXPANDALL,
+ ACTMENU_VIEW_TRANSDELDUPS
};
enum {
@@ -333,6 +334,9 @@ static void do_action_viewmenu(void *arg, int event)
case ACTMENU_VIEW_EXPANDALL: /* Expands all channels */
expand_all_action();
break;
+ case ACTMENU_VIEW_TRANSDELDUPS: /* Don't delete duplicate/overlapping keyframes after transform */
+ G.saction->flag ^= SACTION_NOTRANSKEYCULL;
+ break;
}
allqueue(REDRAWVIEW3D, 0);
}
@@ -378,7 +382,14 @@ static uiBlock *action_viewmenu(void *arg_unused)
"Show Hidden Channels|", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 1,
ACTMENU_VIEW_NOHIDE, "");
-
+
+ // this option may get removed in future...
+ uiDefIconTextBut(block, BUTM, 1, (G.saction->flag & SACTION_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
+ "AfterTrans Delete Dupli-Frames|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_TRANSDELDUPS, "");
+
+
uiDefIconTextBut(block, BUTM, 1, (G.v2d->flag & V2D_VIEWLOCK)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
"Lock Time to Other Windows|", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 1,
diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c
index 468c68021ed..ea02349b51b 100644
--- a/source/blender/src/poselib.c
+++ b/source/blender/src/poselib.c
@@ -455,7 +455,7 @@ void poselib_remove_pose (Object *ob, TimeMarker *marker)
for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
/* check if remove... */
if (IS_EQ(bezt->vec[1][0], marker->frame)) {
- delete_icu_key(icu, i);
+ delete_icu_key(icu, i, 1);
break;
}
}
diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c
index 5d3ab77ab45..3d580c70a1c 100644
--- a/source/blender/src/transform_conversions.c
+++ b/source/blender/src/transform_conversions.c
@@ -2346,6 +2346,102 @@ void flushTransIpoData(TransInfo *t)
/* ********************* ACTION/NLA EDITOR ****************** */
+/* Called by special_aftertrans_update to make sure selected keyframes replace
+ * any other keyframes which may reside on that frame (that is not selected).
+ */
+static void posttrans_ipo_clean (Ipo *ipo)
+{
+ IpoCurve *icu;
+ int i;
+
+ /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
+ for (icu= ipo->curve.first; icu; icu= icu->next) {
+ float *selcache; /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
+ int len, index; /* number of frames in cache, item index */
+
+ /* allocate memory for the cache */
+ // TODO: investigate using GHash for this instead?
+ if (icu->totvert == 0)
+ continue;
+ selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
+ len= 0;
+ index= 0;
+
+ /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
+ * as there is no guarantee what order the keyframes are exactly, even though
+ * they have been sorted by time.
+ */
+
+ /* Loop 1: find selected keyframes */
+ for (i = 0; i < icu->totvert; i++) {
+ BezTriple *bezt= &icu->bezt[i];
+
+ if (BEZSELECTED(bezt)) {
+ selcache[index]= bezt->vec[1][0];
+ index++;
+ len++;
+ }
+ }
+
+ /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
+ if (len) {
+ for (i = 0; i < icu->totvert; i++) {
+ BezTriple *bezt= &icu->bezt[i];
+
+ if (BEZSELECTED(bezt) == 0) {
+ /* check beztriple should be removed according to cache */
+ for (index= 0; index < len; index++) {
+ if (IS_EQ(bezt->vec[1][0], selcache[index])) {
+ delete_icu_key(icu, i, 0);
+ break;
+ }
+ else if (bezt->vec[1][0] > selcache[index])
+ break;
+ }
+ }
+ }
+
+ testhandles_ipocurve(icu);
+ }
+
+ /* free cache */
+ MEM_freeN(selcache);
+ }
+}
+
+/* Called by special_aftertrans_update to make sure selected keyframes replace
+ * any other keyframes which may reside on that frame (that is not selected).
+ * remake_action_ipos should have already been called
+ */
+static void posttrans_action_clean (bAction *act)
+{
+ ListBase act_data = {NULL, NULL};
+ bActListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+ actdata_filter(&act_data, filter, act, ACTCONT_ACTION);
+
+ /* loop through relevant data, removing keyframes from the ipo-blocks that were attached
+ * - all keyframes are converted in/out of global time
+ */
+ for (ale= act_data.first; ale; ale= ale->next) {
+ if (NLA_ACTION_SCALED) {
+ actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
+ posttrans_ipo_clean(ale->key_data);
+ actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
+ }
+ else
+ posttrans_ipo_clean(ale->key_data);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&act_data);
+}
+
+/* ----------------------------- */
+
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
static short FrameOnMouseSide(char side, float frame, float cframe)
{
@@ -3293,7 +3389,6 @@ void special_aftertrans_update(TransInfo *t)
ob = OBACT;
if (datatype == ACTCONT_ACTION) {
- /* Update the curve */
/* Depending on the lock status, draw necessary views */
if (ob) {
ob->ctime= -1234567.0f;
@@ -3304,8 +3399,13 @@ void special_aftertrans_update(TransInfo *t)
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
}
+ /* Do curve updates */
remake_action_ipos((bAction *)data);
+ /* Do curve cleanups? */
+ if ((G.saction->flag & SACTION_NOTRANSKEYCULL)==0)
+ posttrans_action_clean((bAction *)data);
+
G.saction->flag &= ~SACTION_MOVING;
}
else if (datatype == ACTCONT_SHAPEKEY) {
@@ -3318,6 +3418,9 @@ void special_aftertrans_update(TransInfo *t)
sort_time_ipocurve(icu);
testhandles_ipocurve(icu);
}
+
+ if ((G.saction->flag & SACTION_NOTRANSKEYCULL)==0)
+ posttrans_ipo_clean(key->ipo);
}
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);