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:
authorJoshua Leung <aligorith@gmail.com>2009-01-27 14:09:30 +0300
committerJoshua Leung <aligorith@gmail.com>2009-01-27 14:09:30 +0300
commit8078bc65d637c482a7a511aeccbf9ed01e679097 (patch)
tree7dbdf5093ceb6efa64f4ae80c3a45e064382d325 /source/blender/editors
parent2c1214f696b237677be3b4648a3ed0b294b74167 (diff)
Graph Editor:
* Cleaned up code for borderselect with BKEY. There's still a bug here where y-values don't seem to be getting properly checked, so nothing seems to happen. * Set up some code for transforming keyframes. It currently uses the wrong code though (i.e. it uses the code for Action Editor which is 1D not 2D, and doesn't have some of the special checks needed). More work on this later.
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/keyframes_edit.c42
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h6
-rw-r--r--source/blender/editors/space_ipo/ipo_draw.c4
-rw-r--r--source/blender/editors/space_ipo/ipo_ops.c2
-rw-r--r--source/blender/editors/space_ipo/ipo_select.c48
-rw-r--r--source/blender/editors/transform/transform.c10
-rw-r--r--source/blender/editors/transform/transform_conversions.c718
7 files changed, 727 insertions, 103 deletions
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 66049d5e5f7..ad845f45f01 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -38,7 +38,6 @@
#include "DNA_action_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
-#include "DNA_ipo_types.h" // XXX to be phased out
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
@@ -56,7 +55,7 @@
/* This file defines an API and set of callback-operators for non-destructive editing of keyframe data.
*
* Two API functions are defined for actually performing the operations on the data:
- * ipo_keys_bezier_loop() and icu_keys_bezier_loop()
+ * ANIM_fcurve_keys_bezier_loop()
* which take the data they operate on, a few callbacks defining what operations to perform.
*
* As operators which work on keyframes usually apply the same operation on all BezTriples in
@@ -84,6 +83,10 @@ short ANIM_fcurve_keys_bezier_loop(BeztEditData *bed, FCurve *fcu, BeztEditFunc
BezTriple *bezt;
int b;
+ /* sanity check */
+ if (fcu == NULL)
+ return 0;
+
/* if function to apply to bezier curves is set, then loop through executing it on beztriples */
if (bezt_cb) {
/* if there's a validation func, include that check in the loop
@@ -233,6 +236,21 @@ static short ok_bezier_value(BeztEditData *bed, BezTriple *bezt)
return IS_EQ(bezt->vec[1][1], bed->f1);
}
+static short ok_bezier_valuerange(BeztEditData *bed, BezTriple *bezt)
+{
+ /* value range is stored in float properties */
+ return ((bezt->vec[1][1] > bed->f1) && (bezt->vec[1][1] < bed->f2));
+}
+
+static short ok_bezier_region(BeztEditData *bed, BezTriple *bezt)
+{
+ /* rect is stored in data property (it's of type rectf, but may not be set) */
+ if (bed->data)
+ return BLI_in_rctf(bed->data, bezt->vec[1][0], bezt->vec[1][1]);
+ else
+ return 0;
+}
+
BeztEditFunc ANIM_editkeyframes_ok(short mode)
{
@@ -242,10 +260,14 @@ BeztEditFunc ANIM_editkeyframes_ok(short mode)
return ok_bezier_frame;
case BEZT_OK_FRAMERANGE: /* only if bezt falls within the specified frame range (floats) */
return ok_bezier_framerange;
- case BEZT_OK_SELECTED: /* only if bezt is selected */
+ case BEZT_OK_SELECTED: /* only if bezt is selected (self) */
return ok_bezier_selected;
case BEZT_OK_VALUE: /* only if bezt value matches (float) */
return ok_bezier_value;
+ case BEZT_OK_VALUERANGE: /* only if bezier falls within the specified value range (floats) */
+ return ok_bezier_valuerange;
+ case BEZT_OK_REGION: /* only if bezier falls within the specified rect (data -> rectf) */
+ return ok_bezier_region;
default: /* nothing was ok */
return NULL;
}
@@ -355,7 +377,7 @@ static short mirror_bezier_marker(BeztEditData *bed, BezTriple *bezt)
}
/* Note: for markers case, need to set global vars (eww...) */
-// calchandles_ipocurve
+// calchandles_fcurve
BeztEditFunc ANIM_editkeyframes_mirror(short type)
{
switch (type) {
@@ -437,7 +459,7 @@ static short set_bezier_free(BeztEditData *bed, BezTriple *bezt)
}
/* Set all Bezier Handles to a single type */
-// calchandles_ipocurve
+// calchandles_fcurve
BeztEditFunc ANIM_editkeyframes_handles(short code)
{
switch (code) {
@@ -460,21 +482,21 @@ BeztEditFunc ANIM_editkeyframes_handles(short code)
static short set_bezt_constant(BeztEditData *bed, BezTriple *bezt)
{
if (bezt->f2 & SELECT)
- bezt->ipo= IPO_CONST;
+ bezt->ipo= BEZT_IPO_CONST;
return 0;
}
static short set_bezt_linear(BeztEditData *bed, BezTriple *bezt)
{
if (bezt->f2 & SELECT)
- bezt->ipo= IPO_LIN;
+ bezt->ipo= BEZT_IPO_LIN;
return 0;
}
static short set_bezt_bezier(BeztEditData *bed, BezTriple *bezt)
{
if (bezt->f2 & SELECT)
- bezt->ipo= IPO_BEZ;
+ bezt->ipo= BEZT_IPO_BEZ;
return 0;
}
@@ -483,9 +505,9 @@ static short set_bezt_bezier(BeztEditData *bed, BezTriple *bezt)
BeztEditFunc ANIM_editkeyframes_ipo(short code)
{
switch (code) {
- case IPO_CONST: /* constant */
+ case BEZT_IPO_CONST: /* constant */
return set_bezt_constant;
- case IPO_LIN: /* linear */
+ case BEZT_IPO_LIN: /* linear */
return set_bezt_linear;
default: /* bezier */
return set_bezt_bezier;
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index 8fd5a0152c9..0564d83bccd 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -53,6 +53,8 @@ typedef enum eEditKeyframes_Validate {
BEZT_OK_FRAMERANGE,
BEZT_OK_SELECTED,
BEZT_OK_VALUE,
+ BEZT_OK_VALUERANGE,
+ BEZT_OK_REGION,
} eEditKeyframes_Validate;
/* ------------ */
@@ -89,7 +91,7 @@ typedef enum eEditKeyframes_Mirror {
typedef struct BeztEditData {
ListBase list; /* temp list for storing custom list of data to check */
struct Scene *scene; /* pointer to current scene - many tools need access to cfra/etc. */
- void *data; /* pointer to custom data - usually 'Object', but could be other types too */
+ void *data; /* pointer to custom data - usually 'Object' but also 'rectf', but could be other types too */
float f1, f2; /* storage of times/values as 'decimals' */
int i1, i2; /* storage of times/values/flags as 'whole' numbers */
} BeztEditData;
@@ -126,7 +128,7 @@ BeztEditFunc ANIM_editkeyframes_ipo(short mode);
void delete_fcurve_key(struct FCurve *fcu, int index, short do_recalc);
void delete_fcurve_keys(struct FCurve *fcu);
-void duplicate_fcurve_keys(struct FCurve *fcu); // XXX fixme...
+void duplicate_fcurve_keys(struct FCurve *fcu);
void clean_fcurve(struct FCurve *fcu, float thresh);
void smooth_fcurve(struct FCurve *fcu, short mode);
diff --git a/source/blender/editors/space_ipo/ipo_draw.c b/source/blender/editors/space_ipo/ipo_draw.c
index a1c0f37506c..7ec615b83a3 100644
--- a/source/blender/editors/space_ipo/ipo_draw.c
+++ b/source/blender/editors/space_ipo/ipo_draw.c
@@ -617,7 +617,7 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
/* map ipo-points for drawing if scaled F-Curve */
if (nob)
- ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 0);
/* draw curve - we currently calculate colour on the fly, but that should probably be done in advance instead */
col= ipo_rainbow(i, items);
@@ -631,7 +631,7 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
/* undo mapping of keyframes for drawing if scaled F-Curve */
if (nob)
- ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 0);
}
/* free list of curves */
diff --git a/source/blender/editors/space_ipo/ipo_ops.c b/source/blender/editors/space_ipo/ipo_ops.c
index fd825276333..c9988d41413 100644
--- a/source/blender/editors/space_ipo/ipo_ops.c
+++ b/source/blender/editors/space_ipo/ipo_ops.c
@@ -144,7 +144,7 @@ static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap)
#endif // XXX code to be sanitied for new system
/* transform system */
- transform_keymap_for_space(wm, keymap, SPACE_IPO);
+ transform_keymap_for_space(wm, keymap, /*SPACE_IPO*/SPACE_ACTION); // xxx
}
/* --------------- */
diff --git a/source/blender/editors/space_ipo/ipo_select.c b/source/blender/editors/space_ipo/ipo_select.c
index 35a94af106d..dbc69db4e08 100644
--- a/source/blender/editors/space_ipo/ipo_select.c
+++ b/source/blender/editors/space_ipo/ipo_select.c
@@ -184,21 +184,17 @@ void GRAPHEDIT_OT_keyframes_deselectall (wmOperatorType *ot)
/* ******************** Border Select Operator **************************** */
/* This operator currently works in one of three ways:
- * -> BKEY - 1) all keyframes within region are selected (GRAPHKEYS_BORDERSEL_ALLKEYS)
+ * -> BKEY - 1) all keyframes within region are selected (validation with BEZT_OK_REGION)
* -> ALT-BKEY - depending on which axis of the region was larger...
- * -> 2) x-axis, so select all frames within frame range (GRAPHKEYS_BORDERSEL_FRAMERANGE)
- * -> 3) y-axis, so select all frames within channels that region included (GRAPHKEYS_BORDERSEL_CHANNELS)
+ * -> 2) x-axis, so select all frames within frame range (validation with BEZT_OK_FRAMERANGE)
+ * -> 3) y-axis, so select all frames within channels that region included (validation with BEZT_OK_VALUERANGE)
*/
-/* defines for borderselect mode */
-enum {
- GRAPHKEYS_BORDERSEL_ALLKEYS = 0,
- GRAPHKEYS_BORDERSEL_FRAMERANGE,
- GRAPHKEYS_BORDERSEL_CHANNELS,
-} egraphkeys_BorderSelect_Mode;
-
-
-static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short selectmode)
+/* Borderselect only selects keyframes now, as overshooting handles often get caught too,
+ * which means that they may be inadvertantly moved as well.
+ * Also, for convenience, handles should get same status as keyframe (if it was within bounds)
+ */
+static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, short selectmode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -210,30 +206,27 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short
rctf rectf;
/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
- UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin+2, &rectf.xmin, &rectf.ymin);
- UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax-2, &rectf.xmax, &rectf.ymax);
+ UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
/* filter data */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE);
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* get beztriple editing/validation funcs */
select_cb= ANIM_editkeyframes_select(selectmode);
+ ok_cb= ANIM_editkeyframes_ok(mode);
- if (ELEM(mode, GRAPHKEYS_BORDERSEL_FRAMERANGE, GRAPHKEYS_BORDERSEL_ALLKEYS))
- ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
- else
- ok_cb= NULL;
-
/* init editing data */
memset(&bed, 0, sizeof(BeztEditData));
+ bed.data= &rect;
/* loop over data, doing border select */
for (ale= anim_data.first; ale; ale= ale->next) {
Object *nob= ANIM_nla_mapping_get(ac, ale);
/* set horizontal range (if applicable) */
- if (ELEM(mode, GRAPHKEYS_BORDERSEL_FRAMERANGE, GRAPHKEYS_BORDERSEL_ALLKEYS)) {
+ if (mode != BEZT_OK_VALUERANGE) {
/* if channel is mapped in NLA, apply correction */
if (nob) {
bed.f1= get_action_frame(nob, rectf.xmin);
@@ -245,7 +238,8 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short
}
}
- // xxx... select code...
+ /* select keyframes that are in the appropriate places */
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
}
/* cleanup */
@@ -285,15 +279,15 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
* used for tweaking timing when "blocking", while channels is not that useful...
*/
if ((rect.xmax - rect.xmin) >= (rect.ymax - rect.ymin))
- mode= GRAPHKEYS_BORDERSEL_FRAMERANGE;
- //else
- // mode= GRAPHKEYS_BORDERSEL_CHANNELS;
+ mode= BEZT_OK_FRAMERANGE;
+ else
+ mode= BEZT_OK_VALUERANGE;
}
else
- mode= GRAPHKEYS_BORDERSEL_ALLKEYS;
+ mode= BEZT_OK_REGION;
/* apply borderselect action */
- borderselect_action(&ac, rect, mode, selectmode);
+ borderselect_graphkeys(&ac, rect, mode, selectmode);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index ef767a04728..a55d46f9a64 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -352,6 +352,16 @@ static void viewRedrawForce(bContext *C, TransInfo *t)
else
ED_area_tag_redraw(t->sa);
}
+ else if (t->spacetype == SPACE_IPO) {
+ SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
+
+ // TRANSFORM_FIX_ME
+ if (sipo->lock) {
+ // whole window...
+ }
+ else
+ ED_area_tag_redraw(t->sa);
+ }
else if(t->spacetype == SPACE_NODE)
{
//ED_area_tag_redraw(t->sa);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 4fc711babae..8532dda02aa 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2639,45 +2639,6 @@ int clipUVTransform(TransInfo *t, float *vec, int resize)
return 0;
}
-/* ********************* IPO EDITOR ************************* */
-
-/* for IPO Editor transform - but actual creation of transform structures is not performed here
- * due to bad globals that would need to be imported specially for this
- */
-static void createTransIpoData(bContext *C, TransInfo *t)
-{
- // TRANSFORM_FIX_ME
-#if 0
- /* in editipo.c due to some globals that are defined in that file... */
- make_ipo_transdata(t);
-#endif
-}
-
-/* this function is called on recalcData to apply the transforms applied
- * to the transdata on to the actual keyframe data
- */
-void flushTransIpoData(TransInfo *t)
-{
-#if 0 // TRANSFORM_FIX_ME
- TransData2D *td;
- int a;
-
- /* flush to 2d vector from internally used 3d vector */
- for (a=0, td= t->data2d; a<t->total; a++, td++) {
- // FIXME: autosnap needs to be here...
-
- /* we need to unapply the nla-scaling from the time in some situations */
- if (NLA_IPO_SCALED)
- td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
- else
- td->loc2d[0]= td->loc[0];
-
- /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
- if ((t->data[a].flag & TD_TIMEONLY)==0)
- td->loc2d[1]= td->loc[1];
- }
-#endif
-}
/* ********************* ACTION/NLA EDITOR ****************** */
@@ -3162,6 +3123,608 @@ static void createTransActionData(bContext *C, TransInfo *t)
BLI_freelistN(&anim_data);
}
+/* ********************* GRAPH EDITOR ************************* */
+
+#if 0 // GRAPH EDIT TO PORT
+
+/* Helper function for make_ipo_transdata, which is reponsible for associating
+ * source data with transform data
+ */
+static void bezt_to_transdata (TransData *td, TransData2D *td2d, float *loc, float *cent, short selected, short ishandle, short onlytime)
+{
+ /* New location from td gets dumped onto the old-location of td2d, which then
+ * gets copied to the actual data at td2d->loc2d (bezt->vec[n])
+ *
+ * Due to NLA scaling, we apply NLA scaling to some of the verts here,
+ * and then that scaling will be undone after transform is done.
+ */
+
+ if (NLA_IPO_SCALED) {
+ td2d->loc[0] = get_action_frame_inv(OBACT, loc[0]);
+ td2d->loc[1] = loc[1];
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = loc;
+
+ /*td->flag = 0;*/ /* can be set beforehand, else make sure its set to 0 */
+ td->loc = td2d->loc;
+ td->center[0] = get_action_frame_inv(OBACT, cent[0]);
+ td->center[1] = cent[1];
+ td->center[2] = 0.0f;
+
+ VECCOPY(td->iloc, td->loc);
+ }
+ else {
+ td2d->loc[0] = loc[0];
+ td2d->loc[1] = loc[1];
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = loc;
+
+ /*td->flag = 0;*/ /* can be set beforehand, else make sure its set to 0 */
+ td->loc = td2d->loc;
+ VECCOPY(td->center, cent);
+ VECCOPY(td->iloc, td->loc);
+ }
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext= NULL; td->tdi= NULL; td->val= NULL;
+
+ if (selected) {
+ td->flag |= TD_SELECTED;
+ td->dist= 0.0;
+ }
+ else
+ td->dist= MAXFLOAT;
+
+ if (onlytime)
+ td->flag |= TD_TIMEONLY;
+
+ if (ishandle)
+ td->flag |= TD_NOTIMESNAP;
+
+ Mat3One(td->mtx);
+ Mat3One(td->smtx);
+}
+
+/* This function is called by createTransIpoData and remake_ipo_transdata to
+ * create the TransData and TransData2D arrays for transform. The costly counting
+ * stage is only performed for createTransIpoData case, and is indicated by t->total==-1;
+ */
+void make_ipo_transdata (TransInfo *t)
+{
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+
+ EditIpo *ei;
+ BezTriple *bezt, *prevbezt;
+ int a, b;
+
+ /* countsel and propmode are used for proportional edit, which is not yet available */
+ int count=0/*, countsel=0*/;
+ /*int propmode = t->flag & T_PROP_EDIT;*/
+
+ /* count data and allocate memory (if needed) */
+ if (t->total == 0) {
+ /* count data first */
+ if (totipo_vertsel) {
+ /* we're probably in editmode, so only selected verts */
+ if (G.v2d->around == V3D_LOCAL) {
+ /* we're in editmode, but we need to count the number of selected handles only */
+ ei= G.sipo->editipo;
+ for (a=0; a<G.sipo->totipo; a++, ei++) {
+ if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu)) {
+ IpoCurve *icu= ei->icu;
+
+ if (icu->bezt) {
+ bezt= icu->bezt;
+ for (b=0; b < icu->totvert; b++, bezt++) {
+ if (bezt->ipo == IPO_BEZ) {
+ if (bezt->f1 & SELECT) count++;
+ if (bezt->f2 & SELECT) count++;
+ }
+ else if (bezt->f2 & SELECT) count++;
+ }
+ }
+ }
+ }
+ if (count==0) return;
+ }
+ else
+ count= totipo_vertsel;
+ }
+ else if (totipo_edit==0 && totipo_sel!=0) {
+ /* we're not in editmode, so entire curves get moved */
+ ei= G.sipo->editipo;
+ for (a=0; a<G.sipo->totipo; a++, ei++) {
+ if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu)) {
+ IpoCurve *icu= ei->icu;
+
+ if (icu->bezt) {
+ if (icu->ipo == IPO_MIXED) {
+ bezt= icu->bezt;
+ for (b=0; b < icu->totvert; b++, bezt++) {
+ if (bezt->ipo == IPO_BEZ) count += 3;
+ else count++;
+ }
+ }
+ else if (icu->ipo == IPO_BEZ)
+ count+= 3*icu->totvert;
+ else
+ count+= icu->totvert;
+ }
+ else
+ count+= icu->totvert;
+ }
+ }
+ if (count==0) return;
+ }
+ else {
+ /* this case should not happen */
+ return;
+ }
+
+ /* memory allocation */
+ /*t->total= (propmode)? count: countsel;*/
+ t->total= count;
+ t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (IPO Editor)");
+ /* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */
+ t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransData2D (IPO Editor)");
+ }
+
+ td= t->data;
+ td2d= t->data2d;
+
+ /* add verts */
+ if (totipo_vertsel) {
+ /* we're probably in editmode, so only selected verts */
+ ei= G.sipo->editipo;
+ for (a=0; a<G.sipo->totipo; a++, ei++) {
+ /* only consider those curves that are visible and are being edited/used for showkeys */
+ if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
+ if ((ei->flag & IPO_EDIT) || (G.sipo->showkey)) {
+ IpoCurve *icu= ei->icu;
+
+ if (icu->bezt) {
+ short onlytime= (ei->disptype==IPO_DISPBITS) ? 1 : (G.sipo->showkey) ? 1 : 0;
+
+ bezt= icu->bezt;
+ prevbezt= NULL;
+
+ for (b=0; b < icu->totvert; b++, prevbezt=bezt, bezt++) {
+ TransDataCurveHandleFlags *hdata = NULL;
+ short h1=1, h2=1;
+
+ /* only include handles if selected, and interpolaton mode uses beztriples */
+ if ( (!prevbezt && (bezt->ipo==IPO_BEZ)) || (prevbezt && (prevbezt->ipo==IPO_BEZ)) ) {
+ if (bezt->f1 & SELECT) {
+ hdata = initTransDataCurveHandes(td, bezt);
+ bezt_to_transdata(td++, td2d++, bezt->vec[0], bezt->vec[1], 1, 1, onlytime);
+ }
+ else
+ h1= 0;
+ }
+ if (bezt->ipo==IPO_BEZ) {
+ if (bezt->f3 & SELECT) {
+ if (hdata==NULL)
+ hdata = initTransDataCurveHandes(td, bezt);
+ bezt_to_transdata(td++, td2d++, bezt->vec[2], bezt->vec[1], 1, 1, onlytime);
+ }
+ else
+ h2= 0;
+ }
+
+ /* only include main vert if selected */
+ if (bezt->f2 & SELECT) {
+ /* if scaling around individuals centers, do no include keyframes */
+ if (G.v2d->around != V3D_LOCAL) {
+ /* if handles were not selected, store their selection status */
+ if (!(bezt->f1 & SELECT) && !(bezt->f3 & SELECT)) {
+ if (hdata == NULL)
+ hdata = initTransDataCurveHandes(td, bezt);
+ }
+
+ bezt_to_transdata(td++, td2d++, bezt->vec[1], bezt->vec[1], 1, 0, onlytime);
+ }
+
+ /* special hack (must be done after initTransDataCurveHandes(), as that stores handle settings to restore...):
+ * - Check if we've got entire BezTriple selected and we're scaling/rotating that point,
+ * then check if we're using auto-handles.
+ * - If so, change them auto-handles to aligned handles so that handles get affected too
+ */
+ if ((bezt->h1 == HD_AUTO) && (bezt->h2 == HD_AUTO) && ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
+ if (h1 && h2) {
+ bezt->h1= HD_ALIGN;
+ bezt->h2= HD_ALIGN;
+ }
+ }
+ }
+ }
+
+ /* Sets handles based on the selection */
+ testhandles_ipocurve(ei->icu);
+ }
+ }
+ }
+ }
+ }
+ else if (totipo_edit==0 && totipo_sel!=0) {
+ /* we're not in editmode, so entire curves get moved */
+ ei= G.sipo->editipo;
+ for (a=0; a<G.sipo->totipo; a++, ei++) {
+ /* only include curves that are visible and selected */
+ if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu)) {
+ IpoCurve *icu= ei->icu;
+
+ if (icu->bezt) {
+ short onlytime= (ei->disptype==IPO_DISPBITS) ? 1 : (G.sipo->showkey) ? 1 : 0;
+
+ bezt= icu->bezt;
+ prevbezt= NULL;
+
+ for (b=0; b < icu->totvert; b++, prevbezt=bezt, bezt++) {
+ /* only include handles if interpolation mode is bezier is relevant */
+ if ( (!prevbezt && (bezt->ipo==IPO_BEZ)) || (prevbezt && (prevbezt->ipo==IPO_BEZ)) )
+ bezt_to_transdata(td++, td2d++, bezt->vec[0], bezt->vec[1], 1, 1,onlytime);
+ if (bezt->ipo==IPO_BEZ)
+ bezt_to_transdata(td++, td2d++, bezt->vec[2], bezt->vec[1], 1, 1, onlytime);
+
+ /* always include the main handle */
+ bezt_to_transdata(td++, td2d++, bezt->vec[1], bezt->vec[1], 1, 0, onlytime);
+ }
+ }
+ }
+ }
+ }
+}
+
+/* ------------------------ */
+
+/* struct for use in re-sorting BezTriples during IPO transform */
+typedef struct BeztMap {
+ BezTriple *bezt;
+ int oldIndex; /* index of bezt in icu->bezt array before sorting */
+ int newIndex; /* index of bezt in icu->bezt array after sorting */
+ short swapHs; /* swap order of handles (-1=clear; 0=not checked, 1=swap) */
+ char pipo, cipo; /* interpolation of current and next segments */
+} BeztMap;
+
+
+/* This function converts an IpoCurve's BezTriple array to a BeztMap array
+ * NOTE: this allocates memory that will need to get freed later
+ */
+static BeztMap *bezt_to_beztmaps (BezTriple *bezts, int totvert)
+{
+ BezTriple *bezt= bezts;
+ BezTriple *prevbezt= NULL;
+ BeztMap *bezm, *bezms;
+ int i;
+
+ /* allocate memory for this array */
+ if (totvert==0 || bezts==NULL)
+ return NULL;
+ bezm= bezms= MEM_callocN(sizeof(BeztMap)*totvert, "BeztMaps");
+
+ /* assign beztriples to beztmaps */
+ for (i=0; i < totvert; i++, bezm++, prevbezt=bezt, bezt++) {
+ bezm->bezt= bezt;
+
+ bezm->oldIndex= i;
+ bezm->newIndex= i;
+
+ bezm->pipo= (prevbezt) ? prevbezt->ipo : bezt->ipo;
+ bezm->cipo= bezt->ipo;
+ }
+
+ return bezms;
+}
+
+/* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead */
+static void sort_time_beztmaps (BeztMap *bezms, int totvert)
+{
+ BeztMap *bezm;
+ int i, ok= 1;
+
+ /* keep repeating the process until nothing is out of place anymore */
+ while (ok) {
+ ok= 0;
+
+ bezm= bezms;
+ i= totvert;
+ while (i--) {
+ /* is current bezm out of order (i.e. occurs later than next)? */
+ if (i > 0) {
+ if (bezm->bezt->vec[1][0] > (bezm+1)->bezt->vec[1][0]) {
+ bezm->newIndex++;
+ (bezm+1)->newIndex--;
+
+ SWAP(BeztMap, *bezm, *(bezm+1));
+
+ ok= 1;
+ }
+ }
+
+ /* do we need to check if the handles need to be swapped?
+ * optimisation: this only needs to be performed in the first loop
+ */
+ if (bezm->swapHs == 0) {
+ if ( (bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) &&
+ (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0]) )
+ {
+ /* handles need to be swapped */
+ bezm->swapHs = 1;
+ }
+ else {
+ /* handles need to be cleared */
+ bezm->swapHs = -1;
+ }
+ }
+
+ bezm++;
+ }
+ }
+}
+
+/* This function firstly adjusts the pointers that the transdata has to each BezTriple*/
+static void beztmap_to_data (TransInfo *t, EditIpo *ei, BeztMap *bezms, int totvert)
+{
+ BezTriple *bezts = ei->icu->bezt;
+ BeztMap *bezm;
+ TransData2D *td;
+ int i, j;
+ char *adjusted;
+
+ /* dynamically allocate an array of chars to mark whether an TransData's
+ * pointers have been fixed already, so that we don't override ones that are
+ * already done
+ */
+ adjusted= MEM_callocN(t->total, "beztmap_adjusted_map");
+
+ /* for each beztmap item, find if it is used anywhere */
+ bezm= bezms;
+ for (i= 0; i < totvert; i++, bezm++) {
+ /* loop through transdata, testing if we have a hit
+ * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped...
+ */
+ td= t->data2d;
+ for (j= 0; j < t->total; j++, td++) {
+ /* skip item if already marked */
+ if (adjusted[j] != 0) continue;
+
+ if (totipo_vertsel) {
+ /* only selected verts */
+ if (bezm->pipo == IPO_BEZ) {
+ if (bezm->bezt->f1 & SELECT) {
+ if (td->loc2d == bezm->bezt->vec[0]) {
+ if (bezm->swapHs == 1)
+ td->loc2d= (bezts + bezm->newIndex)->vec[2];
+ else
+ td->loc2d= (bezts + bezm->newIndex)->vec[0];
+ adjusted[j] = 1;
+ }
+ }
+ }
+ if (bezm->cipo == IPO_BEZ) {
+ if (bezm->bezt->f3 & SELECT) {
+ if (td->loc2d == bezm->bezt->vec[2]) {
+ if (bezm->swapHs == 1)
+ td->loc2d= (bezts + bezm->newIndex)->vec[0];
+ else
+ td->loc2d= (bezts + bezm->newIndex)->vec[2];
+ adjusted[j] = 1;
+ }
+ }
+ }
+ if (bezm->bezt->f2 & SELECT) {
+ if (td->loc2d == bezm->bezt->vec[1]) {
+ td->loc2d= (bezts + bezm->newIndex)->vec[1];
+ adjusted[j] = 1;
+ }
+ }
+ }
+ else {
+ /* whole curve */
+ if (bezm->pipo == IPO_BEZ) {
+ if (td->loc2d == bezm->bezt->vec[0]) {
+ if (bezm->swapHs == 1)
+ td->loc2d= (bezts + bezm->newIndex)->vec[2];
+ else
+ td->loc2d= (bezts + bezm->newIndex)->vec[0];
+ adjusted[j] = 1;
+ }
+ }
+ if (bezm->cipo == IPO_BEZ) {
+ if (td->loc2d == bezm->bezt->vec[2]) {
+ if (bezm->swapHs == 1)
+ td->loc2d= (bezts + bezm->newIndex)->vec[0];
+ else
+ td->loc2d= (bezts + bezm->newIndex)->vec[2];
+ adjusted[j] = 1;
+ }
+ }
+ if (td->loc2d == bezm->bezt->vec[1]) {
+ td->loc2d= (bezts + bezm->newIndex)->vec[1];
+ adjusted[j] = 1;
+ }
+ }
+ }
+
+ }
+
+ /* free temp memory used for 'adjusted' array */
+ MEM_freeN(adjusted);
+}
+
+/* This function is called by recalcData during the Transform loop to recalculate
+ * the handles of curves and sort the keyframes so that the curves draw correctly.
+ * It is only called if some keyframes have moved out of order.
+ */
+void remake_ipo_transdata (TransInfo *t)
+{
+ EditIpo *ei;
+ int a;
+
+ /* sort and reassign verts */
+ ei= G.sipo->editipo;
+ for (a=0; a<G.sipo->totipo; a++, ei++) {
+ if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
+ if (ei->icu->bezt) {
+ BeztMap *bezm;
+
+ /* adjust transform-data pointers */
+ bezm= bezt_to_beztmaps(ei->icu->bezt, ei->icu->totvert);
+ sort_time_beztmaps(bezm, ei->icu->totvert);
+ beztmap_to_data(t, ei, bezm, ei->icu->totvert);
+
+ /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */
+ sort_time_ipocurve(ei->icu);
+
+ /* free mapping stuff */
+ MEM_freeN(bezm);
+
+ /* make sure handles are all set correctly */
+ testhandles_ipocurve(ei->icu);
+ }
+ }
+ }
+
+ /* remake ipokeys */
+ if (G.sipo->showkey) make_ipokey();
+}
+#endif // GRAPHEDIT TO PORT
+
+static void createTransGraphEditData(bContext *C, TransInfo *t)
+{
+ Scene *scene= CTX_data_scene(C);
+ TransData *td = NULL;
+
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ int count=0;
+ float cfra;
+ char side;
+
+ /* determine what type of data we are operating on */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* which side of the current frame should be allowed */
+ if (t->mode == TFM_TIME_EXTEND) {
+ /* only side on which mouse is gets transformed */
+ float xmouse, ymouse;
+
+ UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
+ side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ side = 'B';
+ }
+
+ /* loop 1: fully select ipo-keys and count how many BezTriples are selected */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(&ac, ale);
+
+ /* convert current-frame to action-time (slightly less accurate, espcially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (nob)
+ cfra = get_action_frame(nob, (float)CFRA);
+ else
+ cfra = (float)CFRA;
+
+ count += count_fcurve_keys(ale->key_data, side, cfra);
+ }
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ /* cleanup temp list */
+ BLI_freelistN(&anim_data);
+ return;
+ }
+
+ /* allocate memory for data */
+ t->total= count;
+
+ t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)");
+ td= t->data;
+
+ if (t->mode == TFM_TIME_SLIDE)
+ t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max");
+
+ /* loop 2: build transdata array */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ /* convert current-frame to action-time (slightly less accurate, espcially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (nob)
+ cfra = get_action_frame(nob, (float)CFRA);
+ else
+ cfra = (float)CFRA;
+
+ td= FCurveToTransData(td, fcu, nob, side, cfra); // XXX... this doesn't do points!
+ }
+
+ /* check if we're supposed to be setting minx/maxx for TimeSlide */
+ if (t->mode == TFM_TIME_SLIDE) {
+ float min=999999999.0f, max=-999999999.0f;
+ 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(&anim_data);
+}
+
+
+/* this function is called on recalcData to apply the transforms applied
+ * to the transdata on to the actual keyframe data
+ */
+void flushTransIpoData(TransInfo *t)
+{
+#if 0 // TRANSFORM_FIX_ME
+ TransData2D *td;
+ int a;
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a=0, td= t->data2d; a<t->total; a++, td++) {
+ // FIXME: autosnap needs to be here...
+
+ /* we need to unapply the nla-scaling from the time in some situations */
+ if (NLA_IPO_SCALED)
+ td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
+ else
+ td->loc2d[0]= td->loc[0];
+
+ /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
+ if ((t->data[a].flag & TD_TIMEONLY)==0)
+ td->loc2d[1]= td->loc[1];
+ }
+#endif
+}
+
/* **************** IpoKey stuff, for Object TransData ********** */
@@ -4226,12 +4789,65 @@ void special_aftertrans_update(TransInfo *t)
}
#endif // XXX future of this is still not clear
- /* make sure all IPO-curves are set correctly */
+ /* make sure all F-Curves are set correctly */
ANIM_editkeyframes_refresh(&ac);
/* clear flag that was set for time-slide drawing */
saction->flag &= ~SACTION_MOVING;
}
+ else if (t->spacetype == SPACE_IPO) {
+ SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
+ Scene *scene;
+ bAnimContext ac;
+
+ /* initialise relevant anim-context 'context' data from TransInfo data */
+ /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+ memset(&ac, 0, sizeof(bAnimContext));
+
+ scene= ac.scene= t->scene;
+ ob= ac.obact= OBACT;
+ ac.sa= t->sa;
+ ac.ar= t->ar;
+ ac.spacetype= (t->sa)? t->sa->spacetype : 0;
+ ac.regiontype= (t->ar)? t->ar->regiontype : 0;
+
+ if (ANIM_animdata_context_getdata(&ac) == 0)
+ return;
+
+ if (ac.datatype)
+ {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE);
+
+ /* get channels to work on */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* these should all be ipo-blocks */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ if ( (sipo->flag & SIPO_NOTRANSKEYCULL)==0 &&
+ ((cancelled == 0) || (duplicate)) )
+ {
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, fcu, 0, 1);
+ posttrans_fcurve_clean(fcu);
+ ANIM_nla_mapping_apply_fcurve(nob, fcu, 1, 1);
+ }
+ else
+ posttrans_fcurve_clean(fcu);
+ }
+ }
+
+ /* free temp memory */
+ BLI_freelistN(&anim_data);
+ }
+
+ /* make sure all F-Curves are set correctly */
+ ANIM_editkeyframes_refresh(&ac);
+ }
else if (t->obedit) {
// TRANSFORM_FIX_ME
// if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
@@ -4260,26 +4876,6 @@ void special_aftertrans_update(TransInfo *t)
posttrans_nla_clean(t);
}
}
- else if (t->spacetype == SPACE_IPO) {
- // FIXME! is there any code from the old transform_ipo that needs to be added back?
-
- /* after transform, remove duplicate keyframes on a frame that resulted from transform */
- if (G.sipo->ipo)
- {
- if ( (G.sipo->flag & SIPO_NOTRANSKEYCULL)==0 &&
- (cancelled == 0) )
- {
- /* NOTE: no need to do NLA scaling stuff here, as when there is NLA scaling,
- * the transformed handles will get moved wrong (seem to match wrong repeat cycle)
- */
- posttrans_ipo_clean(G.sipo->ipo);
- }
- }
-
- /* resetting slow-parents isn't really necessary when editing sequence ipo's */
- if (G.sipo->blocktype==ID_SEQ)
- resetslowpar= 0;
- }
else if ((t->flag & T_POSE) && (t->poseobj)) {
bArmature *arm;
bPose *pose;
@@ -4593,7 +5189,7 @@ void createTransData(bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_IPO) {
t->flag |= T_POINTS|T_2D_EDIT;
- createTransIpoData(C, t);
+ createTransGraphEditData(C, t);
#if 0
if (t->data && (t->flag & T_PROP_EDIT)) {
sort_trans_data(t); // makes selected become first in array