Logo Search packages:      
Sourcecode: blender version File versions

drawipo.c

/**
 * $Id: drawipo.c,v 1.40 2004/12/08 15:11:52 ton Exp $
 *
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version. The Blender
 * Foundation also sells licenses for use in proprietary software under
 * the Blender License.  See http://www.blender.org/BL/ for information
 * about this.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 * All rights reserved.
 *
 * The Original Code is: all of this file.
 *
 * Contributor(s): none yet.
 *
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 */

#include <stdio.h>
#include <math.h>
#include <string.h>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifndef _WIN32
#include <unistd.h>
#else
#include <io.h>
#include "BLI_winstuff.h"
#endif   

#include "BMF_Api.h"

#include "BLI_blenlib.h"
#include "BLI_arithb.h"

#include "DNA_curve_types.h"
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_sequence_types.h"
#include "DNA_userdef_types.h"

#include "BKE_utildefines.h"
#include "BKE_curve.h"
#include "BKE_ipo.h"
#include "BKE_global.h"
#include "BKE_key.h"

#include "BIF_gl.h"
#include "BIF_resources.h"
#include "BIF_screen.h"
#include "BIF_interface.h"
#include "BIF_mywindow.h"
#include "BIF_space.h"
#include "BIF_glutil.h"

#include "BSE_drawipo.h"
#include "BSE_view.h"
#include "BSE_editipo.h"
#include "BSE_editipo_types.h"
#include "BSE_editaction_types.h"
#include "BSE_editnla_types.h"

#include "mydevice.h"
#include "blendef.h"
#include "butspace.h"   // shouldnt be...

/* local define... also used in 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) )   

#define IPOBUTX   65
#define IPOSTEP 35                  /* minimum pixels per gridstep */

static float ipogrid_dx, ipogrid_dy, ipogrid_startx, ipogrid_starty;
static int ipomachtx, ipomachty;

static int vertymin, vertymax, horxmin, horxmax;      /* globals om LEFTMOUSE op scrollbar te testen */

extern short ACTWIDTH;

static void scroll_prstr(float x, float y, float val, char dir, int disptype)
{
      int len, macht;
      char str[32];
      
      if(dir=='v') {
            macht= ipomachty;
            if ELEM(disptype, IPO_DISPDEGR, IPO_DISPTIME) {
                  macht+=1;
                  val *= 10;
            }
      }
      else macht= ipomachtx;
      
      if (macht<=0) sprintf(str, "%.*f", 1-macht, val);
      else sprintf(str, "%d", (int)val);
      
      len= strlen(str);
      if(dir=='h') x-= 4*len;
      
      if(dir=='v' && disptype==IPO_DISPDEGR) {
            str[len]= 186; /* Degree symbol */
            str[len+1]= 0;
      }
      
      glRasterPos2f(x,  y);
      BMF_DrawString(G.fonts, str);
}

static void step_to_grid(float *step, int *macht)
{
      float loga, rem;
      
      /* try to write step as a power of 10 */
      
      loga= log10(*step);
      *macht= (int)(loga);
      
      rem= loga- *macht;
      rem= pow(10.0, rem);
      
      if(loga<0.0) {
            if(rem < 0.2) rem= 0.2;
            else if(rem < 0.5) rem= 0.5;
            else rem= 1.0;
            
            *step= rem*pow(10.0, (float)*macht);
      }
      else {
            if(rem < 2.0) rem= 2.0;
            else if(rem < 5.0) rem= 5.0;
            else rem= 10.0;
            
            *step= rem*pow(10.0, (float)*macht);
            
            (*macht)++;
      }
      
}

void calc_ipogrid()
{
      float space, pixels;
      
      /* rule: gridstep is minimal IPOSTEP pixels */
      /* how large is IPOSTEP pixels? */
      
      if(G.v2d==0) return;
      
      space= G.v2d->cur.xmax - G.v2d->cur.xmin;
      pixels= G.v2d->mask.xmax-G.v2d->mask.xmin;
      
      ipogrid_dx= IPOSTEP*space/pixels;
      step_to_grid(&ipogrid_dx, &ipomachtx);
      
      if ELEM(curarea->spacetype, SPACE_SEQ, SPACE_SOUND) {
            if(ipogrid_dx < 0.1) ipogrid_dx= 0.1;
            ipomachtx-= 2;
            if(ipomachtx<-2) ipomachtx= -2;
      }
      
      space= (G.v2d->cur.ymax - G.v2d->cur.ymin);
      pixels= curarea->winy;
      ipogrid_dy= IPOSTEP*space/pixels;
      step_to_grid(&ipogrid_dy, &ipomachty);
      
      if ELEM(curarea->spacetype, SPACE_SEQ, SPACE_SOUND) {
            if(ipogrid_dy < 1.0) ipogrid_dy= 1.0;
            if(ipomachty<1) ipomachty= 1;
      }
      
      ipogrid_startx= G.v2d->cur.xmin-fmod(G.v2d->cur.xmin, ipogrid_dx);
      if(G.v2d->cur.xmin<0.0) ipogrid_startx-= ipogrid_dx;
      ipogrid_starty= (G.v2d->cur.ymin-fmod(G.v2d->cur.ymin, ipogrid_dy));
      if(G.v2d->cur.ymin<0.0) ipogrid_starty-= ipogrid_dy;
      
}

void draw_ipogrid(void)
{
      float vec1[2], vec2[2];
      int a, step;
      
      vec1[0]= vec2[0]= ipogrid_startx;
      vec1[1]= ipogrid_starty;
      vec2[1]= G.v2d->cur.ymax;
      
      step= (G.v2d->mask.xmax-G.v2d->mask.xmin+1)/IPOSTEP;
      
      if(curarea->spacetype==SPACE_SOUND) glColor3ub(0x70, 0x70, 0x60);
      else BIF_ThemeColor(TH_GRID);
      
      for(a=0; a<step; a++) {
            glBegin(GL_LINE_STRIP);
            glVertex2fv(vec1); glVertex2fv(vec2);
            glEnd();
            vec2[0]= vec1[0]+= ipogrid_dx;
      }
      
      vec2[0]= vec1[0]-= 0.5*ipogrid_dx;
      
      if(curarea->spacetype==SPACE_SOUND) glColor3ub(0x80, 0x80, 0x70);
      else  BIF_ThemeColorShade(TH_GRID, 16);
      
      step++;
      for(a=0; a<=step; a++) {
            glBegin(GL_LINE_STRIP);
            glVertex2fv(vec1); glVertex2fv(vec2);
            glEnd();
            vec2[0]= vec1[0]-= ipogrid_dx;
      }
      
      if(curarea->spacetype!=SPACE_SOUND && curarea->spacetype!=SPACE_ACTION && curarea->spacetype!=SPACE_NLA) {
            vec1[0]= ipogrid_startx;
            vec1[1]= vec2[1]= ipogrid_starty;
            vec2[0]= G.v2d->cur.xmax;
            
            step= (curarea->winy+1)/IPOSTEP;
            
            BIF_ThemeColor(TH_GRID);
            for(a=0; a<=step; a++) {
                  glBegin(GL_LINE_STRIP);
                  glVertex2fv(vec1); glVertex2fv(vec2);
                  glEnd();
                  vec2[1]= vec1[1]+= ipogrid_dy;
            }
            vec2[1]= vec1[1]-= 0.5*ipogrid_dy;
            step++;
            
            if(curarea->spacetype==SPACE_IPO) {
                  BIF_ThemeColorShade(TH_GRID, 16);
                  for(a=0; a<step; a++) {
                        glBegin(GL_LINE_STRIP);
                        glVertex2fv(vec1); glVertex2fv(vec2);
                        glEnd();
                        vec2[1]= vec1[1]-= ipogrid_dy;
                  }
            }
      }
      
      BIF_ThemeColorShade(TH_GRID, -50);
      
      if (curarea->spacetype!=SPACE_ACTION && curarea->spacetype!=SPACE_NLA)
      {     /* Horizontal axis */
            vec1[0]= G.v2d->cur.xmin;
            vec2[0]= G.v2d->cur.xmax;
            vec1[1]= vec2[1]= 0.0;
            glBegin(GL_LINE_STRIP);
            
            glVertex2fv(vec1);
            glVertex2fv(vec2);
            
            glEnd();
      }
      
      /* Vertical axis */
      
      vec1[1]= G.v2d->cur.ymin;
      vec2[1]= G.v2d->cur.ymax;
      vec1[0]= vec2[0]= 0.0;
      glBegin(GL_LINE_STRIP);
      glVertex2fv(vec1); glVertex2fv(vec2);
      glEnd();
      
      /* Limits box */
      if(curarea->spacetype==SPACE_IPO) {
            if(G.sipo->blocktype==ID_SEQ) {
                  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
                  glRectf(0.0,  0.0,  100.0,  1.0); 
                  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            }
            else if(ELEM(G.sipo->blocktype, ID_CU, IPO_CO)) {
                  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
                  glRectf(0.0,  1.0,  G.v2d->cur.xmax,  1.0); 
                  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            }
      }
}

