svn merge -r 16454:16593 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / src / header_ipo.c
1 /**
2  * header_ipo.c oct-2003
3  *
4  * Functions to draw the "Ipo Curve Editor" window header
5  * and handle user events sent to it.
6  * 
7  * $Id$
8  *
9  * ***** BEGIN GPL LICENSE BLOCK *****
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
24  *
25  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL LICENSE BLOCK *****
33  */
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdio.h>
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #include "DNA_action_types.h"
44 #include "DNA_camera_types.h"
45 #include "DNA_curve_types.h"
46 #include "DNA_constraint_types.h"
47 #include "DNA_ID.h"
48 #include "DNA_ipo_types.h"
49 #include "DNA_key_types.h"
50 #include "DNA_lamp_types.h"
51 #include "DNA_material_types.h"
52 #include "DNA_modifier_types.h"
53 #include "DNA_object_types.h"
54 #include "DNA_object_fluidsim.h"
55 #include "DNA_particle_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_screen_types.h"
58 #include "DNA_texture_types.h"
59 #include "DNA_space_types.h"
60 #include "DNA_sequence_types.h"
61 #include "DNA_sound_types.h"
62 #include "DNA_world_types.h"
63
64 #include "BKE_action.h"
65 #include "BKE_constraint.h"
66 #include "BKE_depsgraph.h"
67 #include "BKE_global.h"
68 #include "BKE_ipo.h"
69 #include "BKE_key.h"
70 #include "BKE_main.h"
71 #include "BKE_material.h"
72 #include "BKE_modifier.h"
73 #include "BKE_particle.h"
74 #include "BKE_texture.h"
75 #include "BKE_utildefines.h"
76
77 #include "BLI_blenlib.h"
78
79 #include "BSE_drawipo.h"
80 #include "BSE_editipo_types.h"
81 #include "BSE_edit.h"
82 #include "BSE_editipo.h"
83 #include "BSE_headerbuttons.h"
84 #include "BSE_time.h"
85
86 #include "BIF_editaction.h"
87 #include "BIF_editconstraint.h"
88 #include "BIF_interface.h"
89 #include "BIF_mainqueue.h"
90 #include "BIF_resources.h"
91 #include "BIF_screen.h"
92 #include "BIF_space.h"
93 #include "BIF_toolbox.h"
94
95 #include "nla.h"
96
97 #include "blendef.h"
98 #include "mydevice.h"
99
100 extern int totipo_edit, totipo_sel;
101
102 /* headerbutton call, assuming full context is set */
103 /* it aligns with editipo.c, verify_ipo */
104 void spaceipo_assign_ipo(SpaceIpo *si, Ipo *ipo)
105 {
106         if(si->from==NULL || si->from->lib) return;
107         
108         if(ipo) ipo->id.us++;
109
110         /* first check action ipos */
111         if(si->actname && si->actname[0]) {
112                 Object *ob= (Object *)si->from;
113                 bActionChannel *achan;
114                 
115                 if(ob->action) {
116                         achan= verify_action_channel(ob->action, si->actname);
117                 
118                         if(achan) {
119                                 /* constraint exception */
120                                 if(si->blocktype==ID_CO) {
121                                         bConstraintChannel *conchan= get_constraint_channel(&achan->constraintChannels, si->constname);
122                                         if(conchan) {
123                                                 if(conchan->ipo)
124                                                         conchan->ipo->id.us--;
125                                                 conchan->ipo= ipo;
126                                         }
127                                 }
128                                 else {
129                                         if(achan->ipo)
130                                                 achan->ipo->id.us--;
131                                         achan->ipo= ipo;
132                                 }
133                         }
134                 }
135         }
136         else {
137                 switch(GS(si->from->name)) {
138                         case ID_OB:
139                         {
140                                 Object *ob= (Object *)si->from;
141                                 /* constraint exception */
142                                 if(si->blocktype==ID_CO) {
143                                         /* check the local constraint ipo */
144                                         if(si->bonename && si->bonename[0] && ob->pose) {
145                                                 bPoseChannel *pchan= get_pose_channel(ob->pose, si->bonename);
146                                                 bConstraint *con;
147
148                                                 for(con= pchan->constraints.first; con; con= con->next)
149                                                         if(strcmp(con->name, si->constname)==0)
150                                                                 break;
151                                                 if(con) {
152                                                         if(con->ipo)
153                                                                 con->ipo->id.us--;
154                                                         con->ipo= ipo;
155                                                 }
156                                         }
157                                         else {
158                                                 bConstraintChannel *conchan= get_constraint_channel(&ob->constraintChannels, si->constname);
159                                                 if(conchan) {
160                                                         if(conchan->ipo)
161                                                                 conchan->ipo->id.us--;
162                                                         conchan->ipo= ipo;
163                                                 }
164                                         }
165                                 }
166                                 else if(si->blocktype==ID_FLUIDSIM) { // NT
167                                         FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
168                                         if( fluidmd && fluidmd->fss && 
169                                                 (fluidmd->fss->ipo) ) {
170                                                 // decrement users counter
171                                                 fluidmd->fss->ipo->id.us--; 
172                                         }
173                                         fluidmd->fss->ipo = ipo;
174                                 } 
175                                 else if(si->blocktype==ID_PA) {
176                                         ParticleSystem *psys=psys_get_current(ob);
177                                         if(psys){
178                                                 if(psys->part->ipo){
179                                                         psys->part->ipo->id.us--;
180                                                 }
181                                                 psys->part->ipo = ipo;
182                                         }
183                                 }
184                                 else if(si->blocktype==ID_OB) {
185                                         if(ob->ipo)
186                                                 ob->ipo->id.us--;
187                                         ob->ipo= ipo;
188                                 }
189                         }
190                                 break;
191                         case ID_MA:
192                         {
193                                 Material *ma= (Material *)si->from;
194                                 
195                                 if(ma->ipo)
196                                         ma->ipo->id.us--;
197                                 ma->ipo= ipo;
198                         }
199                                 break;
200                         case ID_TE:
201                         {
202                                 Tex *tex= (Tex *)si->from;
203                                 
204                                 if(tex->ipo)
205                                         tex->ipo->id.us--;
206                                 tex->ipo= ipo;
207                         }
208                                 break;
209                         case ID_SEQ:
210                         {
211                                 Sequence *seq= (Sequence *)si->from;    /* note, sequence is mimicing Id */
212                                 
213                                 if(seq->ipo)
214                                         seq->ipo->id.us--;
215                                 seq->ipo= ipo;
216                         }
217                                 break;
218                         case ID_CU:
219                         {
220                                 Curve *cu= (Curve *)si->from;
221                                 
222                                 if(cu->ipo)
223                                         cu->ipo->id.us--;
224                                 cu->ipo= ipo;
225                         }
226                                 break;
227                         case ID_KE:
228                         {
229                                 Key *key= (Key *)si->from;
230                                 
231                                 if(key->ipo)
232                                         key->ipo->id.us--;
233                                 key->ipo= ipo;
234                         }
235                                 break;
236                         case ID_WO:
237                         {
238                                 World *wo= (World *)si->from;
239                                 
240                                 if(wo->ipo)
241                                         wo->ipo->id.us--;
242                                 wo->ipo= ipo;
243                         }
244                                 break;
245                         case ID_LA:
246                         {
247                                 Lamp *la= (Lamp *)si->from;
248                                 
249                                 if(la->ipo)
250                                         la->ipo->id.us--;
251                                 la->ipo= ipo;
252                         }
253                                 break;
254                         case ID_CA:
255                         {
256                                 Camera *ca= (Camera *)si->from;
257                                 
258                                 if(ca->ipo)
259                                         ca->ipo->id.us--;
260                                 ca->ipo= ipo;
261                         }
262                                 break;
263                         case ID_SO:
264                         {
265                                 bSound *snd= (bSound *)si->from;
266                                 
267                                 if(snd->ipo)
268                                         snd->ipo->id.us--;
269                                 snd->ipo= ipo;
270                         }
271                 }
272         }
273         
274         allqueue(REDRAWVIEW3D, 0);
275         allqueue(REDRAWIPO, 0);
276         allqueue(REDRAWACTION, 0);
277         allqueue(REDRAWNLA, 0);
278         allqueue(REDRAWBUTSALL, 0);
279         
280 }
281
282
283 static void do_ipo_editmenu_transformmenu(void *arg, int event)
284 {
285         switch(event)
286         {
287         case 0: /* grab/move */
288                 transform_ipo('g');
289                 break;
290         case 1: /* rotate */
291                 transform_ipo('r');
292                 break;
293         case 2: /* scale */
294                 transform_ipo('s');
295                 break;
296         }
297 }
298
299 static uiBlock *ipo_editmenu_transformmenu(void *arg_unused)
300 {
301         uiBlock *block;
302         short yco= 0, menuwidth=120;
303
304         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_transformmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
305         uiBlockSetButmFunc(block, do_ipo_editmenu_transformmenu, NULL);
306
307         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
308         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
309         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale|S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
310
311         uiBlockSetDirection(block, UI_RIGHT);
312         uiTextBoundsBlock(block, 60);
313
314         return block;
315 }
316
317 static void do_ipo_editmenu_snapmenu(void *arg, int event)
318 {
319         switch(event) {
320         case 1: /* Horizontal */
321         case 2: /* To Next */
322         case 3: /* To Frame */
323         case 4: /* To Current Frame */
324                 ipo_snap(event);
325             break;
326         }
327         allqueue(REDRAWVIEW3D, 0);
328 }
329
330 static uiBlock *ipo_editmenu_snapmenu(void *arg_unused)
331 {
332         uiBlock *block;
333         short yco = 20, menuwidth = 120;
334
335         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_snapmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
336         uiBlockSetButmFunc(block, do_ipo_editmenu_snapmenu, NULL);
337         
338         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Horizontal|Shift S, 1",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
339         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Next|Shift S, 2",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
340         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Frame|Shift S, 3",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
341         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Current Frame|Shift S, 4",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");   
342         
343         uiBlockSetDirection(block, UI_RIGHT);
344         uiTextBoundsBlock(block, 60);
345         return block;
346 }
347
348 static void do_ipo_editmenu_mirrormenu(void *arg, int event)
349 {
350         switch(event) {
351                 case 1: /* mirror over current frame */
352                 case 2: /* mirror over frame 0 */
353                 case 3: /* mirror over horizontal axis */
354                         ipo_mirror(event);
355                         break;
356         }
357         allqueue(REDRAWVIEW3D, 0);
358 }
359
360 static uiBlock *ipo_editmenu_mirrormenu(void *arg_unused)
361 {
362         uiBlock *block;
363         short yco = 20, menuwidth = 120;
364
365         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_mirrormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
366         uiBlockSetButmFunc(block, do_ipo_editmenu_mirrormenu, NULL);
367         
368         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Over Current Frame|Shift M, 1",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
369         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Over Vertical Axis|Shift M, 2",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
370         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Over Horizontal Axis|Shift M, 3",                        0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");   
371         
372         uiBlockSetDirection(block, UI_RIGHT);
373         uiTextBoundsBlock(block, 60);
374         return block;
375
376
377 static void do_ipo_editmenu_joinmenu(void *arg, int event)
378 {
379         switch(event) {
380         case 1: /* All Selected */
381         case 2: /* Selected Doubles */
382                 join_ipo(event);
383             break;
384         }
385         allqueue(REDRAWVIEW3D, 0);
386 }
387
388 static uiBlock *ipo_editmenu_joinmenu(void *arg_unused)
389 {
390         uiBlock *block;
391         short yco = 20, menuwidth = 120;
392
393         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_joinmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
394         uiBlockSetButmFunc(block, do_ipo_editmenu_joinmenu, NULL);
395         
396         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "All Selected|Ctrl J, 1",                 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
397         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Selected Doubles|Ctrl J, 2",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
398
399         uiBlockSetDirection(block, UI_RIGHT);
400         uiTextBoundsBlock(block, 60);
401         return block;
402 }
403
404 static void do_ipo_editmenu_keymenu(void *arg, int event)
405 {
406         Key *key;
407         KeyBlock *kb;
408         Object *ob= OBACT;
409
410         if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) {
411                 key= ob_get_key((Object *)G.sipo->from);
412                 if(key==NULL) return;
413
414                 kb= BLI_findlink(&key->block, ob->shapenr-1);
415                 kb->type= 0;
416                 switch(event){
417                         case 0:
418                                 kb->type= KEY_LINEAR;
419                                 break;
420                         case 1:
421                                 kb->type= KEY_CARDINAL;
422                                 break;
423                         case 2:
424                                 kb->type= KEY_BSPLINE;
425                                 break;
426                 }
427         }
428 }
429
430 static uiBlock *ipo_editmenu_keymenu(void *arg_unused)
431 {
432         uiBlock *block;
433         short yco= 0, menuwidth=120;
434
435         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_keymenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
436         uiBlockSetButmFunc(block, do_ipo_editmenu_keymenu, NULL);
437
438         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linear|T, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
439         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cardinal|T, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
440         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "BSpline|T, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
441
442         uiBlockSetDirection(block, UI_RIGHT);
443         uiTextBoundsBlock(block, 60);
444
445         return block;
446
447 }
448
449 static void do_ipo_editmenu_handlemenu(void *arg, int event)
450 {
451         switch(event){
452         case 0:
453                 sethandles_ipo(HD_AUTO);
454                 break;
455         case 1:
456         case 2:
457                 sethandles_ipo(HD_ALIGN);
458                 break;
459         case 3:
460                 sethandles_ipo(HD_VECT);
461                 break;
462         case 4:
463                 sethandles_ipo(HD_AUTO_ANIM);
464                 break;
465         }
466 }
467
468 static uiBlock *ipo_editmenu_handlemenu(void *arg_unused)
469 {
470         uiBlock *block;
471         short yco= 0, menuwidth=120;
472
473         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_handlemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
474         uiBlockSetButmFunc(block, do_ipo_editmenu_handlemenu, NULL);
475
476         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
477         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
478         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Aligned|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
479         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Free|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
480         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector|V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
481
482         uiBlockSetDirection(block, UI_RIGHT);
483         uiTextBoundsBlock(block, 60);
484
485         return block;
486 }
487
488 static void do_ipo_editmenu_intpolmenu(void *arg, int event)
489 {
490         EditIpo *ei;
491         int a;
492
493         get_status_editipo();
494
495         ei = G.sipo->editipo;
496
497         switch(event)
498         {
499         case 0:
500                 for(a=0; a<G.sipo->totipo; a++, ei++) {
501                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
502                                 ei->icu->ipo= IPO_CONST;
503                         }
504                 }
505                 break;
506         case 1:
507                 for(a=0; a<G.sipo->totipo; a++, ei++) {
508                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
509                                 ei->icu->ipo= IPO_LIN;
510                         }
511                 }
512                 break;
513         case 2:
514                 for(a=0; a<G.sipo->totipo; a++, ei++) {
515                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
516                                 ei->icu->ipo= IPO_BEZ;
517                         }
518                 }
519                 break;
520         }
521
522         scrarea_queue_winredraw(curarea);
523 }
524
525 static uiBlock *ipo_editmenu_intpolmenu(void *arg_unused)
526 {
527         uiBlock *block;
528         short yco= 0, menuwidth=120;
529
530         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_intpolmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
531         uiBlockSetButmFunc(block, do_ipo_editmenu_intpolmenu, NULL);
532
533         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Constant|T, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
534         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linear|T, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
535         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bezier|T, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
536
537         uiBlockSetDirection(block, UI_RIGHT);
538         uiTextBoundsBlock(block, 60);
539
540         return block;
541 }
542
543 static void do_ipo_editmenu_extendmenu(void *arg, int event)
544 {
545         switch(event)
546         {
547         case 0:
548                 do_ipo_buttons(B_IPOCONT);
549                 break;
550         case 1:
551                 do_ipo_buttons(B_IPOEXTRAP);
552                 break;
553         case 2:
554                 do_ipo_buttons(B_IPOCYCLIC);
555                 break;
556         case 3:
557                 do_ipo_buttons(B_IPOCYCLICX);
558                 break;
559         }
560 }
561
562 static uiBlock *ipo_editmenu_extendmenu(void *arg_unused)
563 {
564         uiBlock *block;
565         short yco= 0, menuwidth=120;
566
567         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_extendmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
568         uiBlockSetButmFunc(block, do_ipo_editmenu_extendmenu, NULL);
569
570         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Constant|E, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
571         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extrapolation|E, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
572         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cyclic|E, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
573         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cyclic Extrapolation|E, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
574
575         uiBlockSetDirection(block, UI_RIGHT);
576         uiTextBoundsBlock(block, 60);
577
578         return block;
579 }
580
581
582 static void do_ipo_editmenu(void *arg, int event)
583 {
584         switch(event)
585         {
586         case 0:
587                 del_ipo(1);
588                 break;
589         case 1:
590                 add_duplicate_editipo();
591                 break;
592         case 2:
593                 ipo_record();
594                 break;
595         case 3:
596                 mainqenter(IKEY, 1);
597                 break;
598         case 4 :
599                 add_blockhandler(curarea, IPO_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
600                 break;
601         case 5:
602                 //join_ipo();
603                 break;
604         case 6:
605                 /*IPO Editmode*/
606                 set_editflag_editipo();
607                 break;
608         case 7:
609                 sethandles_ipo(HD_AUTO_ANIM);
610                 break;
611         case 8: /* clean ipo */
612                 clean_ipo();
613                 break;
614         case 9: /* smooth ipo */
615                 smooth_ipo();
616                 break;
617         }
618 }
619
620 static uiBlock *ipo_editmenu(void *arg_unused)
621 {
622         uiBlock *block;
623         EditIpo *ei;
624         short yco= 0, menuwidth=120;
625         int a,isedit = 0;
626
627         get_status_editipo();
628
629         ei = G.sipo->editipo;
630
631         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
632         uiBlockSetButmFunc(block, do_ipo_editmenu, NULL);
633
634         uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
635         
636         uiDefIconTextBlockBut(block, ipo_editmenu_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");     
637         
638         uiDefIconTextBlockBut(block, ipo_editmenu_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");       
639
640         uiDefIconTextBlockBut(block, ipo_editmenu_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 19, "");   
641         
642         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); 
643
644         /*Look to see if any ipos are being edited, so there can be a check next to the menu option*/
645         for(a=0; a<G.sipo->totipo; a++, ei++) {         
646                 if(ei->icu) {
647                         if(ei->flag & IPO_VISIBLE) {
648                                 if(totipo_edit && (ei->flag & IPO_EDIT)) {
649                                         isedit = 1;
650                                         break;
651                                 }
652                         }
653                 }
654         }
655         if(isedit)
656                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT,   "Edit Selected|TAB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");                
657         else
658                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Edit Selected|TAB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
659         
660         ei = get_active_editipo();
661         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
662         
663         if(ei && ei->icu && ei->icu->driver)
664                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert 1:1 Curve...|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
665         else
666                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe...|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
667         
668         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
669
670         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
671         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Record Mouse Movement|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
672         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clean IPO Curves|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
673         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Smooth IPO Curves|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
674         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
675         uiDefIconTextBlockBut(block, ipo_editmenu_joinmenu, NULL, ICON_RIGHTARROW_THIN, "Join", 0, yco-=20, 120, 19, "");       
676
677         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
678         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped Handles|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
679         
680         if (!G.sipo->showkey){
681                 uiDefIconTextBlockBut(block, ipo_editmenu_extendmenu, NULL, ICON_RIGHTARROW_THIN, "Extend Mode", 0, yco-=20, 120, 19, "");      
682                 uiDefIconTextBlockBut(block, ipo_editmenu_intpolmenu, NULL, ICON_RIGHTARROW_THIN, "Interpolation Mode   ", 0, yco-=20, 120, 20, "");
683                 if(ei != NULL && (ei->flag & IPO_EDIT))
684                         uiDefIconTextBlockBut(block, ipo_editmenu_handlemenu, NULL, ICON_RIGHTARROW_THIN, "Handle Type", 0, yco-=20, 120, 19, "");
685                 if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0)
686                         uiDefIconTextBlockBut(block, ipo_editmenu_keymenu, NULL, ICON_RIGHTARROW_THIN, "Key Type", 0, yco-=20, 120, 19, "");
687         }
688         
689
690         if(curarea->headertype==HEADERTOP) {
691                 uiBlockSetDirection(block, UI_DOWN);
692         }
693         else {
694                 uiBlockSetDirection(block, UI_TOP);
695                 uiBlockFlipOrder(block);
696         }
697
698         uiTextBoundsBlock(block, 50);
699
700         return block;
701 }
702
703 static void do_ipo_viewmenu(void *arg, int event)
704 {
705         extern int play_anim(int mode);
706         
707         switch(event)
708         {
709         case 1:
710                 do_ipo_buttons(B_IPOHOME);
711                 break;
712         case 2:
713                 ipo_toggle_showkey();
714                 scrarea_queue_headredraw(curarea);
715                 scrarea_queue_winredraw(curarea);
716                 allqueue(REDRAWVIEW3D, 0);
717                 break;
718         case 3:
719                 move_to_frame();
720                 break;
721         case 4:
722                 mainqenter(PADPLUSKEY,1);
723                 break;
724         case 5:
725                 mainqenter(PADMINUS,1);
726                 break;
727         case 6: /* Play Animation */
728                 play_anim(0);
729                 break;
730         case 7: /* Play Animation in All */
731                 play_anim(1);
732                 break;  
733         case 8:
734                 add_blockhandler(curarea, IPO_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
735                 break;  
736         case 9:
737                 G.v2d->flag ^= V2D_VIEWLOCK;
738                 if(G.v2d->flag & V2D_VIEWLOCK)
739                         view2d_do_locks(curarea, 0);
740                 break;  
741         case 10: /* center view to current frame */
742                 center_currframe();
743                 scrarea_queue_winredraw(curarea);
744                 break;
745         case 11:
746                 do_ipo_buttons(B_IPOVIEWCENTER);
747                 break;
748         case 12:        
749                 G.sipo->flag ^= SIPO_LOCK_VIEW;
750                 break;
751         case 13: /* Set Preview Range */
752                 anim_previewrange_set();
753                 break;
754         case 14: /* Clear Preview Range */
755                 anim_previewrange_clear();
756                 break;
757         case 15: /* AutoMerge Keyframes */
758                 G.sipo->flag ^= SIPO_NOTRANSKEYCULL;
759                 break;
760         }
761 }
762
763 static uiBlock *ipo_viewmenu(void *arg_unused)
764 {
765         uiBlock *block;
766         EditIpo *ei;
767         short yco= 0, menuwidth=120;
768
769         ei = get_active_editipo();
770
771         block= uiNewBlock(&curarea->uiblocks, "ipo_viewmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
772         uiBlockSetButmFunc(block, do_ipo_viewmenu, NULL);
773
774         uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Channel Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
775         
776         if (G.sipo->showkey)
777                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
778         else
779                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
780         
781         uiDefIconTextBut(block, BUTM, 1, (G.sipo->flag & SIPO_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, 
782                                          "AutoMerge Keyframes|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
783         
784         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
785
786         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Out|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
787         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom In|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
788
789         uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
790         
791         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Animation|Alt A", 0, yco-=20, 
792                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
793         //uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Animation in 3D View|Alt Shift A", 0, yco-=20,
794         //                               menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
795
796         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
797         
798         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Preview Range|Ctrl P", 0, yco-=20, 
799                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
800         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Preview Range|Alt P", 0, yco-=20,
801                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
802         
803         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
804
805
806         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center on Current Frame|Shift C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, "");
807         uiDefIconTextBut(block, BUTM, 1, (G.v2d->flag & V2D_VIEWLOCK)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, 
808                                          "Lock Time to Other Windows|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
809         
810         if (G.sipo->flag & SIPO_LOCK_VIEW)
811                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Lock View Area", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, "");
812         else
813                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Lock View Area", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, "");
814
815         if (ei != NULL && (ei->flag & IPO_EDIT)) {
816                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Current Frame to Selected|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
817         }
818
819         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
820
821         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View Selected|NumPad .",                 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
822         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
823         if(!curarea->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,20, "");
824         else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 20, "");
825
826         if(curarea->headertype==HEADERTOP) {
827                 uiBlockSetDirection(block, UI_DOWN);
828         }
829         else {
830                 uiBlockSetDirection(block, UI_TOP);
831                 uiBlockFlipOrder(block);
832         }
833
834         uiTextBoundsBlock(block, 50);
835
836         return block;
837 }
838
839 static void do_ipo_selectmenu(void *arg, int event)
840 {
841         switch(event)
842         {
843         case 0:
844                 borderselect_ipo();
845                 break;
846         case 1:
847                 swap_selectall_editipo();
848                 break;
849         case 2:
850                 borderselect_markers();
851                 allqueue(REDRAWMARKER, 0);
852                 break;
853         case 3:
854                 deselect_markers(1, 0);
855                 allqueue(REDRAWMARKER, 0);
856                 break;
857         }
858 }
859
860 static uiBlock *ipo_selectmenu(void *arg_unused)
861 {
862         uiBlock *block;
863         short yco= 0, menuwidth=120;
864
865         block= uiNewBlock(&curarea->uiblocks, "ipo_selectmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
866         uiBlockSetButmFunc(block, do_ipo_selectmenu, NULL);
867
868         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
869         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select Markers|Ctrl B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
870         
871         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
872         
873         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
874         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All Markers|Ctrl A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
875
876         if(curarea->headertype==HEADERTOP) {
877                 uiBlockSetDirection(block, UI_DOWN);
878         }
879         else {
880                 uiBlockSetDirection(block, UI_TOP);
881                 uiBlockFlipOrder(block);
882         }
883
884         uiTextBoundsBlock(block, 50);
885
886         return block;
887 }
888
889 static void do_ipo_markermenu(void *arg, int event)
890 {       
891         switch(event)
892         {
893                 case 1:
894                         add_marker(CFRA);
895                         break;
896                 case 2:
897                         duplicate_marker();
898                         break;
899                 case 3:
900                         remove_marker();
901                         break;
902                 case 4:
903                         rename_marker();
904                         break;
905                 case 5:
906                         transform_markers('g', 0);
907                         break;
908         }
909         
910         allqueue(REDRAWMARKER, 0);
911 }
912
913 static uiBlock *ipo_markermenu(void *arg_unused)
914 {
915         uiBlock *block;
916         short yco= 0, menuwidth=120;
917
918         block= uiNewBlock(&curarea->uiblocks, "ipo_markermenu", 
919                                           UI_EMBOSSP, UI_HELV, curarea->headwin);
920         uiBlockSetButmFunc(block, do_ipo_markermenu, NULL);
921
922         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Marker|M", 0, yco-=20, 
923                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
924         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate Marker|Ctrl Shift D", 0, yco-=20, 
925                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
926         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Marker|X", 0, yco-=20,
927                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
928                                          
929         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
930
931         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "(Re)Name Marker|Ctrl M", 0, yco-=20,
932                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
933         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Marker|Ctrl G", 0, yco-=20,
934                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
935         
936         if(curarea->headertype==HEADERTOP) {
937                 uiBlockSetDirection(block, UI_DOWN);
938         }
939         else {
940                 uiBlockSetDirection(block, UI_TOP);
941                 uiBlockFlipOrder(block);
942         }
943
944         uiTextBoundsBlock(block, 50);
945
946         return block;
947 }
948
949 static char *ipo_modeselect_pup(void)
950 {
951         Object *ob= OBACT;
952         static char formatstring[] = "|%s %%x%d %%i%d";
953         static char string[1024];
954         char *str = string;
955         
956         str += sprintf(str, "Ipo type: %%t");
957
958         if(ob)
959                 str += sprintf(str,formatstring, "Object",ID_OB, ICON_OBJECT);
960
961         if(ob && give_current_material(ob, ob->actcol)) // check for material
962                 str += sprintf(str,formatstring, "Material",ID_MA, ICON_MATERIAL);
963
964         if(G.scene->world)
965                 str += sprintf(str,formatstring, "World",ID_WO, ICON_WORLD);
966
967         if(ob && ob->type==OB_CURVE)
968                 str += sprintf(str,formatstring, "Path",ID_CU, ICON_CURVE);
969
970         if(ob && ob->type==OB_CAMERA)
971                 str += sprintf(str,formatstring, "Camera",ID_CA, ICON_CAMERA);
972         
973         if(ob && ob->type==OB_LAMP)
974                 str += sprintf(str,formatstring, "Lamp",ID_LA, ICON_LAMP);
975
976         if((ob && give_current_texture(ob, ob->actcol))||(give_current_world_texture()))
977                 str += sprintf(str,formatstring, "Texture",ID_TE, ICON_TEXTURE);
978
979         if(ob){
980                 FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
981                 
982                 if ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE)
983                         str += sprintf(str,formatstring, "Shape",ID_KE, ICON_EDIT);
984                 if (ob->type==OB_ARMATURE)
985                         str += sprintf(str,formatstring, "Pose",ID_PO, ICON_POSE_HLT);
986 #ifdef __CON_IPO
987                 str += sprintf(str,formatstring, "Constraint",ID_CO, ICON_CONSTRAINT);
988 #endif
989                 if(fluidmd) {
990                         str += sprintf(str,formatstring,"Fluidsim",ID_FLUIDSIM, ICON_WORLD);
991                 }
992
993                 if(ob->particlesystem.first) {
994                         str += sprintf(str,formatstring,"Particles",ID_PA, ICON_PARTICLES);
995                 }
996         }
997
998         str += sprintf(str,formatstring, "Sequence",ID_SEQ, ICON_SEQUENCE);
999
1000         return (string);
1001 }
1002
1003 void do_ipo_buttons(short event)
1004 {
1005         EditIpo *ei;
1006         View2D *v2d;
1007         rcti rect;
1008         Object *ob= OBACT;
1009         float xmin, ymin, dx, dy;
1010         int a, val, first;
1011         short mval[2];
1012
1013         if(curarea->win==0) return;
1014
1015         switch(event) {
1016         case B_IPOVIEWCENTER:
1017         case B_IPOHOME:
1018
1019                 /* boundbox */
1020
1021                 v2d= &(G.sipo->v2d);
1022                 first= 1;
1023
1024                 ei= G.sipo->editipo;
1025                 if(ei==0) return;
1026                 
1027                 /* map ipo-points for drawing if scaled ipo */
1028                 if (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) {
1029                         actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 0);
1030                 }
1031                 
1032                 for(a=0; a<G.sipo->totipo; a++, ei++) {
1033                         if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1034                         
1035                                 boundbox_ipocurve(ei->icu, (event==B_IPOVIEWCENTER));
1036                                 
1037                                 if(first) {
1038                                         v2d->tot= ei->icu->totrct;
1039                                         first= 0;
1040                                 }
1041                                 else BLI_union_rctf(&(v2d->tot), &(ei->icu->totrct));
1042                         }
1043                 }
1044                 
1045                 /* undo mapping of ipo-points for drawing if scaled ipo */
1046                 if (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) {
1047                         actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 0);
1048                 }
1049
1050                 /* speciale home */
1051                 if(G.qual & LR_SHIFTKEY) {
1052                         v2d->tot.xmin= SFRA;
1053                         v2d->tot.xmax= EFRA;
1054                 }
1055
1056                 /* zoom out a bit */
1057                 dx= 0.10*(v2d->tot.xmax-v2d->tot.xmin);
1058                 dy= 0.10*(v2d->tot.ymax-v2d->tot.ymin);
1059                 
1060                 if(dx<v2d->min[0]) dx= v2d->min[0];
1061                 if(dy<v2d->min[1]) dy= v2d->min[1];
1062                 
1063                 v2d->cur.xmin= v2d->tot.xmin- dx;
1064                 v2d->cur.xmax= v2d->tot.xmax+ dx;
1065                 v2d->cur.ymin= v2d->tot.ymin- dy;
1066                 v2d->cur.ymax= v2d->tot.ymax+ dy;
1067
1068                 test_view2d(G.v2d, curarea->winx, curarea->winy);
1069                 view2d_do_locks(curarea, V2D_LOCK_COPY);
1070                 if(G.sipo->ipo) G.sipo->ipo->cur = G.v2d->cur;
1071                 
1072                 scrarea_queue_winredraw(curarea);
1073                 break;
1074         case B_IPOBORDER:
1075                 val= get_border(&rect, 3);
1076                 if(val) {
1077                         mval[0]= rect.xmin;
1078                         mval[1]= rect.ymin;
1079                         areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
1080                         mval[0]= rect.xmax;
1081                         mval[1]= rect.ymax;
1082                         areamouseco_to_ipoco(G.v2d, mval, &(G.v2d->cur.xmax), &(G.v2d->cur.ymax));
1083                         G.v2d->cur.xmin= xmin;
1084                         G.v2d->cur.ymin= ymin;
1085                         
1086                         test_view2d(G.v2d, curarea->winx, curarea->winy);
1087                         view2d_do_locks(curarea, V2D_LOCK_COPY);
1088                         scrarea_queue_winredraw(curarea);
1089                 }
1090                 break;
1091
1092         case B_IPOPIN:
1093                 allqueue (REDRAWIPO, 0);
1094                 break;
1095
1096         case B_IPOCOPY:
1097                 copy_editipo();
1098                 break;
1099         case B_IPOPASTE:
1100                 paste_editipo();
1101                 break;
1102         case B_IPOCONT:
1103                 set_exprap_ipo(IPO_HORIZ);
1104                 break;
1105         case B_IPOEXTRAP:
1106                 set_exprap_ipo(IPO_DIR);
1107                 break;
1108         case B_IPOCYCLIC:
1109                 set_exprap_ipo(IPO_CYCL);
1110                 break;
1111         case B_IPOCYCLICX:
1112                 set_exprap_ipo(IPO_CYCLX);
1113                 break;
1114         case B_IPOMAIN:
1115                 /* pass 1 to enforce a refresh when there's no Ipo */
1116                 test_editipo(1);
1117                 scrarea_queue_winredraw(curarea);
1118                 scrarea_queue_headredraw(curarea);
1119                 if(ob) ob->ipowin= G.sipo->blocktype;
1120                 break;
1121         case B_IPOSHOWKEY:
1122                 /* reverse value because of winqread */
1123                 G.sipo->showkey= 1-G.sipo->showkey;
1124                 ipo_toggle_showkey();
1125                 scrarea_queue_headredraw(curarea);
1126                 scrarea_queue_winredraw(curarea);
1127                 allqueue(REDRAWVIEW3D, 0);
1128                 break;
1129         case B_VIEW2DZOOM:
1130                 view2dzoom(event);
1131                 scrarea_queue_headredraw(curarea);
1132                 break;
1133         case B_IPO_ACTION_OB:
1134                 if(ob && G.sipo->from && G.sipo->pin==0) {
1135                         if(ob->ipoflag & OB_ACTION_OB) {        /* check if channel exists, and flip ipo link */
1136                                 bActionChannel *achan;
1137                                 
1138                                 if(has_ipo_code(ob->ipo, OB_LAY))
1139                                         notice("Note: Layer Ipo doesn't work in Actions");
1140                                 
1141                                 if(ob->action==NULL) 
1142                                         ob->action= add_empty_action("ObAction");
1143                                 achan= verify_action_channel(ob->action, "Object");
1144                                 if(achan->ipo==NULL && ob->ipo) {
1145                                         achan->ipo= ob->ipo;
1146                                         ob->ipo= NULL;
1147                                 }
1148                                 
1149                                 /* object constraints */
1150                                 if(ob->constraintChannels.first) {
1151                                         free_constraint_channels(&achan->constraintChannels);
1152                                         achan->constraintChannels= ob->constraintChannels;
1153                                         ob->constraintChannels.first= ob->constraintChannels.last= NULL;
1154                                 }
1155                         }
1156                         else if(ob->action) {
1157                                 bActionChannel *achan= get_action_channel(ob->action, "Object");
1158                                 if(achan) {
1159                                         
1160                                         if(achan->ipo && ob->ipo==NULL) {
1161                                                 ob->ipo= achan->ipo;
1162                                                 achan->ipo= NULL;
1163                                         }
1164                                         
1165                                         /* object constraints */
1166                                         if(achan->constraintChannels.first) {
1167                                                 free_constraint_channels(&ob->constraintChannels);
1168                                                 ob->constraintChannels= achan->constraintChannels;
1169                                                 achan->constraintChannels.first= achan->constraintChannels.last= NULL;
1170                                         }
1171                                 }
1172                         }
1173                         allqueue(REDRAWVIEW3D, 0);
1174                         allqueue(REDRAWIPO, 0);
1175                         allqueue(REDRAWACTION, 0);
1176                         allqueue(REDRAWOOPS, 0);
1177                         allqueue(REDRAWNLA, 0);
1178                 }
1179                 break;
1180                 
1181         case B_IPO_ACTION_KEY:
1182                 if(ob && G.sipo->from && G.sipo->pin==0) {
1183                         Key *key= ob_get_key(ob);
1184                         if(key) {
1185                                 if(ob->ipoflag & OB_ACTION_KEY) {       /* check if channel exists, and flip ipo link */
1186                                         bActionChannel *achan;
1187                                         
1188                                         if(ob->action==NULL) 
1189                                                 ob->action= add_empty_action("ShapeAction");
1190                                         achan= verify_action_channel(ob->action, "Shape");
1191                                         if(achan->ipo==NULL && key->ipo) {
1192                                                 achan->ipo= key->ipo;
1193                                                 key->ipo= NULL;
1194                                         }
1195                                 }
1196                                 else if(ob->action) {
1197                                         bActionChannel *achan= get_action_channel(ob->action, "Shape");
1198                                         if(achan) {
1199                                                 if(achan->ipo && key->ipo==NULL) {
1200                                                         key->ipo= achan->ipo;
1201                                                         achan->ipo= NULL;
1202                                                 }
1203                                         }
1204                                 }
1205                                 allqueue(REDRAWVIEW3D, 0);
1206                                 allqueue(REDRAWIPO, 0);
1207                                 allqueue(REDRAWACTION, 0);
1208                                 allqueue(REDRAWOOPS, 0);
1209                                 allqueue(REDRAWNLA, 0);
1210                         }
1211                 }
1212                 break;
1213         case B_IPOVIEWALL:
1214                 /* set visible active */
1215                 for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++) {
1216                         if (ei->icu)    ei->flag |= IPO_VISIBLE;
1217                         else                    ei->flag &= ~IPO_VISIBLE;
1218                 }
1219                 break;
1220         case B_IPOREDRAW:
1221                 DAG_object_flush_update(G.scene, ob, OB_RECALC);
1222                 allqueue(REDRAWVIEW3D, 0);
1223                 allqueue(REDRAWIPO, 0);
1224                 break;
1225         }
1226 }
1227
1228 void ipo_buttons(void)
1229 {
1230         Object *ob;
1231         EditIpo *ei;
1232         uiBlock *block;
1233         short xco,xmax;
1234         char naam[20];
1235         int icon=0, allow_pin= B_IPOPIN;
1236
1237         sprintf(naam, "header %d", curarea->headwin);
1238         block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSS, UI_HELV, curarea->headwin);
1239
1240         if(area_is_active_area(curarea)) uiBlockSetCol(block, TH_HEADER);
1241         else uiBlockSetCol(block, TH_HEADERDESEL);
1242
1243         curarea->butspacetype= SPACE_IPO;
1244
1245         xco = 8;
1246         uiDefIconTextButC(block, ICONTEXTROW,B_NEWSPACE, ICON_VIEW3D, windowtype_pup(), xco,0,XIC+10,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Displays Current Window Type. Click for menu of available types.");
1247         xco+= XIC+14;
1248         
1249         test_editipo(0);        /* test if current editipo is OK, make_editipo sets v2d->cur */
1250
1251         uiBlockSetEmboss(block, UI_EMBOSSN);
1252         if(curarea->flag & HEADER_NO_PULLDOWN) {
1253                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_RIGHT,
1254                                 xco,2,XIC,YIC-2,
1255                                 &(curarea->flag), 0, 0, 0, 0, "Enables display of pulldown menus");
1256         } else {
1257                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_DOWN,
1258                                 xco,2,XIC,YIC-2,
1259                                 &(curarea->flag), 0, 0, 0, 0, "Hides pulldown menus");
1260         }
1261         uiBlockSetEmboss(block, UI_EMBOSS);
1262         xco+=XIC;
1263
1264         /* pull down menus */
1265         if((curarea->flag & HEADER_NO_PULLDOWN)==0) {
1266                 uiBlockSetEmboss(block, UI_EMBOSSP);
1267         
1268                 ei = get_active_editipo();
1269         
1270                 xmax= GetButStringLength("View");
1271                 uiDefPulldownBut(block,ipo_viewmenu, NULL, "View", xco, -2, xmax-3, 24, "");
1272                 xco+=xmax;
1273         
1274                 xmax= GetButStringLength("Select");
1275                 uiDefPulldownBut(block,ipo_selectmenu, NULL, "Select", xco, -2, xmax-3, 24, "");
1276                 xco+=xmax;
1277                 
1278                 xmax= GetButStringLength("Marker");
1279                 uiDefPulldownBut(block,ipo_markermenu, NULL, "Marker", xco, -2, xmax-3, 24, "");
1280                 xco+=xmax;
1281                 
1282                 if (G.sipo->showkey) {
1283                         xmax= GetButStringLength("Key");
1284                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Key", xco, -2, xmax-3, 24, "");
1285                 }
1286                 else if(ei != NULL && (ei->flag & IPO_EDIT)) {
1287                         xmax= GetButStringLength("Point");
1288                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Point", xco, -2, xmax-3, 24, "");
1289                 }
1290                 else {
1291                         xmax= GetButStringLength("Curve");
1292                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Curve", xco, -2, xmax-3, 24, "");
1293                 }
1294                 xco+=xmax;
1295         }
1296
1297         /* end of pull down menus */
1298         uiBlockSetEmboss(block, UI_EMBOSS);
1299
1300         ob= OBACT;
1301         
1302         /* action switch option, only when active object is there and no pin */
1303         uiSetButLock(G.sipo->pin, "Can't change because of pinned data");
1304         
1305         /* define whether ipos are on Object or on action */
1306         if(ob) {
1307                 static short fake1= 1;
1308                 
1309                 uiBlockBeginAlign(block);
1310                 
1311                 if(G.sipo->blocktype==ID_OB) {
1312                         uiDefIconButBitS(block, TOG, OB_ACTION_OB, B_IPO_ACTION_OB, ICON_ACTION,        xco,0,XIC,YIC, &(ob->ipoflag), 0, 0, 0, 0, "Sets Ipo to be included in an Action or not");
1313                         xco+= XIC;
1314                 }
1315                 else if(G.sipo->blocktype==ID_KE) {
1316                         uiDefIconButBitS(block, TOG, OB_ACTION_KEY, B_IPO_ACTION_KEY, ICON_ACTION,      xco,0,XIC,YIC, &(ob->ipoflag), 0, 0, 0, 0, "Sets Ipo to be included in an Action or not");
1317                         xco+= XIC;
1318                 }
1319                 else if(G.sipo->blocktype==ID_CO) {
1320                         
1321                         if(ob->pose==NULL)
1322                                 uiDefIconButBitS(block, TOG, OB_ACTION_OB, B_IPO_ACTION_OB, ICON_ACTION,        xco,0,XIC,YIC, &(ob->ipoflag), 0, 0, 0, 0, "Sets Ipo to be included in an Action or not");
1323                         else {
1324                                 bConstraint *con= get_active_constraint(ob);
1325                                 if(con)
1326                                         uiDefIconButBitS(block, TOGN, CONSTRAINT_OWN_IPO, B_IPOREDRAW, ICON_ACTION,     xco,0,XIC,YIC, &con->flag, 0, 0, 0, 0, 
1327                                                                          (con->flag & CONSTRAINT_OWN_IPO)?"Ipo is connected to Constraint itself":"Ipo is connected to Pose Action"
1328                                                                          );
1329                         }
1330                         xco+= XIC;
1331                 }
1332                 else if(G.sipo->blocktype==ID_PO) {     /* only to indicate we have action ipos */
1333                         uiSetButLock(1, "Pose Action Ipo cannot be switched");
1334                         uiDefIconButS(block, TOG, 1, ICON_ACTION,       xco,0,XIC,YIC, &fake1, 0, 0, 0, 0, "Ipo is connected to Pose Action");
1335                         xco+= XIC;
1336                 }
1337                 uiClearButLock();
1338         }
1339         
1340         /* ipo muting */
1341         if (G.sipo->ipo) {
1342                 uiDefIconButS(block, ICONTOG, 1, ICON_MUTE_IPO_OFF, xco,0,XIC,YIC, &(G.sipo->ipo->muteipo), 0, 0, 0, 0, "Mute IPO-block");
1343                 xco += XIC;
1344         }
1345         
1346         /* mainmenu, only when data is there and no pin */
1347         uiSetButLock(G.sipo->pin, "Can't change because of pinned data");
1348
1349         if (G.sipo->blocktype == ID_OB)
1350                 icon = ICON_OBJECT;
1351         else if (G.sipo->blocktype == ID_MA)
1352                 icon = ICON_MATERIAL;
1353         else if (G.sipo->blocktype == ID_WO)
1354                 icon = ICON_WORLD;
1355         else if (G.sipo->blocktype == ID_CU)
1356                 icon = ICON_ANIM;
1357         else if (G.sipo->blocktype == ID_CA)
1358                 icon = ICON_CAMERA;
1359         else if (G.sipo->blocktype == ID_LA)
1360                 icon = ICON_LAMP;
1361         else if (G.sipo->blocktype == ID_KE)
1362                 icon = ICON_EDIT;
1363         else if (G.sipo->blocktype == ID_PO)
1364                 icon = ICON_POSE_HLT;
1365         else if (G.sipo->blocktype == ID_CO)
1366                 icon = ICON_CONSTRAINT;
1367         else if (G.sipo->blocktype == ID_SEQ)
1368                 icon = ICON_SEQUENCE;
1369         else if(G.sipo->blocktype == ID_TE)
1370                 icon = ICON_TEXTURE;
1371         else if(G.sipo->blocktype == ID_FLUIDSIM)
1372                 icon = ICON_WORLD;
1373         else if(G.sipo->blocktype == ID_PA)
1374                 icon = ICON_PARTICLES;
1375
1376         uiDefIconTextButS(block, MENU, B_IPOMAIN, icon, ipo_modeselect_pup(), xco,0,100,20, &(G.sipo->blocktype), 0, 0, 0, 0, "Show IPO type");
1377
1378         xco += 85;
1379
1380         if(G.sipo->blocktype==ID_MA) {
1381                 uiDefButS(block, NUM, B_IPOMAIN, "",    xco+=XIC,0,XIC-4,YIC, &G.sipo->channel, 0.0, MAX_MTEX-1.0, 0, 0, "Channel Number of the active Material texture.");
1382                 xco-= 4;
1383         }
1384         if(G.sipo->blocktype==ID_WO) {
1385                 uiDefButS(block, NUM, B_IPOMAIN, "",    xco+=XIC,0,XIC-4,YIC, &G.sipo->channel, 0.0, MAX_MTEX-1.0, 0, 0, "Channel Number of the active World texture.");
1386                 xco-= 4;
1387         }
1388         
1389         if(G.sipo->blocktype==ID_LA) {
1390                 uiDefButS(block, NUM, B_IPOMAIN, "",    xco+=XIC,0,XIC-4,YIC, &G.sipo->channel, 0.0, MAX_MTEX-1.0, 0, 0, "Channel Number of the active Lamp texture. ");
1391                 xco-= 4;
1392         }
1393         
1394         uiBlockEndAlign(block);
1395         
1396         uiClearButLock();
1397
1398         /* if(G.sipo->blocktype==ID_SEQ)
1399            allow_pin= 0; */
1400         xco= std_libbuttons(block, (short)(xco+1.5*XIC), 0, allow_pin, &G.sipo->pin, B_IPOBROWSE, ID_IP, 
1401                                                 G.sipo->blocktype, (ID*)G.sipo->ipo, G.sipo->from, &(G.sipo->menunr), B_IPOALONE, B_IPOLOCAL, B_IPODELETE, 0, B_KEEPDATA);
1402
1403         /* COPY PASTE */
1404         xco-= XIC/2;
1405         uiBlockBeginAlign(block);
1406         if(curarea->headertype==HEADERTOP) {
1407                 uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYUP,        xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
1408                 uiSetButLock(G.sipo->ipo && G.sipo->ipo->id.lib, ERROR_LIBDATA_MESSAGE);
1409                 uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEUP,      xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
1410         }
1411         else {
1412                 uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYDOWN,      xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
1413                 uiSetButLock(G.sipo->ipo && G.sipo->ipo->id.lib, ERROR_LIBDATA_MESSAGE);
1414                 uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEDOWN,    xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
1415         }
1416         uiBlockEndAlign(block);
1417         xco+=XIC/2;
1418         
1419         uiClearButLock();
1420
1421         /* ZOOMBORDER */
1422         uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE,  xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area (Shift B)");
1423         
1424         xco+=XIC/2;
1425         
1426         /* draw LOCK */
1427         uiDefIconButS(block, ICONTOG, 1, ICON_UNLOCKED, xco+=XIC,0,XIC,YIC, &(G.sipo->lock), 0, 0, 0, 0, "Toggles forced redraw of other windows to reflect changes in real time");
1428         
1429         /* always do as last */
1430         curarea->headbutlen= xco+2*XIC;
1431
1432         uiDrawBlock(block);
1433 }