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