void areamouseco_to_ipoco(View2D *v2d, short *mval, float *x, float *y)
{
      float div, ofs;
      
      div= v2d->mask.xmax-v2d->mask.xmin;
      ofs= v2d->mask.xmin;
      
      *x= v2d->cur.xmin+ (v2d->cur.xmax-v2d->cur.xmin)*(mval[0]-ofs)/div;
      
      div= v2d->mask.ymax-v2d->mask.ymin;
      ofs= v2d->mask.ymin;
      
      *y= v2d->cur.ymin+ (v2d->cur.ymax-v2d->cur.ymin)*(mval[1]-ofs)/div;
}

void ipoco_to_areaco(View2D *v2d, float *vec, short *mval)
{
      float x, y;
      
      mval[0]= 3200;
      
      x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
      y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);

      if(x>=0.0 && x<=1.0) {
            if(y>=0.0 && y<=1.0) {
                  mval[0]= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
                  mval[1]= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
            }
      }
}

void ipoco_to_areaco_noclip(View2D *v2d, float *vec, short *mval)
{
      float x, y;
      
      x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
      y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);
      
      x= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
      y= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
      
      if(x<-32760) mval[0]= -32760;
      else if(x>32760) mval[0]= 32760;
      else mval[0]= x;
      
      if(y<-32760) mval[1]= -32760;
      else if(y>32760) mval[1]= 32760;
      else mval[1]= y;
}

int in_ipo_buttons(void)
{
      short mval[2];
      
      getmouseco_areawin(mval);
      
      if(mval[0]< G.v2d->mask.xmax) return 0;
      else return 1;
}


void view2d_zoom(View2D *v2d, float factor, int winx, int winy) 
{
      float dx= factor*(v2d->cur.xmax-v2d->cur.xmin);
      float dy= factor*(v2d->cur.ymax-v2d->cur.ymin);
      if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
            v2d->cur.xmin+= dx;
            v2d->cur.xmax-= dx;
      }
      if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
            v2d->cur.ymin+= dy;
            v2d->cur.ymax-= dy;
      }
      test_view2d(v2d, winx, winy);
}


void test_view2d(View2D *v2d, int winx, int winy)
{
      /* cur is not allowed to be larger than max, smaller than min, or outside of tot */
      rctf *cur, *tot;
      float dx, dy, temp, fac, zoom;
      
      /* correct winx for scroll */
      if(v2d->scroll & L_SCROLL) winx-= SCROLLB;
      if(v2d->scroll & B_SCROLL) winy-= SCROLLH;
      
      cur= &v2d->cur;
      tot= &v2d->tot;
      
      dx= cur->xmax-cur->xmin;
      dy= cur->ymax-cur->ymin;


      /* Reevan's test */
      if (v2d->keepzoom & V2D_LOCKZOOM_Y)
            v2d->cur.ymax=v2d->cur.ymin+((float)winy);

      if (v2d->keepzoom & V2D_LOCKZOOM_X)
            v2d->cur.xmax=v2d->cur.xmin+((float)winx);

      if(v2d->keepzoom) {
            
            zoom= ((float)winx)/dx;
            
            if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
                  if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
                  else fac= zoom/v2d->maxzoom;
                  
                  dx*= fac;
                  temp= 0.5*(cur->xmax+cur->xmin);
                  
                  cur->xmin= temp-0.5*dx;
                  cur->xmax= temp+0.5*dx;
            }
            
            zoom= ((float)winy)/dy;
            
            if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
                  if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
                  else fac= zoom/v2d->maxzoom;
                  
                  dy*= fac;
                  temp= 0.5*(cur->ymax+cur->ymin);
                  cur->ymin= temp-0.5*dy;
                  cur->ymax= temp+0.5*dy;
            }
      }
      else {
            if(dx<G.v2d->min[0]) {
                  dx= G.v2d->min[0];
                  temp= 0.5*(cur->xmax+cur->xmin);
                  cur->xmin= temp-0.5*dx;
                  cur->xmax= temp+0.5*dx;
            }
            else if(dx>G.v2d->max[0]) {
                  dx= G.v2d->max[0];
                  temp= 0.5*(cur->xmax+cur->xmin);
                  cur->xmin= temp-0.5*dx;
                  cur->xmax= temp+0.5*dx;
            }
            
            if(dy<G.v2d->min[1]) {
                  dy= G.v2d->min[1];
                  temp= 0.5*(cur->ymax+cur->ymin);
                  cur->ymin= temp-0.5*dy;
                  cur->ymax= temp+0.5*dy;
            }
            else if(dy>G.v2d->max[1]) {
                  dy= G.v2d->max[1];
                  temp= 0.5*(cur->ymax+cur->ymin);
                  cur->ymin= temp-0.5*dy;
                  cur->ymax= temp+0.5*dy;
            }
      }

      if(v2d->keepaspect) {
            short do_x=0, do_y=0;
            
            /* when a window edge changes, the aspect ratio can't be used to
               find which is the best new 'cur' rect. thats why it stores 'old' */
            if(winx!=v2d->oldwinx) do_x= 1;
            if(winy!=v2d->oldwiny) do_y= 1;
            
            dx= (cur->ymax-cur->ymin)/(cur->xmax-cur->xmin);
            dy= ((float)winy)/((float)winx);
            
            if(do_x==do_y) {  // both sizes change, ctrl+uparrow
                  if(do_x==1 && do_y==1) {
                        if( ABS(winx-v2d->oldwinx)>ABS(winy-v2d->oldwiny)) do_y= 0;
                        else do_x= 0;
                  }
                  else if( dy > 1.0) do_x= 0; else do_x= 1;
            }
            
            v2d->oldwinx= winx; 
            v2d->oldwiny= winy;
            
            if( do_x ) {
                  
                  /* portrait window: correct for x */
                  dx= cur->ymax-cur->ymin;
                  temp= (cur->xmax+cur->xmin);
                  
                  cur->xmin= temp/2.0 - 0.5*dx/dy;
                  cur->xmax= temp/2.0 + 0.5*dx/dy;
            }
            else {
                  dx= cur->xmax-cur->xmin;
                  temp= (cur->ymax+cur->ymin);
                  
                  cur->ymin= temp/2.0 - 0.5*dy*dx;
                  cur->ymax= temp/2.0 + 0.5*dy*dx;
            }
      }
      
      if(v2d->keeptot) {
            dx= cur->xmax-cur->xmin;
            dy= cur->ymax-cur->ymin;
            
            if(dx > tot->xmax-tot->xmin) {
                  if(v2d->keepzoom==0) {
                        if(cur->xmin<tot->xmin) cur->xmin= tot->xmin;
                        if(cur->xmax>tot->xmax) cur->xmax= tot->xmax;
                  }
                  else {
                        if(cur->xmax < tot->xmax) {
                              dx= tot->xmax-cur->xmax;
                              cur->xmin+= dx;
                              cur->xmax+= dx;
                        }
                        else if(cur->xmin > tot->xmin) {
                              dx= cur->xmin-tot->xmin;
                              cur->xmin-= dx;
                              cur->xmax-= dx;
                        }
                  }
            }
            else {
                  if(cur->xmin < tot->xmin) {
                        dx= tot->xmin-cur->xmin;
                        cur->xmin+= dx;
                        cur->xmax+= dx;
                  }
                  else if(cur->xmax > tot->xmax) {
                        dx= cur->xmax-tot->xmax;
                        cur->xmin-= dx;
                        cur->xmax-= dx;
                  }
            }
            
            if(dy > tot->ymax-tot->ymin) {
                  if(v2d->keepzoom==0) {
                        if(cur->ymin<tot->ymin) cur->ymin= tot->ymin;
                        if(cur->ymax>tot->ymax) cur->ymax= tot->ymax;
                  }
                  else {
                        if(cur->ymax < tot->ymax) {
                              dy= tot->ymax-cur->ymax;
                              cur->ymin+= dy;
                              cur->ymax+= dy;
                        }
                        else if(cur->ymin > tot->ymin) {
                              dy= cur->ymin-tot->ymin;
                              cur->ymin-= dy;
                              cur->ymax-= dy;
                        }
                  }
            }
            else {
                  if(cur->ymin < tot->ymin) {
                        dy= tot->ymin-cur->ymin;
                        cur->ymin+= dy;
                        cur->ymax+= dy;
                  }
                  else if(cur->ymax > tot->ymax) {
                        dy= cur->ymax-tot->ymax;
                        cur->ymin-= dy;
                        cur->ymax-= dy;
                  }
            }
      }
}


