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-03-15 13:39:02 +0300
committerJoshua Leung <aligorith@gmail.com>2009-03-15 13:39:02 +0300
commit329aa658c97470a6ac2861c0c9b8108ff0c48182 (patch)
tree7ed0dac0fb21860dfaab04c4c5269ed6057249eb /source/blender/editors/space_graph
parent6508ad460fa91d605de2f62320711b19a319e2cb (diff)
F-Curve Modifiers: Groundwork for getting these working
- Completed cleaning up the drawing code so that F-Curves with modifiers now get drawn to reflect this. - Added a temporary operator to add modifiers (hotkey Ctrl-Shift-M)
Diffstat (limited to 'source/blender/editors/space_graph')
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c81
-rw-r--r--source/blender/editors/space_graph/graph_draw.c431
-rw-r--r--source/blender/editors/space_graph/graph_edit.c120
-rw-r--r--source/blender/editors/space_graph/graph_intern.h10
-rw-r--r--source/blender/editors/space_graph/graph_ops.c9
-rw-r--r--source/blender/editors/space_graph/space_graph.c9
6 files changed, 404 insertions, 256 deletions
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 859aab9283e..7c078ad184d 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -52,6 +52,7 @@
#include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
#include "BKE_object.h"
#include "BKE_global.h"
#include "BKE_scene.h"
@@ -218,32 +219,92 @@ static void graph_panel_drivers(const bContext *C, ARegion *ar, short cntrl, bAn
/* -------------- */
+#define B_FMODIFIER_REDRAW 20
+
static void do_graph_region_modifier_buttons(bContext *C, void *arg, int event)
{
- //Scene *scene= CTX_data_scene(C);
-
switch(event) {
+ case B_REDR:
+ case B_FMODIFIER_REDRAW:
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return; /* no notifier! */
+ }
+}
+
+/* for now, just print name of modifier */
+static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco)
+{
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+ uiBut *but;
+ short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE);
+ short width= 314;
+ short height = 0;
+ int rb_col;
+
+ /* draw header */
+ {
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ /* rounded header */
+ if (active) uiBlockSetCol(block, TH_BUT_ACTION);
+ rb_col= (active)?-20:20;
+ uiDefBut(block, ROUNDBOX, B_REDR, "", 10-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), "");
+ if (active) uiBlockSetCol(block, TH_AUTO);
+
+ /* expand */
+ uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 10-7, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded");
+
+ /* name */
+ if (fmi)
+ uiDefBut(block, LABEL, 1, fmi->name, 10+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type");
+ else
+ uiDefBut(block, LABEL, 1, "<Unknown Modifier>", 10+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type");
+
+ /* delete button */
+ but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 10+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
+ //uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
+ uiBlockSetEmboss(block, UI_EMBOSS);
}
- /* default for now */
- //WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+ /* when modifier is expanded, draw settings */
+ if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
+ height= 97;
+
+ /* draw backdrop */
+ if (active) uiBlockSetCol(block, TH_BUT_ACTION);
+ uiDefBut(block, ROUNDBOX, B_REDR, "", 10-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, "");
+ if (active) uiBlockSetCol(block, TH_AUTO);
+ }
+
+ /* adjust height for new to start */
+ (*yco) -= (height + 27);
}
static void graph_panel_modifiers(const bContext *C, ARegion *ar, short cntrl, bAnimListElem *ale)
{
- //FCurve *fcu= (FCurve *)ale->data;
- //FModifier *fcm;
+ FCurve *fcu= (FCurve *)ale->data;
+ FModifier *fcm;
uiBlock *block;
+ int yco= 190;
block= uiBeginBlock(C, ar, "graph_panel_modifiers", UI_EMBOSS, UI_HELV);
if (uiNewPanel(C, ar, block, "Modifiers", "Graph", 340, 30, 318, 254)==0) return;
uiBlockSetHandleFunc(block, do_graph_region_modifier_buttons, NULL);
-
- /* to force height */
- uiNewPanelHeight(block, 204); // XXX variable height!
+ /* 'add modifier' button at top of panel */
+ // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
+ uiDefButO(block, BUT, "GRAPHEDIT_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 225, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve");
+
+ /* draw each modifier */
+ for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next)
+ graph_panel_modifier_draw(block, fcu, fcm, &yco);
+ /* since these buttons can have variable height */
+ if (yco < 0)
+ uiNewPanelHeight(block, (204 - yco));
+ else
+ uiNewPanelHeight(block, 204);
}
/* -------------- */
@@ -253,7 +314,7 @@ static void graph_panel_modifiers(const bContext *C, ARegion *ar, short cntrl, b
* when the caller is done with it.
*/
// TODO: move this to anim api with another name?
-static bAnimListElem *get_active_fcurve_channel (bAnimContext *ac)
+bAnimListElem *get_active_fcurve_channel (bAnimContext *ac)
{
ListBase anim_data = {NULL, NULL};
int filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE | ANIMFILTER_CURVESONLY);
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 1efa257c317..bd57e9750eb 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -27,6 +27,7 @@
#include <stdio.h>
#include <math.h>
#include <string.h>
+#include <float.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -401,9 +402,62 @@ static void draw_fcurve_samples (SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
/* Curve ---------------- */
+/* minimum pixels per gridstep
+ * XXX: defined in view2d.c - must keep these in sync or relocate to View2D header!
+ */
+#define MINGRIDSTEP 35
+
+/* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */
+static void draw_fcurve_curve (FCurve *fcu, SpaceIpo *sipo, View2D *v2d, View2DGrid *grid)
+{
+ ChannelDriver *driver;
+ float samplefreq, ctime;
+ float stime, etime;
+
+ /* disable any drivers temporarily */
+ driver= fcu->driver;
+ fcu->driver= NULL;
+
+
+ /* Note about sampling frequency:
+ * Ideally, this is chosen such that we have 1-2 pixels = 1 segment
+ * which means that our curves can be as smooth as possible. However,
+ * this does mean that curves may not be fully accurate (i.e. if they have
+ * sudden spikes which happen at the sampling point, we may have problems).
+ * Also, this may introduce lower performance on less densely detailed curves,'
+ * though it is impossible to predict this from the modifiers!
+ *
+ * If the automatically determined sampling frequency is likely to cause an infinite
+ * loop (i.e. too close to FLT_EPSILON), fall back to default of 0.001
+ */
+ /* grid->dx is the first float in View2DGrid struct, so just cast to float pointer, and use it
+ * It represents the number of 'frames' between gridlines, but we divide by MINGRIDSTEP to get pixels-steps
+ */
+ // TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted?
+ samplefreq= *((float *)grid) / MINGRIDSTEP;
+ if (IS_EQ(samplefreq, 0)) samplefreq= 0.001f;
+
+
+ /* the start/end times are simply the horizontal extents of the 'cur' rect */
+ stime= v2d->cur.xmin;
+ etime= v2d->cur.xmax;
+
+
+ /* at each sampling interval, add a new vertex */
+ glBegin(GL_LINE_STRIP);
+
+ for (ctime= stime; ctime <= etime; ctime += samplefreq)
+ glVertex2f( ctime, evaluate_fcurve(fcu, ctime) );
+
+ glEnd();
+
+ /* restore driver */
+ fcu->driver= driver;
+}
+
/* helper func - draw a samples-based F-Curve */
// TODO: add offset stuff...
-static void draw_fcurve_repeat_samples (FCurve *fcu, View2D *v2d)
+static void draw_fcurve_curve_samples (FCurve *fcu, View2D *v2d)
{
FPoint *prevfpt= fcu->fpt;
FPoint *fpt= prevfpt + 1;
@@ -412,26 +466,23 @@ static void draw_fcurve_repeat_samples (FCurve *fcu, View2D *v2d)
glBegin(GL_LINE_STRIP);
- /* extrapolate to left? */
- if ( (fcu->modifiers.first == NULL)/* || ( ((FModifier *)fcu->modifiers.first)->type != FMODIFIER_TYPE_CYCLES) */) {
- /* left-side of view comes before first keyframe, so need to extend as not cyclic */
- if (prevfpt->vec[0] > v2d->cur.xmin) {
- v[0]= v2d->cur.xmin;
-
- /* y-value depends on the interpolation */
- if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
- /* just extend across the first keyframe's value */
- v[1]= prevfpt->vec[1];
- }
- else {
- /* extrapolate linear dosnt use the handle, use the next points center instead */
- fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
- if (fac) fac= 1.0f/fac;
- v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
- }
-
- glVertex2fv(v);
+ /* extrapolate to left? - left-side of view comes before first keyframe? */
+ if (prevfpt->vec[0] > v2d->cur.xmin) {
+ v[0]= v2d->cur.xmin;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
+ /* just extend across the first keyframe's value */
+ v[1]= prevfpt->vec[1];
+ }
+ else {
+ /* extrapolate linear dosnt use the handle, use the next points center instead */
+ fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
+ if (fac) fac= 1.0f/fac;
+ v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
}
+
+ glVertex2fv(v);
}
/* if only one sample, add it now */
@@ -440,7 +491,6 @@ static void draw_fcurve_repeat_samples (FCurve *fcu, View2D *v2d)
/* loop over samples, drawing segments */
/* draw curve between first and last keyframe (if there are enough to do so) */
- // XXX this doesn't take into account modifiers, or sample data
while (b--) {
/* Linear interpolation: just add one point (which should add a new line segment) */
glVertex2fv(prevfpt->vec);
@@ -455,95 +505,90 @@ static void draw_fcurve_repeat_samples (FCurve *fcu, View2D *v2d)
}
/* extrapolate to right? (see code for left-extrapolation above too) */
- if ( (fcu->modifiers.first == NULL)/* || ( ((FModifier *)fcu->modifiers.first)->type != FMODIFIER_TYPE_CYCLES) */) {
- if (prevfpt->vec[0] < v2d->cur.xmax) {
- v[0]= v2d->cur.xmax;
-
- /* y-value depends on the interpolation */
- if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
- /* based on last keyframe's value */
- v[1]= prevfpt->vec[1];
- }
- else {
- /* extrapolate linear dosnt use the handle, use the previous points center instead */
- fpt = prevfpt-1;
- fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
- if (fac) fac= 1.0f/fac;
- v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
- }
-
- glVertex2fv(v);
+ if (prevfpt->vec[0] < v2d->cur.xmax) {
+ v[0]= v2d->cur.xmax;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
+ /* based on last keyframe's value */
+ v[1]= prevfpt->vec[1];
+ }
+ else {
+ /* extrapolate linear dosnt use the handle, use the previous points center instead */
+ fpt = prevfpt-1;
+ fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
+ if (fac) fac= 1.0f/fac;
+ v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
}
+
+ glVertex2fv(v);
}
glEnd();
}
/* helper func - draw one repeat of an F-Curve */
-static void draw_fcurve_repeat (FCurve *fcu, View2D *v2d, float cycxofs, float cycyofs, float *facp)
+static void draw_fcurve_curve_bezts (FCurve *fcu, View2D *v2d, View2DGrid *grid)
{
BezTriple *prevbezt= fcu->bezt;
BezTriple *bezt= prevbezt+1;
float v1[2], v2[2], v3[2], v4[2];
float *fp, data[120];
- float fac= *(facp);
+ float fac= 0.0f;
int b= fcu->totvert-1;
int resol;
glBegin(GL_LINE_STRIP);
/* extrapolate to left? */
- if ( (fcu->modifiers.first == NULL)/* || ( ((FModifier *)fcu->modifiers.first)->type != FMODIFIER_TYPE_CYCLES) */) {
+ if (prevbezt->vec[1][0] > v2d->cur.xmin) {
/* left-side of view comes before first keyframe, so need to extend as not cyclic */
- if (prevbezt->vec[1][0] > v2d->cur.xmin) {
- v1[0]= v2d->cur.xmin;
-
- /* y-value depends on the interpolation */
- if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
- /* just extend across the first keyframe's value */
- v1[1]= prevbezt->vec[1][1];
- }
- else if (prevbezt->ipo==BEZT_IPO_LIN) {
- /* extrapolate linear dosnt use the handle, use the next points center instead */
- fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
- if (fac) fac= 1.0f/fac;
- v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
- }
- else {
- /* based on angle of handle 1 (relative to keyframe) */
- fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
- if (fac) fac= 1.0f/fac;
- v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
- }
-
- glVertex2fv(v1);
+ v1[0]= v2d->cur.xmin;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
+ /* just extend across the first keyframe's value */
+ v1[1]= prevbezt->vec[1][1];
+ }
+ else if (prevbezt->ipo==BEZT_IPO_LIN) {
+ /* extrapolate linear dosnt use the handle, use the next points center instead */
+ fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if (fac) fac= 1.0f/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
+ }
+ else {
+ /* based on angle of handle 1 (relative to keyframe) */
+ fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if (fac) fac= 1.0f/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
}
+
+ glVertex2fv(v1);
}
/* if only one keyframe, add it now */
if (fcu->totvert == 1) {
- v1[0]= prevbezt->vec[1][0] + cycxofs;
- v1[1]= prevbezt->vec[1][1] + cycyofs;
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
glVertex2fv(v1);
}
/* draw curve between first and last keyframe (if there are enough to do so) */
- // XXX this doesn't take into account modifiers, or sample data
while (b--) {
if ((fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST)) {
/* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */
- v1[0]= prevbezt->vec[1][0]+cycxofs;
- v1[1]= prevbezt->vec[1][1]+cycyofs;
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
glVertex2fv(v1);
- v1[0]= bezt->vec[1][0]+cycxofs;
- v1[1]= prevbezt->vec[1][1]+cycyofs;
+ v1[0]= bezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
glVertex2fv(v1);
}
else if (prevbezt->ipo==BEZT_IPO_LIN) {
/* Linear interpolation: just add one point (which should add a new line segment) */
- v1[0]= prevbezt->vec[1][0]+cycxofs;
- v1[1]= prevbezt->vec[1][1]+cycyofs;
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
glVertex2fv(v1);
}
else {
@@ -560,23 +605,23 @@ static void draw_fcurve_repeat (FCurve *fcu, View2D *v2d, float cycxofs, float c
if (resol < 2) {
/* only draw one */
- v1[0]= prevbezt->vec[1][0]+cycxofs;
- v1[1]= prevbezt->vec[1][1]+cycyofs;
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
glVertex2fv(v1);
}
else {
/* clamp resolution to max of 32 */
if (resol > 32) resol= 32;
- v1[0]= prevbezt->vec[1][0]+cycxofs;
- v1[1]= prevbezt->vec[1][1]+cycyofs;
- v2[0]= prevbezt->vec[2][0]+cycxofs;
- v2[1]= prevbezt->vec[2][1]+cycyofs;
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ v2[0]= prevbezt->vec[2][0];
+ v2[1]= prevbezt->vec[2][1];
- v3[0]= bezt->vec[0][0]+cycxofs;
- v3[1]= bezt->vec[0][1]+cycyofs;
- v4[0]= bezt->vec[1][0]+cycxofs;
- v4[1]= bezt->vec[1][1]+cycyofs;
+ v3[0]= bezt->vec[0][0];
+ v3[1]= bezt->vec[0][1];
+ v4[0]= bezt->vec[1][0];
+ v4[1]= bezt->vec[1][1];
correct_bezpart(v1, v2, v3, v4);
@@ -594,152 +639,41 @@ static void draw_fcurve_repeat (FCurve *fcu, View2D *v2d, float cycxofs, float c
/* last point? */
if (b == 0) {
- v1[0]= prevbezt->vec[1][0]+cycxofs;
- v1[1]= prevbezt->vec[1][1]+cycyofs;
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
glVertex2fv(v1);
}
}
/* extrapolate to right? (see code for left-extrapolation above too) */
- if ( (fcu->modifiers.first == NULL)/* || ( ((FModifier *)fcu->modifiers.first)->type != FMODIFIER_TYPE_CYCLES) */) {
- if (prevbezt->vec[1][0] < v2d->cur.xmax) {
- v1[0]= v2d->cur.xmax;
-
- /* y-value depends on the interpolation */
- if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
- /* based on last keyframe's value */
- v1[1]= prevbezt->vec[1][1];
- }
- else if (prevbezt->ipo==BEZT_IPO_LIN) {
- /* extrapolate linear dosnt use the handle, use the previous points center instead */
- bezt = prevbezt-1;
- fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
- if (fac) fac= 1.0f/fac;
- v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
- }
- else {
- /* based on angle of handle 1 (relative to keyframe) */
- fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
- if (fac) fac= 1.0f/fac;
- v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
- }
-
- glVertex2fv(v1);
+ if (prevbezt->vec[1][0] < v2d->cur.xmax) {
+ v1[0]= v2d->cur.xmax;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
+ /* based on last keyframe's value */
+ v1[1]= prevbezt->vec[1][1];
+ }
+ else if (prevbezt->ipo==BEZT_IPO_LIN) {
+ /* extrapolate linear dosnt use the handle, use the previous points center instead */
+ bezt = prevbezt-1;
+ fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if (fac) fac= 1.0f/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
+ }
+ else {
+ /* based on angle of handle 1 (relative to keyframe) */
+ fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if (fac) fac= 1.0f/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
}
+
+ glVertex2fv(v1);
}
glEnd();
-
- /* return fac, as we alter it */
- *(facp) = fac;
}
-#if 0 // XXX old animation system unconverted code!
-
-/* draw all ipo-curves */
-static void draw_ipocurves(SpaceIpo *sipo, ARegion *ar, int sel)
-{
- View2D *v2d= &ar->v2d;
- EditIpo *ei;
- int nr, val/*, pickselcode=0*/;
-
- /* if we're drawing for GL_SELECT, reset pickselcode first
- * - there's only one place that will do this, so it should be fine
- */
- //if (G.f & G_PICKSEL)
- // pickselcode= 1;
-
- ei= sipo->editipo;
- for (nr=0; nr<sipo->totipo; nr++, ei++) {
- if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
- /* val is used to indicate if curve can be edited */
- //if (G.f & G_PICKSEL) {
- // /* when using OpenGL to select stuff (on mouseclick) */
- // glLoadName(pickselcode++);
- // val= 1;
- //}
- //else {
- /* filter to only draw those that are selected or unselected (based on drawing mode */
- val= (ei->flag & (IPO_SELECT+IPO_EDIT)) != 0;
- val= (val==sel);
- //}
-
- /* only draw those curves that we can draw */
- if (val) {
- IpoCurve *icu= ei->icu;
- float cycdx=0.0f, cycdy=0.0f, cycxofs=0.0f, cycyofs=0.0f;
- const int lastindex= (icu->totvert-1);
- float fac= 0.0f;
- int cycount=1;
-
- /* set color for curve curve:
- * - bitflag curves (evil) must always be drawn coloured as they cannot work with IPO-Keys
- * - when IPO-Keys are shown, individual curves are not editable, so we show by drawing them all black
- */
- if ((sipo->showkey) && (ei->disptype!=IPO_DISPBITS)) UI_ThemeColor(TH_TEXT);
- else cpack(ei->col);
-
- /* cyclic curves - get offset and number of repeats to display */
- if (icu->extrap & IPO_CYCL) {
- BezTriple *bezt= icu->bezt;
- BezTriple *lastbezt= bezt + lastindex;
-
- /* calculate cycle length and amplitude */
- cycdx= lastbezt->vec[1][0] - bezt->vec[1][0];
- cycdy= lastbezt->vec[1][1] - bezt->vec[1][1];
-
- /* check that the cycle does have some length */
- if (cycdx > 0.01f) {
- /* count cycles before first frame */
- while (icu->bezt->vec[1][0]+cycxofs > v2d->cur.xmin) {
- cycxofs -= cycdx;
- if (icu->extrap & IPO_DIR) cycyofs-= cycdy;
- cycount++;
- }
-
- /* count cycles after last frame (and adjust offset) */
- fac= 0.0f;
- while (lastbezt->vec[1][0]+fac < v2d->cur.xmax) {
- cycount++;
- fac += cycdx;
- }
- }
- }
-
- /* repeat process for each repeat */
- while (cycount--) {
- /* bitflag curves are drawn differently to normal curves */
- if (ei->disptype==IPO_DISPBITS)
- draw_ipocurve_repeat_bits(icu, v2d, cycxofs);
- else
- draw_ipocurve_repeat_normal(icu, v2d, cycxofs, cycyofs, &fac);
-
- /* prepare for next cycle by adjusing offsets */
- cycxofs += cycdx;
- if (icu->extrap & IPO_DIR) cycyofs += cycdy;
- }
-
- /* vertical line that indicates the end of a speed curve */
- if ((sipo->blocktype==ID_CU) && (icu->adrcode==CU_SPEED)) {
- int b= icu->totvert-1;
-
- if (b) {
- BezTriple *bezt= icu->bezt+b;
-
- glColor3ub(0, 0, 0);
-
- glBegin(GL_LINES);
- glVertex2f(bezt->vec[1][0], 0.0f);
- glVertex2f(bezt->vec[1][0], bezt->vec[1][1]);
- glEnd();
- }
- }
- }
- }
- }
-}
-#endif // XXX old animation system unconverted code
-
#if 0
static void draw_ipokey(SpaceIpo *sipo, ARegion *ar)
{
@@ -758,7 +692,9 @@ static void draw_ipokey(SpaceIpo *sipo, ARegion *ar)
}
#endif
-void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
+/* Public Curve-Drawing API ---------------- */
+
+void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid *grid)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -774,20 +710,22 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
*/
for (ale=anim_data.first; ale; ale=ale->next) {
FCurve *fcu= (FCurve *)ale->key_data;
- Object *nob= ANIM_nla_mapping_get(ac, ale);
- float fac=0.0f; // dummy var
+ //FModifier *fcm= fcurve_active_modifier(fcu);
+ //Object *nob= ANIM_nla_mapping_get(ac, ale);
/* map keyframes for drawing if scaled F-Curve */
- if (nob)
- ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 0);
+ //if (nob)
+ // ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 0);
- /* draw curve - if there's an active modifier (or a stack of modifiers) drawing these takes presidence,
- * unless modifiers in use will not alter any of the values within the keyframed area...
+ /* draw curve:
+ * - curve line may be result of one or more destructive modifiers or just the raw data,
+ * so we need to check which method should be used
+ * - controls from active modifier take precidence over keyframes
+ * (XXX! editing tools need to take this into account!)
*/
-
-
- /* draw curve - as defined by keyframes */
- if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) {
+
+ /* 1) draw curve line */
+ {
/* set color/drawing style for curve itself */
if ( ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED) ) {
/* protected curves (non editable) are drawn with dotted lines */
@@ -803,18 +741,35 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
glColor3fv(fcu->color);
}
+ /* anti-aliased lines for less jagged appearance */
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
/* draw F-Curve */
- if (fcu->bezt)
- draw_fcurve_repeat(fcu, &ar->v2d, 0, 0, &fac); // XXX this call still needs a lot more work
- else if (fcu->fpt)
- draw_fcurve_repeat_samples(fcu, &ar->v2d);
- /*else modifiers? */
+ if (fcu->modifiers.first) {
+ /* draw a curve affected by modifiers by sampling its points */
+ draw_fcurve_curve(fcu, sipo, &ar->v2d, grid);
+ }
+ else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) {
+ /* just draw curve based on defined data (i.e. no modifiers) */
+ if (fcu->bezt)
+ draw_fcurve_curve_bezts(fcu, &ar->v2d, grid);
+ else if (fcu->fpt)
+ draw_fcurve_curve_samples(fcu, &ar->v2d);
+ }
/* restore settings */
setlinestyle(0);
-
- /* draw handles and vertices as appropriate */
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ }
+
+ /* 2) draw handles and vertices as appropriate based on active */
+ if ((fcu->modifiers.first) && (fcm) && (fcm->type != FMODIFIER_TYPE_CYCLES)) {
+ // TODO: need to add code to show these... for cycles modifier, should fall through though...
+ }
+ else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) {
if (fcu->bezt) {
/* only draw handles/vertices on keyframes */
draw_fcurve_handles(sipo, ar, fcu);
@@ -827,8 +782,8 @@ 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, 0);
+ //if (nob)
+ // ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 0);
}
/* free list of curves */
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index d98ed38da9c..43a3b3628ad 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1018,12 +1018,25 @@ void GRAPHEDIT_OT_keyframes_handletype (wmOperatorType *ot)
* of values to -180 degrees to 180 degrees.
*/
+#if 0 // XXX this is not ready for the primetime yet
+
+/* set of three euler-rotation F-Curves */
+typedef struct tEulerFilter {
+ ID *id; /* ID-block which owns the channels */
+ FCurve *fcu1, *fcu2, *fcu3; /* x,y,z rotation curves */
+ int i1, i2, i3; /* current index for each curve */
+} tEulerFilter;
+
static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op)
{
bAnimContext ac;
- //ListBase anim_data= {NULL, NULL};
- //bAnimListElem *ale;
- //int filter;
+
+ ListBase anim_data= {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ ListBase eulers = {NULL, NULL};
+ tEulerFilter *euf= NULL;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -1035,7 +1048,33 @@ static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op)
* 2) Each set of three F-Curves is processed for each keyframe, with the values being
* processed according to one of several ways.
*/
+
+ /* step 1: extract only the rotation f-curves */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ /* check if this is an appropriate F-Curve
+ * - only rotation curves
+ * - for pchan curves, make sure we're only using the euler curves
+ */
+ if (ELEM(0, fcu->rna_path, strstr(fcu->rna_path, "rotation")))
+ continue;
+ if (strstr(fcu->rna_path, "pose.pose_channels")) {
+ if (strstr(fcu->rna_path, "euler_rotation") == 0)
+ continue;
+ }
+
+ /* check if current set of 3-curves is suitable to add this curve to
+ * - things like whether the current set of curves is 'full' should be checked later only
+ * - first check if id-blocks are compatible
+ */
+ if ((euf) && (ale->id != euf->id)) {
+
+ }
+ }
// XXX for now
return OPERATOR_CANCELLED;
@@ -1055,6 +1094,8 @@ void GRAPHEDIT_OT_keyframes_euler_filter (wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
+#endif // XXX this is not ready for the primetime yet
+
/* ***************** Snap Current Frame Operator *********************** */
/* helper callback for graphkeys_cfrasnap_exec() -> used to help get the average time of all selected beztriples */
@@ -1376,3 +1417,76 @@ void GRAPHEDIT_OT_keyframes_smooth (wmOperatorType *ot)
}
/* ************************************************************************** */
+/* F-CURVE MODIFIERS */
+
+/* ******************** Add F-Curve Modifier Operator *********************** */
+
+/* F-Modifier types - duplicate of existing codes... */
+ // XXX how can we have this list from the RNA definitions instead?
+EnumPropertyItem prop_fmodifier_types[] = {
+ {FMODIFIER_TYPE_GENERATOR, "GENERATOR", "Generator", ""},
+ {FMODIFIER_TYPE_ENVELOPE, "ENVELOPE", "Envelope", ""},
+ {FMODIFIER_TYPE_CYCLES, "CYCLES", "Cycles", ""},
+ {FMODIFIER_TYPE_NOISE, "NOISE", "Noise", ""},
+ {FMODIFIER_TYPE_FILTER, "FILTER", "Filter", ""},
+ {FMODIFIER_TYPE_PYTHON, "PYTHON", "Python", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ bAnimListElem *ale;
+ FCurve *fcu;
+ short type;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ // xxx call the raw methods here instead?
+ ale= get_active_fcurve_channel(&ac);
+ if (ale == NULL)
+ return OPERATOR_CANCELLED;
+
+ fcu= (FCurve *)ale->data;
+ MEM_freeN(ale);
+ if (fcu == NULL)
+ return OPERATOR_CANCELLED;
+
+
+ /* get type of modifier to add */
+ type= RNA_enum_get(op->ptr, "type");
+
+ /* add F-Modifier of specified type to active F-Curve */
+ fcurve_add_modifier(fcu, type);
+
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_fmodifier_add (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add F-Curve Modifier";
+ ot->idname= "GRAPHEDIT_OT_fmodifier_add";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= graph_fmodifier_add_exec;
+ ot->poll= ED_operator_areaactive; // XXX need active F-Curve
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_fmodifier_types, 0, "Type", "");
+}
+
+/* ************************************************************************** */
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index 6144556378a..ab915a97232 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -31,9 +31,11 @@
struct bContext;
struct wmWindowManager;
struct bAnimContext;
+struct bAnimListElem;
struct SpaceIpo;
struct ScrArea;
struct ARegion;
+struct View2DGrid;
/* internal exports only */
@@ -44,7 +46,7 @@ struct ARegion *graph_has_buttons_region(struct ScrArea *sa);
/* ***************************************** */
/* graph_draw.c */
void graph_draw_channel_names(struct bAnimContext *ac, struct SpaceIpo *sipo, struct ARegion *ar);
-void graph_draw_curves(struct bAnimContext *ac, struct SpaceIpo *sipo, struct ARegion *ar);
+void graph_draw_curves(struct bAnimContext *ac, struct SpaceIpo *sipo, struct ARegion *ar, struct View2DGrid *grid);
/* ***************************************** */
/* graph_header.c */
@@ -119,11 +121,17 @@ enum {
GRAPHKEYS_MIRROR_MARKER,
} eGraphKeys_Mirror_Mode;
+/* ----------- */
+
+void GRAPHEDIT_OT_fmodifier_add(struct wmOperatorType *ot);
+
/* ***************************************** */
/* graph_buttons.c */
void GRAPHEDIT_OT_properties(struct wmOperatorType *ot);
void graph_region_buttons(const struct bContext *C, struct ARegion *ar);
+struct bAnimListElem *get_active_fcurve_channel(struct bAnimContext *ac);
+
/* ***************************************** */
/* graph_ops.c */
void graphedit_keymap(struct wmWindowManager *wm);
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 80b8dcbf0ff..91cc7557476 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -126,6 +126,10 @@ void graphedit_operatortypes(void)
WM_operatortype_append(GRAPHEDIT_OT_keyframes_paste);
//TODO: insertkey...
+
+ /* F-Curve Modifiers */
+ // XXX temporary?
+ WM_operatortype_append(GRAPHEDIT_OT_fmodifier_add);
}
/* ************************** registration - keymaps **********************************/
@@ -195,6 +199,11 @@ static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap)
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_set_previewrange", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+ /* F-Curve Modifiers */
+ // XXX these are temporary? operators...
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+
+
/* transform system */
transform_keymap_for_space(wm, keymap, SPACE_IPO);
}
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index e6365db92ad..9466a0674d1 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -230,12 +230,13 @@ static void graph_main_area_draw(const bContext *C, ARegion *ar)
unitx= (sipo->flag & SIPO_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
grid= UI_view2d_grid_calc(C, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, ar->winx, ar->winy);
UI_view2d_grid_draw(C, v2d, grid, V2D_GRIDLINES_ALL);
- UI_view2d_grid_free(grid);
/* draw data */
- if (ANIM_animdata_get_context(C, &ac)) {
- graph_draw_curves(&ac, sipo, ar);
- }
+ if (ANIM_animdata_get_context(C, &ac))
+ graph_draw_curves(&ac, sipo, ar, grid);
+
+ /* only free grid after drawing data, as we need to use it to determine sampling rate */
+ UI_view2d_grid_free(grid);
/* current frame */
if (sipo->flag & SIPO_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;