Animato/2.5 - Graph Editor (i.e. the new 'IPO Editor')
authorJoshua Leung <aligorith@gmail.com>
Mon, 26 Jan 2009 11:33:16 +0000 (11:33 +0000)
committerJoshua Leung <aligorith@gmail.com>
Mon, 26 Jan 2009 11:33:16 +0000 (11:33 +0000)
This commit brings back the drawing code for the 'Graph Editor'. I've decided to call it this, as currently it can show either F-Curves for Animation stored in Actions, or F-Curves for Drivers.

Currently, it shows all curves, since some of the necessary filtering code (i.e. for limiting curve visibility) hasn't been put in place yet. At least this serves as good proof that we can have F-Curves from multiple sources at least.

It should be noted that the code still has to be modified to work with some of the new Animato features, such as F-Curve Modifiers (cycles are an example of one of the features that use this). Also, a nicer way to set the colours of the curves needs to be investigated.

Notes:
* Fixed a few bugs in RNA User-Preferences wrapping

* The keyframe drawing uses the new-style drawing for handles from AnimSys2. There's a minor bug that sometimes occurs, where a distorted handle gets drawn at the origin of the grid on the first run. Hints anyone?

* Removed most of the old data from SpaceIpo struct, as the new code uses that. Maybe later, the directories/files at least should get renamed.

* Removed ancient hack for NVidia/TNT drivers. It is probably no longer needed, but could be restored if someone needs it.

16 files changed:
source/blender/blenkernel/BKE_fcurve.h
source/blender/blenkernel/intern/ipo.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/animation/anim_draw.c
source/blender/editors/animation/anim_filter.c
source/blender/editors/include/ED_anim_api.h
source/blender/editors/interface/resources.c
source/blender/editors/space_action/action_draw.c
source/blender/editors/space_ipo/ipo_draw.c
source/blender/editors/space_ipo/ipo_header.c
source/blender/editors/space_ipo/ipo_intern.h
source/blender/editors/space_ipo/space_ipo.c
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesrna/intern/rna_userdef.c
source/blender/windowmanager/intern/wm_files.c

index 8732d63f0472f7e240abba8e74ae61da8d43fa86..bed909fd0409e6b31e67b7b65355c19d05c6e891 100644 (file)
@@ -95,6 +95,8 @@ void testhandles_fcurve(struct FCurve *fcu);
 void sort_time_fcurve(struct FCurve *fcu);
 short test_time_fcurve(struct FCurve *fcu);
 
+void correct_bezpart(float *v1, float *v2, float *v3, float *v4);
+
 /* -------- Evaluation --------  */
 
 /* evaluate fcurve */
index e6ee3a1468106f8e12c88d63a07e4d5b0be1bf48..9fef1c657ca46804d6435188b5b9482d61b8338c 100644 (file)
@@ -1065,8 +1065,6 @@ void do_versions_ipos_to_animato(Main *main)
                 * are likely to be drivers, but it's hard to trace that from here, so move this to Ob loop?
                 */
                if (key->ipo) {
-                       printf("\t\tconverting key->ipo %s -> %s \n", id->name+2, key->ipo->id.name+2);
-                       
                        /* Add AnimData block */
                        adt= BKE_id_add_animdata(id);
                        
index 3600c64d35280dad7ab5522358870db54ff199ac..85d7883de24fb0f920e614e31f76f5d85a6259c4 100644 (file)
@@ -3932,63 +3932,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        
 }
 