void calc_scrollrcts(View2D *v2d, int winx, int winy)
{
      v2d->mask.xmin= v2d->mask.ymin= 0;
      v2d->mask.xmax= winx;
      v2d->mask.ymax= winy;
      
      if(curarea->spacetype==SPACE_ACTION) {
            v2d->mask.xmin+= ACTWIDTH;
            v2d->hor.xmin+=ACTWIDTH;
      }
      else if(curarea->spacetype==SPACE_NLA){
            v2d->mask.xmin+= NLAWIDTH;
            v2d->hor.xmin+=NLAWIDTH;
      }
      else if(curarea->spacetype==SPACE_IPO) {
            v2d->mask.xmax-= IPOBUTX;
            
            if(v2d->mask.xmax<IPOBUTX)
                  v2d->mask.xmax= winx;
      }
      
      if(v2d->scroll) {
            if(v2d->scroll & L_SCROLL) {
                  v2d->vert= v2d->mask;
                  v2d->vert.xmax= SCROLLB;
                  v2d->mask.xmin= SCROLLB;
            }
            else if(v2d->scroll & R_SCROLL) {
                  v2d->vert= v2d->mask;
                  v2d->vert.xmin= v2d->vert.xmax-SCROLLB;
                  v2d->mask.xmax= v2d->vert.xmin;
            }
            
            if(v2d->scroll & B_SCROLL) {
                  v2d->hor= v2d->mask;
                  v2d->hor.ymax= SCROLLH;
                  v2d->mask.ymin= SCROLLH;
            }
            else if(v2d->scroll & T_SCROLL) {
                  v2d->hor= v2d->mask;
                  v2d->hor.ymin= v2d->hor.ymax-SCROLLH;
                  v2d->mask.ymax= v2d->hor.ymin;
            }
      }
}

      /* draws a line in left vertical scrollbar at the given height */
static void draw_solution_line(View2D *v2d, float h)
{
      float vec[2];
      short mval[2];

      vec[0]= v2d->cur.xmin;
      vec[1]= h;
      ipoco_to_areaco(v2d, vec, mval);
      if(mval[0]!=3200) {
            glBegin(GL_LINES);
            glVertex2f(v2d->vert.xmin, mval[1]);
            glVertex2f(v2d->vert.xmax, mval[1]);
            glEnd();
      }
}

static void draw_solution(SpaceIpo *sipo)
{
      View2D *v2d= &sipo->v2d;
      EditIpo *ei;
      int a;

      if (!(v2d->scroll & VERT_SCROLL)) return;

      ei= sipo->editipo;
      for(a=0; a<sipo->totipo; a++, ei++) {
            if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
                  cpack(ei->col);
                        
                        /* DISPBITS ipos have 'multiple' values. */
                  if(ei->disptype==IPO_DISPBITS) {
                        int b, val= ei->icu->curval;
                              
                        for (b=0; b<31; b++)
                              if (val & (1<<b))
                                    draw_solution_line(v2d, b+1);
                  } else {
                        draw_solution_line(v2d, ei->icu->curval);
                  }
            }
      }
}

