Stage two of the giant animation recode project; Ipo/Action/NLA cleanup
[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/BL DUAL 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. The Blender
15  * Foundation also sells licenses for use in proprietary software under
16  * the Blender License.  See http://www.blender.org/BL/ for information
17  * about this.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
27  *
28  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
29  * All rights reserved.
30  *
31  * The Original Code is: all of this file.
32  *
33  * Contributor(s): none yet.
34  *
35  * ***** END GPL/BL DUAL LICENSE BLOCK *****
36  */
37
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
41
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45
46 #include "DNA_action_types.h"
47 #include "DNA_camera_types.h"
48 #include "DNA_curve_types.h"
49 #include "DNA_constraint_types.h"
50 #include "DNA_ID.h"
51 #include "DNA_ipo_types.h"
52 #include "DNA_key_types.h"
53 #include "DNA_lamp_types.h"
54 #include "DNA_material_types.h"
55 #include "DNA_object_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_global.h"
67 #include "BKE_main.h"
68 #include "BKE_material.h"
69 #include "BKE_texture.h"
70 #include "BKE_utildefines.h"
71
72 #include "BLI_blenlib.h"
73
74 #include "BSE_drawipo.h"
75 #include "BSE_editipo_types.h"
76 #include "BSE_edit.h"
77 #include "BSE_editipo.h"
78 #include "BSE_headerbuttons.h"
79
80 #include "BIF_editaction.h"
81 #include "BIF_interface.h"
82 #include "BIF_mainqueue.h"
83 #include "BIF_resources.h"
84 #include "BIF_screen.h"
85 #include "BIF_space.h"
86
87 #include "nla.h"
88
89 #include "blendef.h"
90 #include "mydevice.h"
91
92 static int viewmovetemp = 0;
93 extern int totipo_edit, totipo_sel;
94
95 /* headerbutton call, assuming full context is set */
96 /* it aligns with editipo.c, verify_ipo */
97 void spaceipo_assign_ipo(SpaceIpo *si, Ipo *ipo)
98 {
99         if(si->from==NULL || si->from->lib) return;
100         
101         if(ipo) ipo->id.us++;
102
103         /* first check action ipos */
104         if(si->actname && si->actname[0]) {
105                 Object *ob= (Object *)si->from;
106                 bActionChannel *achan;
107                 
108                 if(ob->action) {
109                         achan= get_action_channel(ob->action, si->actname);
110                 
111                         if(achan) {
112                                 /* constraint exception */
113                                 if(si->blocktype==ID_CO) {
114                                         bConstraintChannel *conchan= get_constraint_channel(&achan->constraintChannels, si->constname);
115                                         if(conchan) {
116                                                 if(conchan->ipo)
117                                                         conchan->ipo->id.us--;
118                                                 conchan->ipo= ipo;
119                                         }
120                                 }
121                                 else {
122                                         if(achan->ipo)
123                                                 achan->ipo->id.us--;
124                                         achan->ipo= ipo;
125                                 }
126                         }
127                 }
128         }
129         else {
130                 switch(GS(si->from->name)) {
131                         case ID_OB:
132                         {
133                                 Object *ob= (Object *)si->from;
134                                 /* constraint exception */
135                                 if(si->blocktype==ID_CO) {
136                                         bConstraintChannel *conchan= get_constraint_channel(&ob->constraintChannels, si->constname);
137                                         if(conchan) {
138                                                 if(conchan->ipo)
139                                                         conchan->ipo->id.us--;
140                                                 conchan->ipo= ipo;
141                                         }
142                                 }
143                                 else if(si->blocktype==ID_OB) {
144                                         if(ob->ipo)
145                                                 ob->ipo->id.us--;
146                                         ob->ipo= ipo;
147                                 }
148                         }
149                                 break;
150                         case ID_MA:
151                         {
152                                 Material *ma= (Material *)si->from;
153                                 
154                                 if(ma->ipo)
155                                         ma->ipo->id.us--;
156                                 ma->ipo= ipo;
157                         }
158                                 break;
159                         case ID_TE:
160                         {
161                                 Tex *tex= (Tex *)si->from;
162                                 
163                                 if(tex->ipo)
164                                         tex->ipo->id.us--;
165                                 tex->ipo= ipo;
166                         }
167                                 break;
168                         case ID_SEQ:
169                         {
170                                 Sequence *seq= (Sequence *)si->from;    /* note, sequence is mimicing Id */
171                                 
172                                 if((seq->type & SEQ_EFFECT)||(seq->type == SEQ_SOUND)) {
173                                         if(seq->ipo)
174                                                 seq->ipo->id.us--;
175                                         seq->ipo= ipo;
176                                 }
177                         }
178                                 break;
179                         case ID_CU:
180                         {
181                                 Curve *cu= (Curve *)si->from;
182                                 
183                                 if(cu->ipo)
184                                         cu->ipo->id.us--;
185                                 cu->ipo= ipo;
186                         }
187                                 break;
188                         case ID_KE:
189                         {
190                                 Key *key= (Key *)si->from;
191                                 
192                                 if(key->ipo)
193                                         key->ipo->id.us--;
194                                 key->ipo= ipo;
195                         }
196                                 break;
197                         case ID_WO:
198                         {
199                                 World *wo= (World *)si->from;
200                                 
201                                 if(wo->ipo)
202                                         wo->ipo->id.us--;
203                                 wo->ipo= ipo;
204                         }
205                                 break;
206                         case ID_LA:
207                         {
208                                 Lamp *la= (Lamp *)si->from;
209                                 
210                                 if(la->ipo)
211                                         la->ipo->id.us--;
212                                 la->ipo= ipo;
213                         }
214                                 break;
215                         case ID_CA:
216                         {
217                                 Camera *ca= (Camera *)si->from;
218                                 
219                                 if(ca->ipo)
220                                         ca->ipo->id.us--;
221                                 ca->ipo= ipo;
222                         }
223                                 break;
224                         case ID_SO:
225                         {
226                                 bSound *snd= (bSound *)si->from;
227                                 
228                                 if(snd->ipo)
229                                         snd->ipo->id.us--;
230                                 snd->ipo= ipo;
231                         }
232                 }
233         }
234         
235         allqueue(REDRAWVIEW3D, 0);
236         allqueue(REDRAWIPO, 0);
237         allqueue(REDRAWACTION, 0);
238         allqueue(REDRAWNLA, 0);
239         allqueue(REDRAWBUTSALL, 0);
240         
241 }
242
243
244 static void do_ipo_editmenu_transformmenu(void *arg, int event)
245 {
246         switch(event)
247         {
248         case 0: /* grab/move */
249                 transform_ipo('g');
250                 break;
251         case 1: /* scale */
252                 transform_ipo('s');
253                 break;
254         }
255 }
256
257 static uiBlock *ipo_editmenu_transformmenu(void *arg_unused)
258 {
259         uiBlock *block;
260         short yco= 0, menuwidth=120;
261
262         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_transformmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
263         uiBlockSetButmFunc(block, do_ipo_editmenu_transformmenu, NULL);
264
265         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
266         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale|S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
267
268         uiBlockSetDirection(block, UI_RIGHT);
269         uiTextBoundsBlock(block, 60);
270
271         return block;
272 }
273
274 static void do_ipo_editmenu_snapmenu(void *arg, int event)
275 {
276         switch(event) {
277         case 1: /* Horizontal */
278         case 2: /* To Next */
279         case 3: /* To Frame */
280         case 4: /* To Current Frame */
281                 ipo_snap(event);
282             break;
283         }
284         allqueue(REDRAWVIEW3D, 0);
285 }
286
287 static uiBlock *ipo_editmenu_snapmenu(void *arg_unused)
288 {
289         uiBlock *block;
290         short yco = 20, menuwidth = 120;
291
292         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_snapmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
293         uiBlockSetButmFunc(block, do_ipo_editmenu_snapmenu, NULL);
294         
295         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Horizontal|Shift S, 1",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
296         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Next|Shift S, 2",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
297         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Frame|Shift S, 3",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
298         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Current Frame|Shift S, 4",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");   
299         
300         uiBlockSetDirection(block, UI_RIGHT);
301         uiTextBoundsBlock(block, 60);
302         return block;
303 }
304
305 static void do_ipo_editmenu_joinmenu(void *arg, int event)
306 {
307         switch(event) {
308         case 1: /* All Selected */
309         case 2: /* Selected Doubles */
310                 join_ipo(event);
311             break;
312         }
313         allqueue(REDRAWVIEW3D, 0);
314 }
315
316 static uiBlock *ipo_editmenu_joinmenu(void *arg_unused)
317 {
318         uiBlock *block;
319         short yco = 20, menuwidth = 120;
320
321         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_joinmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
322         uiBlockSetButmFunc(block, do_ipo_editmenu_joinmenu, NULL);
323         
324         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "All Selected|J, 1",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
325         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Selected Doubles|J, 2",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
326
327         uiBlockSetDirection(block, UI_RIGHT);
328         uiTextBoundsBlock(block, 60);
329         return block;
330 }
331
332 static void do_ipo_editmenu_keymenu(void *arg, int event)
333 {
334         Key *key;
335         KeyBlock *kb;
336         Object *ob= OBACT;
337
338         if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) {
339                 key= (Key *)G.sipo->from;
340                 if(key==NULL) return;
341
342                 kb= BLI_findlink(&key->block, ob->shapenr-1);
343                 kb->type= 0;
344                 switch(event){
345                         case 0:
346                                 kb->type= KEY_LINEAR;
347                                 break;
348                         case 1:
349                                 kb->type= KEY_CARDINAL;
350                                 break;
351                         case 2:
352                                 kb->type= KEY_BSPLINE;
353                                 break;
354                 }
355         }
356 }
357
358 static uiBlock *ipo_editmenu_keymenu(void *arg_unused)
359 {
360         uiBlock *block;
361         EditIpo *ei;
362         short yco= 0, menuwidth=120;
363
364         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_keymenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
365         uiBlockSetButmFunc(block, do_ipo_editmenu_keymenu, NULL);
366
367         ei = get_active_editipo();
368
369         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linear", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
370         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cardinal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
371         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "BSpline", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
372
373         uiBlockSetDirection(block, UI_RIGHT);
374         uiTextBoundsBlock(block, 60);
375
376         return block;
377
378 }
379
380 static void do_ipo_editmenu_handlemenu(void *arg, int event)
381 {
382         switch(event){
383         case 0:
384                 sethandles_ipo(HD_AUTO);
385                 break;
386         case 1:
387         case 2:
388                 sethandles_ipo(HD_ALIGN);
389                 break;
390         case 3:
391                 sethandles_ipo(HD_VECT);
392                 break;
393         }
394 }
395
396 static uiBlock *ipo_editmenu_handlemenu(void *arg_unused)
397 {
398         uiBlock *block;
399         short yco= 0, menuwidth=120;
400
401         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_handlemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
402         uiBlockSetButmFunc(block, do_ipo_editmenu_handlemenu, NULL);
403
404         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
405         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Aligned|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
406         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Free|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
407         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector|V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
408
409         uiBlockSetDirection(block, UI_RIGHT);
410         uiTextBoundsBlock(block, 60);
411
412         return block;
413 }
414
415 static void do_ipo_editmenu_intpolmenu(void *arg, int event)
416 {
417         EditIpo *ei;
418         int a;
419
420         get_status_editipo();
421
422         ei = G.sipo->editipo;
423
424         switch(event)
425         {
426         case 0:
427                 for(a=0; a<G.sipo->totipo; a++, ei++) {
428                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
429                                 ei->icu->ipo= IPO_CONST;
430                         }
431                 }
432                 break;
433         case 1:
434                 for(a=0; a<G.sipo->totipo; a++, ei++) {
435                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
436                                 ei->icu->ipo= IPO_LIN;
437                         }
438                 }
439                 break;
440         case 2:
441                 for(a=0; a<G.sipo->totipo; a++, ei++) {
442                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
443                                 ei->icu->ipo= IPO_BEZ;
444                         }
445                 }
446                 break;
447         }
448
449         scrarea_queue_winredraw(curarea);
450 }
451
452 static uiBlock *ipo_editmenu_intpolmenu(void *arg_unused)
453 {
454         uiBlock *block;
455         short yco= 0, menuwidth=120;
456
457         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_intpolmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
458         uiBlockSetButmFunc(block, do_ipo_editmenu_intpolmenu, NULL);
459
460         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Constant", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
461         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linear", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
462         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bezier", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
463
464         uiBlockSetDirection(block, UI_RIGHT);
465         uiTextBoundsBlock(block, 60);
466
467         return block;
468 }
469
470 static void do_ipo_editmenu_extendmenu(void *arg, int event)
471 {
472         switch(event)
473         {
474         case 0:
475                 do_ipo_buttons(B_IPOCONT);
476                 break;
477         case 1:
478                 do_ipo_buttons(B_IPOEXTRAP);
479                 break;
480         case 2:
481                 do_ipo_buttons(B_IPOCYCLIC);
482                 break;
483         case 3:
484                 do_ipo_buttons(B_IPOCYCLICX);
485                 break;
486         }
487 }
488
489 static uiBlock *ipo_editmenu_extendmenu(void *arg_unused)
490 {
491         uiBlock *block;
492         short yco= 0, menuwidth=120;
493
494         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_extendmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
495         uiBlockSetButmFunc(block, do_ipo_editmenu_extendmenu, NULL);
496
497         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Constant", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
498         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extrapolation", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
499         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cyclic", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
500         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cyclic Extrapolation", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
501
502         uiBlockSetDirection(block, UI_RIGHT);
503         uiTextBoundsBlock(block, 60);
504
505         return block;
506 }
507
508
509 static void do_ipo_editmenu(void *arg, int event)
510 {
511         switch(event)
512         {
513         case 0:
514                 del_ipo();
515                 break;
516         case 1:
517                 add_duplicate_editipo();
518                 break;
519         case 2:
520                 ipo_record();
521                 break;
522         case 3:
523                 mainqenter(IKEY, 1);
524                 break;
525         case 4 :
526                 add_blockhandler(curarea, IPO_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
527                 break;
528         case 5:
529                 //join_ipo();
530                 break;
531         case 6:
532                 /*IPO Editmode*/
533                 set_editflag_editipo();
534         }
535 }
536
537 static uiBlock *ipo_editmenu(void *arg_unused)
538 {
539         uiBlock *block;
540         EditIpo *ei;
541         short yco= 0, menuwidth=120;
542         int a,isedit = 0;
543
544         get_status_editipo();
545
546         ei = G.sipo->editipo;
547
548         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
549         uiBlockSetButmFunc(block, do_ipo_editmenu, NULL);
550
551         uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
552         
553         uiDefIconTextBlockBut(block, ipo_editmenu_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");     
554         
555         uiDefIconTextBlockBut(block, ipo_editmenu_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");       
556
557         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); 
558
559         /*Look to see if any ipos are being edited, so there can be a check next to the menu option*/
560         for(a=0; a<G.sipo->totipo; a++, ei++) {         
561                 if(ei->icu) {
562                         if(ei->flag & IPO_VISIBLE) {
563                                 if(totipo_edit && (ei->flag & IPO_EDIT)) {
564                                         isedit = 1;
565                                         break;
566                                 }
567                         }
568                 }
569         }
570         if(isedit)
571                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT,   "Edit Selected|TAB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");                
572         else
573                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Edit Selected|TAB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
574         
575         ei = get_active_editipo();
576         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
577         
578         if(ei && ei->icu && ei->icu->driver)
579                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert 1:1 Curve...|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
580         else
581                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe...|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
582         
583         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
584
585         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
586         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Record Mouse Movement|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
587         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
588         uiDefIconTextBlockBut(block, ipo_editmenu_joinmenu, NULL, ICON_RIGHTARROW_THIN, "Join", 0, yco-=20, 120, 19, "");       
589
590         if (!G.sipo->showkey){
591                 uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
592                 
593                 uiDefIconTextBlockBut(block, ipo_editmenu_extendmenu, NULL, ICON_RIGHTARROW_THIN, "Extend Mode", 0, yco-=20, 120, 19, "");      
594                 uiDefIconTextBlockBut(block, ipo_editmenu_intpolmenu, NULL, ICON_RIGHTARROW_THIN, "Interpolation Mode", 0, yco-=20, 120, 20, "");
595                 if(ei != NULL && (ei->flag & IPO_EDIT))
596                         uiDefIconTextBlockBut(block, ipo_editmenu_handlemenu, NULL, ICON_RIGHTARROW_THIN, "Handle Type", 0, yco-=20, 120, 19, "");
597                 if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0)
598                         uiDefIconTextBlockBut(block, ipo_editmenu_keymenu, NULL, ICON_RIGHTARROW_THIN, "Key Type", 0, yco-=20, 120, 19, "");
599         }
600         
601
602         if(curarea->headertype==HEADERTOP) {
603                 uiBlockSetDirection(block, UI_DOWN);
604         }
605         else {
606                 uiBlockSetDirection(block, UI_TOP);
607                 uiBlockFlipOrder(block);
608         }
609
610         uiTextBoundsBlock(block, 50);
611
612         return block;
613 }
614
615 static void do_ipo_viewmenu(void *arg, int event)
616 {
617         extern int play_anim(int mode);
618         
619         switch(event)
620         {
621         case 1:
622                 do_ipo_buttons(B_IPOHOME);
623                 break;
624         case 2:
625                 ipo_toggle_showkey();
626                 scrarea_queue_headredraw(curarea);
627                 scrarea_queue_winredraw(curarea);
628                 allqueue(REDRAWVIEW3D, 0);
629                 break;
630         case 3:
631                 move_to_frame();
632                 break;
633         case 4:
634                 mainqenter(PADPLUSKEY,1);
635                 break;
636         case 5:
637                 mainqenter(PADMINUS,1);
638                 break;
639         case 6: /* Play Animation */
640                 play_anim(0);
641                 break;
642         case 7: /* Play Animation in All */
643                 play_anim(1);
644                 break;  
645         case 8:
646                 add_blockhandler(curarea, IPO_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
647                 break;  
648         }
649 }
650
651 static uiBlock *ipo_viewmenu(void *arg_unused)
652 {
653         uiBlock *block;
654         EditIpo *ei;
655         short yco= 0, menuwidth=120;
656
657         ei = get_active_editipo();
658
659         block= uiNewBlock(&curarea->uiblocks, "ipo_viewmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
660         uiBlockSetButmFunc(block, do_ipo_viewmenu, NULL);
661
662
663         uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Channel Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
664         if (G.sipo->showkey)
665                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
666         else
667                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
668
669         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
670
671         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Out|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
672         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom In|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
673
674         uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
675         
676         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Animation|Alt A", 0, yco-=20, 
677                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
678         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Animation in 3D View|Alt Shift A", 0, yco-=20,
679                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
680
681         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
682
683         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
684
685         if (ei != NULL && (ei->flag & IPO_EDIT)) {
686                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Current Frame to Selected|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
687         }
688
689         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, "");
690         else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 20, "");
691
692         if(curarea->headertype==HEADERTOP) {
693                 uiBlockSetDirection(block, UI_DOWN);
694         }
695         else {
696                 uiBlockSetDirection(block, UI_TOP);
697                 uiBlockFlipOrder(block);
698         }
699
700         uiTextBoundsBlock(block, 50);
701
702         return block;
703 }
704
705 static void do_ipo_selectmenu(void *arg, int event)
706 {
707         switch(event)
708         {
709         case 0:
710                 borderselect_ipo();
711                 break;
712         case 1:
713                 swap_selectall_editipo();
714                 break;
715         }
716 }
717
718 static uiBlock *ipo_selectmenu(void *arg_unused)
719 {
720         uiBlock *block;
721         short yco= 0, menuwidth=120;
722
723         block= uiNewBlock(&curarea->uiblocks, "ipo_selectmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
724         uiBlockSetButmFunc(block, do_ipo_selectmenu, NULL);
725
726         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
727         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
728         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
729
730         if(curarea->headertype==HEADERTOP) {
731                 uiBlockSetDirection(block, UI_DOWN);
732         }
733         else {
734                 uiBlockSetDirection(block, UI_TOP);
735                 uiBlockFlipOrder(block);
736         }
737
738         uiTextBoundsBlock(block, 50);
739
740         return block;
741 }
742
743
744 static char *ipo_modeselect_pup(void)
745 {
746         Object *ob= OBACT;
747         static char string[1024];
748         char tmpstr[1024];
749         char formatstring[1024];
750
751         strcpy(string, "Ipo type: %t");
752         
753         strcpy(formatstring, "|%s %%x%d %%i%d");
754
755         if(ob) {
756                 sprintf(tmpstr,formatstring,"Object",ID_OB, ICON_OBJECT);
757                 strcat(string,tmpstr);
758         }
759
760         if(ob && give_current_material(ob, ob->actcol)) { // check for material
761                 sprintf(tmpstr,formatstring,"Material",ID_MA, ICON_MATERIAL);
762                 strcat(string,tmpstr);
763         }
764
765         if(G.scene->world) {
766                 sprintf(tmpstr,formatstring,"World",ID_WO, ICON_WORLD);
767                 strcat(string,tmpstr);
768         }
769
770         if(ob && ob->type==OB_CURVE) {
771                 sprintf(tmpstr,formatstring,"Path",ID_CU, ICON_CURVE);
772                 strcat(string,tmpstr);
773         }
774
775         if(ob && ob->type==OB_CAMERA) {
776                 sprintf(tmpstr,formatstring,"Camera",ID_CA, ICON_CAMERA);
777                 strcat(string,tmpstr);
778         }
779         
780         if(ob && ob->type==OB_LAMP) {
781                 sprintf(tmpstr,formatstring,"Lamp",ID_LA, ICON_LAMP);
782                 strcat(string,tmpstr);
783         }
784
785         if(ob && give_current_texture(ob, ob->actcol)) {
786                 sprintf(tmpstr,formatstring,"Texture",ID_TE, ICON_TEXTURE);
787                 strcat(string,tmpstr);
788         }
789
790         if(ob){
791                 if ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE) {
792                         sprintf(tmpstr,formatstring,"Shape",ID_KE, ICON_EDIT);
793                         strcat(string,tmpstr);
794                 }
795                 if (ob->type==OB_ARMATURE){
796                         sprintf(tmpstr,formatstring,"Pose",ID_PO, ICON_POSE_HLT);
797                         strcat(string,tmpstr);
798                 }
799 #ifdef __CON_IPO
800                 sprintf(tmpstr,formatstring,"Constraint",ID_CO, ICON_CONSTRAINT);
801                 strcat(string,tmpstr);
802 #endif
803         }
804
805         sprintf(tmpstr,formatstring,"Sequence",ID_SEQ, ICON_SEQUENCE);
806         strcat(string,tmpstr);
807
808
809         return (string);
810 }
811
812 void do_ipo_buttons(short event)
813 {
814         EditIpo *ei;
815         View2D *v2d;
816         rcti rect;
817         Object *ob= OBACT;
818         float xmin, ymin, dx, dy;
819         int a, val, first;
820         short mval[2];
821
822         if(curarea->win==0) return;
823
824         switch(event) {
825         case B_IPOHOME:
826
827                 /* boundbox */
828
829                 v2d= &(G.sipo->v2d);
830                 first= 1;
831
832                 ei= G.sipo->editipo;
833                 if(ei==0) return;
834                 for(a=0; a<G.sipo->totipo; a++, ei++) {
835                         if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
836                         
837                                 boundbox_ipocurve(ei->icu);
838                                 
839                                 if(first) {
840                                         v2d->tot= ei->icu->totrct;
841                                         first= 0;
842                                 }
843                                 else BLI_union_rctf(&(v2d->tot), &(ei->icu->totrct));
844                         }
845                 }
846
847                 /* speciale home */
848                 if(G.qual & LR_SHIFTKEY) {
849                         v2d->tot.xmin= SFRA;
850                         v2d->tot.xmax= EFRA;
851                 }
852
853                 /* zoom out a bit */
854                 dx= 0.10*(v2d->tot.xmax-v2d->tot.xmin);
855                 dy= 0.10*(v2d->tot.ymax-v2d->tot.ymin);
856                 
857                 if(dx<v2d->min[0]) dx= v2d->min[0];
858                 if(dy<v2d->min[1]) dy= v2d->min[1];
859                 
860                 v2d->cur.xmin= v2d->tot.xmin- dx;
861                 v2d->cur.xmax= v2d->tot.xmax+ dx;
862                 v2d->cur.ymin= v2d->tot.ymin- dy;
863                 v2d->cur.ymax= v2d->tot.ymax+ dy;
864
865                 test_view2d(G.v2d, curarea->winx, curarea->winy);
866                 if(G.sipo->ipo) G.sipo->ipo->cur = G.v2d->cur;
867                 
868                 scrarea_queue_winredraw(curarea);
869                 break;
870         case B_IPOBORDER:
871                 val= get_border(&rect, 2);
872                 if(val) {
873                         mval[0]= rect.xmin;
874                         mval[1]= rect.ymin;
875                         areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
876                         mval[0]= rect.xmax;
877                         mval[1]= rect.ymax;
878                         areamouseco_to_ipoco(G.v2d, mval, &(G.v2d->cur.xmax), &(G.v2d->cur.ymax));
879                         G.v2d->cur.xmin= xmin;
880                         G.v2d->cur.ymin= ymin;
881                         
882                         test_view2d(G.v2d, curarea->winx, curarea->winy);
883                         scrarea_queue_winredraw(curarea);
884                 }
885                 break;
886
887         case B_IPOPIN:
888                 allqueue (REDRAWIPO, 0);
889                 break;
890
891         case B_IPOCOPY:
892                 copy_editipo();
893                 break;
894         case B_IPOPASTE:
895                 paste_editipo();
896                 break;
897         case B_IPOCONT:
898                 set_exprap_ipo(IPO_HORIZ);
899                 break;
900         case B_IPOEXTRAP:
901                 set_exprap_ipo(IPO_DIR);
902                 break;
903         case B_IPOCYCLIC:
904                 set_exprap_ipo(IPO_CYCL);
905                 break;
906         case B_IPOCYCLICX:
907                 set_exprap_ipo(IPO_CYCLX);
908                 break;
909         case B_IPOMAIN:
910                 scrarea_queue_winredraw(curarea);
911                 scrarea_queue_headredraw(curarea);
912                 if(ob) ob->ipowin= G.sipo->blocktype;
913                 break;
914         case B_IPOSHOWKEY:
915                 /* reverse value because of winqread */
916                 G.sipo->showkey= 1-G.sipo->showkey;
917                 ipo_toggle_showkey();
918                 scrarea_queue_headredraw(curarea);
919                 scrarea_queue_winredraw(curarea);
920                 allqueue(REDRAWVIEW3D, 0);
921                 break;
922         case B_VIEW2DZOOM:
923                 viewmovetemp= 0;
924                 view2dzoom(event);
925                 scrarea_queue_headredraw(curarea);
926                 break;
927         case B_IPO_ACTION_OB:
928                 if(ob && G.sipo->from && G.sipo->pin==0) {
929                         if(ob->ipoflag & OB_ACTION_OB) {        /* check if channel exists, and flip ipo link */
930                                 bActionChannel *achan;
931                                 
932                                 if(ob->action==NULL) 
933                                         ob->action= add_empty_action(ID_OB);
934                                 achan= verify_action_channel(ob->action, "Object");
935                                 if(achan->ipo==NULL && ob->ipo) {
936                                         achan->ipo= ob->ipo;
937                                         ob->ipo= NULL;
938                                 }
939                                 
940                                 /* object constraints */
941                                 if(ob->constraintChannels.first) {
942                                         free_constraint_channels(&achan->constraintChannels);
943                                         achan->constraintChannels= ob->constraintChannels;
944                                         ob->constraintChannels.first= ob->constraintChannels.last= NULL;
945                                 }
946                         }
947                         else if(ob->action) {
948                                 bActionChannel *achan= get_action_channel(ob->action, "Object");
949                                 if(achan) {
950                                         
951                                         if(achan->ipo && ob->ipo==NULL) {
952                                                 ob->ipo= achan->ipo;
953                                                 achan->ipo= NULL;
954                                         }
955                                         
956                                         /* object constraints */
957                                         if(achan->constraintChannels.first) {
958                                                 free_constraint_channels(&ob->constraintChannels);
959                                                 ob->constraintChannels= achan->constraintChannels;
960                                                 achan->constraintChannels.first= achan->constraintChannels.last= NULL;
961                                         }
962                                 }
963                         }
964                         allqueue(REDRAWVIEW3D, 0);
965                         allqueue(REDRAWIPO, 0);
966                         allqueue(REDRAWACTION, 0);
967                         allqueue(REDRAWOOPS, 0);
968                         allqueue(REDRAWNLA, 0);
969                 }
970                 break;
971         case B_IPO_ACTION_KEY:
972                 
973                 break;
974         } 
975 }
976
977 void ipo_buttons(void)
978 {
979         Object *ob;
980         EditIpo *ei;
981         uiBlock *block;
982         short xco,xmax;
983         char naam[20];
984         int icon=0;
985
986         sprintf(naam, "header %d", curarea->headwin);
987         block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSS, UI_HELV, curarea->headwin);
988
989         if(area_is_active_area(curarea)) uiBlockSetCol(block, TH_HEADER);
990         else uiBlockSetCol(block, TH_HEADERDESEL);
991
992         curarea->butspacetype= SPACE_IPO;
993
994         xco = 8;
995         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.");
996         xco+= XIC+14;
997         
998         test_editipo(); /* test if current editipo is OK, make_editipo sets v2d->cur */
999
1000         uiBlockSetEmboss(block, UI_EMBOSSN);
1001         if(curarea->flag & HEADER_NO_PULLDOWN) {
1002                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_RIGHT,
1003                                 xco,2,XIC,YIC-2,
1004                                 &(curarea->flag), 0, 0, 0, 0, "Enables display of pulldown menus");
1005         } else {
1006                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_DOWN,
1007                                 xco,2,XIC,YIC-2,
1008                                 &(curarea->flag), 0, 0, 0, 0, "Hides pulldown menus");
1009         }
1010         uiBlockSetEmboss(block, UI_EMBOSS);
1011         xco+=XIC;
1012
1013         /* pull down menus */
1014         if((curarea->flag & HEADER_NO_PULLDOWN)==0) {
1015                 uiBlockSetEmboss(block, UI_EMBOSSP);
1016         
1017                 ei = get_active_editipo();
1018         
1019                 xmax= GetButStringLength("View");
1020                 uiDefPulldownBut(block,ipo_viewmenu, NULL, "View", xco, -2, xmax-3, 24, "");
1021                 xco+=xmax;
1022         
1023                 xmax= GetButStringLength("Select");
1024                 uiDefPulldownBut(block,ipo_selectmenu, NULL, "Select", xco, -2, xmax-3, 24, "");
1025                 xco+=xmax;
1026         
1027                 if (G.sipo->showkey) {
1028                         xmax= GetButStringLength("Key");
1029                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Key", xco, -2, xmax-3, 24, "");
1030                 }
1031                 else if(ei != NULL && (ei->flag & IPO_EDIT)) {
1032                         xmax= GetButStringLength("Point");
1033                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Point", xco, -2, xmax-3, 24, "");
1034                 }
1035                 else {
1036                         xmax= GetButStringLength("Curve");
1037                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Curve", xco, -2, xmax-3, 24, "");
1038                 }
1039                         
1040                 xco+=xmax;
1041         }
1042
1043         /* end of pull down menus */
1044         uiBlockSetEmboss(block, UI_EMBOSS);
1045
1046         ob= OBACT;
1047         
1048         /* action switch option, only when active object is there and no pin */
1049         uiSetButLock(G.sipo->pin, "Can't change because of pinned data");
1050         
1051         /* define whether ipos are on Object or on action */
1052         if(ob) {
1053                 static short fake1= 1;
1054                 
1055                 uiBlockBeginAlign(block);
1056                 
1057                 if(G.sipo->blocktype==ID_OB) {
1058                         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");
1059                         xco+= XIC;
1060                 }
1061                 else if(G.sipo->blocktype==ID_KE) {
1062                         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");
1063                         xco+= XIC;
1064                 }
1065                 else if(G.sipo->blocktype==ID_CO) {
1066                         
1067                         if(G.sipo->from && G.sipo->actname[0]==0)
1068                                 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");
1069                         else {
1070                                 uiSetButLock(1, "Pose Constraint Ipo cannot be switched");
1071                                 uiDefIconButS(block, TOG, 1, ICON_ACTION,       xco,0,XIC,YIC, &fake1, 0, 0, 0, 0, "Ipo is connected to Pose Action");
1072                         }
1073                         xco+= XIC;
1074                 }
1075                 else if(G.sipo->blocktype==ID_PO) {     /* only to indicate we have action ipos */
1076                         uiSetButLock(1, "Pose Action Ipo cannot be switched");
1077                         uiDefIconButS(block, TOG, 1, ICON_ACTION,       xco,0,XIC,YIC, &fake1, 0, 0, 0, 0, "Ipo is connected to Pose Action");
1078                         xco+= XIC;
1079                 }
1080                 uiClearButLock();
1081         }
1082         
1083         /* mainmenu, only when data is there and no pin */
1084         uiSetButLock(G.sipo->pin, "Can't change because of pinned data");
1085
1086         if (G.sipo->blocktype == ID_OB)
1087                 icon = ICON_OBJECT;
1088         else if (G.sipo->blocktype == ID_MA)
1089                 icon = ICON_MATERIAL;
1090         else if (G.sipo->blocktype == ID_WO)
1091                 icon = ICON_WORLD;
1092         else if (G.sipo->blocktype == ID_CU)
1093                 icon = ICON_ANIM;
1094         else if (G.sipo->blocktype == ID_CA)
1095                 icon = ICON_CAMERA;
1096         else if (G.sipo->blocktype == ID_LA)
1097                 icon = ICON_LAMP;
1098         else if (G.sipo->blocktype == ID_KE)
1099                 icon = ICON_EDIT;
1100         else if (G.sipo->blocktype == ID_PO)
1101                 icon = ICON_POSE_HLT;
1102         else if (G.sipo->blocktype == ID_CO)
1103                 icon = ICON_CONSTRAINT;
1104         else if (G.sipo->blocktype == ID_SEQ)
1105                 icon = ICON_SEQUENCE;
1106         else if(G.sipo->blocktype == ID_TE)
1107                 icon = ICON_TEXTURE;
1108
1109         uiDefIconTextButS(block, MENU, B_IPOMAIN, icon, ipo_modeselect_pup(), xco,0,100,20, &(G.sipo->blocktype), 0, 0, 0, 0, "Show IPO type");
1110
1111         xco += 85;
1112
1113         if(G.sipo->blocktype==ID_MA) {
1114                 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.");
1115                 xco-= 4;
1116         }
1117         if(G.sipo->blocktype==ID_WO) {
1118                 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.");
1119                 xco-= 4;
1120         }
1121         
1122         if(G.sipo->blocktype==ID_LA) {
1123                 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. ");
1124                 xco-= 4;
1125         }
1126         
1127         uiBlockEndAlign(block);
1128         
1129         uiClearButLock();
1130
1131         xco= std_libbuttons(block, (short)(xco+1.5*XIC), 0, B_IPOPIN, &G.sipo->pin, B_IPOBROWSE, (ID*)G.sipo->ipo, G.sipo->from, &(G.sipo->menunr), B_IPOALONE, B_IPOLOCAL, B_IPODELETE, 0, B_KEEPDATA);
1132
1133         /* COPY PASTE */
1134         xco-= XIC/2;
1135         if(curarea->headertype==HEADERTOP) {
1136                 uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYUP,        xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
1137                 uiSetButLock(G.sipo->ipo && G.sipo->ipo->id.lib, "Can't edit library data");
1138                 uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEUP,      xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
1139         }
1140         else {
1141                 uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYDOWN,      xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
1142                 uiSetButLock(G.sipo->ipo && G.sipo->ipo->id.lib, "Can't edit library data");
1143                 uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEDOWN,    xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
1144         }
1145         xco+=XIC/2;
1146         
1147         uiClearButLock();
1148         /* ZOOMBORDER */
1149         uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE,  xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area");
1150         
1151         /* draw LOCK */
1152         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");
1153
1154         /* always do as last */
1155         curarea->headbutlen= xco+2*XIC;
1156
1157         uiDrawBlock(block);
1158 }