-/* Nasty exception; IpoWindow stores a non-ID pointer in *from for sequence
-   strips... bad code warning! 
-
-   We work around it by retrieving the missing pointer from the corresponding
-   Sequence-structure. 
-
-   This is needed, to make Ipo-Pinning work for Sequence-Ipos...
-*/
-// XXX old animation system - depreceated stuff...
-static Sequence * find_sequence_from_ipo_helper(Main * main, Ipo * ipo)
-{
-       Sequence *seq;
-       Scene *sce;
-       
-       for(sce=main->scene.first; sce; sce=sce->id.next) {
-               int found = 0;
-
-               SEQ_BEGIN(sce->ed, seq) {
-                       if (seq->ipo == ipo) {
-                               found = 1;
-                               break;
-                       }
-               } 
-               SEQ_END
-
-               if (found) {
-                       break;
-               }
-               seq = NULL;
-       }
-
-       if (seq)
-        return seq;
-       else
-               return NULL;
-}
-
-static void lib_link_screen_sequence_ipos(Main *main)
-{
-       bScreen *sc;
-       ScrArea *sa;
-
-       for(sc= main->screen.first; sc; sc= sc->id.next) {
-               for(sa= sc->areabase.first; sa; sa= sa->next) {
-                       SpaceLink *sl;
-                       for (sl= sa->spacedata.first; sl; sl= sl->next) {
-                               if(sl->spacetype == SPACE_IPO) {
-                                       SpaceIpo *sipo= (SpaceIpo *)sl;
-                                       if(sipo->blocktype==ID_SEQ) {
-                                               sipo->from = (ID*) find_sequence_from_ipo_helper(main, sipo->ipo);
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
 /* ************ READ WM ***************** */
 
 static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
@@ -4123,13 +4066,9 @@ static void lib_link_screen(FileData *fd, Main *main)
                                        }
                                        else if(sl->spacetype==SPACE_IPO) {
                                                SpaceIpo *sipo= (SpaceIpo *)sl;
-                                               sipo->editipo= 0;
-                                               
-                                               if(sipo->blocktype==ID_SEQ) sipo->from= NULL;   // no libdata
-                                               else sipo->from= newlibadr(fd, sc->id.lib, sipo->from);
                                                
-                                               sipo->ipokey.first= sipo->ipokey.last= 0;
-                                               sipo->ipo= newlibadr(fd, sc->id.lib, sipo->ipo);
+                                               if(sipo->ads)
+                                                       sipo->ads->source= newlibadr(fd, sc->id.lib, sipo->ads->source);
                                        }
                                        else if(sl->spacetype==SPACE_BUTS) {
                                                SpaceButs *sbuts= (SpaceButs *)sl;
@@ -4325,17 +4264,6 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
                                        if((v3d->layact & v3d->lay)==0) v3d->layact= v3d->lay;
                                        
                                }
-                               else if(sl->spacetype==SPACE_IPO) {
-                                       SpaceIpo *sipo= (SpaceIpo *)sl;
-                                       
-                                       if(sipo->blocktype==ID_SEQ) sipo->from= NULL;   // no libdata
-                                       else sipo->from= restore_pointer_by_name(newmain, (ID *)sipo->from, 0);
-                                       
-                                       // not free sipo->ipokey, creates dependency with src/
-                                       sipo->ipo= restore_pointer_by_name(newmain, (ID *)sipo->ipo, 0);
-                                       if(sipo->editipo) MEM_freeN(sipo->editipo);
-                                       sipo->editipo= NULL;
-                               }
                                else if(sl->spacetype==SPACE_BUTS) {
                                        SpaceButs *sbuts= (SpaceButs *)sl;
                                        sbuts->lockpoin= NULL;
@@ -4574,6 +4502,11 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                
                                view3d_split_250(v3d, &sl->regionbase);
                        }
+                       else if (sl->spacetype==SPACE_IPO) {
+                               SpaceIpo *sipo= (SpaceIpo*)sl;
+                               
+                               sipo->ads= newdataadr(fd, sipo->ads);
+                       }
                        else if (sl->spacetype==SPACE_OOPS) {
                                SpaceOops *soops= (SpaceOops*) sl;
                                
@@ -5518,8 +5451,14 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
                                SpaceIpo *sipo= (SpaceIpo *)sl;
                                memcpy(&ar->v2d, &sipo->v2d, sizeof(View2D));
                                
+                               /* init mainarea view2d */
                                ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
                                ar->v2d.scroll |= (V2D_SCROLL_LEFT|V2D_SCROLL_SCALE_VERTICAL);
+                               
+                               /* init dopesheet */
+                               // XXX move this elsewhere instead?
+                               sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
+                               
                                //ar->v2d.flag |= V2D_IS_INITIALISED;
                                break;
                        }
@@ -8861,7 +8800,6 @@ static void lib_link_all(FileData *fd, Main *main)
        lib_link_armature(fd, main);
        lib_link_action(fd, main);
        lib_link_vfont(fd, main);
-       lib_link_screen_sequence_ipos(main);
        lib_link_nodetree(fd, main);    /* has to be done after scene/materials, this will verify group nodes */
        lib_link_brush(fd, main);
        lib_link_particlesettings(fd, main);
index 843cadd47365c2eb5fdc32cdf71a69d4d9b90a6c..e0962eadfca356d0c7b299ab64c92118b4ddf7de 100644 (file)
@@ -193,25 +193,15 @@ Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
                return NULL;
        
        /* handling depends on the type of animation-context we've got */
-       if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_IPO)) {
-               /* Action Editor (action mode) or Ipo Editor (ipo mode):
+       if (ac->datatype == ANIMCONT_ACTION) {
+               /* Action Editor (action mode) or Graph Editor (ipo mode):
                 * Only use if editor is not pinned, and active object has action
                 */
                if (ac->obact && ac->obact->action) {
-                       /* Action Editor */
-                       if (ac->datatype == ANIMCONT_ACTION) {
-                               SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
-                               
-                               if (saction->pin == 0)
-                                       return ac->obact;
-                       }
-                       /* IPO Editor */
-                       else if (ac->datatype == ANIMCONT_IPO) {
-                               SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
-                               
-                               if (sipo->pin == 0)
-                                       return ac->obact;
-                       }
+                       SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
+                       
+                       if (saction->pin == 0)
+                               return ac->obact;
                }
        }
        else if ((ac->datatype == ANIMCONT_DOPESHEET) && (ale)) {
@@ -225,6 +215,7 @@ Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
                                return ob;
                }
        }
+       // XXX todo: add F-Curves mode (Graph Editor) ...
        
        /* no appropriate object found */
        return NULL;
index fc1a225eb77c3a84a5e981f30457fb34e0ab10b0..361a384cf036673c6a06b04e350025af754fe289 100644 (file)
@@ -196,11 +196,40 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
 
 /* ----------- Private Stuff - IPO Editor ------------- */
 
-/* Get data being edited in IPO Editor (depending on current 'mode') */
-static short ipoedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
+/* Get data being edited in Graph Editor (depending on current 'mode') */
+static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
 {
-       // XXX FIXME...
-       return 0;
+       /* sync settings with current view status, then return appropriate data */
+       switch (sipo->mode) {
+               case SIPO_MODE_ANIMATION:       /* Animation F-Curve Editor */
+                       /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+                       sipo->ads->source= (ID *)ac->scene;
+                       sipo->ads->filterflag &= ~ADS_FILTER_ONLYDRIVERS;
+                       
+                       ac->datatype= ANIMCONT_FCURVES;
+                       ac->data= sipo->ads;
+                       
+                       ac->mode= sipo->mode;
+                       return 1;
+               
+               case SIPO_MODE_DRIVERS:         /* Driver F-Curve Editor */
+                       /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+                       sipo->ads->source= (ID *)ac->scene;
+                       sipo->ads->filterflag |= ADS_FILTER_ONLYDRIVERS;
+                       
+                       ac->datatype= ANIMCONT_FCURVES;
+                       ac->data= sipo->ads;
+                       
+                       ac->mode= sipo->mode;
+                       return 1;
+               
+               default: /* unhandled yet */
+                       ac->datatype= ANIMCONT_NONE;
+                       ac->data= NULL;
+                       
+                       ac->mode= -1;
+                       return 0;
+       }
 }
 
 /* ----------- Public API --------------- */
@@ -227,7 +256,7 @@ short ANIM_animdata_context_getdata (bAnimContext *ac)
                        case SPACE_IPO:
                        {
                                SpaceIpo *sipo= (SpaceIpo *)sa->spacedata.first;
-                               ok= ipoedit_get_context(ac, sipo);
+                               ok= graphedit_get_context(ac, sipo);
                        }
                                break;
                }
@@ -436,16 +465,19 @@ static int animdata_filter_fcurves (ListBase *anim_data, FCurve *first, bActionG
         * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too...
         */
        for (fcu= first; ((fcu) && (fcu->grp==grp)); fcu= fcu->next) {
-               /* only work with this channel and its subchannels if it is editable */
-               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
-                       /* only include this curve if selected */
-                       if (!(filter_mode & ANIMFILTER_SEL) || (SEL_FCU(fcu))) {
-                               /* owner/ownertype will be either object or action-channel, depending if it was dopesheet or part of an action */
-                               ale= make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
-                               
-                               if (ale) {
-                                       BLI_addtail(anim_data, ale);
-                                       items++;
+               /* only include if visible (Graph Editor check, not channels check) */
+               if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
+                       /* only work with this channel and its subchannels if it is editable */
+                       if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
+                               /* only include this curve if selected */
+                               if (!(filter_mode & ANIMFILTER_SEL) || (SEL_FCU(fcu))) {
+                                       /* owner/ownertype will be either object or action-channel, depending if it was dopesheet or part of an action */
+                                       ale= make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
+                                       
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
                                }
                        }
                }
@@ -985,7 +1017,7 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
 /* This function filters the active data source to leave only animation channels suitable for
  * usage by the caller. It will return the length of the list 
  * 
- *     *act_data: is a pointer to a ListBase, to which the filtered animation channels
+ *     *anim_data: is a pointer to a ListBase, to which the filtered animation channels
  *             will be placed for use.
  *     filter_mode: how should the data be filtered - bitmapping accessed flags
  */
@@ -1003,20 +1035,20 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode
                        case ANIMCONT_ACTION:
                                items= animdata_filter_action(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
                                break;
+                               
                        case ANIMCONT_SHAPEKEY:
                                items= animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
                                break;
+                               
                        case ANIMCONT_GPENCIL:
                                //items= animdata_filter_gpencil(anim_data, data, filter_mode);
                                break;
+                               
                        case ANIMCONT_DOPESHEET:
+                       case ANIMCONT_FCURVES:
+                       case ANIMCONT_DRIVERS:
                                items= animdata_filter_dopesheet(anim_data, data, filter_mode);
                                break;
-                               
-                       case ANIMCONT_IPO:
-                               // FIXME: this will be used for showing a single IPO-block (not too useful from animator perspective though!)
-                               //items= 0;
-                               break;
                }
                        
                /* remove any weedy entries */
index 11ffa435149e1a8e210e2d7e51687b39543cf613..4531e282e2f8f2ddd291e9de7d07b593003c59a6 100644 (file)
@@ -74,7 +74,8 @@ typedef enum eAnimCont_Types {
        ANIMCONT_SHAPEKEY,              /* shapekey (Key) */
        ANIMCONT_GPENCIL,               /* grease pencil (screen) */
        ANIMCONT_DOPESHEET,             /* dopesheet (bDopesheet) */
-       ANIMCONT_IPO,                   /* single IPO (Ipo) */          // XXX
+       ANIMCONT_FCURVES,               /* animation F-Curves (bDopesheet) */           // XXX 
+       ANIMCONT_DRIVERS,               /* drivers (bDopesheet) */
 } eAnimCont_Types;
 
 /* --------------- Channels -------------------- */
@@ -142,12 +143,13 @@ typedef enum eAnim_KeyType {
 /* filtering flags  - under what circumstances should a channel be added */
 // XXX was ACTFILTER_*
 typedef enum eAnimFilter_Flags {
-       ANIMFILTER_VISIBLE              = (1<<0),       /* should channels be visible */
+       ANIMFILTER_VISIBLE              = (1<<0),       /* should channels be visible (in terms of hierarchy only) */
        ANIMFILTER_SEL                  = (1<<1),       /* should channels be selected */
        ANIMFILTER_FOREDIT              = (1<<2),       /* does editable status matter */
        ANIMFILTER_CURVESONLY   = (1<<3),       /* don't include summary-channels, etc. */
        ANIMFILTER_CHANNELS             = (1<<4),       /* make list for interface drawing */
        ANIMFILTER_ACTGROUPED   = (1<<5),       /* belongs to the active actiongroup */
+       ANIMFILTER_CURVEVISIBLE = (1<<6),       /* F-Curve is visible for editing/viewing in Graph Editor */
 } eAnimFilter_Flags;
 
 
index 0152e347f386cbf00e1a727cd226158c355b2555..8b320de82574ce339e205cf0f8c3901c3e82a674 100644 (file)
@@ -449,6 +449,9 @@ void ui_theme_init_userdef(void)
        SETCOL(btheme->tipo.handle_vertex, 0xff, 0x70, 0xff, 255);
        SETCOL(btheme->tipo.handle_vertex_select, 0xff, 0xff, 0x70, 255);
        btheme->tipo.handle_vertex_size= 3;
+       
+       SETCOL(btheme->tipo.ds_channel, 0x36, 0x13, 0xca, 255);
+       SETCOL(btheme->tipo.ds_subchannel, 0x60, 0x43, 0xd2, 255);
 
        /* space file */
        /* to have something initialized */
index 227881408a0aac8e8d3d35f83f52886287b9633e..3152abcae9415e62866616cc4a79d516856c1edc 100644 (file)
@@ -630,6 +630,7 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
                                                        
                                                case ANIMTYPE_DSMAT: /* for now, this is special case for materials */
                                                        offset= 21;
+                                                       indent= 1;
                                                        break;
                                                        
                                                default:
index 653dc05a981bc26968aa60497d38d7432526f58a..f68d524d288e4691c082e31553b87373e73571cf 100644 (file)
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 
+#include "DNA_anim_types.h"
 #include "DNA_action_types.h"
+#include "DNA_camera_types.h"
 #include "DNA_curve_types.h"
-#include "DNA_ipo_types.h"
 #include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_view2d_types.h"
 #include "DNA_windowmanager_types.h"
 
+#include "BKE_animsys.h"
+#include "BKE_context.h"
 #include "BKE_curve.h"
 #include "BKE_depsgraph.h"
-#include "BKE_ipo.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
 #include "BKE_key.h"
 #include "BKE_object.h"
 #include "BKE_utildefines.h"
 #include "ED_anim_api.h"
 #include "ED_util.h"
 
+#include "ipo_intern.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
 #include "UI_resources.h"
 #include "UI_view2d.h"
+#include "UI_text.h"
 
-/* **************************** */
-// XXX stubs to remove!
-
-// NOTE: the code in this file has yet to be rewritten to get rid of the editipo system which is past its use-by-date - Aligorith
-
-typedef struct EditIpo {
-       IpoCurve *icu;
-       short disptype;
-       short flag;
-       unsigned int col;
-} EditIpo;
-
-#define ISPOIN(a, b, c)                       ( (a->b) && (a->c) )  
-#define ISPOIN3(a, b, c, d)           ( (a->b) && (a->c) && (a->d) )
-#define ISPOIN4(a, b, c, d, e)        ( (a->b) && (a->c) && (a->d) && (a->e) )
+/* XXX */
+extern void ui_rasterpos_safe(float x, float y, float aspect);
+extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
 
 /* *************************** */
+/* Curve Drawing */
+
+/* Points ---------------- */
 
-/* helper func - draw keyframe vertices only for an IPO-curve */
-static void draw_ipovertices_keyframes(IpoCurve *icu, View2D *v2d, short disptype, short edit, short sel)
+/* helper func - draw keyframe vertices only for an F-Curve */
+static void draw_fcurve_vertices_keyframes (FCurve *fcu, View2D *v2d, short edit, short sel)
 {
-       BezTriple *bezt= icu->bezt;
-       float v1[2];
-       int a, b;
+       BezTriple *bezt= fcu->bezt;
+       int i;
        
        bglBegin(GL_POINTS);
        
-       for (a = 0; a < icu->totvert; a++, bezt++) {
-               /* IPO_DISPBITS is used for displaying curves for bitflag variables */
-               if (disptype == IPO_DISPBITS) {
-                       /*if (v2d->cur.xmin < bezt->vec[1][0] < v2d->cur.xmax) {*/
-                       short ok= 0;
-                       
-                       if (edit) {
-                               if ((bezt->f2 & SELECT) == sel) 
-                                       ok= 1;
-                       }
-                       else ok= 1;
-                       
-                       if (ok) {
-                               int val= (int)bezt->vec[1][1];
-                               v1[0]= bezt->vec[1][0];
-                               
-                               for (b= 0; b < 31; b++) {
-                                       if (val & (1<<b)) {     
-                                               v1[1]= b + 1;
-                                               bglVertex3fv(v1);
-                                       }
-                               }
-                       }
-                       /*}*/
-               } 
-               else { /* normal (non bit) curves */
-                       if (edit) {
-                               /* Only the vertex of the line, the
-                                * handler are drawn later
-                                */
-                               if ((bezt->f2 & SELECT) == sel) /* && G.v2d->cur.xmin < bezt->vec[1][0] < G.v2d->cur.xmax)*/
-                                       bglVertex3fv(bezt->vec[1]);
-                       }
-                       else {
-                               /* draw only if in bounds */
-                               /*if (G.v2d->cur.xmin < bezt->vec[1][0] < G.v2d->cur.xmax)*/
+       for (i = 0; i < fcu->totvert; i++, bezt++) {
+               if (edit) {
+                       /* Only the vertex of the line, the
+                        * handler are drawn later
+                        */
+                       if ((bezt->f2 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[1][0] < v2d->cur.xmax)*/
                                bglVertex3fv(bezt->vec[1]);
-                       }
+               }
+               else {
+                       /* draw only if in bounds */
+                       /*if (v2d->cur.xmin < bezt->vec[1][0] < v2d->cur.xmax)*/
+                       bglVertex3fv(bezt->vec[1]);
                }
        }
+       
        bglEnd();
 }
 
-/* helper func - draw handle vertex for an IPO-Curve as a round unfilled circle */
-static void draw_ipohandle_control(float x, float y, float xscale, float yscale, float hsize)
+
+/* helper func - draw handle vertex for an F-Curve as a round unfilled circle */
+static void draw_fcurve_handle_control (float x, float y, float xscale, float yscale, float hsize)
 {
        static GLuint displist=0;
        
        /* initialise round circle shape */
+       // FIXME: sometimes, this will draw incorrectly (i.e. a scaled copy shows up at the origin)
        if (displist == 0) {
                GLUquadricObj *qobj;
                
@@ -156,7 +134,7 @@ static void draw_ipohandle_control(float x, float y, float xscale, float yscale,
                
                qobj    = gluNewQuadric(); 
                gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
-               gluDisk(qobj, 0.07,  0.8, 12, 1);
+               gluDisk(qobj, 0.07,  0.6, 8, 1);
                gluDeleteQuadric(qobj);  
                
                glEndList();
@@ -174,13 +152,13 @@ static void draw_ipohandle_control(float x, float y, float xscale, float yscale,
        glTranslatef(-x, -y, 0.0f);
 }
 
-/* helper func - draw handle vertices only for an IPO-curve (if it is in EditMode) */
-static void draw_ipovertices_handles(IpoCurve *icu, View2D *v2d, short disptype, short sel)
+/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
+static void draw_fcurve_vertices_handles (FCurve *fcu, View2D *v2d, short sel)
 {
-       BezTriple *bezt= icu->bezt;
+       BezTriple *bezt= fcu->bezt;
        BezTriple *prevbezt = NULL;
        float hsize, xscale, yscale;
-       int a;
+       int i;
        
        /* get view settings */
        hsize= UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
@@ -190,225 +168,178 @@ static void draw_ipovertices_handles(IpoCurve *icu, View2D *v2d, short disptype,
        if (sel) UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
        else UI_ThemeColor(TH_HANDLE_VERTEX);
        
-       for (a= 0; a < icu->totvert; a++, prevbezt=bezt, bezt++) {
-               if (disptype != IPO_DISPBITS) {
-                       if (ELEM(icu->ipo, IPO_BEZ, IPO_MIXED)) {
-                               /* Draw the editmode handels for a bezier curve (others don't have handles) 
-                                * if their selection status matches the selection status we're drawing for
-                                *      - first handle only if previous beztriple was bezier-mode
-                                *      - second handle only if current beztriple is bezier-mode
-                                */
-                               if ( (!prevbezt && (bezt->ipo==IPO_BEZ)) || (prevbezt && (prevbezt->ipo==IPO_BEZ)) ) {
-                                       if ((bezt->f1 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/
-                                               draw_ipohandle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize);
-                               }
-                               
-                               if (bezt->ipo==IPO_BEZ) {
-                                       if ((bezt->f3 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/
-                                               draw_ipohandle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize);
-                               }
-                       }
+       for (i=0; i < fcu->totvert; i++, prevbezt=bezt, bezt++) {
+               /* Draw the editmode handels for a bezier curve (others don't have handles) 
+                * if their selection status matches the selection status we're drawing for
+                *      - first handle only if previous beztriple was bezier-mode
+                *      - second handle only if current beztriple is bezier-mode
+                */
+               if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) {
+                       if ((bezt->f1 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/
+                               draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize);
+               }
+               
+               if (bezt->ipo==BEZT_IPO_BEZ) {
+                       if ((bezt->f3 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/
+                               draw_fcurve_handle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize);
                }
        }
 }
 
-static void draw_ipovertices(SpaceIpo *sipo, ARegion *ar, int sel)
+/* helper func - set color to draw F-Curve data with */
+static void set_fcurve_vertex_color (SpaceIpo *sipo, FCurve *fcu, short sel)
+{
+#if 0
+               if (sipo->showkey) {
+                       if (sel) UI_ThemeColor(TH_TEXT_HI);
+                       else UI_ThemeColor(TH_TEXT);
+               } 
+#endif
+               if ((fcu->flag & FCURVE_PROTECTED)==0) {
+                       /* Curve's points are being edited */
+                       if (sel) UI_ThemeColor(TH_VERTEX_SELECT); 
+                       else UI_ThemeColor(TH_VERTEX);
+               } 
+               else {
+                       /* Curve's points cannot be edited */
+                       if (sel) UI_ThemeColor(TH_TEXT_HI);
+                       else UI_ThemeColor(TH_TEXT);
+               }
+}
+
+
+void draw_fcurve_vertices (SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
 {
        View2D *v2d= &ar->v2d;
-       EditIpo *ei= sipo->editipo;
-       int nr, val = 0;
        
-       /* this shouldn't get called while drawing in selection-buffer anyway */
-       //if (G.f & G_PICKSEL) return;
+       /* only draw points if curve is visible 
+        *      - draw unselected points before selected points as separate passes to minimise color-changing overhead
+        *         (XXX dunno if this is faster than drawing all in one pass though) 
+        *         and also to make sure in the case of overlapping points that the selected is always visible
+        *      - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users)
+        */
        
        glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
        
-       for (nr=0; nr<sipo->totipo; nr++, ei++) {
-               if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
-                       /* select colors to use to draw keyframes */
-                       if (sipo->showkey) {
-                               if (sel) UI_ThemeColor(TH_TEXT_HI);
-                               else UI_ThemeColor(TH_TEXT);
-                       } 
-                       else if (ei->flag & IPO_EDIT) {
-                               if (sel) UI_ThemeColor(TH_VERTEX_SELECT); 
-                               else UI_ThemeColor(TH_VERTEX);
-                       } 
-                       else {
-                               if (sel) UI_ThemeColor(TH_TEXT_HI);
-                               else UI_ThemeColor(TH_TEXT);
-                               
-                               val= (ei->icu->flag & IPO_SELECT)!=0;
-                               if (sel != val) continue;
-                       }
-                       
-                       /* We can't change the color in the middle of
-                        * GL_POINTS because then Blender will segfault
-                        * on TNT2 / Linux with NVidia's drivers
-                        * (at least up to ver. 4349) 
-                        */             
-                       
-                       /* draw keyframes, then the handles (if in editmode) */
-                       draw_ipovertices_keyframes(ei->icu, v2d, ei->disptype, (ei->flag & IPO_EDIT), sel);
-                       
-                       /* Now draw the two vertex of the handles,
-                        * This needs to be done after the keyframes, 
-                        * because we can't call glPointSize
-                        * in the middle of a glBegin/glEnd also the
-                        * bug comment before.
-                        */
-                       if ((ei->flag & IPO_EDIT) && (sipo->flag & SIPO_NOHANDLES)==0)
-                               draw_ipovertices_handles(ei->icu, v2d, ei->disptype, sel);
-               }
+       /* draw the two handles first (if they're shown, and if curve is being edited) */
+       if ((fcu->flag & FCURVE_PROTECTED)==0 && (sipo->flag & SIPO_NOHANDLES)==0) {
+               set_fcurve_vertex_color(sipo, fcu, 0);
+               draw_fcurve_vertices_handles(fcu, v2d, 0);
+               
+               set_fcurve_vertex_color(sipo, fcu, 1);
+               draw_fcurve_vertices_handles(fcu, v2d, 1);
        }
+               
+       /* draw keyframes over the handles */
+       set_fcurve_vertex_color(sipo, fcu, 0);
+       draw_fcurve_vertices_keyframes(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), 0);
        
-       glPointSize(1.0);
+       set_fcurve_vertex_color(sipo, fcu, 1);
+       draw_fcurve_vertices_keyframes(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), 1);
+       
+       glPointSize(1.0f);
 }
 
-/* draw lines for IPO-curve handles only (this is only done in EditMode) */
-static void draw_ipohandles(SpaceIpo *sipo, ARegion *ar, int sel)
+/* Handles ---------------- */
+
+/* draw lines for F-Curve handles only (this is only done in EditMode) */
+static void draw_fcurve_handles (SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
 {
-       EditIpo *ei;
        extern unsigned int nurbcol[];
        unsigned int *col;
-       int a, b;
+       
+       BezTriple *bezt=fcu->bezt, *prevbezt=NULL;
+       float *fp;
+       int sel, b;
        
        /* don't draw handle lines if handles are not shown */
-       if (sipo->flag & SIPO_NOHANDLES)
+       if ((sipo->flag & SIPO_NOHANDLES) || (fcu->flag & FCURVE_PROTECTED))
                return;
        
-       if (sel) col= nurbcol+4;
-       else col= nurbcol;
-       
-       ei= sipo->editipo;
-       for (a=0; a<sipo->totipo; a++, ei++) {
-               if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, disptype!=IPO_DISPBITS) {
-                       if (ELEM(ei->icu->ipo, IPO_BEZ, IPO_MIXED)) {
-                               BezTriple *bezt=ei->icu->bezt, *prevbezt=NULL;
-                               float *fp;
+       /* slightly hacky, but we want to draw unselected points before selected ones*/
+       for (sel= 0; sel < 2; sel++) {
+               if (sel) col= nurbcol+4;
+               else col= nurbcol;
+                       
+               for (b= 0; b < fcu->totvert; b++, prevbezt=bezt, bezt++) {
+                       if ((bezt->f2 & SELECT)==sel) {
+                               fp= bezt->vec[0];
                                
-                               for (b= 0; b < ei->icu->totvert; b++, prevbezt=bezt, bezt++) {
-                                       if ((bezt->f2 & SELECT)==sel) {
-                                               fp= bezt->vec[0];
-                                               
-                                               /* only draw first handle if previous segment had handles */
-                                               if ( (!prevbezt && (bezt->ipo==IPO_BEZ)) || (prevbezt && (prevbezt->ipo==IPO_BEZ)) ) 
-                                               {
-                                                       cpack(col[bezt->h1]);
-                                                       glBegin(GL_LINE_STRIP); 
-                                                       glVertex2fv(fp); glVertex2fv(fp+3); 
-                                                       glEnd();
-                                                       
-                                               }
-                                               
-                                               /* only draw second handle if this segment is bezier */
-                                               if (bezt->ipo == IPO_BEZ) 
-                                               {
-                                                       cpack(col[bezt->h2]);
-                                                       glBegin(GL_LINE_STRIP); 
-                                                       glVertex2fv(fp+3); glVertex2fv(fp+6); 
-                                                       glEnd();
-                                               }
-                                       }
-                                       else {
-                                               /* only draw first handle if previous segment was had handles, and selection is ok */
-                                               if ( ((bezt->f1 & SELECT)==sel) && 
-                                                        ( (!prevbezt && (bezt->ipo==IPO_BEZ)) || (prevbezt && (prevbezt->ipo==IPO_BEZ)) ) ) 
-                                               {
-                                                       fp= bezt->vec[0];
-                                                       cpack(col[bezt->h1]);
-                                                       
-                                                       glBegin(GL_LINE_STRIP); 
-                                                       glVertex2fv(fp); glVertex2fv(fp+3); 
-                                                       glEnd();
-                                               }
-                                               
-                                               /* only draw second handle if this segment is bezier, and selection is ok */
-                                               if ( ((bezt->f3 & SELECT)==sel) &&
-                                                        (bezt->ipo == IPO_BEZ) )
-                                               {
-                                                       fp= bezt->vec[1];
-                                                       cpack(col[bezt->h2]);
-                                                       
-                                                       glBegin(GL_LINE_STRIP); 
-                                                       glVertex2fv(fp); glVertex2fv(fp+3); 
-                                                       glEnd();
-                                               }
-                                       }
+                               /* only draw first handle if previous segment had handles */
+                               if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) 
+                               {
+                                       cpack(col[bezt->h1]);
+                                       glBegin(GL_LINE_STRIP); 
+                                               glVertex2fv(fp); glVertex2fv(fp+3); 
+                                       glEnd();
+                                       
                                }
-                       }
-               }
-       }
-}
-
-/* helper func - draw one repeat of an ipo-curve: bitflag curve only (this is evil stuff to expose to user like this) */
-static void draw_ipocurve_repeat_bits (IpoCurve *icu, View2D *v2d, float cycxofs)
-{
-       BezTriple *bezt= icu->bezt;
-       int a;
-       
-       /* loop over each keyframe, drawing a line extending from that point */
-       for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) {
-               int val= (int)bezt->vec[1][1];
-               int b= 0;
-               
-               /* for each bit in the int, draw a line if the keyframe incorporates it */
-               for (b = 0; b < 31; b++) {
-                       if (val & (1<<b)) {
-                               float v1[2];
                                
-                               /* value stays constant */
-                               v1[1]= b+1;
-                               
-                               glBegin(GL_LINE_STRIP);
-                                       /* extend left too if first keyframe, and not cyclic extrapolation */
-                                       if ((a == 0) && !(icu->extrap & IPO_CYCL)) {
-                                               v1[0]= v2d->cur.xmin+cycxofs;
-                                               glVertex2fv(v1);
-                                       }
-                                       
-                                       /* must pass through current keyframe */
-                                       v1[0]= bezt->vec[1][0] + cycxofs;
-                                       glVertex2fv(v1); 
+                               /* only draw second handle if this segment is bezier */
+                               if (bezt->ipo == BEZT_IPO_BEZ) 
+                               {
+                                       cpack(col[bezt->h2]);
+                                       glBegin(GL_LINE_STRIP); 
+                                               glVertex2fv(fp+3); glVertex2fv(fp+6); 
+                                       glEnd();
+                               }
+                       }
+                       else {
+                               /* only draw first handle if previous segment was had handles, and selection is ok */
+                               if ( ((bezt->f1 & SELECT)==sel) && 
+                                        ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) ) 
+                               {
+                                       fp= bezt->vec[0];
+                                       cpack(col[bezt->h1]);
                                        
-                                       /* 1. if there is a next keyframe, extend until then OR
-                                        * 2. extend until 'infinity' if not cyclic extrapolation
-                                        */
-                                       if ((a+1) < icu->totvert) v1[0]= (bezt+1)->vec[1][0]+cycxofs;
-                                       else if ((icu->extrap & IPO_CYCL)==0) v1[0]= v2d->cur.xmax+cycxofs;
+                                       glBegin(GL_LINE_STRIP); 
+                                               glVertex2fv(fp); glVertex2fv(fp+3); 
+                                       glEnd();
+                               }
+                               
+                               /* only draw second handle if this segment is bezier, and selection is ok */
+                               if ( ((bezt->f3 & SELECT)==sel) &&
+                                        (bezt->ipo == BEZT_IPO_BEZ) )
+                               {
+                                       fp= bezt->vec[1];
+                                       cpack(col[bezt->h2]);
                                        
-                                       glVertex2fv(v1);
-                               glEnd();
+                                       glBegin(GL_LINE_STRIP); 
+                                               glVertex2fv(fp); glVertex2fv(fp+3); 
+                                       glEnd();
+                               }
                        }
                }
        }
 }
 
-/* helper func - draw one repeat of an ipo-curve: normal curve */
-static void draw_ipocurve_repeat_normal (IpoCurve *icu, View2D *v2d, float cycxofs, float cycyofs, float *facp)
+/* Curve ---------------- */
+
+/* helper func - draw one repeat of an F-Curve */
+static void draw_fcurve_repeat (FCurve *fcu, View2D *v2d, float cycxofs, float cycyofs, float *facp)
 {
-       BezTriple *prevbezt= icu->bezt;
+       BezTriple *prevbezt= fcu->bezt;
        BezTriple *bezt= prevbezt+1;
        float v1[2], v2[2], v3[2], v4[2];
        float *fp, data[120];
        float fac= *(facp);
-       int b= icu->totvert-1;
+       int b= fcu->totvert-1;
        int resol;
        
        glBegin(GL_LINE_STRIP);
        
        /* extrapolate to left? */
-       if ((icu->extrap & IPO_CYCL)==0) {
+       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 (prevbezt->vec[1][0] > v2d->cur.xmin) {
                        v1[0]= v2d->cur.xmin;
                        
                        /* y-value depends on the interpolation */
-                       if ((icu->extrap==IPO_HORIZ) || (prevbezt->ipo==IPO_CONST) || (icu->totvert==1)) {
+                       if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (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==IPO_LIN) {
+                       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;
@@ -426,15 +357,16 @@ static void draw_ipocurve_repeat_normal (IpoCurve *icu, View2D *v2d, float cycxo
        }
        
        /* if only one keyframe, add it now */
-       if (icu->totvert == 1) {
+       if (fcu->totvert == 1) {
                v1[0]= prevbezt->vec[1][0] + cycxofs;
                v1[1]= prevbezt->vec[1][1] + cycyofs;
                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 (prevbezt->ipo==IPO_CONST) {
+               if (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;
@@ -444,7 +376,7 @@ static void draw_ipocurve_repeat_normal (IpoCurve *icu, View2D *v2d, float cycxo
                        v1[1]= prevbezt->vec[1][1]+cycyofs;
                        glVertex2fv(v1);
                }
-               else if (prevbezt->ipo==IPO_LIN) {
+               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;
@@ -456,7 +388,7 @@ static void draw_ipocurve_repeat_normal (IpoCurve *icu, View2D *v2d, float cycxo
                         */
                        
                        /* resol not depending on horizontal resolution anymore, drivers for example... */
-                       if (icu->driver) 
+                       if (fcu->driver) 
                                resol= 32;
                        else 
                                resol= 3.0*sqrt(bezt->vec[1][0] - prevbezt->vec[1][0]);
@@ -481,7 +413,7 @@ static void draw_ipocurve_repeat_normal (IpoCurve *icu, View2D *v2d, float cycxo
                                v4[0]= bezt->vec[1][0]+cycxofs;
                                v4[1]= bezt->vec[1][1]+cycyofs;
                                
-// XXX old sys!                                correct_bezpart(v1, v2, v3, v4);
+                               correct_bezpart(v1, v2, v3, v4);
                                
                                forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, 3);
                                forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, 3);
@@ -504,16 +436,16 @@ static void draw_ipocurve_repeat_normal (IpoCurve *icu, View2D *v2d, float cycxo
        }
        
        /* extrapolate to right? (see code for left-extrapolation above too) */
-       if ((icu->extrap & IPO_CYCL)==0) {
+       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 ((icu->extrap==IPO_HORIZ) || (prevbezt->ipo==IPO_CONST) || (icu->totvert==1)) {
+                       if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
                                /* based on last keyframe's value */
                                v1[1]= prevbezt->vec[1][1];
                        } 
-                       else if (prevbezt->ipo==IPO_LIN) {
+                       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]);
@@ -537,6 +469,8 @@ static void draw_ipocurve_repeat_normal (IpoCurve *icu, View2D *v2d, float cycxo
        *(facp) = fac;
 } 
 
+#if 0 // XXX old animation system unconverted code!
+
 /* draw all ipo-curves */
 static void draw_ipocurves(SpaceIpo *sipo, ARegion *ar, int sel)
 {
@@ -639,6 +573,7 @@ static void draw_ipocurves(SpaceIpo *sipo, ARegion *ar, int sel)
                }
        }
 }
+#endif // XXX old animation system unconverted code
 
 #if 0
 static void draw_ipokey(SpaceIpo *sipo, ARegion *ar)
@@ -658,56 +593,472 @@ static void draw_ipokey(SpaceIpo *sipo, ARegion *ar)
 }
 #endif
 
-void drawipospace(ScrArea *sa, ARegion *ar)
+void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
 {
-       SpaceIpo *sipo= sa->spacedata.first;
-       //View2D *v2d= &ar->v2d;
-       //      EditIpo *ei;
-
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
        
-       if(sipo->editipo) {
+       unsigned int col;
+       int items, i;
+       
+       /* build list of curves to draw */
+               // XXX enable ANIMFILTER_CURVEVISIBLE when we have a method to set them
+       filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CURVESONLY/*|ANIMFILTER_CURVEVISIBLE*/);
+       items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
                
-               /* correct scale for degrees? */
-               // XXX this should be calculated elsewhere
-#if 0
-               disptype= -1;
-               ei= sipo->editipo;
-               for(a=0; a<sipo->totipo; a++, ei++) {
-                       if(ei->flag & IPO_VISIBLE) {
-                               if(disptype== -1) disptype= ei->disptype;
-                               else if(disptype!=ei->disptype) disptype= 0;
-                       }
-               }
-#endif
-               // now set grid size (done elsehwere now)
+       /* for each curve:
+        *      draw curve, then handle-lines, and finally vertices in this order so that 
+        *      the data will be layered correctly
+        */
+       for (ale=anim_data.first, i=0; ale; ale=ale->next, i++) {
+               FCurve *fcu= (FCurve *)ale->key_data;
+               Object *nob= ANIM_nla_mapping_get(ac, ale);
+               float fac=0.0f; // dummy var
                
-               /* ipokeys */
-#if 0
-               if(sipo->showkey) {
-                       //if(sipo->ipokey.first==0) make_ipokey();
-                       //else update_ipokey_val();
-                       make_ipokey();
-                       draw_ipokey(sipo);
-               }
-#endif
+               /* map ipo-points for drawing if scaled F-Curve */
+               if (nob)
+                       ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1); 
+               
+               /* draw curve - we currently calculate colour on the fly, but that should probably be done in advance instead */
+               col= ipo_rainbow(i, items);
+               cpack(col);
                
-               /* map ipo-points for drawing if scaled ipo */
-               //if (NLA_IPO_SCALED)
-               //      ANIM_nla_mapping_apply_ipo(OBACT, sipo->ipo, 0, 0);
-
-               /* draw deselect */
-               draw_ipocurves(sipo, ar, 0);
-               draw_ipohandles(sipo, ar, 0);
-               draw_ipovertices(sipo, ar, 0);
+               draw_fcurve_repeat(fcu, &ar->v2d, 0, 0, &fac); // XXX this call still needs a lot more work
                
-               /* draw select */
-               draw_ipocurves(sipo, ar, 1);
-               draw_ipohandles(sipo, ar, 1);
-               draw_ipovertices(sipo, ar, 1);
+               /* draw handles and vertices as appropriate */
+               draw_fcurve_handles(sipo, ar, fcu);
+               draw_fcurve_vertices(sipo, ar, fcu);
                
-               /* undo mapping of ipo-points for drawing if scaled ipo */
-               //if (NLA_IPO_SCALED)
-               //      ANIM_nla_mapping_apply_ipo(OBACT, sipo->ipo, 1, 0);
                
+               /* undo mapping of keyframes for drawing if scaled F-Curve */
+               if (nob)
+                       ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1); 
        }
+       
+       /* free list of curves */
+       BLI_freelistN(&anim_data);
+}
+
+/* ************************************************************************* */
+/* Channel List */
+
+// XXX quite a few of these need to be kept in sync with their counterparts in Action Editor
+// as they're the same. We have 2 separate copies of this for now to make it easier to develop
+// the diffences between the two editors, but one day these should be merged!
+
+/* left hand part */
+void graph_draw_channel_names(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar) 
+{
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       View2D *v2d= &ar->v2d;
+       float x= 0.0f, y= 0.0f;
+       int items, height;
+       
+       /* build list of channels to draw */
+       filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
+       items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+       
+       /* Update max-extent of channels here (taking into account scrollers):
+        *      - this is done to allow the channel list to be scrollable, but must be done here
+        *        to avoid regenerating the list again and/or also because channels list is drawn first
+        *      - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
+        *        start of list offset, and the second is as a correction for the scrollers.
+        */
+       height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
+       if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
+               /* don't use totrect set, as the width stays the same 
+                * (NOTE: this is ok here, the configuration is pretty straightforward) 
+                */
+               v2d->tot.ymin= (float)(-height);
+       }
+       
+       /* loop through channels, and set up drawing depending on their type  */        
+       y= (float)ACHANNEL_FIRST;
+       
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
+               const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
+               
+               /* check if visible */
+               if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+                        IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
+               {
+                       bActionGroup *grp = NULL;
+                       short indent= 0, offset= 0, sel= 0, group= 0;
+                       int expand= -1, protect = -1, special= -1, mute = -1;
+                       char name[128];
+                       
+                       /* determine what needs to be drawn */
+                       switch (ale->type) {
+                               case ANIMTYPE_OBJECT: /* object */
+                               {
+                                       Base *base= (Base *)ale->data;
+                                       Object *ob= base->object;
+                                       
+                                       group= 4;
+                                       indent= 0;
+                                       
+                                       /* icon depends on object-type */
+                                       if (ob->type == OB_ARMATURE)
+                                               special= ICON_ARMATURE;
+                                       else    
+                                               special= ICON_OBJECT;
+                                               
+                                       /* only show expand if there are any channels */
+                                       if (EXPANDED_OBJC(ob))
+                                               expand= ICON_TRIA_DOWN;
+                                       else
+                                               expand= ICON_TRIA_RIGHT;
+                                       
+                                       sel = SEL_OBJC(base);
+                                       strcpy(name, ob->id.name+2);
+                               }
+                                       break;
+                               case ANIMTYPE_FILLACTD: /* action widget */
+                               {
+                                       bAction *act= (bAction *)ale->data;
+                                       
+                                       group = 4;
+                                       indent= 1;
+                                       special= ICON_ACTION;
+                                       
+                                       if (EXPANDED_ACTC(act))
+                                               expand= ICON_TRIA_DOWN;
+                                       else
+                                               expand= ICON_TRIA_RIGHT;
+                                       
+                                       sel = SEL_ACTC(act);
+                                       strcpy(name, "Action");
+                               }
+                                       break;
+                               case ANIMTYPE_FILLMATD: /* object materials (dopesheet) expand widget */
+                               {
+                                       Object *ob = (Object *)ale->data;
+                                       
+                                       group = 4;
+                                       indent = 1;
+                                       special = ICON_MATERIAL;
+                                       
+                                       if (FILTER_MAT_OBJC(ob))
+                                               expand = ICON_TRIA_DOWN;
+                                       else
+                                               expand = ICON_TRIA_RIGHT;
+                                               
+                                       strcpy(name, "Materials");
+                               }
+                                       break;
+                               
+                               
+                               case ANIMTYPE_DSMAT: /* single material (dopesheet) expand widget */
+                               {
+                                       Material *ma = (Material *)ale->data;
+                                       
+                                       group = 0;
+                                       indent = 0;
+                                       special = ICON_MATERIAL;
+                                       offset = 21;
+                                       
+                                       if (FILTER_MAT_OBJD(ma))
+                                               expand = ICON_TRIA_DOWN;
+                                       else
+                                               expand = ICON_TRIA_RIGHT;
+                                       
+                                       strcpy(name, ma->id.name+2);
+                               }
+                                       break;
+                               case ANIMTYPE_DSLAM: /* lamp (dopesheet) expand widget */
+                               {
+                                       Lamp *la = (Lamp *)ale->data;
+                                       
+                                       group = 4;
+                                       indent = 1;
+                                       special = ICON_LAMP;
+                                       
+                                       if (FILTER_LAM_OBJD(la))
+                                               expand = ICON_TRIA_DOWN;
+                                       else
+                                               expand = ICON_TRIA_RIGHT;
+                                       
+                                       strcpy(name, la->id.name+2);
+                               }
+                                       break;
+                               case ANIMTYPE_DSCAM: /* camera (dopesheet) expand widget */
+                               {
+                                       Camera *ca = (Camera *)ale->data;
+                                       
+                                       group = 4;
+                                       indent = 1;
+                                       special = ICON_CAMERA;
+                                       
+                                       if (FILTER_CAM_OBJD(ca))
+                                               expand = ICON_TRIA_DOWN;
+                                       else
+                                               expand = ICON_TRIA_RIGHT;
+                                       
+                                       strcpy(name, ca->id.name+2);
+                               }
+                                       break;
+                               case ANIMTYPE_DSCUR: /* curve (dopesheet) expand widget */
+                               {
+                                       Curve *cu = (Curve *)ale->data;
+                                       
+                                       group = 4;
+                                       indent = 1;
+                                       special = ICON_CURVE;
+                                       
+                                       if (FILTER_CUR_OBJD(cu))
+                                               expand = ICON_TRIA_DOWN;
+                                       else
+                                               expand = ICON_TRIA_RIGHT;
+                                       
+                                       strcpy(name, cu->id.name+2);
+                               }
+                                       break;
+                               case ANIMTYPE_DSSKEY: /* shapekeys (dopesheet) expand widget */
+                               {
+                                       Key *key= (Key *)ale->data;
+                                       
+                                       group = 4;
+                                       indent = 1;
+                                       special = ICON_EDIT;
+                                       
+                                       if (FILTER_SKE_OBJD(key))       
+                                               expand = ICON_TRIA_DOWN;
+                                       else
+                                               expand = ICON_TRIA_RIGHT;
+                                               
+                                       //sel = SEL_OBJC(base);
+                                       strcpy(name, "Shape Keys");
+                               }
+                                       break;
+                                       
+                               
+                               case ANIMTYPE_GROUP: /* action group */
+                               {
+                                       bActionGroup *agrp= (bActionGroup *)ale->data;
+                                       
+                                       group= 2;
+                                       indent= 0;
+                                       special= -1;
+                                       
+                                       offset= (ale->id) ? 21 : 0;
+                                       
+                                       /* only show expand if there are any channels */
+                                       if (agrp->channels.first) {
+                                               if (EXPANDED_AGRP(agrp))
+                                                       expand = ICON_TRIA_DOWN;
+                                               else
+                                                       expand = ICON_TRIA_RIGHT;
+                                       }
+                                       
+                                       if (EDITABLE_AGRP(agrp))
+                                               protect = ICON_UNLOCKED;
+                                       else
+                                               protect = ICON_LOCKED;
+                                               
+                                       sel = SEL_AGRP(agrp);
+                                       strcpy(name, agrp->name);
+                               }
+                                       break;
+                               case ANIMTYPE_FCURVE: /* F-Curve channel */
+                               {
+                                       FCurve *fcu = (FCurve *)ale->data;
+                                       
+                                       indent = 0;
+                                       
+                                       //group= (ale->grp) ? 1 : 0;
+                                       //grp= ale->grp;
+                                       
+                                       // XXX include some UI element to allow toggling of visibility
+                                       
+                                       switch (ale->ownertype) {
+                                               case ANIMTYPE_NONE:     /* no owner */
+                                               case ANIMTYPE_FCURVE: 
+                                                       offset= 0;
+                                                       break;
+                                                       
+                                               case ANIMTYPE_DSMAT: /* for now, this is special case for materials */
+                                                       offset= 21;
+                                                       indent= 1;
+                                                       break;
+                                                       
+                                               default:
+                                                       offset= 14;
+                                                       break;
+                                       }
+                                       
+                                       if (fcu->flag & FCURVE_MUTED)
+                                               mute = ICON_MUTE_IPO_ON;
+                                       else    
+                                               mute = ICON_MUTE_IPO_OFF;
+                                               
+                                       if (EDITABLE_FCU(fcu))
+                                               protect = ICON_UNLOCKED;
+                                       else
+                                               protect = ICON_LOCKED;
+                                       
+                                       sel = SEL_FCU(fcu);
+                                       
+                                       // for now, we just print the full path... this needs more work!
+                                       getname_anim_fcurve(name, ale->id, fcu);
+                                       //sprintf(name, "%s[%d]", fcu->rna_path, fcu->array_index);
+                               }
+                                       break;
+                                       
+                               case ANIMTYPE_SHAPEKEY: /* shapekey channel */
+                               {
+                                       KeyBlock *kb = (KeyBlock *)ale->data;
+                                       
+                                       indent = 0;
+                                       special = -1;
+                                       
+                                       offset= (ale->id) ? 21 : 0;
+                                       
+                                       if (kb->name[0] == '\0')
+                                               sprintf(name, "Key %d", ale->index);
+                                       else
+                                               strcpy(name, kb->name);
+                               }
+                                       break;
+                       }       
+                       
+                       /* now, start drawing based on this information */
+                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                       glEnable(GL_BLEND);
+                       
+                       /* draw backing strip behind channel name */
+                       if (group == 4) {
+                               /* only used in dopesheet... */
+                               if (ale->type == ANIMTYPE_OBJECT) {
+                                       /* object channel - darker */
+                                       UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
+                                       uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+                                       gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
+                               }
+                               else {
+                                       /* sub-object folders - lighter */
+                                       UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
+                                       
+                                       offset += 7 * indent;
+                                       glBegin(GL_QUADS);
+                                               glVertex2f(x+offset, yminc);
+                                               glVertex2f(x+offset, ymaxc);
+                                               glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
+                                               glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
+                                       glEnd();
+                                       
+                                       /* clear group value, otherwise we cause errors... */
+                                       group = 0;
+                               }
+                       }
+                       else if (group == 3) {
+                               /* only for gp-data channels */
+                               UI_ThemeColorShade(TH_GROUP, 20);
+                               uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+                               gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
+                       }
+                       else if (group == 2) {
+                               /* only for action group channels */
+                               if (ale->flag & AGRP_ACTIVE)
+                                       UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
+                               else
+                                       UI_ThemeColorShade(TH_GROUP, 20);
+                               uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+                               gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
+                       }
+                       else {
+                               /* for normal channels 
+                                *      - use 3 shades of color group/standard color for 3 indention level
+                                *      - only use group colors if allowed to, and if actually feasible
+                                */
+                               if ((grp) && (grp->customCol)) 
+                               {
+                                       char cp[3];
+                                       
+                                       if (indent == 2) {
+                                               VECCOPY(cp, grp->cs.solid);
+                                       }
+                                       else if (indent == 1) {
+                                               VECCOPY(cp, grp->cs.select);
+                                       }
+                                       else {
+                                               VECCOPY(cp, grp->cs.active);
+                                       }
+                                       
+                                       glColor3ub(cp[0], cp[1], cp[2]);
+                               }
+                               else
+                                       UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
+                               
+                               indent += group;
+                               offset += 7 * indent;
+                               glBegin(GL_QUADS);
+                                       glVertex2f(x+offset, yminc);
+                                       glVertex2f(x+offset, ymaxc);
+                                       glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
+                                       glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
+                               glEnd();
+                       }
+                       
+                       /* draw expand/collapse triangle */
+                       if (expand > 0) {
+                               UI_icon_draw(x+offset, yminc, expand);
+                               offset += 17;
+                       }
+                       
+                       /* draw special icon indicating certain data-types */
+                       if (special > -1) {
+                               if (ELEM(group, 3, 4)) {
+                                       /* for gpdatablock channels */
+                                       UI_icon_draw(x+offset, yminc, special);
+                                       offset += 17;
+                               }
+                               else {
+                                       /* for ipo/constraint channels */
+                                       UI_icon_draw(x+offset, yminc, special);
+                                       offset += 17;
+                               }
+                       }
+                       glDisable(GL_BLEND);
+                       
+                       /* draw name */
+                       if (sel)
+                               UI_ThemeColor(TH_TEXT_HI);
+                       else
+                               UI_ThemeColor(TH_TEXT);
+                       offset += 3;
+                       ui_rasterpos_safe(x+offset, y-4, 1.0f);
+                       UI_DrawString(G.font, name, 0);
+                       
+                       /* reset offset - for RHS of panel */
+                       offset = 0;
+                       
+                       /* set blending again, as text drawing may clear it */
+                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                       glEnable(GL_BLEND);
+                       
+                       /* draw protect 'lock' */
+                       if (protect > -1) {
+                               offset = 16;
+                               UI_icon_draw((float)ACHANNEL_NAMEWIDTH-offset, yminc, protect);
+                       }
+                       
+                       /* draw mute 'eye' */
+                       if (mute > -1) {
+                               offset += 16;
+                               UI_icon_draw((float)(ACHANNEL_NAMEWIDTH-offset), yminc, mute);
+                       }
+                       glDisable(GL_BLEND);
+               }
+               
+               /* adjust y-position for next one */
+               y -= ACHANNEL_STEP;
+       }
+       
+       /* free tempolary channels */
+       BLI_freelistN(&anim_data);
 }
index da39fbacc44576e58ba04bb7b880c32d9d4b34eb..df2dcd289142c5a353764a8caca23b8bb9b14b4e 100644 (file)
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "DNA_anim_types.h"
 #include "DNA_space_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
@@ -41,6 +42,7 @@
 #include "BKE_context.h"
 #include "BKE_screen.h"
 
+#include "ED_anim_api.h"
 #include "ED_screen.h"
 #include "ED_types.h"
 #include "ED_util.h"
 
 #include "ipo_intern.h"
 
+/* ********************************************************* */
+/* Menu Defines... */
+
+/* button events */
+enum {
+       B_REDR  = 0,
+       B_GRAPHCOPYKEYS,
+       B_GRAPHPASTEKEYS,
+} eActHeader_ButEvents;
 
 /* ************************ header area region *********************** */
 
@@ -91,25 +102,29 @@ static uiBlock *dummy_viewmenu(bContext *C, uiMenuBlockHandle *handle, void *arg
        return block;
 }
 
-static void do_ipo_buttons(bContext *C, void *arg, int event)
+static void do_graph_buttons(bContext *C, void *arg, int event)
 {
-       switch(event) {
+       switch (event) {
+               case B_REDR:
+                       ED_area_tag_redraw(CTX_wm_area(C));
+                       break;
        }
 }
 
 
-void ipo_header_buttons(const bContext *C, ARegion *ar)
+void graph_header_buttons(const bContext *C, ARegion *ar)
 {
        ScrArea *sa= CTX_wm_area(C);
+       SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
        uiBlock *block;
        int xco, yco= 3;
        
        block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS, UI_HELV);
-       uiBlockSetHandleFunc(block, do_ipo_buttons, NULL);
+       uiBlockSetHandleFunc(block, do_graph_buttons, NULL);
        
        xco= ED_area_header_standardbuttons(C, block, yco);
        
-       if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+       if ((sa->flag & HEADER_NO_PULLDOWN)==0) {
                int xmax;
                
                /* pull down menus */
@@ -118,10 +133,17 @@ void ipo_header_buttons(const bContext *C, ARegion *ar)
                xmax= GetButStringLength("View");
                uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C), 
                                                 "View", xco, yco-2, xmax-3, 24, "");
+               xco+= xmax;
        }
        
        uiBlockSetEmboss(block, UI_EMBOSS);
-
+       
+       /* mode selector */
+       uiDefButS(block, MENU, B_REDR, 
+                       "Editor Mode %t|F-Curve Editor %x0|Drivers %x1", 
+                       xco,yco,90,YIC, &sipo->mode, 0, 1, 0, 0, 
+                       "Editing modes for this editor");
+       
        /* always as last  */
        UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
        
index 86b20d4bdd04e2b288b56bc035833f7cf2e9163e..61fa095c157ddca9387b721c92d4fd0cfcfa4b2a 100644 (file)
 #ifndef ED_IPO_INTERN_H
 #define ED_IPO_INTERN_H
 
+struct bContext;
+struct bAnimContext;
+struct SpaceIpo;
+struct ARegion;
+
 /* internal exports only */
 
+/* ipo_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);
 
 /* ipo_header.c */
-void ipo_header_buttons(const bContext *C, ARegion *ar);
+void graph_header_buttons(const bContext *C, struct ARegion *ar);
 
 
 #endif /* ED_IPO_INTERN_H */
index 38d0468bc37cfe71e89f2b912b36bc20eb08f783..6ee3af04594bc043b4badf11cb5b64ac17b09298 100644 (file)
@@ -29,7 +29,7 @@
 #include <string.h>
 #include <stdio.h>
 
-#include "DNA_ipo_types.h"
+#include "DNA_anim_types.h"
 #include "DNA_object_types.h"
 #include "DNA_space_types.h"
 #include "DNA_scene_types.h"
 
 /* ******************** default callbacks for ipo space ***************** */
 
-static SpaceLink *ipo_new(const bContext *C)
+static SpaceLink *graph_new(const bContext *C)
 {
        Scene *scene= CTX_data_scene(C);
        ARegion *ar;
        SpaceIpo *sipo;
        
-       sipo= MEM_callocN(sizeof(SpaceIpo), "initipo");
+       sipo= MEM_callocN(sizeof(SpaceIpo), "init graphedit");
        sipo->spacetype= SPACE_IPO;
-       sipo->blocktype= ID_OB;
+       
+       /* allocate DopeSheet data for Graph Editor */
+       sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
        
        /* header */
-       ar= MEM_callocN(sizeof(ARegion), "header for ipo");
+       ar= MEM_callocN(sizeof(ARegion), "header for graphedit");
        
        BLI_addtail(&sipo->regionbase, ar);
        ar->regiontype= RGN_TYPE_HEADER;
        ar->alignment= RGN_ALIGN_BOTTOM;
        
        /* channels */
-       ar= MEM_callocN(sizeof(ARegion), "main area for ipo");
+       ar= MEM_callocN(sizeof(ARegion), "main area for graphedit");
        
        BLI_addtail(&sipo->regionbase, ar);
        ar->regiontype= RGN_TYPE_CHANNELS;
@@ -89,7 +91,7 @@ static SpaceLink *ipo_new(const bContext *C)
        ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
        
        /* main area */
-       ar= MEM_callocN(sizeof(ARegion), "main area for ipo");
+       ar= MEM_callocN(sizeof(ARegion), "main area for graphedit");
        
        BLI_addtail(&sipo->regionbase, ar);
        ar->regiontype= RGN_TYPE_WINDOW;
@@ -112,42 +114,41 @@ static SpaceLink *ipo_new(const bContext *C)
        
        ar->v2d.keeptot= 0;
        
-       /* channel list region XXX */
-
-       
        return (SpaceLink *)sipo;
 }
 
 /* not spacelink itself */
-static void ipo_free(SpaceLink *sl)
+static void graph_free(SpaceLink *sl)
 {      
-       SpaceIpo *si= (SpaceIpo*) sl;
+       SpaceIpo *si= (SpaceIpo *)sl;
        
-       if(si->editipo) MEM_freeN(si->editipo);
-       // XXX free_ipokey(&si->ipokey);
-
+       if (si->ads) {
+               BLI_freelistN(&si->ads->chanbase);
+               MEM_freeN(si->ads);
+       }
 }
 
 
 /* spacetype; init callback */
-static void ipo_init(struct wmWindowManager *wm, ScrArea *sa)
+static void graph_init(struct wmWindowManager *wm, ScrArea *sa)
 {
-
+       //SpaceIpo *si= (SpaceIpo *)sa->spacedata.first;
+       
 }
 
-static SpaceLink *ipo_duplicate(SpaceLink *sl)
+static SpaceLink *graph_duplicate(SpaceLink *sl)
 {
        SpaceIpo *sipon= MEM_dupallocN(sl);
        
        /* clear or remove stuff from old */
-       sipon->editipo= NULL;
-       sipon->ipokey.first= sipon->ipokey.last= NULL;
+       //sipon->ipokey.first= sipon->ipokey.last= NULL;
+       sipon->ads= MEM_dupallocN(sipon->ads);
        
        return (SpaceLink *)sipon;
 }
 
 /* add handlers, stuff you only do once or on area/region changes */
-static void ipo_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void graph_main_area_init(wmWindowManager *wm, ARegion *ar)
 {
        ListBase *keymap;
        
@@ -158,15 +159,16 @@ static void ipo_main_area_init(wmWindowManager *wm, ARegion *ar)
        WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
 }
 
-static void ipo_main_area_draw(const bContext *C, ARegion *ar)
+static void graph_main_area_draw(const bContext *C, ARegion *ar)
 {
        /* draw entirely, view changes should be handled here */
        SpaceIpo *sipo= (SpaceIpo*)CTX_wm_space_data(C);
+       bAnimContext ac;
        View2D *v2d= &ar->v2d;
        View2DGrid *grid;
        View2DScrollers *scrollers;
        float col[3];
-       short unit=0, flag=0;
+       short unitx=0, unity=V2D_UNIT_VALUES, flag=0;
        
        /* clear and setup matrix */
        UI_GetThemeColor3fv(TH_BACK, col);
@@ -176,12 +178,15 @@ static void ipo_main_area_draw(const bContext *C, ARegion *ar)
        UI_view2d_view_ortho(C, v2d);
        
        /* grid */
-       unit= (sipo->flag & SIPO_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
-       grid= UI_view2d_grid_calc(C, v2d, unit, V2D_GRID_NOCLAMP, V2D_UNIT_VALUES/*unit-y*/, V2D_GRID_NOCLAMP, ar->winx, ar->winy);
+       unitx= (sipo->flag & SIPO_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
+       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);
        
-       /* data... */
+       /* draw data */
+       if (ANIM_animdata_get_context(C, &ac)) {
+               graph_draw_curves(&ac, sipo, ar);
+       }
        
        /* current frame */
        if (sipo->flag & SIPO_DRAWTIME)         flag |= DRAWCFRA_UNIT_SECONDS;
@@ -201,27 +206,34 @@ static void ipo_main_area_draw(const bContext *C, ARegion *ar)
        
        /* scrollers */
                // FIXME: args for scrollers depend on the type of data being shown...
-       scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_NOCLAMP, V2D_UNIT_VALUES/*unit-y*/, V2D_GRID_NOCLAMP);
+       scrollers= UI_view2d_scrollers_calc(C, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP);
        UI_view2d_scrollers_draw(C, v2d, scrollers);
        UI_view2d_scrollers_free(scrollers);
 }
 
-void ipo_operatortypes(void)
+void graph_operatortypes(void)
 {
 }
 
-void ipo_keymap(struct wmWindowManager *wm)
+void graph_keymap(struct wmWindowManager *wm)
 {
 }
 
-static void ipo_channel_area_init(wmWindowManager *wm, ARegion *ar)
+static void graph_channel_area_init(wmWindowManager *wm, ARegion *ar)
 {
+       ListBase *keymap;
+       
        UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+       
+       /* own keymap */
+       keymap= WM_keymap_listbase(wm, "Animation_Channels", 0, 0);     /* XXX weak? */
+       WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
 }
 
-static void ipo_channel_area_draw(const bContext *C, ARegion *ar)
+static void graph_channel_area_draw(const bContext *C, ARegion *ar)
 {
-       //SpaceIpo *sipo= C->area->spacedata.first;
+       SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
+       bAnimContext ac;
        View2D *v2d= &ar->v2d;
        View2DScrollers *scrollers;
        float col[3];
@@ -233,7 +245,10 @@ static void ipo_channel_area_draw(const bContext *C, ARegion *ar)
        
        UI_view2d_view_ortho(C, v2d);
        
-       /* data... */
+       /* draw channels */
+       if (ANIM_animdata_get_context(C, &ac)) {
+               graph_draw_channel_names(&ac, sipo, ar);
+       }
        
        /* reset view matrix */
        UI_view2d_view_restore(C);
@@ -245,12 +260,12 @@ static void ipo_channel_area_draw(const bContext *C, ARegion *ar)
 }
 
 /* add handlers, stuff you only do once or on area/region changes */
-static void ipo_header_area_init(wmWindowManager *wm, ARegion *ar)
+static void graph_header_area_init(wmWindowManager *wm, ARegion *ar)
 {
        UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
 }
 
-static void ipo_header_area_draw(const bContext *C, ARegion *ar)
+static void graph_header_area_draw(const bContext *C, ARegion *ar)
 {
        float col[3];
        
@@ -266,28 +281,88 @@ static void ipo_header_area_draw(const bContext *C, ARegion *ar)
        /* set view2d view matrix for scrolling (without scrollers) */
        UI_view2d_view_ortho(C, &ar->v2d);
        
-       ipo_header_buttons(C, ar);
+       graph_header_buttons(C, ar);
        
        /* restore view matrix? */
        UI_view2d_view_restore(C);
 }
 
-static void ipo_main_area_listener(ARegion *ar, wmNotifier *wmn)
+static void graph_main_area_listener(ARegion *ar, wmNotifier *wmn)
 {
        /* context changes */
        switch(wmn->category) {
-               
                case NC_SCENE:
                        switch(wmn->data) {
+                               case ND_OB_ACTIVE:
                                case ND_FRAME:
                                case ND_MARKERS:
                                        ED_region_tag_redraw(ar);
                                        break;
-                               }
+                       }
+                       break;
+               case NC_OBJECT:
+                       switch(wmn->data) {
+                               case ND_BONE_ACTIVE:
+                               case ND_BONE_SELECT:
+                                       ED_region_tag_redraw(ar);
+                                       break;
+                       }
+                       break;
+       }
+}
+
+/* editor level listener */
+static void graph_listener(ScrArea *sa, wmNotifier *wmn)
+{
+       /* context changes */
+       switch (wmn->category) {
+               case NC_SCENE:
+                       /*switch (wmn->data) {
+                               case ND_OB_ACTIVE:
+                               case ND_OB_SELECT:
+                                       ED_area_tag_refresh(sa);
+                                       break;
+                       }*/
+                       ED_area_tag_refresh(sa);
+                       break;
+               case NC_OBJECT:
+                       /*switch (wmn->data) {
+                               case ND_BONE_SELECT:
+                               case ND_BONE_ACTIVE:
+                                       ED_area_tag_refresh(sa);
+                                       break;
+                       }*/
+                       ED_area_tag_refresh(sa);
                        break;
        }
 }
 
+static void graph_refresh(const bContext *C, ScrArea *sa)
+{
+       SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first;
+       
+       /* updates to data needed depends on Graph Editor mode... */
+       switch (sipo->mode) {
+               case SIPO_MODE_ANIMATION: /* all animation */
+               {
+                       
+               }
+                       break;
+               
+               case SIPO_MODE_DRIVERS: /* drivers only  */
+               {
+                       Object *ob= CTX_data_active_object(C);
+                       
+                       /* sync changes to bones to the corresponding action channels */
+                       ANIM_pose_to_action_sync(ob, sa);
+               }
+                       break; 
+       }
+       
+       /* region updates? */
+       // XXX resizing y-extents of tot should go here?
+}
+
 /* only called once, from space/spacetypes.c */
 void ED_spacetype_ipo(void)
 {
@@ -296,42 +371,44 @@ void ED_spacetype_ipo(void)
        
        st->spaceid= SPACE_IPO;
        
-       st->new= ipo_new;
-       st->free= ipo_free;
-       st->init= ipo_init;
-       st->duplicate= ipo_duplicate;
-       st->operatortypes= ipo_operatortypes;
-       st->keymap= ipo_keymap;
+       st->new= graph_new;
+       st->free= graph_free;
+       st->init= graph_init;
+       st->duplicate= graph_duplicate;
+       st->operatortypes= graph_operatortypes;
+       st->keymap= graph_keymap;
+       st->listener= graph_listener;
+       st->refresh= graph_refresh;
        
        /* regions: main window */
-       art= MEM_callocN(sizeof(ARegionType), "spacetype ipo region");
+       art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
        art->regionid = RGN_TYPE_WINDOW;
-       art->init= ipo_main_area_init;
-       art->draw= ipo_main_area_draw;
-       art->listener= ipo_main_area_listener;
+       art->init= graph_main_area_init;
+       art->draw= graph_main_area_draw;
+       art->listener= graph_main_area_listener;
        art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_MARKERS|ED_KEYMAP_ANIMATION;
 
        BLI_addhead(&st->regiontypes, art);
        
        /* regions: header */
-       art= MEM_callocN(sizeof(ARegionType), "spacetype ipo region");
+       art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
        art->regionid = RGN_TYPE_HEADER;
        art->minsizey= HEADERY;
        art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
        
-       art->init= ipo_header_area_init;
-       art->draw= ipo_header_area_draw;
+       art->init= graph_header_area_init;
+       art->draw= graph_header_area_draw;
        
        BLI_addhead(&st->regiontypes, art);
        
        /* regions: channels */
-       art= MEM_callocN(sizeof(ARegionType), "spacetype ipo region");
+       art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
        art->regionid = RGN_TYPE_CHANNELS;
        art->minsizex= 200;
        art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
        
-       art->init= ipo_channel_area_init;
-       art->draw= ipo_channel_area_draw;
+       art->init= graph_channel_area_init;
+       art->draw= graph_channel_area_draw;
        
        BLI_addhead(&st->regiontypes, art);
        
index 37995145ff8a77d3fb6af91e33a7d162a16d7784..b7788a1b92af7e0b54f37890b3af2d36832929a3 100644 (file)
@@ -287,10 +287,12 @@ typedef struct bDopeSheet {
 typedef enum DOPESHEET_FILTERFLAG {
                /* general filtering */
        ADS_FILTER_ONLYSEL                      = (1<<0),
+       ADS_FILTER_ONLYDRIVERS          = (1<<1),
        
                /* datatype-based filtering */
        ADS_FILTER_NOOBJ                        = (1<<4),       // XXX
        ADS_FILTER_NOARM                        = (1<<5),       // XXX
+       
        ADS_FILTER_NOSHAPEKEYS          = (1<<6),
        ADS_FILTER_NOCAM                        = (1<<10),
        ADS_FILTER_NOMAT                        = (1<<11),
index 33a45f76a22f9bbcc2f9a8d6f2634bf28dc971d2..dffea96ce416d3f2631612c61896d4f72c828484 100644 (file)
@@ -38,7 +38,6 @@
 /* Hum ... Not really nice... but needed for spacebuts. */
 #include "DNA_view2d_types.h"
 
-struct Ipo;
 struct ID;
 struct Text;
 struct Script;
@@ -51,6 +50,7 @@ struct bNodeTree;
 struct uiBlock;
 struct FileList;
 struct bGPdata;
+struct bDopeSheet;
 struct FileSelectParams;
 struct wmOperator;
 struct wmTimer;
@@ -78,6 +78,8 @@ typedef struct SpaceInfo {
        short blockhandler[8];
 } SpaceInfo;
 
+/* 'Graph' Editor (formerly known as the IPO Editor) */
+// XXX for now, we keep all old data...
 typedef struct SpaceIpo {
        SpaceLink *next, *prev;
        ListBase regionbase;            /* storage of regions for inactive spaces */
@@ -85,25 +87,18 @@ typedef struct SpaceIpo {
        float blockscale;
 
        short blockhandler[8];
-       
-       unsigned int rowbut, pad2; 
        View2D v2d; /* depricated, copied to region */
        
-       void *editipo;
-       ListBase ipokey;
+               // 'IPO keys' - vertical lines for 
+       //ListBase ipokey;              // XXX it's not clear how these will come back yet
+       //short showkey;                        // XXX this doesn't need to be restored until ipokeys come back
        
-       /* the ipo context we need to store */
-       struct Ipo *ipo;
-       struct ID *from;
-       char actname[32], constname[32], bonename[32];
-
-       short totipo, pin;
-       short butofs, channel;
-       short showkey, blocktype;
-       short menunr, lock;
-       short flag, autosnap;
-       float median[3];
-       rctf tot;
+       struct bDopeSheet *ads; /* settings for filtering animation data (NOTE: we use a pointer due to code-linking issues) */
+       
+       short mode;                             /* mode for the Graph editor (eGraphEdit_Mode) */
+       short flag;                             /* settings for Graph editor */
+       short autosnap;                 /* time-transform autosnapping settings for Graph editor (eAnimEdit_AutoSnap in DNA_action_types.h) */
+       char pin, lock;
 } SpaceIpo;
 
 typedef struct SpaceButs {
@@ -588,13 +583,21 @@ typedef struct SpaceImaSel {
 #define SI_DRAW_STRETCH        1<<21
 #define SI_DISPGP              1<<22
 
-/* SpaceIpo->flag */
+/* SpaceIpo->flag (Graph Editor Settings) */
 #define SIPO_LOCK_VIEW                 (1<<0)
 #define SIPO_NOTRANSKEYCULL            (1<<1)
 #define SIPO_NOHANDLES                 (1<<2)
 #define SIPO_NODRAWCFRANUM             (1<<3)
 #define SIPO_DRAWTIME                  (1<<4)
 
+/* SpaceIpo->mode (Graph Editor Mode) */
+enum {
+               /* all animation curves (from all over Blender) */
+       SIPO_MODE_ANIMATION     = 0,
+               /* drivers only */
+       SIPO_MODE_DRIVERS,
+} eGraphEdit_Mode;
+
 /* SpaceText flags (moved from DNA_text_types.h) */
 
 #define ST_SCROLL_SELECT        0x0001 // scrollable
index 24f5df4dbcfb14235e93860ed6ab9d2039d3e602..e1fee06d6f4d207ebcd221f75fffa0d27a2d5a86 100644 (file)
@@ -398,8 +398,8 @@ static void rna_def_userdef_theme_space_ipo(BlenderRNA *brna)
        RNA_def_property_array(prop, 3);
        RNA_def_property_ui_text(prop, "Handle Vertex Select", "");
 
-       prop= RNA_def_property(srna, "handle_vertex_size", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 3);
+       prop= RNA_def_property(srna, "handle_vertex_size", PROP_INT, PROP_NONE);
+       RNA_def_property_range(prop, 0, 255);
        RNA_def_property_ui_text(prop, "Handle Vertex Size", "");
 }
 
@@ -1320,10 +1320,10 @@ static void rna_def_userdef_edit(StructRNA *srna)
        RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_AUTOMATKEY);
        RNA_def_property_ui_text(prop, "Use Visual Keying", "Use Visual keying automatically for constrained objects.");
 
-       prop= RNA_def_property(srna, "new_ipo_curve_type", PROP_ENUM, PROP_NONE);
+       prop= RNA_def_property(srna, "new_interpolation_type", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_items(prop, new_ipo_curve_types);
        RNA_def_property_enum_sdna(prop, NULL, "ipo_new");
-       RNA_def_property_ui_text(prop, "New Ipo Curve Type", "");
+       RNA_def_property_ui_text(prop, "New Interpolation Type", "");
 
        prop= RNA_def_property(srna, "grease_pencil_manhattan_distance", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "gp_manhattendist");
index e60eecc9a04b2329fa662345d7550051ce4eaf03..4bd3cf3f39f302ef5e3a6b49a66d202ed3f75b94 100644 (file)
@@ -327,6 +327,10 @@ static void init_userdef_themes(void)
                        /* DopeSheet - (Object) Channel color */
                        SETCOL(btheme->tact.ds_channel, 0x36, 0x13, 0xca, 255);
                        SETCOL(btheme->tact.ds_subchannel, 0x60, 0x43, 0xd2, 255);
+                       
+                       /* Graph Editor - (Object) Channel color */
+                       SETCOL(btheme->tipo.ds_channel, 0x36, 0x13, 0xca, 255);
+                       SETCOL(btheme->tipo.ds_subchannel, 0x60, 0x43, 0xd2, 255);
                }
                
                /* adjust grease-pencil distances */