void drawscroll(int disptype)
{
      rcti vert, hor;
      float fac, dfac, val, fac2, tim;
      int darker, dark, light, lighter;
      
      vert= (G.v2d->vert);
      hor= (G.v2d->hor);
      
      darker= -40;
      dark= 0;
      light= 20;
      lighter= 50;
      
      if(G.v2d->scroll & HOR_SCROLL) {
            
            BIF_ThemeColorShade(TH_SHADE1, light);
            glRecti(hor.xmin,  hor.ymin,  hor.xmax,  hor.ymax);
            
            /* slider */
            fac= (G.v2d->cur.xmin- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
            if(fac<0.0) fac= 0.0;
            horxmin= hor.xmin+fac*(hor.xmax-hor.xmin);
            
            fac= (G.v2d->cur.xmax- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
            if(fac>1.0) fac= 1.0;
            horxmax= hor.xmin+fac*(hor.xmax-hor.xmin);
            
            if(horxmin > horxmax) horxmin= horxmax;
            
            BIF_ThemeColorShade(TH_SHADE1, dark);
            glRecti(horxmin,  hor.ymin,  horxmax,  hor.ymax);

            /* decoration bright line */
            BIF_ThemeColorShade(TH_SHADE1, lighter);
            sdrawline(hor.xmin, hor.ymax, hor.xmax, hor.ymax);

            /* the numbers: convert ipogrid_startx and -dx to scroll coordinates */
            fac= (ipogrid_startx- G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
            fac= hor.xmin+fac*(hor.xmax-hor.xmin);
            
            dfac= (ipogrid_dx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
            dfac= dfac*(hor.xmax-hor.xmin);
            
            BIF_ThemeColor(TH_TEXT);
            val= ipogrid_startx;
            while(fac < hor.xmax) {
                  
                  if(curarea->spacetype==SPACE_OOPS);
                  else if(curarea->spacetype==SPACE_SEQ) {
                        fac2= val/(float)G.scene->r.frs_sec;
                        tim= floor(fac2);
                        fac2= fac2-tim;
                        scroll_prstr(fac, 3.0+(float)(hor.ymin), tim+G.scene->r.frs_sec*fac2/100.0, 'h', disptype);
                  }
                  else if(curarea->spacetype==SPACE_SOUND) {
                        SpaceSound *ssound= curarea->spacedata.first;
                        
                        if(ssound->flag & SND_DRAWFRAMES) {
                              ipomachtx= 1;
                              scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
                        }
                        else {
                              fac2= val/(float)G.scene->r.frs_sec;
                              scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
                        }
                  }
                  else {
                        scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
                  }
                  
                  fac+= dfac;
                  val+= ipogrid_dx;
            }
      }
      
      if(G.v2d->scroll & VERT_SCROLL) {
            BIF_ThemeColorShade(TH_SHADE1, light);
            glRecti(vert.xmin,  vert.ymin,  vert.xmax,  vert.ymax);
            
            /* slider */
            fac= (G.v2d->cur.ymin- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
            if(fac<0.0) fac= 0.0;
            vertymin= vert.ymin+fac*(vert.ymax-vert.ymin);
            
            fac= (G.v2d->cur.ymax- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
            if(fac>1.0) fac= 1.0;
            vertymax= vert.ymin+fac*(vert.ymax-vert.ymin);
            
            if(vertymin > vertymax) vertymin= vertymax;
            
            BIF_ThemeColorShade(TH_SHADE1, dark);
            glRecti(vert.xmin,  vertymin,  vert.xmax,  vertymax);

            /* decoration black line */
            BIF_ThemeColorShade(TH_SHADE1, darker);
            if(G.v2d->scroll & HOR_SCROLL) 
                  sdrawline(vert.xmax, vert.ymin+SCROLLH, vert.xmax, vert.ymax);
            else 
                  sdrawline(vert.xmax, vert.ymin, vert.xmax, vert.ymax);

            /* the numbers: convert ipogrid_starty and -dy to scroll coordinates */
            fac= (ipogrid_starty- G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
            fac= vert.ymin+SCROLLH+fac*(vert.ymax-vert.ymin-SCROLLH);
            
            dfac= (ipogrid_dy)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
            dfac= dfac*(vert.ymax-vert.ymin-SCROLLH);
            
            if(curarea->spacetype==SPACE_OOPS);
            else if(curarea->spacetype==SPACE_SEQ) {
                  BIF_ThemeColor(TH_TEXT);
                  val= ipogrid_starty;
                  fac+= 0.5*dfac;
                  while(fac < vert.ymax) {
                        scroll_prstr((float)(vert.xmax)-14.0, fac, val, 'v', disptype);
                        fac+= dfac;
                        val+= ipogrid_dy;
                  }
            }
            else if (curarea->spacetype==SPACE_NLA){
            }
            else if (curarea->spacetype==SPACE_ACTION){
                  /* No digits on vertical axis in action mode! */
            }
            else {
                  BIF_ThemeColor(TH_TEXT);
                  val= ipogrid_starty;
                  while(fac < vert.ymax) {
                        scroll_prstr((float)(vert.xmax)-14.0, fac, val, 'v', disptype);
                        fac+= dfac;
                        val+= ipogrid_dy;
                  }
            }
      }
}

static void draw_ipobuts(SpaceIpo *sipo)
{
      ScrArea *area= sipo->area;
      View2D *v2d= &sipo->v2d;
      uiBlock *block;
      uiBut *but;
      EditIpo *ei;
      int a, y, sel, tot;
      char naam[20];
      
      if(area->winx<IPOBUTX) return;
      
      if(sipo->butofs) {
            tot= 30+IPOBUTY*sipo->totipo;
            if(tot<area->winy) sipo->butofs= 0;
      }
      
      BIF_ThemeColor(TH_SHADE2);
      glRects(v2d->mask.xmax,  0,  area->winx,  area->winy);
      
      cpack(0x0);
      sdrawline(v2d->mask.xmax, 0, v2d->mask.xmax, area->winy);

      if(sipo->totipo==0) return;
      if(sipo->editipo==0) return;
      
      sprintf(naam, "ipowin %d", area->win);
      block= uiNewBlock(&area->uiblocks, naam, UI_EMBOSSN, UI_HELV, area->win);

      ei= sipo->editipo;
      y= area->winy-30+sipo->butofs;
      for(a=0; a<sipo->totipo; a++, ei++, y-=IPOBUTY) {
            
            but= uiDefButS(block, TOG|BIT|6, a+1, ei->name,  v2d->mask.xmax+18, y, IPOBUTX-15, IPOBUTY-1, &(ei->flag), 0, 0, 0, 0, "");
            // no hilite, its not visible, but most of all the winmatrix is not correct later on...
            uiButSetFlag(but, UI_TEXT_LEFT|UI_NO_HILITE);
            
            if(ei->icu) {
                  cpack(ei->col);
                  
                  glRects(v2d->mask.xmax+8,  y+2,  v2d->mask.xmax+15, y+IPOBUTY-2);
                  sel= ei->flag & (IPO_SELECT + IPO_EDIT);
                  
                  uiEmboss((float)(v2d->mask.xmax+8), (float)(y+2), (float)(v2d->mask.xmax+15), (float)(y+IPOBUTY-2), sel);
            }
            
            if(sipo->blocktype==ID_KE) {
                  Key *key= (Key *)sipo->from;
                  if(key==0 || key->type==KEY_NORMAL) break;
            }
      }
      uiDrawBlock(block);
}

static void calc_ipoverts(SpaceIpo *sipo)
{
      View2D *v2d= &sipo->v2d;
      EditIpo *ei;
      BezTriple *bezt;
      BPoint *bp;
      int a, b;
      
      ei= G.sipo->editipo;
      for(a=0; a<sipo->totipo; a++, ei++) {
            if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
                  if(ei->icu->bezt) {
                        bezt= ei->icu->bezt;
                        b= ei->icu->totvert;
                        while(b--) {
                              ipoco_to_areaco(v2d, bezt->vec[0], bezt->s[0]);
                              ipoco_to_areaco(v2d, bezt->vec[1], bezt->s[1]);
                              ipoco_to_areaco(v2d, bezt->vec[2], bezt->s[2]);
                              bezt++;
                        }
                  }
                  else if(ei->icu->bp) {
                        bp= ei->icu->bp;
                        b= ei->icu->totvert;
                        while(b--) {
                              ipoco_to_areaco(v2d, bp->vec, bp->s);
                              bp++;
                        }
                  }
            }
      }
}


static void draw_ipovertices(int sel)
{
      EditIpo *ei;
      BezTriple *bezt;
      float v1[2];
      int val, ok, nr, a, b;
      
      if(G.f & G_PICKSEL) return;
      
      glPointSize(3.0);
      
      ei= G.sipo->editipo;
      for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
            if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
                  
                  if(G.sipo->showkey) {
                        if(sel) BIF_ThemeColor(TH_TEXT_HI);
                         else BIF_ThemeColor(TH_TEXT);
                  } else if(ei->flag & IPO_EDIT) {
                        if(sel) BIF_ThemeColor(TH_VERTEX_SELECT); 
                        else BIF_ThemeColor(TH_VERTEX);
                  } else {
                        if(sel) BIF_ThemeColor(TH_TEXT_HI);
                         else BIF_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) */          
                  
                  bglBegin(GL_POINTS);
                  
                  bezt= ei->icu->bezt;
                  a= ei->icu->totvert;
                  while(a--) {                        
                        
                        if(ei->disptype==IPO_DISPBITS) {
                              ok= 0;
                              if(ei->flag & IPO_EDIT) {
                                    if( (bezt->f2 & 1) == sel ) ok= 1;
                              }
                              else ok= 1;
                              
                              if(ok) {
                                    val= bezt->vec[1][1];
                                    b= 0;
                                    v1[0]= bezt->vec[1][0];
                                    
                                    while(b<31) {
                                          if(val & (1<<b)) {      
                                                v1[1]= b+1;
                                                bglVertex3fv(v1);
                                          }
                                          b++;
                                    }
                              }
                        }
                        else {
                              
                              if(ei->flag & IPO_EDIT) {
                                    if(ei->icu->ipo==IPO_BEZ) {
                                          if( (bezt->f1 & 1) == sel )   
                                                bglVertex3fv(bezt->vec[0]);
                                          if( (bezt->f3 & 1) == sel )   
                                                bglVertex3fv(bezt->vec[2]);
                                    }
                                    if( (bezt->f2 & 1) == sel )   
                                          bglVertex3fv(bezt->vec[1]);
                                    
                              }
                              else {
                                    bglVertex3fv(bezt->vec[1]);
                              }
                        }
                        
                        bezt++;
                  }

                  bglEnd();
            }
      }
      
      glPointSize(1.0);
}

static void draw_ipohandles(int sel)
{
      extern unsigned int nurbcol[];
      EditIpo *ei;
      BezTriple *bezt;
      float *fp;
      unsigned int *col;
      int a, b;
      
      if(sel) col= nurbcol+4;
      else col= nurbcol;
      
      ei= G.sipo->editipo;
      for(a=0; a<G.sipo->totipo; a++, ei++) {
            if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, disptype!=IPO_DISPBITS) {
                  if(ei->icu->ipo==IPO_BEZ) {
                        bezt= ei->icu->bezt;
                        b= ei->icu->totvert;
                        while(b--) {
                              
                              if( (bezt->f2 & 1)==sel) {
                                    fp= bezt->vec[0];
                                    cpack(col[bezt->h1]);
                                    
                                    glBegin(GL_LINE_STRIP); 
                                    glVertex2fv(fp); glVertex2fv(fp+3); 
                                    glEnd();
                                    cpack(col[bezt->h2]);
                                    
                                    glBegin(GL_LINE_STRIP); 
                                    glVertex2fv(fp+3); glVertex2fv(fp+6); 
                                    glEnd();
                              }
                              else if( (bezt->f1 & 1)==sel) {
                                    fp= bezt->vec[0];
                                    cpack(col[bezt->h1]);
                                    
                                    glBegin(GL_LINE_STRIP); 
                                    glVertex2fv(fp); glVertex2fv(fp+3); 
                                    glEnd();
                              }
                              else if( (bezt->f3 & 1)==sel) {
                                    fp= bezt->vec[1];
                                    cpack(col[bezt->h2]);
                                    
                                    glBegin(GL_LINE_STRIP); 
                                    glVertex2fv(fp); glVertex2fv(fp+3); 
                                    glEnd();
                              }
                              
                              bezt++;
                        }
                  }
            }
      }
}

int pickselcode;

static void init_pickselcode(void)
{
      pickselcode= 1;
}

static void draw_ipocurves(int sel)
{
      EditIpo *ei;
      IpoCurve *icu;
      BezTriple *bezt, *prevbezt;
      float *fp, fac, data[120], v1[2], v2[2], v3[2], v4[2];
      float cycdx=0, cycdy=0, cycxofs, cycyofs;
      int a, b, resol, cycount, val, nr;
      
      
      ei= G.sipo->editipo;
      for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
            if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
                  
                  if(G.f & G_PICKSEL) {
                        glLoadName(pickselcode++);
                        val= 1;
                  }
                  else {
                        val= (ei->flag & (IPO_SELECT+IPO_EDIT))!=0;
                        val= (val==sel);
                  }
                  
                  if(val) {
                        
                        cycyofs= cycxofs= 0.0;
                        cycount= 1;
                        
                        icu= ei->icu;     
                        
                        /* curve */
                        if(G.sipo->showkey) BIF_ThemeColor(TH_TEXT); 
                        else cpack(ei->col);
                        
                        /* cyclic */
                        if(icu->extrap & IPO_CYCL) {
                              cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - icu->bezt->vec[1][0];
                              cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
                              if(cycdx>0.01) {
                                    
                                    while(icu->bezt->vec[1][0]+cycxofs > G.v2d->cur.xmin) {
                                          cycxofs-= cycdx;
                                          if(icu->extrap & IPO_DIR) cycyofs-= cycdy;
                                          cycount++;
                                    }
                                    bezt= icu->bezt+(icu->totvert-1);
                                    fac= 0.0;
                                    while(bezt->vec[1][0]+fac < G.v2d->cur.xmax) {
                                          cycount++;
                                          fac+= cycdx;
                                    }
                              }
                        }
                        
                        while(cycount--) {
                              
                              if(ei->disptype==IPO_DISPBITS) {
                                    
                                    /* lines */
                                    cpack(ei->col);
                                    bezt= icu->bezt;
                                    a= icu->totvert;
                                    
                                    while(a--) {
                                          val= bezt->vec[1][1];
                                          b= 0;
                                          
                                          while(b<31) {
                                                if(val & (1<<b)) {
                                                      v1[1]= b+1;
                                                      
                                                      glBegin(GL_LINE_STRIP);
                                                      if(icu->extrap & IPO_CYCL) ;
                                                      else if(a==icu->totvert-1) {
                                                            v1[0]= G.v2d->cur.xmin+cycxofs;
                                                            glVertex2fv(v1);
                                                      }
                                                      v1[0]= bezt->vec[1][0]+cycxofs;
                                                      glVertex2fv(v1); 
                                                      
                                                      if(a) v1[0]= (bezt+1)->vec[1][0]+cycxofs;
                                                      else if(icu->extrap & IPO_CYCL) ;
                                                      else v1[0]= G.v2d->cur.xmax+cycxofs;
                                                      
                                                      glVertex2fv(v1);
                                                      glEnd();
                                                }
                                                b++;
                                          }
                                          bezt++;
                                    }
                                    
                              }
                              else {
                                    
                                    b= icu->totvert-1;
                                    prevbezt= icu->bezt;
                                    bezt= prevbezt+1;
                                    
                                    glBegin(GL_LINE_STRIP);
                                    
                                    /* extrapolate to left? */
                                    if( (icu->extrap & IPO_CYCL)==0) {
                                          if(prevbezt->vec[1][0] > G.v2d->cur.xmin) {
                                                v1[0]= G.v2d->cur.xmin;
                                                if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
                                                else {
                                                      fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
                                                      if(fac!=0.0) fac= 1.0/fac;
                                                      v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
                                                }
                                                glVertex2fv(v1);
                                          }
                                    }
                                    
                                    if(b==0) {
                                          v1[0]= prevbezt->vec[1][0]+cycxofs;
                                          v1[1]= prevbezt->vec[1][1]+cycyofs;
                                          glVertex2fv(v1);
                                    }
                                    
                                    while(b--) {
                                          if(icu->ipo==IPO_CONST) {
                                                v1[0]= prevbezt->vec[1][0]+cycxofs;
                                                v1[1]= prevbezt->vec[1][1]+cycyofs;
                                                glVertex2fv(v1);
                                                v1[0]= bezt->vec[1][0]+cycxofs;
                                                v1[1]= prevbezt->vec[1][1]+cycyofs;
                                                glVertex2fv(v1);
                                          }
                                          else if(icu->ipo==IPO_LIN) {
                                                v1[0]= prevbezt->vec[1][0]+cycxofs;
                                                v1[1]= prevbezt->vec[1][1]+cycyofs;
                                                glVertex2fv(v1);
                                          }
                                          else {
                                                resol= 3.0*sqrt(bezt->vec[1][0] - prevbezt->vec[1][0]);
                                                
                                                if(resol<2) {
                                                      v1[0]= prevbezt->vec[1][0]+cycxofs;
                                                      v1[1]= prevbezt->vec[1][1]+cycyofs;
                                                      glVertex2fv(v1);
                                                }
                                                else {
                                                      if(resol>32) resol= 32;
                                                      
                                                      v1[0]= prevbezt->vec[1][0]+cycxofs;
                                                      v1[1]= prevbezt->vec[1][1]+cycyofs;
                                                      v2[0]= prevbezt->vec[2][0]+cycxofs;
                                                      v2[1]= prevbezt->vec[2][1]+cycyofs;
                                                      
                                                      v3[0]= bezt->vec[0][0]+cycxofs;
                                                      v3[1]= bezt->vec[0][1]+cycyofs;
                                                      v4[0]= bezt->vec[1][0]+cycxofs;
                                                      v4[1]= bezt->vec[1][1]+cycyofs;
                                                      
                                                      correct_bezpart(v1, v2, v3, v4);
                                                      
                                                      maakbez(v1[0], v2[0], v3[0], v4[0], data, resol);
                                                      maakbez(v1[1], v2[1], v3[1], v4[1], data+1, resol);
                                                      
                                                      fp= data;
                                                      while(resol--) {
                                                            glVertex2fv(fp);
                                                            fp+= 3;
                                                      }
                                                }
                                          }
                                          prevbezt= bezt;
                                          bezt++;
                                          
                                          /* last point? */
                                          if(b==0) {
                                                v1[0]= prevbezt->vec[1][0]+cycxofs;
                                                v1[1]= prevbezt->vec[1][1]+cycyofs;
                                                glVertex2fv(v1);
                                          }
                                    }
                                    
                                    /* extrapolate to right? */
                                    if( (icu->extrap & IPO_CYCL)==0) {
                                          if(prevbezt->vec[1][0] < G.v2d->cur.xmax) {
                                                v1[0]= G.v2d->cur.xmax;
                                                if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
                                                else {
                                                      fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
                                                      if(fac!=0.0) fac= 1.0/fac;
                                                      v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
                                                }
                                                glVertex2fv(v1);
                                          }
                                    }
                                    
                                    glEnd();
                                    
                              }
                              cycxofs+= cycdx;
                              if(icu->extrap & IPO_DIR) cycyofs+= cycdy;
                        }
                        
                        /* line that indicates the end of a speed curve */
                        if(G.sipo->blocktype==ID_CU && icu->adrcode==CU_SPEED) {
                              b= icu->totvert-1;
                              if(b) {
                                    glColor3ub(0, 0, 0);
                                    bezt= icu->bezt+b;
                                    glBegin(GL_LINES);
                                    glVertex2f(bezt->vec[1][0], 0.0);
                                    glVertex2f(bezt->vec[1][0], bezt->vec[1][1]);
                                    glEnd();
                              }
                        }
                  }
            }
      }
}

static void draw_cfra(SpaceIpo *sipo)
{
      View2D *v2d= &sipo->v2d;
      Object *ob;
      float vec[2];
      
      vec[0]= (G.scene->r.cfra);
      vec[0]*= G.scene->r.framelen;
      
      vec[1]= v2d->cur.ymin;
      glColor3ub(0x60, 0xc0, 0x40); // no theme, should be global color once...
      glLineWidth(2.0);
      
      glBegin(GL_LINE_STRIP);
      glVertex2fv(vec);
      vec[1]= v2d->cur.ymax;
      glVertex2fv(vec);
      glEnd();
      
      if(sipo->blocktype==ID_OB) {
            ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
            if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
                  vec[0]-= ob->sf;
                  
                  BIF_ThemeColorShade(TH_HILITE, -30);
                  
                  glBegin(GL_LINE_STRIP);
                  glVertex2fv(vec);
                  vec[1]= G.v2d->cur.ymin;
                  glVertex2fv(vec);
                  glEnd();
            }
      }
      
      glLineWidth(1.0);
}

static void draw_ipokey(SpaceIpo *sipo)
{
      IpoKey *ik;
      
      glBegin(GL_LINES);
      for (ik= sipo->ipokey.first; ik; ik= ik->next) {
            if(ik->flag & 1) glColor3ub(0xFF, 0xFF, 0x99);
            else glColor3ub(0xAA, 0xAA, 0x55);
            
            glVertex2f(ik->val, G.v2d->cur.ymin);
            glVertex2f(ik->val, G.v2d->cur.ymax);
      }
      glEnd();
}

static void draw_key(SpaceIpo *sipo, int visible)
{
      View2D *v2d= &sipo->v2d;
      Key *key;
      KeyBlock *kb, *act=NULL;
      unsigned int col;
      
      key= (Key *)sipo->from;
      if(key==0)
            return;
      
      if(key->type== KEY_RELATIVE) if(visible==0) return;
      
      kb= key->block.first;
      while(kb) {
            if(kb->type==KEY_LINEAR) setlinestyle(2);
            else if(kb->type==KEY_BSPLINE) setlinestyle(4);
            else setlinestyle(0);
            
            if(kb==key->refkey) col= 0x22FFFF;
            else col= 0xFFFF00;
            
            if( (kb->flag & SELECT)==0)   col-= 0x225500;
            else act= kb;
            
            cpack(col);
            
            glBegin(GL_LINE_STRIP);
            glVertex2f(v2d->cur.xmin, kb->pos);
            glVertex2f(v2d->cur.xmax, kb->pos);
            glEnd();
            
            kb= kb->next;
      }
      
      if(act) {
            if(act->type==KEY_LINEAR) setlinestyle(2);
            else if(act->type==KEY_BSPLINE) setlinestyle(4);
            else setlinestyle(0);
            
            if(act==key->refkey) cpack(0x22FFFF);
            else cpack(0xFFFF00);
            
            glBegin(GL_LINE_STRIP);
            glVertex2f(v2d->cur.xmin, act->pos);
            glVertex2f(v2d->cur.xmax, act->pos);
            glEnd();
      }
      
      setlinestyle(0);
}

/* ************************** buttons *********************** */


#define B_SETSPEED            3401
#define B_MUL_IPO       3402
#define B_TRANS_IPO           3403
#define B_IPO_NONE            3404

static float hspeed= 0;


static void boundbox_ipo_visible(SpaceIpo *si)
{
      EditIpo *ei;
      Key *key;
      KeyBlock *kb;
      int a, first= 1;

      ei= si->editipo;
      if(ei==0)
            return;

      for(a=0; a<si->totipo; a++, ei++) {
            
            if(ei->icu) {
                  if(ei->flag & IPO_VISIBLE) {
      
                        boundbox_ipocurve(ei->icu);
                        if(first) {
                              si->v2d.tot= ei->icu->totrct;
                              first= 0;
                        }
                        else BLI_union_rctf(&(si->v2d.tot), &(ei->icu->totrct));
                  }
            }
      }
      /* keylines? */
      if(si->blocktype==ID_KE) {
            key= (Key *)si->from;
            if(key && key->block.first) {
                  kb= key->block.first;
                  if(kb->pos < si->v2d.tot.ymin) si->v2d.tot.ymin= kb->pos;
                  kb= key->block.last;
                  if(kb->pos > si->v2d.tot.ymax) si->v2d.tot.ymax= kb->pos;
            }
      }
      si->tot= si->v2d.tot;
}


/* is used for both read and write... */
static void ipo_editvertex_buts(uiBlock *block, SpaceIpo *si, float min, float max)
{
      EditIpo *ei;
      BezTriple *bezt;
      float median[3];
      int a, b, tot, iskey=0;
      
      median[0]= median[1]= median[2]= 0.0;
      tot= 0;
      
      ei= G.sipo->editipo;
      for(a=0; a<G.sipo->totipo; a++, ei++) {
            
            if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
                  if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {

                        if(ei->icu->bezt) {
                              bezt= ei->icu->bezt;
                              b= ei->icu->totvert;
                              while(b--) {
                                    // all three selected 
                                    if(bezt->f2 & 1) {
                                          VecAddf(median, median, bezt->vec[1]);
                                          tot++;
                                    }
                                    else {
                                          if(bezt->f1 & 1) {
                                                VecAddf(median, median, bezt->vec[0]);
                                                tot++;
                                          }
                                          if(bezt->f3 & 1) {
                                                VecAddf(median, median, bezt->vec[2]);
                                                tot++;
                                          }
                                    }
                                    bezt++;
                              }
                              
                        }
                  }
            }
      }
      /* check for keys */
      if(tot==0) {
            if(G.sipo->blocktype==ID_KE) {
                  Key *key= (Key *)G.sipo->from;
                  KeyBlock *kb;
                  
                  if(key==0) return;
                  iskey= 1;
                  
                  kb= key->block.first;
                  while(kb) {
                        if(kb->flag & SELECT) {
                              median[1]+= kb->pos;
                              tot++;
                        }
                        kb= kb->next;
                  }
            }
      }
      if(tot==0) return;

      median[0] /= (float)tot;
      median[1] /= (float)tot;
      median[2] /= (float)tot;
      
      if(block) { // buttons
      
            VECCOPY(si->median, median);
            
            if(tot==1) {
                  if(iskey) 
                        uiDefButF(block, NUM, B_TRANS_IPO, "Key Y:",    10, 80, 300, 19, &(si->median[1]), min, max, 10, 0, "");
                  else {
                        uiDefButF(block, NUM, B_TRANS_IPO, "Vertex X:", 10, 100, 300, 19, &(si->median[0]), min, max, 100, 0, "");
                        uiDefButF(block, NUM, B_TRANS_IPO, "Vertex Y:", 10, 80, 300, 19, &(si->median[1]), min, max, 100, 0, "");
                  }
            }
            else {
                  if(iskey) 
                        uiDefButF(block, NUM, B_TRANS_IPO, "Median Key Y:",   10, 80, 300, 19, &(si->median[1]), min, max, 10, 0, "");
                  else {
                        uiDefButF(block, NUM, B_TRANS_IPO, "Median X:", 10, 100, 300, 19, &(si->median[0]), min, max, 100, 0, "");
                        uiDefButF(block, NUM, B_TRANS_IPO, "Median Y:", 10, 80, 300, 19, &(si->median[1]), min, max, 100, 0, "");
                  }
            }
      }
      else if(iskey) {  // apply
            VecSubf(median, si->median, median);

            if(G.sipo->blocktype==ID_KE) {
                  Key *key= (Key *)G.sipo->from;
                  KeyBlock *kb;
                  
                  if(key==0) return;
                  
                  kb= key->block.first;
                  while(kb) {
                        if(kb->flag & SELECT) {
                              kb->pos+= median[1];
                              tot++;
                        }
                        kb= kb->next;
                  }                 
                  sort_keys(key);
            }
      }
      else {
            
            VecSubf(median, si->median, median);

            ei= G.sipo->editipo;
            for(a=0; a<G.sipo->totipo; a++, ei++) {
                  
                  if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
                        if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {

                              if(ei->icu->bezt) {
                                    bezt= ei->icu->bezt;
                                    b= ei->icu->totvert;
                                    while(b--) {
                                          // all three selected
                                          if(bezt->f2 & 1) {
                                                VecAddf(bezt->vec[0], bezt->vec[0], median);
                                                VecAddf(bezt->vec[1], bezt->vec[1], median);
                                                VecAddf(bezt->vec[2], bezt->vec[2], median);
                                          }
                                          else {
                                                if(bezt->f1 & 1) {
                                                      VecAddf(bezt->vec[0], bezt->vec[0], median);
                                                }
                                                if(bezt->f3 & 1) {
                                                      VecAddf(bezt->vec[2], bezt->vec[2], median);
                                                }
                                          }
                                          bezt++;
                                    }
                                    
                              }
                        }
                  }
            }
      }
}

void do_ipobuts(unsigned short event)
{

      switch(event) {
      case B_SETSPEED:
            set_speed_editipo(hspeed);
            break;
      case B_MUL_IPO:
            scale_editipo();
            allqueue(REDRAWIPO, 0);
            break;
      case B_TRANS_IPO:
            ipo_editvertex_buts(NULL, G.sipo, 0.0, 0.0);
            editipo_changed(G.sipo, 1);
            allqueue(REDRAWIPO, 0);
            break;
      }
}


static void ipo_panel_properties(short cntrl)   // IPO_HANDLER_PROPERTIES
{
      extern int totipo_vis;  // editipo.c
      uiBlock *block;
      
      block= uiNewBlock(&curarea->uiblocks, "ipo_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
      uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
      uiSetPanelHandler(IPO_HANDLER_PROPERTIES);  // for close and esc
      if(uiNewPanel(curarea, block, "Transform Properties", "Ipo", 10, 230, 318, 204)==0) return;


      boundbox_ipo_visible(G.sipo); // should not be needed... transform/draw calls should update
      
      /* note ranges for buttons below are idiot... we need 2 ranges, one for sliding scale, one for real clip */
      if(G.sipo->ipo && G.sipo->ipo->curve.first && totipo_vis) {
            extern int totipo_vertsel;    // editipo.c
            uiDefBut(block, LABEL, 0, "Visible curves",           10, 200, 150, 19, NULL, 1.0, 0.0, 0, 0, "");
            
            uiDefButF(block, NUM, B_MUL_IPO, "Xmin:",       10, 180, 150, 19, &G.sipo->tot.xmin, G.sipo->tot.xmin-1000.0, 18000.0, 100, 0, "");
            uiDefButF(block, NUM, B_MUL_IPO, "Xmax:",       160, 180, 150, 19, &G.sipo->tot.xmax, G.sipo->tot.ymin-1000.0, 18000.0, 100, 0, "");
            
            uiDefButF(block, NUM, B_MUL_IPO, "Ymin:",       10, 160, 150, 19, &G.sipo->tot.ymin, G.sipo->tot.ymin-1000.0, 5000.0, 100, 0, "");
            uiDefButF(block, NUM, B_MUL_IPO, "Ymax:",       160, 160, 150, 19, &G.sipo->tot.ymax, G.sipo->tot.ymin-1000.0, 5000.0, 100, 0, "");

            /* SPEED BUTTON */
            if(totipo_vertsel) {
                  uiDefButF(block, NUM, B_IPO_NONE, "Speed:",                 10,130,150,19, &hspeed, 0.0, 180.0, 1, 0, "");
                  uiDefBut(block, BUT, B_SETSPEED,"SET",                160,130,50,19, 0, 0, 0, 0, 0, "");
            }
      }

      /* this one also does keypositions */
      if(G.sipo->ipo) ipo_editvertex_buts(block, G.sipo, -10000, 18000);
}

static void ipo_blockhandlers(ScrArea *sa)
{
      SpaceIpo *sipo= sa->spacedata.first;
      short a;

      /* warning; blocks need to be freed each time, handlers dont remove (for ipo moved to drawipospace) */

      for(a=0; a<SPACE_MAXHANDLER; a+=2) {
            switch(sipo->blockhandler[a]) {

            case IPO_HANDLER_PROPERTIES:
                  ipo_panel_properties(sipo->blockhandler[a+1]);
                  break;
            
            }
            /* clear action value for event */
            sipo->blockhandler[a+1]= 0;
      }
      uiDrawBlocksPanels(sa, 0);

}


void drawipospace(ScrArea *sa, void *spacedata)
{
      SpaceIpo *sipo= sa->spacedata.first;
      View2D *v2d= &sipo->v2d;
      EditIpo *ei;
      float col[3];
      int ofsx, ofsy, a, disptype;

      bwin_clear_viewmat(sa->win);  /* clear buttons view */
      glLoadIdentity();
      
      uiFreeBlocksWin(&sa->uiblocks, sa->win);  /* for panel handler to work */
      
      v2d->hor.xmax+=IPOBUTX;
      calc_scrollrcts(G.v2d, sa->winx, sa->winy);

      BIF_GetThemeColor3fv(TH_BACK, col);
      glClearColor(col[0], col[1], col[2], 0.0); 

      if (sipo->pin)
            glClearColor(col[0]+0.05,col[1],col[2], 0.0);   // litepink
      else
            glClearColor(col[0],col[1],col[2], 0.0);

      glClear(GL_COLOR_BUFFER_BIT);
      
      if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
            if(v2d->scroll) { 
                  ofsx= sa->winrct.xmin;  // ivm mywin 
                  ofsy= sa->winrct.ymin;
                  glViewport(ofsx+v2d->mask.xmin,  ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1); 
                  glScissor(ofsx+v2d->mask.xmin,  ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1);
            } 
      }

      test_editipo();   /* test if current editipo is correct, make_editipo sets v2d->cur */

      myortho2(v2d->cur.xmin, v2d->cur.xmax, v2d->cur.ymin, v2d->cur.ymax);
      
 
      if(sipo->editipo) {
            
            /* correct scale for degrees? */
            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;
                  }
            }
            
            calc_ipogrid();   
            draw_ipogrid();
            
            calc_ipoverts(sipo);
            
            draw_cfra(sipo);
            
            /* ipokeys */
            if(sipo->showkey) {
                  if(sipo->ipokey.first==0) make_ipokey();
                  draw_ipokey(sipo);
            }
            
            if(sipo->blocktype==ID_KE) {
                  ei= sipo->editipo;
                  draw_key(sipo, ei->flag & IPO_VISIBLE);
            }

            /* draw deselect */
            draw_ipocurves(0);
            draw_ipohandles(0);
            draw_ipovertices(0);
            
            /* draw select */
            draw_ipocurves(1);
            draw_ipohandles(1);
            draw_ipovertices(1);
            
            /* restore viewport */
            mywinset(sa->win);
            
            if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
                  
                  /* ortho at pixel level sa */
                  myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
                  
                  if(v2d->scroll) {
                        drawscroll(disptype);
                        draw_solution(sipo);
                  }
                  
                  draw_ipobuts(sipo);
            }
      }
      else {
            calc_ipogrid();
            draw_ipogrid();
      }
      
      myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
      draw_area_emboss(sa);

      /* it is important to end a view in a transform compatible with buttons */
      bwin_scalematrix(sa->win, sipo->blockscale, sipo->blockscale, sipo->blockscale);
      /* only draw panels when relevant */
      if(sipo->editipo) ipo_blockhandlers(sa);

      sa->win_swap= WIN_BACK_OK;
}

void scroll_ipobuts()
{
      int tot;
      short yo, mval[2];
      
      tot= 30+IPOBUTY*G.sipo->totipo;
      if(tot<curarea->winy) return;
      
      getmouseco_areawin(mval);
      yo= mval[1];
      
      while(get_mbut()&M_MOUSE) {
            getmouseco_areawin(mval);
            if(mval[1]!=yo) {
                  G.sipo->butofs+= (mval[1]-yo);
                  if(G.sipo->butofs<0) G.sipo->butofs= 0;
                  else if(G.sipo->butofs+curarea->winy>tot) G.sipo->butofs= tot-curarea->winy;
                  
                  scrarea_do_windraw(curarea);
                  screen_swapbuffers();
                  
                  yo= mval[1];
            }
            else BIF_wait_for_statechange();
      }
}

/* total mess function, especially with mousewheel, needs cleanup badly (ton) */
int view2dzoom(unsigned short event)
{
      float fac, dx, dy, wtemp;
      short mval[2], mvalo[2];
      
      areawinset(curarea->win);     /* from buttons */
      curarea->head_swap= 0;
      getmouseco_areawin(mvalo);
      
      while( (get_mbut()&(L_MOUSE|M_MOUSE)) || (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) {
      
            /* regular mousewheel:   zoom regular
            * alt-shift mousewheel: zoom y only
            * alt-ctrl mousewheel:  zoom x only
            */
            if (event==WHEELUPMOUSE) {
                  if(U.uiflag & USER_WHEELZOOMDIR)
                        wtemp = -0.0375;
                  else
                        wtemp = 0.03;
                  if(curarea->spacetype!=SPACE_BUTS) wtemp*= 3;
                  
                  dx= (float)(wtemp*(G.v2d->cur.xmax-G.v2d->cur.xmin));
                  dy= (float)(wtemp*(G.v2d->cur.ymax-G.v2d->cur.ymin));
                  
                  switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
                  case 0:
                        break;
                  case (LR_SHIFTKEY|LR_ALTKEY):
                        dx = 0;
                        break;
                  case (LR_CTRLKEY|LR_ALTKEY):
                        dy = 0;
                        break;
                  default:
                        if(curarea->spacetype==SPACE_BUTS); // exception
                        else return 0;
                        break;
                  }
            }
            else if (event==WHEELDOWNMOUSE) {
                  if(U.uiflag & USER_WHEELZOOMDIR)
                        wtemp = 0.03;
                  else
                        wtemp = -0.0375;
                  if(curarea->spacetype!=SPACE_BUTS) wtemp*= 3;
                  
                  dx= (float)(wtemp*(G.v2d->cur.xmax-G.v2d->cur.xmin));
                  dy= (float)(wtemp*(G.v2d->cur.ymax-G.v2d->cur.ymin));
                  
                  switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
                        case 0:
                        break;
                  case (LR_SHIFTKEY|LR_ALTKEY):
                        dx = 0;
                        break;
                  case (LR_CTRLKEY|LR_ALTKEY):
                        dy = 0;
                        break;
                  default:
                        if(curarea->spacetype==SPACE_BUTS);
                        else return 0;
                        break;
                  }
            }
            else {
                  getmouseco_areawin(mval);
                  if(U.viewzoom==USER_ZOOM_SCALE) {
                        float dist;
                        
                        dist = (G.v2d->mask.xmax - G.v2d->mask.xmin)/2.0;
                        dx= 1.0-(fabs(mvalo[0]-dist)+2.0)/(fabs(mval[0]-dist)+2.0);
                        dx*= 0.5*(G.v2d->cur.xmax-G.v2d->cur.xmin);

                        dist = (G.v2d->mask.ymax - G.v2d->mask.ymin)/2.0;
                        dy= 1.0-(fabs(mvalo[1]-dist)+2.0)/(fabs(mval[1]-dist)+2.0);
                        dy*= 0.5*(G.v2d->cur.ymax-G.v2d->cur.ymin);
      
                  }
                  else {
                        fac= 0.01*(mval[0]-mvalo[0]);
                        dx= fac*(G.v2d->cur.xmax-G.v2d->cur.xmin);
                        fac= 0.01*(mval[1]-mvalo[1]);
                        dy= fac*(G.v2d->cur.ymax-G.v2d->cur.ymin);
                        
                        if(U.viewzoom==USER_ZOOM_CONT) {
                              dx/= 20.0;
                              dy/= 20.0;
                        }
                  }
            }
            if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
                  
                  if(U.viewzoom!=USER_ZOOM_CONT) {
                        mvalo[0]= mval[0];
                        mvalo[1]= mval[1];
                  }
                  
                  G.v2d->cur.xmin+= dx;
                  G.v2d->cur.xmax-= dx;
                  if(curarea->spacetype!=SPACE_SEQ && curarea->spacetype!=SPACE_SOUND && curarea->spacetype!=SPACE_NLA && curarea->spacetype!=SPACE_ACTION) {
                        G.v2d->cur.ymin+= dy;
                        G.v2d->cur.ymax-= dy;
                  }
            
                  test_view2d(G.v2d, curarea->winx, curarea->winy);     /* cur min max rects */
                  scrarea_do_windraw(curarea);
                  screen_swapbuffers();
            }
            else BIF_wait_for_statechange();
            /* return if we were using the mousewheel
            */
            if ( (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) return 1;
      }
      return 1;
}

void center_currframe(void)
{
      /* place the current frame in the
       * center of the 2D window.
       */
      float width;
  
      areawinset(curarea->win);
      curarea->head_swap= 0;

      width = G.v2d->cur.xmax - G.v2d->cur.xmin;
      G.v2d->cur.xmin = CFRA - 0.5*(width);
      G.v2d->cur.xmax = CFRA + 0.5*(width);

      test_view2d(G.v2d, curarea->winx, curarea->winy);
      scrarea_do_windraw(curarea);
      screen_swapbuffers();
      curarea->head_swap= 0;
}

/* total mess function, especially with mousewheel, needs cleanup badly (ton) */
int view2dmove(unsigned short event)
{
      /* return 1 when something was done */
      float facx=0.0, facy=0.0, dx, dy, left=1.0, right=1.0;
      short mval[2], mvalo[2], leftret=1, mousebut;
      
      /* init */
      scrarea_do_windraw(curarea);
      curarea->head_swap= 0;

      /* try to do some zooming if the
       * middlemouse and ctrl are pressed
       * or if the mousewheel is being used.
       * Return if zooming was done.
       */
      
      /* check for left mouse / right mouse button select */
      if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
            else mousebut = L_MOUSE;
      
      if ( (G.qual & LR_CTRLKEY) || (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) {
            /* patch for oops & buttonswin, standard scroll no zoom */
            if(curarea->spacetype==SPACE_OOPS) {
                  SpaceOops *soops= curarea->spacedata.first;
                  if(soops->type==SO_OUTLINER);
                  else if (view2dzoom(event)) {
                        curarea->head_swap= 0;
                        return 0;
                  }
            }
            else if(curarea->spacetype==SPACE_BUTS && (G.qual & LR_CTRLKEY)==0);
            else if (view2dzoom(event)) {
                  curarea->head_swap= 0;
                  return 0;
            }
      }
      
      /* test where mouse is */
      getmouseco_areawin(mvalo);
      
      if ELEM6(curarea->spacetype, SPACE_IPO, SPACE_SEQ, SPACE_OOPS, SPACE_SOUND, SPACE_ACTION, SPACE_NLA) 
            {
                  if( BLI_in_rcti(&G.v2d->mask, (int)mvalo[0], (int)mvalo[1]) ) {
                        facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
                        facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
                  }
                  else if(IN_2D_VERT_SCROLL((int)mvalo)) {
                        facy= -(G.v2d->tot.ymax-G.v2d->tot.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
                        if(get_mbut() & mousebut) {
                              /* which part of scrollbar should move? */
                              if(mvalo[1]< (vertymin+vertymax)/2 ) right= 0.0;
                              else left= 0.0;
                              leftret= 0;
                        }
                  }
                  else if(IN_2D_HORIZ_SCROLL((int)mvalo)) {
                        facx= -(G.v2d->tot.xmax-G.v2d->tot.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
                        if(get_mbut() & mousebut) {
                              /* which part of scrollbar should move? */
                              if(mvalo[0]< (horxmin+horxmax)/2 ) right= 0.0;
                              else left= 0.0;
                              leftret= 0;
                        }
                  }
            }
            else {
                  facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(curarea->winx);
                  facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(curarea->winy);         
            }
            
            /* no x move in outliner */
            if(curarea->spacetype==SPACE_OOPS && G.v2d->scroll) facx= 0.0;
            
            /* no y move in audio */
            if(curarea->spacetype==SPACE_SOUND) facy= 0.0;
            
            if(get_mbut() & mousebut && leftret) return 0;
            if(facx==0.0 && facy==0.0) return 1;
            
    while( (get_mbut()&(L_MOUSE|M_MOUSE)) || 
           (event==WHEELUPMOUSE) ||
           (event==WHEELDOWNMOUSE) ) {

      /* If the mousewheel is used with shift key
       * the scroll up and down. If the mousewheel
       * is used with the ctrl key then scroll left
       * and right.
       */
            if (event==WHEELUPMOUSE || event==WHEELDOWNMOUSE) {
                  if(event==WHEELDOWNMOUSE) {   
                        facx= -facx; facy= -facy;
                  }
                  switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
                  case (LR_SHIFTKEY):
                        dx = 0.0;
                        dy= facy*20.0;
                        break;
                  case (LR_CTRLKEY):
                        dx= facx*20.0;
                        dy = 0.0;
                        break;
                  default:
                        if(curarea->spacetype==SPACE_OOPS) {
                              dx= 0.0;
                              dy= facy*20;
                        }
                        else if(curarea->spacetype==SPACE_BUTS) {
                              if(G.buts->align==BUT_HORIZONTAL) {
                                    dx= facx*30; dy= 0.0;
                              } else {
                                    dx= 0.0; dy= facy*30;
                              }
                        }
                        else return 0;
                        break;
                  }
                  mval[0]= mvalo[0]+1; // force redraw below
                  mval[1]= mvalo[1]+1;
            }
            else {
                  getmouseco_areawin(mval);
                  dx= facx*(mvalo[0]-mval[0]);
                  dy= facy*(mvalo[1]-mval[1]);
            }

            if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {

                  G.v2d->cur.xmin+= left*dx;
                  G.v2d->cur.xmax+= right*dx;
                  G.v2d->cur.ymin+= left*dy;
                  G.v2d->cur.ymax+= right*dy;
                        
                  test_view2d(G.v2d, curarea->winx, curarea->winy);
                        
                  scrarea_do_windraw(curarea);
                  screen_swapbuffers();
                        
                  mvalo[0]= mval[0];
                  mvalo[1]= mval[1];
                        
            }
            else BIF_wait_for_statechange();
                  /* return if we were using the mousewheel
                  */
            if ( (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) return 1;
      }

    curarea->head_swap= 0;
    return 1;
}

void view2dborder(void)
{
      
}

EditIpo *select_proj_ipo(rctf *rectf, int event)
{
      EditIpo *ei;
      float xmin, ymin, xmax, ymax;
      /* this was IGLuint, but it's a useless typedef... */
      GLuint buffer[MAXPICKBUF];
      int a, b;
      int code, hits;
      short mval[2];
      
      G.f |= G_PICKSEL;
      
      if(rectf==0) {
            getmouseco_areawin(mval);
            
            mval[0]-= 6; mval[1]-= 6;
            areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
            mval[0]+= 12; mval[1]+= 12;
            areamouseco_to_ipoco(G.v2d, mval, &xmax, &ymax);
            
            myortho2(xmin, xmax, ymin, ymax);
      }
      else myortho2(rectf->xmin, rectf->xmax, rectf->ymin, rectf->ymax);
      
      glSelectBuffer( MAXPICKBUF, buffer); 
      glRenderMode(GL_SELECT);
      glInitNames();    /* whatfor? but otherwise it does not work */
      glPushName(-1);
      
      /* get rid of buttons view */
      glPushMatrix();
      glLoadIdentity();
      
      init_pickselcode();     /* drawipo.c */
      draw_ipocurves(0);      
      
      /* restore buttons view */
      glPopMatrix();

      G.f -= G_PICKSEL;
      
      hits= glRenderMode(GL_RENDER);
      glPopName();      /* see above (pushname) */
      if(hits<1) return 0;
      
      code= 1;
      ei= G.sipo->editipo;
      for(a=0; a<G.sipo->totipo; a++, ei++) {
            if ISPOIN(ei, icu, flag & IPO_VISIBLE) {
                  if(rectf) {
                        for(b=0; b<hits; b++) {
                              /* conversion for glSelect */
                              if(code == buffer[ (4 * b) + 3] ) {
                                    if(event==LEFTMOUSE) ei->flag |= IPO_SELECT;
                                    else ei->flag &= ~IPO_SELECT;
                                    ei->icu->flag= ei->flag;
                              }
                        }
                  }
                  else {
                        /* also conversion for glSelect */
                        if(code==buffer[ 3 ]) return ei;
                  }
                  code++;
            }
      }
      return 0;
}


Generated by  Doxygen 1.6.0   Back to index