Fix for weight painting errors, as reported by Bassam.
[blender.git] / source / blender / src / buttons_object.c
1 /**
2  * $Id: 
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <time.h>
34 #include <math.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #include "MEM_guardedalloc.h"
43
44 #include "DNA_screen_types.h"
45 #include "DNA_space_types.h"
46 #include "DNA_scene_types.h"
47
48 #include "BKE_action.h"
49 #include "BKE_global.h"
50 #include "BKE_main.h"
51 #include "BKE_library.h"
52 #include "BKE_softbody.h"
53
54 #include "BLI_blenlib.h"
55 #include "BLI_arithb.h"
56
57 #include "BSE_filesel.h"
58 #include "BSE_headerbuttons.h"
59
60 #include "BIF_butspace.h"
61 #include "BDR_editcurve.h"
62 #include "BIF_gl.h"
63 #include "BIF_glutil.h"
64 #include "BIF_graphics.h"
65 #include "BIF_interface.h"
66 #include "BIF_keyval.h"
67 #include "BIF_mainqueue.h"
68 #include "BIF_mywindow.h"
69 #include "BIF_poseobject.h"
70 #include "BIF_resources.h"
71 #include "BIF_screen.h"
72 #include "BIF_space.h"
73 #include "BIF_toolbox.h"
74
75 #include "BDR_drawobject.h"
76
77 #include "mydevice.h"
78 #include "blendef.h"
79
80 /* -----includes for this file specific----- */
81
82
83 #include "DNA_action_types.h"
84 #include "DNA_armature_types.h"
85 #include "DNA_camera_types.h"
86 #include "DNA_constraint_types.h"
87 #include "DNA_curve_types.h"
88 #include "DNA_effect_types.h"
89 #include "DNA_group_types.h"
90 #include "DNA_image_types.h"
91 #include "DNA_key_types.h"
92 #include "DNA_lamp_types.h"
93 #include "DNA_lattice_types.h"
94 #include "DNA_material_types.h"
95 #include "DNA_meta_types.h"
96 #include "DNA_mesh_types.h"
97 #include "DNA_modifier_types.h"
98 #include "DNA_object_types.h"
99 #include "DNA_object_force.h"
100 #include "DNA_radio_types.h"
101 #include "DNA_screen_types.h"
102 #include "DNA_sound_types.h"
103 #include "DNA_texture_types.h"
104 #include "DNA_userdef_types.h"
105 #include "DNA_vfont_types.h"
106 #include "DNA_view3d_types.h"
107 #include "DNA_world_types.h"
108
109 #include "BKE_anim.h"
110 #include "BKE_armature.h"
111 #include "BKE_constraint.h"
112 #include "BKE_curve.h"
113 #include "BKE_depsgraph.h"
114 #include "BKE_displist.h"
115 #include "BKE_effect.h"
116 #include "BKE_font.h"
117 #include "BKE_image.h"
118 #include "BKE_ipo.h"
119 #include "BKE_lattice.h"
120 #include "BKE_material.h"
121 #include "BKE_mball.h"
122 #include "BKE_mesh.h"
123 #include "BKE_modifier.h"
124 #include "BKE_object.h"
125 #include "BKE_sound.h"
126 #include "BKE_texture.h"
127 #include "BKE_utildefines.h"
128 #include "BKE_DerivedMesh.h"
129
130 #include "BIF_editconstraint.h"
131 #include "BSE_editipo.h"
132 #include "BDR_editobject.h"
133
134 #include "butspace.h" // own module
135
136 static float prspeed=0.0;
137 float prlen=0.0;
138
139
140 /* ********************* CONSTRAINT ***************************** */
141
142 static void constraint_active_func(void *ob_v, void *con_v)
143 {
144         Object *ob= ob_v;
145         bConstraint *con;
146         ListBase *lb;
147         
148         /* lets be nice and escape if its active already */
149         if(con_v) {
150                 con= con_v;
151                 if(con->flag & CONSTRAINT_ACTIVE) return;
152         }
153         
154         lb= get_active_constraints(ob);
155         
156         for(con= lb->first; con; con= con->next) {
157                 if(con==con_v) con->flag |= CONSTRAINT_ACTIVE;
158                 else con->flag &= ~CONSTRAINT_ACTIVE;
159         }
160
161         /* make sure ipowin and buttons shows it */
162         if(ob->ipowin==IPO_CO) {
163                 allqueue(REDRAWIPO, IPO_CO);
164                 allspace(REMAKEIPO, 0);
165                 allqueue(REDRAWNLA, 0);
166         }
167         allqueue(REDRAWBUTSOBJECT, 0);
168 }
169
170 static void add_constraint_to_active(Object *ob, bConstraint *con)
171 {
172         ListBase *list;
173         
174         list = get_active_constraints(ob);
175         if (list) {
176                 unique_constraint_name(con, list);
177                 BLI_addtail(list, con);
178                 
179                 con->flag |= CONSTRAINT_ACTIVE;
180                 for(con= con->prev; con; con= con->prev)
181                         con->flag &= ~CONSTRAINT_ACTIVE;
182         }
183 }
184
185 static void enable_constraint_ipo_func (void *ob_v, void *con_v)
186 {
187         Object *ob= ob_v;
188         bConstraint *con = con_v;
189         bConstraintChannel *chan;
190         ListBase *conbase;
191
192         conbase = get_active_constraint_channels(ob, 1);        // 1 == create
193
194         if (!conbase)
195                 return;
196
197         /* See if this list already has an appropriate channel */
198         chan = find_constraint_channel(conbase, con->name);
199
200         if (!chan){
201                 /* Add a new constraint channel */
202                 chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
203                 strcpy(chan->name, con->name);
204                 BLI_addtail(conbase, chan);
205         }
206
207         /* Ensure there is an ipo to display */
208         if (!chan->ipo){
209                 chan->ipo = add_ipo(con->name, IPO_CO);
210         }
211
212         /* make sure ipowin shows it */
213         ob->ipowin= IPO_CO;
214         allqueue(REDRAWIPO, IPO_CO);
215         allspace(REMAKEIPO, 0);
216         allqueue(REDRAWNLA, 0);
217 }
218
219
220 static void add_influence_key_to_constraint_func (void *ob_v, void *con_v)
221 {
222         Object *ob= ob_v;
223         bConstraint *con = con_v;
224         bConstraintChannel *chan;
225         ListBase *conbase;
226         IpoCurve *icu;
227         
228         conbase = get_active_constraint_channels(ob, 1);        // 1=make
229         
230         if (!conbase)
231                 return;
232         
233         /* See if this list already has an appropriate channel */
234         chan = find_constraint_channel(conbase, con->name);
235         
236         if (!chan){
237                 /* Add a new constraint channel */
238                 chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
239                 strcpy(chan->name, con->name);
240                 BLI_addtail(conbase, chan);
241         }
242         
243         /* Ensure there is an ipo to display */
244         if (!chan->ipo){
245                 chan->ipo = add_ipo(con->name, IPO_CO);
246         }
247         
248         /* now insert an ipo key */
249         icu= get_ipocurve(NULL, IPO_CO, CO_ENFORCE, chan->ipo);
250         insert_vert_ipo(icu, CFRA, con->enforce);
251         
252         /* make sure ipowin shows it */
253         ob->ipowin= IPO_CO;
254         allqueue(REDRAWIPO, IPO_CO);
255         allspace(REMAKEIPO, 0);
256         allqueue(REDRAWNLA, 0);
257         
258         BIF_undo_push("Insert Influence Key");
259 }
260
261
262 static void del_constraint_func (void *ob_v, void *con_v)
263 {
264         bConstraint *con= con_v;
265         bConstraintChannel *chan;
266         ListBase *lb;
267         
268         /* remove ipo channel */
269         lb= get_active_constraint_channels(ob_v, 0);
270         if(lb) {
271                 chan = find_constraint_channel(lb, con->name);
272                 if(chan) {
273                         if(chan->ipo) chan->ipo->id.us--;
274                         BLI_freelinkN(lb, chan);
275                 }
276         }
277         /* remove constraint itself */
278         lb= get_active_constraints(ob_v);
279         free_constraint_data (con);
280         BLI_freelinkN(lb, con);
281         
282         constraint_active_func(ob_v, NULL);
283
284         BIF_undo_push("Delete constraint");
285         allqueue(REDRAWBUTSOBJECT, 0);
286         allqueue(REDRAWIPO, 0); 
287
288 }
289
290 static void verify_constraint_name_func (void *ob_v, void *con_v)
291 {
292         ListBase *conlist;
293         bConstraint *con= con_v;
294         
295         if (!con)
296                 return;
297         
298         conlist = get_active_constraints(ob_v);
299         unique_constraint_name (con, conlist);
300         constraint_active_func(ob_v, con);
301
302 }
303
304 static void get_constraint_typestring (char *str, bConstraint *con)
305 {
306         switch (con->type){
307         case CONSTRAINT_TYPE_CHILDOF:
308                 strcpy (str, "Child Of");
309                 return;
310         case CONSTRAINT_TYPE_NULL:
311                 strcpy (str, "Null");
312                 return;
313         case CONSTRAINT_TYPE_TRACKTO:
314                 strcpy (str, "Track To");
315                 return;
316         case CONSTRAINT_TYPE_MINMAX:
317                 strcpy (str, "Floor");
318                 return;
319         case CONSTRAINT_TYPE_KINEMATIC:
320                 strcpy (str, "IK Solver");
321                 return;
322         case CONSTRAINT_TYPE_ROTLIKE:
323                 strcpy (str, "Copy Rotation");
324                 return;
325         case CONSTRAINT_TYPE_LOCLIKE:
326                 strcpy (str, "Copy Location");
327                 return;
328         case CONSTRAINT_TYPE_ACTION:
329                 strcpy (str, "Action");
330                 return;
331         case CONSTRAINT_TYPE_LOCKTRACK:
332                 strcpy (str, "Locked Track");
333                 return;
334         case CONSTRAINT_TYPE_FOLLOWPATH:
335                 strcpy (str, "Follow Path");
336                 return;
337         case CONSTRAINT_TYPE_STRETCHTO:
338                 strcpy (str, "Stretch To");
339                 return;
340         default:
341                 strcpy (str, "Unknown");
342                 return;
343         }
344 }
345
346 static int get_constraint_col(bConstraint *con)
347 {
348         switch (con->type) {
349         case CONSTRAINT_TYPE_NULL:
350                 return TH_BUT_NEUTRAL;
351         case CONSTRAINT_TYPE_KINEMATIC:
352                 return TH_BUT_SETTING2;
353         case CONSTRAINT_TYPE_TRACKTO:
354                 return TH_BUT_SETTING;
355         case CONSTRAINT_TYPE_ROTLIKE:
356                 return TH_BUT_SETTING1;
357         case CONSTRAINT_TYPE_LOCLIKE:
358                 return TH_BUT_POPUP;
359         case CONSTRAINT_TYPE_MINMAX:
360                 return TH_BUT_POPUP;
361         case CONSTRAINT_TYPE_ACTION:
362                 return TH_BUT_ACTION;
363         case CONSTRAINT_TYPE_LOCKTRACK:
364                 return TH_BUT_SETTING;
365         case CONSTRAINT_TYPE_FOLLOWPATH:
366                 return TH_BUT_SETTING2;
367         case CONSTRAINT_TYPE_STRETCHTO:
368                 return TH_BUT_SETTING;
369         default:
370                 return TH_REDALERT;
371         }
372 }
373
374 static void constraint_moveUp(void *ob_v, void *con_v)
375 {
376         bConstraint *con, *constr= con_v;
377         ListBase *conlist;
378         
379         if(constr->prev) {
380                 conlist = get_active_constraints(ob_v);
381                 for(con= conlist->first; con; con= con->next) {
382                         if(con==constr) {
383                                 BLI_remlink(conlist, con);
384                                 BLI_insertlink(conlist, con->prev->prev, con);
385                                 break;
386                         }
387                 }
388         }
389         BIF_undo_push("Move constraint");
390 }
391
392 static void constraint_moveDown(void *ob_v, void *con_v)
393 {
394         bConstraint *con, *constr= con_v;
395         ListBase *conlist;
396         
397         if(constr->next) {
398                 conlist = get_active_constraints(ob_v);
399                 for(con= conlist->first; con; con= con->next) {
400                         if(con==constr) {
401                                 BLI_remlink(conlist, con);
402                                 BLI_insertlink(conlist, con->next, con);
403                                 break;
404                         }
405                 }
406         }
407         BIF_undo_push("Move constraint");
408 }
409
410
411 static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, short *xco, short *yco)
412 {
413         Object *ob= OBACT;
414         uiBut *but;
415         char typestr[64];
416         short height, width = 265;
417         int curCol, rb_col;
418
419         /* unless button has own callback, it adds this callback to button */
420         uiBlockSetFunc(block, constraint_active_func, ob, con);
421         
422         get_constraint_typestring (typestr, con);
423
424         curCol = get_constraint_col(con);
425
426         /* Draw constraint header */
427         uiBlockSetEmboss(block, UI_EMBOSSN);
428         
429         /* rounded header */
430         rb_col= (con->flag & CONSTRAINT_ACTIVE)?10:-10;
431         uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-1, width+40, 22, NULL, 5.0, 0.0, 
432                          (con->flag & CONSTRAINT_EXPAND)?3:15 , rb_col-20, ""); 
433         
434         /* open/close */
435         uiDefIconButBitS(block, ICONTOG, CONSTRAINT_EXPAND, B_CONSTRAINT_TEST, ICON_DISCLOSURE_TRI_RIGHT, *xco-10, *yco, 20, 20, &con->flag, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Constraint");
436         
437         /* up down */
438         uiBlockSetEmboss(block, UI_EMBOSS);
439         but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier up in stack");
440         uiButSetFunc(but, constraint_moveUp, ob, con);
441         
442         but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+20, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier down in stack");
443         uiButSetFunc(but, constraint_moveDown, ob, con);
444         
445         if (con->flag & CONSTRAINT_EXPAND) {
446                 
447                 if (con->flag & CONSTRAINT_DISABLE) {
448                         BIF_ThemeColor(TH_REDALERT);
449                         uiBlockSetCol(block, TH_REDALERT);
450                 }
451                 else
452                         BIF_ThemeColor(curCol);
453
454                 /*if (type==TARGET_BONE)
455                         but = uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Bone Constraint%t|Track To%x2|IK Solver%x3|Copy Rotation%x8|Copy Location%x9|Action%x12|Null%x0", *xco+20, *yco, 100, 20, &con->type, 0.0, 0.0, 0.0, 0.0, "Constraint type"); 
456                 else
457                         but = uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Object Constraint%t|Track To%x2|Copy Rotation%x8|Copy Location%x9|Null%x0", *xco+20, *yco, 100, 20, &con->type, 0.0, 0.0, 0.0, 0.0, "Constraint type"); 
458                 */
459                 uiBlockSetEmboss(block, UI_EMBOSS);
460                 
461                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, *xco+10, *yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
462                 
463                 but = uiDefBut(block, TEX, B_CONSTRAINT_TEST, "", *xco+120, *yco, 85, 18, con->name, 0.0, 29.0, 0.0, 0.0, "Constraint name"); 
464                 uiButSetFunc(but, verify_constraint_name_func, ob, con);
465         }       
466         else{
467                 uiBlockSetEmboss(block, UI_EMBOSSN);
468
469                 if (con->flag & CONSTRAINT_DISABLE) {
470                         uiBlockSetCol(block, TH_REDALERT);
471                         BIF_ThemeColor(TH_REDALERT);
472                 }
473                 else
474                         BIF_ThemeColor(curCol);
475                 
476                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, *xco+10, *yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
477                 
478                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, con->name, *xco+120, *yco-1, 135, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
479         }
480
481         uiBlockSetCol(block, TH_AUTO);  
482         
483         uiBlockSetEmboss(block, UI_EMBOSSN);
484         
485         but = uiDefIconBut(block, BUT, B_CONSTRAINT_CHANGETARGET, ICON_X, *xco+262, *yco, 19, 19, list, 0.0, 0.0, 0.0, 0.0, "Delete constraint");
486         uiButSetFunc(but, del_constraint_func, ob, con);
487
488         uiBlockSetEmboss(block, UI_EMBOSS);
489
490
491         /* Draw constraint data*/
492         if (!(con->flag & CONSTRAINT_EXPAND)) {
493                 (*yco)-=21;
494         }
495         else {
496                 switch (con->type){
497                 case CONSTRAINT_TYPE_ACTION:
498                         {
499                                 bActionConstraint *data = con->data;
500                                 bArmature *arm;
501
502                                 height = 88;
503                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
504                                 
505                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
506
507                                 /* Draw target parameters */
508                                 uiBlockBeginAlign(block);
509                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
510
511                                 arm = get_armature(data->tar);
512                                 if (arm){
513                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
514                                 }
515                                 else
516                                         strcpy (data->subtarget, "");
517                                 uiBlockEndAlign(block);
518
519                                 /* Draw action button */
520                                 uiBlockBeginAlign(block);
521                                 uiDefButS(block, TOG, B_CONSTRAINT_TEST, "Local",                                               *xco+((width/2)-117), *yco-46, 78, 18, &data->local, 0, 0, 0, 0, "Use true local rotation difference");
522                                 uiDefIDPoinBut(block, test_actionpoin_but, B_CONSTRAINT_TEST, "AC:",    *xco+((width/2)-117), *yco-64, 78, 18, &data->act, "Action containing the keyed motion for this bone"); 
523                                 uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Key on%t|X Rot%x0|Y Rot%x1|Z Rot%x2", *xco+((width/2)-117), *yco-84, 78, 18, &data->type, 0, 24, 0, 0, "Specify which transformation channel from the target is used to key the action");
524
525                                 uiBlockBeginAlign(block);
526                                 uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Start:", *xco+((width/2)-36), *yco-64, 78, 18, &data->start, 1, MAXFRAME, 0.0, 0.0, "Starting frame of the keyed motion"); 
527                                 uiDefButS(block, NUM, B_CONSTRAINT_TEST, "End:", *xco+((width/2)-36), *yco-84, 78, 18, &data->end, 1, MAXFRAME, 0.0, 0.0, "Ending frame of the keyed motion"); 
528                                 
529                                 uiBlockBeginAlign(block);
530                                 uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Min:", *xco+((width/2)+45), *yco-64, 78, 18, &data->min, -180, 180, 0, 0, "Minimum value for target channel range");
531                                 uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Max:", *xco+((width/2)+45), *yco-84, 78, 18, &data->max, -180, 180, 0, 0, "Maximum value for target channel range");
532                                 uiBlockEndAlign(block);
533                         }
534                         break;
535                 case CONSTRAINT_TYPE_LOCLIKE:
536                         {
537                                 bLocateLikeConstraint *data = con->data;
538                                 bArmature *arm;
539                                 
540                                 height = 66;
541                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
542
543                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
544
545                                 /* Draw target parameters */
546                                 uiBlockBeginAlign(block);
547                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
548
549                                 arm = get_armature(data->tar);
550                                 if (arm){
551                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
552                                 }
553                                 else
554                                         strcpy (data->subtarget, "");
555                                 uiBlockEndAlign(block);
556                                 
557                                 /* Draw XYZ toggles */
558                                 uiBlockBeginAlign(block);
559                                 but=uiDefButBitI(block, TOG, LOCLIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
560                                 but=uiDefButBitI(block, TOG, LOCLIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
561                                 but=uiDefButBitI(block, TOG, LOCLIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
562                                 uiBlockEndAlign(block);
563                         }
564                         break;
565                 case CONSTRAINT_TYPE_ROTLIKE:
566                         {
567                                 bRotateLikeConstraint *data = con->data;
568                                 bArmature *arm;
569                                 
570                                 height = 46;
571                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
572                                 
573                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
574
575                                 /* Draw target parameters */
576                                 uiBlockBeginAlign(block);
577                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
578
579                                 arm = get_armature(data->tar);
580                                 if (arm){
581                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
582                                 }
583                                 else
584                                         strcpy (data->subtarget, "");
585                                 uiBlockEndAlign(block);
586                         }
587                         break;
588                 case CONSTRAINT_TYPE_KINEMATIC:
589                         {
590                                 bKinematicConstraint *data = con->data;
591                                 bArmature *arm;
592                                 
593                                 height = 108;
594                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
595                                 
596                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
597
598                                 /* Draw target parameters */
599                                 uiDefButBitS(block, TOG, CONSTRAINT_IK_ROT, B_CONSTRAINT_TEST, "Rot", *xco, *yco-24,60,19, &data->flag, 0, 0, 0, 0, "Chain follows rotation of target");
600                                 
601                                 uiBlockBeginAlign(block);
602                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 19, &data->tar, "Target Object"); 
603
604                                 arm = get_armature(data->tar);
605                                 if (arm)
606                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,19, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
607                                 else
608                                         strcpy (data->subtarget, "");
609         
610                                 uiBlockBeginAlign(block);
611                                 uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tip", *xco, *yco-64, 142, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tip als last element in Chain");
612                                 uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco+142, *yco-64,143,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain");
613                                 
614                                 uiBlockBeginAlign(block);
615                                 uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco, *yco-86, 142, 19, &data->weight, 0.01, 1.0, 2, 2, "For Tree-IK: weight of position control for this target");
616                                 uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "RotW ", *xco+142, *yco-86, 143, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target");
617                                 uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Tolerance:", *xco, *yco-106, 142, 19, &data->tolerance, 0.0001f, 1.0, 0, 0, "Maximum distance to target after solving"); 
618                                 uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+142, *yco-106, 143, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations"); 
619                                 
620                         }
621                         break;
622                 case CONSTRAINT_TYPE_TRACKTO:
623                         {
624                                 bTrackToConstraint *data = con->data;
625                                 bArmature *arm;
626
627                                 height = 66;
628                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
629                                 
630                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
631
632                                 /* Draw target parameters */
633                                 uiBlockBeginAlign(block);
634                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
635
636                                 arm = get_armature(data->tar);
637                                 if (arm){
638                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
639                                 }
640                                 else
641                                         strcpy (data->subtarget, "");
642                                 uiBlockEndAlign(block);
643
644                                 uiBlockBeginAlign(block);
645                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "To:", *xco+12, *yco-64, 25, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
646                                 
647                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",     *xco+39, *yco-64,17,18, &data->reserved1, 12.0, 0.0, 0, 0, "The axis that points to the target object");
648                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y",     *xco+56, *yco-64,17,18, &data->reserved1, 12.0, 1.0, 0, 0, "The axis that points to the target object");
649                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",     *xco+73, *yco-64,17,18, &data->reserved1, 12.0, 2.0, 0, 0, "The axis that points to the target object");
650                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X",    *xco+90, *yco-64,24,18, &data->reserved1, 12.0, 3.0, 0, 0, "The axis that points to the target object");
651                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y",    *xco+114, *yco-64,24,18, &data->reserved1, 12.0, 4.0, 0, 0, "The axis that points to the target object");
652                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z",    *xco+138, *yco-64,24,18, &data->reserved1, 12.0, 5.0, 0, 0, "The axis that points to the target object");
653                                 uiBlockEndAlign(block);
654                                 
655                                 uiBlockBeginAlign(block);
656                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Up:", *xco+174, *yco-64, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
657                                 
658                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",     *xco+204, *yco-64,17,18, &data->reserved2, 13.0, 0.0, 0, 0, "The axis that points upward");
659                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y",     *xco+221, *yco-64,17,18, &data->reserved2, 13.0, 1.0, 0, 0, "The axis that points upward");
660                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",     *xco+238, *yco-64,17,18, &data->reserved2, 13.0, 2.0, 0, 0, "The axis that points upward");
661                                 uiBlockEndAlign(block);
662                         }
663                         break;
664                 case CONSTRAINT_TYPE_MINMAX:
665                         {
666                                 bMinMaxConstraint *data = con->data;
667                                 bArmature *arm;
668
669                                 height = 66;
670                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
671                                 
672                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
673
674                                 uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Offset:", *xco, *yco-44, 100, 18, &data->offset, -100, 100, 100.0, 0.0, "Offset from the position of the object center"); 
675
676                                 /* Draw target parameters */
677                                 uiBlockBeginAlign(block);
678                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
679
680                                 arm = get_armature(data->tar);
681                                 if (arm){
682                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
683                                 }
684                                 else
685                                         strcpy (data->subtarget, "");
686                                 uiBlockEndAlign(block);
687
688                                 but=uiDefButBitS(block, TOG, 1, B_CONSTRAINT_TEST, "Sticky", *xco, *yco-24, 54, 18, &data->sticky, 0, 24, 0, 0, "Immobilize object while constrained");
689                                 
690                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Max/Min:", *xco-8, *yco-64, 54, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
691
692                                 uiBlockBeginAlign(block);                       
693                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",     *xco+51, *yco-64,17,18, &data->minmaxflag, 12.0, 0.0, 0, 0, "Will not pass below X of target");
694                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y",     *xco+67, *yco-64,17,18, &data->minmaxflag, 12.0, 1.0, 0, 0, "Will not pass below Y of target");
695                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",     *xco+85, *yco-64,17,18, &data->minmaxflag, 12.0, 2.0, 0, 0, "Will not pass below Z of target");
696                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X",    *xco+102, *yco-64,24,18, &data->minmaxflag, 12.0, 3.0, 0, 0, "Will not pass above X of target");
697                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y",    *xco+126, *yco-64,24,18, &data->minmaxflag, 12.0, 4.0, 0, 0, "Will not pass above Y of target");
698                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z",    *xco+150, *yco-64,24,18, &data->minmaxflag, 12.0, 5.0, 0, 0, "Will not pass above Z of target");
699                                 uiBlockEndAlign(block);
700                         }
701                         break;
702                 case CONSTRAINT_TYPE_LOCKTRACK:
703                         {
704                                 bLockTrackConstraint *data = con->data;
705                                 bArmature *arm;
706                                 height = 66;
707                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
708
709                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
710
711                                 /* Draw target parameters */
712                                 uiBlockBeginAlign(block);
713                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
714
715                                 arm = get_armature(data->tar);
716                                 if (arm){
717                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
718                                 }
719                                 else
720                                         strcpy (data->subtarget, "");
721                                 uiBlockEndAlign(block);
722                                 
723                                 uiBlockBeginAlign(block);
724                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "To:", *xco+12, *yco-64, 25, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
725                                 
726                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",     *xco+39, *yco-64,17,18, &data->trackflag, 12.0, 0.0, 0, 0, "The axis that points to the target object");
727                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y",     *xco+56, *yco-64,17,18, &data->trackflag, 12.0, 1.0, 0, 0, "The axis that points to the target object");
728                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",     *xco+73, *yco-64,17,18, &data->trackflag, 12.0, 2.0, 0, 0, "The axis that points to the target object");
729                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X",    *xco+90, *yco-64,24,18, &data->trackflag, 12.0, 3.0, 0, 0, "The axis that points to the target object");
730                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y",    *xco+114, *yco-64,24,18, &data->trackflag, 12.0, 4.0, 0, 0, "The axis that points to the target object");
731                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z",    *xco+138, *yco-64,24,18, &data->trackflag, 12.0, 5.0, 0, 0, "The axis that points to the target object");
732                                 uiBlockEndAlign(block);
733                                 
734                                 uiBlockBeginAlign(block);
735                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Lock:", *xco+166, *yco-64, 38, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
736                                 
737                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",     *xco+204, *yco-64,17,18, &data->lockflag, 13.0, 0.0, 0, 0, "The axis that is locked");
738                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y",     *xco+221, *yco-64,17,18, &data->lockflag, 13.0, 1.0, 0, 0, "The axis that is locked");
739                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",     *xco+238, *yco-64,17,18, &data->lockflag, 13.0, 2.0, 0, 0, "The axis that is locked");
740                                 uiBlockEndAlign(block);
741                         }
742                         break;
743                 case CONSTRAINT_TYPE_FOLLOWPATH:
744                         {
745                                 bFollowPathConstraint *data = con->data;
746
747                                 height = 66;
748                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
749                                 
750                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
751
752                                 /* Draw target parameters */
753                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
754                                 
755                                 /* Draw Curve Follow toggle */
756                                 but=uiDefButBitI(block, TOG, 1, B_CONSTRAINT_TEST, "CurveFollow", *xco+39, *yco-44, 100, 18, &data->followflag, 0, 24, 0, 0, "Object will follow the heading and banking of the curve");
757
758                                 /* Draw Offset number button */
759                                 uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Offset:", *xco+155, *yco-44, 100, 18, &data->offset, -MAXFRAMEF, MAXFRAMEF, 100.0, 0.0, "Offset from the position corresponding to the time frame"); 
760
761                                 uiBlockBeginAlign(block);
762                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Fw:", *xco+12, *yco-64, 27, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
763                                 
764                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",     *xco+39, *yco-64,17,18, &data->trackflag, 12.0, 0.0, 0, 0, "The axis that points forward along the path");
765                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y",     *xco+56, *yco-64,17,18, &data->trackflag, 12.0, 1.0, 0, 0, "The axis that points forward along the path");
766                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",     *xco+73, *yco-64,17,18, &data->trackflag, 12.0, 2.0, 0, 0, "The axis that points forward along the path");
767                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X",    *xco+90, *yco-64,24,18, &data->trackflag, 12.0, 3.0, 0, 0, "The axis that points forward along the path");
768                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y",    *xco+114, *yco-64,24,18, &data->trackflag, 12.0, 4.0, 0, 0, "The axis that points forward along the path");
769                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z",    *xco+138, *yco-64,24,18, &data->trackflag, 12.0, 5.0, 0, 0, "The axis that points forward along the path");
770                                 uiBlockEndAlign(block);
771                                 
772                                 uiBlockBeginAlign(block);
773                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Up:", *xco+174, *yco-64, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
774                                 
775                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",     *xco+204, *yco-64,17,18, &data->upflag, 13.0, 0.0, 0, 0, "The axis that points upward");
776                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y",     *xco+221, *yco-64,17,18, &data->upflag, 13.0, 1.0, 0, 0, "The axis that points upward");
777                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",     *xco+238, *yco-64,17,18, &data->upflag, 13.0, 2.0, 0, 0, "The axis that points upward");
778                                 uiBlockEndAlign(block);
779                         }
780                         break;
781                 case CONSTRAINT_TYPE_STRETCHTO:
782                         {
783                                 bStretchToConstraint *data = con->data;
784                                 bArmature *arm;
785                                 
786                                 height = 105;
787                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
788                                 
789                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
790
791
792                                 /* Draw target parameters */
793                                 uiBlockBeginAlign(block);
794                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
795
796                                 arm = get_armature(data->tar);
797                                 if (arm){
798                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
799                                 }
800                                 else
801                                         strcpy (data->subtarget, "");
802                                 uiBlockEndAlign(block);
803
804                                 
805                                 uiBlockBeginAlign(block);
806                                 uiDefButF(block,BUTM,B_CONSTRAINT_TEST,"R",*xco, *yco-60,20,18,&(data->orglength),0.0,0,0,0,"Recalculate RLenght");
807                                 uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Rest Length:",*xco+18, *yco-60,237,18,&(data->orglength),0.0,100,0.5,0.5,"Lenght at Rest Position");
808                                 uiBlockEndAlign(block);
809
810                                 uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Volume Variation:",*xco+18, *yco-82,237,18,&(data->bulge),0.0,100,0.5,0.5,"Factor between volume variation and stretching");
811
812                                 uiBlockBeginAlign(block);
813                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Vol:",*xco+14, *yco-104,30,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
814                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"XZ",     *xco+44, *yco-104,30,18, &data->volmode, 12.0, 0.0, 0, 0, "Keep Volume: Scaling X & Z");
815                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",      *xco+74, *yco-104,20,18, &data->volmode, 12.0, 1.0, 0, 0, "Keep Volume: Scaling X");
816                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",      *xco+94, *yco-104,20,18, &data->volmode, 12.0, 2.0, 0, 0, "Keep Volume: Scaling Z");
817                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"NONE", *xco+114, *yco-104,50,18, &data->volmode, 12.0, 3.0, 0, 0, "Ignore Volume");
818                                 uiBlockEndAlign(block);
819
820                                 
821                                 uiBlockBeginAlign(block);
822                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Plane:",*xco+175, *yco-104,40,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
823                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",       *xco+215, *yco-104,20,18, &data->plane, 12.0, 0.0, 0, 0, "Keep X axis");
824                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",       *xco+235, *yco-104,20,18, &data->plane, 12.0, 2.0, 0, 0, "Keep Z axis");
825                                 uiBlockEndAlign(block);
826                                 }
827                         break;
828                 case CONSTRAINT_TYPE_NULL:
829                         {
830                                 height = 17;
831                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
832                                 
833                         }
834                         break;
835                 default:
836                         height = 0;
837                         break;
838                 }
839
840                 (*yco)-=(24+height);
841         }
842
843         if (con->type!=CONSTRAINT_TYPE_NULL) {
844                 uiBlockBeginAlign(block);
845                 uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "Influence ", *xco, *yco, 197, 20, &(con->enforce), 0.0, 1.0, 0.0, 0.0, "Amount of influence this constraint will have on the final solution");
846                 but = uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Show", *xco+200, *yco, 45, 20, 0, 0.0, 1.0, 0.0, 0.0, "Show constraint's ipo in the Ipo window, adds a channel if not there");
847                 /* If this is on an object or bone, add ipo channel the constraint */
848                 uiButSetFunc (but, enable_constraint_ipo_func, ob, con);
849                 but = uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Key", *xco+245, *yco, 40, 20, 0, 0.0, 1.0, 0.0, 0.0, "Add an influence keyframe to the constraint");
850                 /* Add a keyframe to the influence IPO */
851                 uiButSetFunc (but, add_influence_key_to_constraint_func, ob, con);
852                 uiBlockEndAlign(block);
853                 (*yco)-=24;
854         } else {
855                 (*yco)-=3;
856         }
857         
858 }
859
860 static uiBlock *add_constraintmenu(void *arg_unused)
861 {
862         Object *ob= OBACT;
863         uiBlock *block;
864         ListBase *conlist;
865         short yco= 0;
866         
867         conlist = get_active_constraints(ob);
868         
869         block= uiNewBlock(&curarea->uiblocks, "add_constraintmenu", UI_EMBOSSP, UI_HELV, curarea->win);
870
871         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIKE,"Copy Location",         0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
872         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIKE,"Copy Rotation",         0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
873         
874         uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
875         
876         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_TRACKTO,"Track To",              0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
877         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_MINMAX,"Floor",          0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
878         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK,"Locked Track",                0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
879         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH,"Follow Path",                0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
880         
881         uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
882         
883         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_STRETCHTO,"Stretch To",          0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
884
885         if (ob->flag & OB_POSEMODE) {
886                 uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
887                 
888                 uiDefBut(block, BUTM, B_CONSTRAINT_ADD_KINEMATIC,"IK Solver",           0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
889                 uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ACTION,"Action",         0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
890                 
891         }
892         uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
893
894         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_NULL,"Null",             0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
895         
896         uiTextBoundsBlock(block, 50);
897         uiBlockSetDirection(block, UI_DOWN);
898                 
899         return block;
900 }
901
902 void do_constraintbuts(unsigned short event)
903 {
904         Object *ob= OBACT;
905         
906         switch(event) {
907         case B_CONSTRAINT_TEST:
908                 break;  // no handling
909                 
910         case B_CONSTRAINT_CHANGETARGET:
911                 if(ob->pose) ob->pose->flag |= POSE_RECALC;     // checks & sorts pose channels
912                 DAG_scene_sort(G.scene);
913                 break;
914                 
915         case B_CONSTRAINT_ADD_NULL:
916                 {
917                         bConstraint *con;
918                         
919                         con = add_new_constraint(CONSTRAINT_TYPE_NULL);
920                         add_constraint_to_active(ob, con);
921
922                         BIF_undo_push("Add constraint");
923                 }
924                 break;
925         case B_CONSTRAINT_ADD_KINEMATIC:
926                 {
927                         bConstraint *con;
928                         
929                         con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
930                         add_constraint_to_active(ob, con);
931
932                         BIF_undo_push("Add constraint");
933                 }
934                 break;
935         case B_CONSTRAINT_ADD_TRACKTO:
936                 {
937                         bConstraint *con;
938
939                         con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
940                         add_constraint_to_active(ob, con);
941
942                         BIF_undo_push("Add constraint");
943                 }
944                 break;
945         case B_CONSTRAINT_ADD_MINMAX:
946                 {
947                         bConstraint *con;
948
949                         con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
950                         add_constraint_to_active(ob, con);
951
952                         BIF_undo_push("Add constraint");
953                 }
954                 break;
955         case B_CONSTRAINT_ADD_ROTLIKE:
956                 {
957                         bConstraint *con;
958
959                         con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
960                         add_constraint_to_active(ob, con);
961
962                         BIF_undo_push("Add constraint");
963                 }
964                 break;
965         case B_CONSTRAINT_ADD_LOCLIKE:
966                 {
967                         bConstraint *con;
968
969                         con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
970                         add_constraint_to_active(ob, con);
971
972                         BIF_undo_push("Add constraint");
973                 }
974                 break;
975         case B_CONSTRAINT_ADD_ACTION:
976                 {
977                         bConstraint *con;
978
979                         con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
980                         add_constraint_to_active(ob, con);
981
982                         BIF_undo_push("Add constraint");
983                 }
984                 break;
985         case B_CONSTRAINT_ADD_LOCKTRACK:
986                 {
987                         bConstraint *con;
988
989                         con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
990                         add_constraint_to_active(ob, con);
991
992                         BIF_undo_push("Add constraint");
993                 }
994                 break;
995         case B_CONSTRAINT_ADD_FOLLOWPATH:
996                 {
997                         bConstraint *con;
998
999                         con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
1000                         add_constraint_to_active(ob, con);
1001
1002                 }
1003                 break;
1004         case B_CONSTRAINT_ADD_STRETCHTO:
1005                 {
1006                         bConstraint *con;
1007                         con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
1008                         add_constraint_to_active(ob, con);
1009                                 
1010                         BIF_undo_push("Add constraint");
1011                 }
1012                 break;
1013
1014         default:
1015                 break;
1016         }
1017
1018         object_test_constraints(ob);
1019         
1020         if(ob->pose) update_pose_constraint_flags(ob->pose);
1021         
1022         if(ob->type==OB_ARMATURE) DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1023         else DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
1024         
1025         allqueue (REDRAWVIEW3D, 0);
1026         allqueue (REDRAWBUTSOBJECT, 0);
1027 }
1028
1029 void object_panel_constraint(char *context)
1030 {
1031         uiBlock *block;
1032         Object *ob= OBACT;
1033         ListBase *conlist;
1034         bConstraint *curcon;
1035         short xco, yco;
1036         char str[64];
1037         
1038         block= uiNewBlock(&curarea->uiblocks, "object_panel_constraint", UI_EMBOSS, UI_HELV, curarea->win);
1039         if(uiNewPanel(curarea, block, "Constraints", context, 640, 0, 318, 204)==0) return;
1040
1041         /* this is a variable height panel, newpanel doesnt force new size on existing panels */
1042         /* so first we make it default height */
1043         uiNewPanelHeight(block, 204);
1044
1045         if(G.obedit==OBACT) return;     // ??
1046         
1047         conlist = get_active_constraints(OBACT);
1048         
1049         if (conlist) {
1050                  
1051                 uiDefBlockBut(block, add_constraintmenu, NULL, "Add Constraint", 0, 190, 130, 20, "Add a new constraint");
1052                 
1053                 /* print active object or bone */
1054                 str[0]= 0;
1055                 if (ob->flag & OB_POSEMODE){
1056                         bPoseChannel *pchan= get_active_posechannel(ob);
1057                         if(pchan) sprintf(str, "To Bone: %s", pchan->name);
1058                 }
1059                 else {
1060                         sprintf(str, "To Object: %s", ob->id.name+2);
1061                 }
1062                 uiDefBut(block, LABEL, 1, str,  150, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Displays Active Object or Bone name");
1063                 
1064                 /* Go through the list of constraints and draw them */
1065                 xco = 10;
1066                 yco = 160;
1067                 
1068                 for (curcon = conlist->first; curcon; curcon=curcon->next) {
1069                         /* Draw default constraint header */                    
1070                         draw_constraint(block, conlist, curcon, &xco, &yco);    
1071                 }
1072                 
1073                 if(yco < 0) uiNewPanelHeight(block, 204-yco);
1074                 
1075         }
1076 }
1077
1078 static void object_panel_draw(Object *ob)
1079 {
1080         uiBlock *block;
1081         int xco, a, dx, dy;
1082         
1083         block= uiNewBlock(&curarea->uiblocks, "object_panel_draw", UI_EMBOSS, UI_HELV, curarea->win);
1084         if(uiNewPanel(curarea, block, "Draw", "Object", 320, 0, 318, 204)==0) return;
1085
1086         /* LAYERS */
1087         xco= 120;
1088         dx= 35;
1089         dy= 30;
1090
1091         uiDefBut(block, LABEL, 0, "Layers",                             10,170,100,20, NULL, 0, 0, 0, 0, "");
1092         
1093         uiBlockBeginAlign(block);
1094         for(a=0; a<5; a++)
1095                 uiDefButBitI(block, TOG, 1<<a, B_OBLAY+a, "",   (short)(xco+a*(dx/2)), 180, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, "");
1096         for(a=0; a<5; a++)
1097                 uiDefButBitI(block, TOG, 1<<(a+10), B_OBLAY+a+10, "",   (short)(xco+a*(dx/2)), 165, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, "");
1098                 
1099         xco+= 7;
1100         uiBlockBeginAlign(block);
1101         for(a=5; a<10; a++)
1102                 uiDefButBitI(block, TOG, 1<<a, B_OBLAY+a, "",   (short)(xco+a*(dx/2)), 180, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, "");
1103         for(a=5; a<10; a++)
1104                 uiDefButBitI(block, TOG, 1<<(a+10), B_OBLAY+a+10, "",   (short)(xco+a*(dx/2)), 165, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, "");
1105
1106         uiBlockEndAlign(block);
1107
1108         uiDefBut(block, LABEL, 0, "Drawtype",                                           10,120,100,20, NULL, 0, 0, 0, 0, "");
1109         
1110         uiBlockBeginAlign(block);
1111         uiDefButC(block, ROW, REDRAWVIEW3D, "Shaded",   10,100,100, 20, &ob->dt, 0, OB_SHADED, 0, 0, "Draw active object shaded or textured");
1112         uiDefButC(block, ROW, REDRAWVIEW3D, "Solid",    10,80,100, 20, &ob->dt, 0, OB_SOLID, 0, 0, "Draw active object in solid");
1113         uiDefButC(block, ROW, REDRAWVIEW3D, "Wire",             10,60, 100, 20, &ob->dt, 0, OB_WIRE, 0, 0, "Draw active object in wireframe");
1114         uiDefButC(block, ROW, REDRAWVIEW3D, "Bounds",   10,40, 100, 20, &ob->dt, 0, OB_BOUNDBOX, 0, 0, "Only draw object with bounding box");
1115         uiBlockEndAlign(block);
1116         
1117         uiDefBut(block, LABEL, 0, "Draw Extra",                                                 120,120,90,20, NULL, 0, 0, 0, 0, "");
1118         
1119         uiBlockBeginAlign(block);
1120         uiDefButBitC(block, TOG, OB_BOUNDBOX, REDRAWVIEW3D, "Bounds",                           120, 100, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's bounds");
1121         uiDefButBitC(block, TOG, OB_DRAWNAME, REDRAWVIEW3D, "Name",             210, 100, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's name");
1122         
1123         uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Polyheder%x4",
1124                                                                                                                                         120, 80, 90, 20, &ob->boundtype, 0, 0, 0, 0, "Selects the boundary display type");
1125         uiDefButBitC(block, TOG, OB_AXIS, REDRAWVIEW3D, "Axis",                 210, 80, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's centre and axis");
1126         
1127         uiDefButBitC(block, TOG, OB_TEXSPACE, REDRAWVIEW3D, "TexSpace", 120, 60, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's texture space");
1128         uiDefButBitC(block, TOG, OB_DRAWWIRE, REDRAWVIEW3D, "Wire",             210, 60, 90, 20, &ob->dtx, 0, 0, 0, 0, "Adds the active object's wireframe over solid drawing");
1129         
1130         uiDefButBitC(block, TOG, OB_DRAWTRANSP, REDRAWVIEW3D, "Transp", 120, 40, 90, 20, &ob->dtx, 0, 0, 0, 0, "Enables transparent materials for the active object (Mesh only)");
1131         uiDefButBitC(block, TOG, OB_DRAWXRAY, REDRAWVIEW3D, "X-ray",    210, 40, 90, 20, &ob->dtx, 0, 0, 0, 0, "Makes the active object draw in front of others");
1132
1133 }
1134
1135 static void softbody_bake(Object *ob)
1136 {
1137         SoftBody *sb= ob->soft;
1138         ScrArea *sa;
1139         float frameleno= G.scene->r.framelen;
1140         int cfrao= CFRA;
1141         unsigned short event=0;
1142         short val;
1143         
1144         G.scene->r.framelen= 1.0;               // baking has to be in uncorrected time
1145         CFRA= sb->sfra;
1146         update_for_newframe_muted();    // put everything on this frame
1147         sbObjectToSoftbody(ob); // put softbody in restposition
1148         ob->softflag |= OB_SB_BAKEDO;
1149         
1150         curarea->win_swap= 0;           // clean swapbuffers
1151         
1152         for(; CFRA <= sb->efra; CFRA++) {
1153                 set_timecursor(CFRA);
1154                 
1155                 update_for_newframe_muted();
1156                 
1157                 for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1158                         if(sa->spacetype == SPACE_VIEW3D) {
1159                                 scrarea_do_windraw(sa);
1160                         }
1161                 }
1162                 screen_swapbuffers();
1163                 
1164                 while(qtest()) {
1165                         
1166                         event= extern_qread(&val);
1167                         if(event==ESCKEY) break;
1168                 }
1169                 if(event==ESCKEY) break;
1170         }
1171         
1172         if(event==ESCKEY) sbObjectToSoftbody(ob);       // clears all
1173         
1174         /* restore */
1175         waitcursor(0);
1176         ob->softflag &= ~OB_SB_BAKEDO;
1177         CFRA= cfrao;
1178         G.scene->r.framelen= frameleno;
1179         update_for_newframe_muted();
1180         allqueue(REDRAWVIEW3D, 0);
1181         allqueue(REDRAWBUTSOBJECT, 0);
1182 }
1183
1184
1185 void do_object_panels(unsigned short event)
1186 {
1187         Object *ob;
1188         Effect *eff;
1189         
1190         ob= OBACT;
1191
1192         switch(event) {
1193         case B_TRACKBUTS:
1194                 ob= OBACT;
1195                 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
1196                 allqueue(REDRAWVIEW3D, 0);
1197                 break;
1198         case B_RECALCPATH:
1199                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1200                 allqueue(REDRAWVIEW3D, 0);
1201                 break;
1202         case B_PRINTSPEED:
1203                 ob= OBACT;
1204                 if(ob) {
1205                         float vec[3];
1206                         CFRA++;
1207                         do_ob_ipo(ob);
1208                         where_is_object(ob);
1209                         VECCOPY(vec, ob->obmat[3]);
1210                         CFRA--;
1211                         do_ob_ipo(ob);
1212                         where_is_object(ob);
1213                         VecSubf(vec, vec, ob->obmat[3]);
1214                         prspeed= Normalise(vec);
1215                         scrarea_queue_winredraw(curarea);
1216                 }
1217                 break;
1218         case B_PRINTLEN:
1219                 ob= OBACT;
1220                 if(ob && ob->type==OB_CURVE) {
1221                         Curve *cu=ob->data;
1222                         
1223                         if(cu->path) prlen= cu->path->totdist; else prlen= -1.0;
1224                         scrarea_queue_winredraw(curarea);
1225                 } 
1226                 break;
1227         case B_RELKEY:
1228                 allspace(REMAKEIPO, 0);
1229                 allqueue(REDRAWBUTSOBJECT, 0);
1230                 allqueue(REDRAWIPO, 0);
1231                 break;
1232         case B_CURVECHECK:
1233                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1234                 allqueue(REDRAWVIEW3D, 0);
1235                 break;
1236         
1237         case B_SOFTBODY_CHANGE:
1238                 ob= OBACT;
1239                 if(ob) {
1240                         ob->softflag |= OB_SB_REDO;
1241                         allqueue(REDRAWBUTSOBJECT, 0);
1242                         allqueue(REDRAWVIEW3D, 0);
1243                 }
1244                 break;
1245         case B_SOFTBODY_DEL_VG:
1246                 ob= OBACT;
1247                 if(ob && ob->soft) {
1248                         ob->soft->vertgroup= 0;
1249                         ob->softflag |= OB_SB_REDO;
1250                         allqueue(REDRAWBUTSOBJECT, 0);
1251                         allqueue(REDRAWVIEW3D, 0);
1252                 }
1253                 break;
1254         case B_SOFTBODY_BAKE:
1255                 ob= OBACT;
1256                 if(ob && ob->soft) softbody_bake(ob);
1257                 break;
1258         case B_SOFTBODY_BAKE_FREE:
1259                 ob= OBACT;
1260                 if(ob && ob->soft) sbObjectToSoftbody(ob);
1261                 allqueue(REDRAWBUTSOBJECT, 0);
1262                 allqueue(REDRAWVIEW3D, 0);
1263                 break;
1264                 
1265         default:
1266                 if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
1267                         ob= OBACT;
1268                         if(ob) {
1269                                 int a=B_SELEFFECT;
1270                                 
1271                                 eff= ob->effect.first;
1272                                 while(eff) {
1273                                         if(event==a) eff->flag |= SELECT;
1274                                         else eff->flag &= ~SELECT;
1275                                         
1276                                         a++;
1277                                         eff= eff->next;
1278                                 }
1279                                 allqueue(REDRAWBUTSOBJECT, 0);
1280                         }
1281                 }
1282         }
1283
1284 }
1285
1286 static void object_panel_anim(Object *ob)
1287 {
1288         uiBlock *block;
1289         char str[32];
1290         
1291         block= uiNewBlock(&curarea->uiblocks, "object_panel_anim", UI_EMBOSS, UI_HELV, curarea->win);
1292         if(uiNewPanel(curarea, block, "Anim settings", "Object", 0, 0, 318, 204)==0) return;
1293         
1294         uiBlockBeginAlign(block);
1295         uiDefButC(block, ROW,B_TRACKBUTS,"TrackX",      24,190,59,19, &ob->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object");
1296         uiDefButC(block, ROW,B_TRACKBUTS,"Y",           85,190,19,19, &ob->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object");
1297         uiDefButC(block, ROW,B_TRACKBUTS,"Z",           104,190,19,19, &ob->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object");
1298         uiDefButC(block, ROW,B_TRACKBUTS,"-X",          124,190,24,19, &ob->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object");
1299         uiDefButC(block, ROW,B_TRACKBUTS,"-Y",          150,190,24,19, &ob->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object");
1300         uiDefButC(block, ROW,B_TRACKBUTS,"-Z",          178,190,24,19, &ob->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object");
1301         uiBlockBeginAlign(block);
1302         uiDefButC(block, ROW,REDRAWVIEW3D,"UpX",        226,190,45,19, &ob->upflag, 13.0, 0.0, 0, 0, "Specify the axis that points up");
1303         uiDefButC(block, ROW,REDRAWVIEW3D,"Y",          274,190,20,19, &ob->upflag, 13.0, 1.0, 0, 0, "Specify the axis that points up");
1304         uiDefButC(block, ROW,REDRAWVIEW3D,"Z",          298,190,19,19, &ob->upflag, 13.0, 2.0, 0, 0, "Specify the axis that points up");
1305         uiBlockBeginAlign(block);
1306         uiDefButBitC(block, TOG, OB_DRAWKEY, REDRAWVIEW3D, "Draw Key",          24,160,71,19, &ob->ipoflag, 0, 0, 0, 0, "Draw object as key position");
1307         uiDefButBitC(block, TOG, OB_DRAWKEYSEL, REDRAWVIEW3D, "Draw Key Sel",   97,160,81,19, &ob->ipoflag, 0, 0, 0, 0, "Limit the drawing of object keys");
1308         uiDefButBitC(block, TOG, OB_POWERTRACK, REDRAWVIEW3D, "Powertrack",             180,160,78,19, &ob->transflag, 0, 0, 0, 0, "Switch objects rotation off");
1309         uiDefButBitS(block, TOG, PARSLOW, 0, "SlowPar",                                 260,160,56,19, &ob->partype, 0, 0, 0, 0, "Create a delay in the parent relationship");
1310         uiBlockBeginAlign(block);
1311         uiDefButBitC(block, TOG, OB_DUPLIFRAMES, REDRAWVIEW3D, "DupliFrames",   24,128,89,19, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame");
1312         uiDefButBitC(block, TOG, OB_DUPLIVERTS, REDRAWVIEW3D, "DupliVerts",             114,128,82,19, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices");
1313         uiDefButBitC(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot",              200,128,31,19, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to facenormal");
1314         uiDefButBitC(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed",     234,128,82,19, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame");
1315         uiBlockBeginAlign(block);
1316         uiDefButS(block, NUM, REDRAWVIEW3D, "DupSta:",          24,105,141,19, &ob->dupsta, 1.0, (MAXFRAMEF - 1.0f), 0, 0, "Specify startframe for Dupliframes");
1317         uiDefButS(block, NUM, REDRAWVIEW3D, "DupOn:",           170,105,146,19, &ob->dupon, 1.0, 1500.0, 0, 0, "");
1318         uiDefButS(block, NUM, REDRAWVIEW3D, "DupEnd",           24,82,140,19, &ob->dupend, 1.0, MAXFRAMEF, 0, 0, "Specify endframe for Dupliframes");
1319         uiDefButS(block, NUM, REDRAWVIEW3D, "DupOff",           171,82,145,19, &ob->dupoff, 0.0, 1500.0, 0, 0, "");
1320         uiBlockBeginAlign(block);
1321         uiDefButBitC(block, TOG, OB_OFFS_OB, REDRAWALL, "Offs Ob",                      24,51,56,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on its own objectipo");
1322         uiDefButBitC(block, TOG, OB_OFFS_PARENT, REDRAWALL, "Offs Par",                 82,51,56,20 , &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the parent");
1323         uiDefButBitC(block, TOG, OB_OFFS_PARTICLE, REDRAWALL, "Offs Particle",          140,51,103,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the particle effect");
1324         
1325         uiBlockBeginAlign(block);
1326         uiDefButF(block, NUM, REDRAWALL, "TimeOffset:",                 24,17,115,30, &ob->sf, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify an offset in frames");
1327         uiDefBut(block, BUT, B_AUTOTIMEOFS, "Automatic Time",   139,17,104,31, 0, 0, 0, 0, 0, "Generate automatic timeoffset values for all selected frames");
1328         uiDefBut(block, BUT, B_PRINTSPEED,      "PrSpeed",                      248,17,67,31, 0, 0, 0, 0, 0, "Print objectspeed");
1329         uiBlockEndAlign(block);
1330         
1331         sprintf(str, "%.4f", prspeed);
1332         uiDefBut(block, LABEL, 0, str,                                                  247,40,63,31, NULL, 1.0, 0, 0, 0, "");
1333         
1334 }
1335
1336 void do_effects_panels(unsigned short event)
1337 {
1338         Object *ob;
1339         Base *base;
1340         Effect *eff, *effn;
1341         int type;
1342         
1343         ob= OBACT;
1344
1345         switch(event) {
1346
1347     case B_AUTOTIMEOFS:
1348                 auto_timeoffs();
1349                 break;
1350         case B_FRAMEMAP:
1351                 G.scene->r.framelen= G.scene->r.framapto;
1352                 G.scene->r.framelen/= G.scene->r.images;
1353                 allqueue(REDRAWALL, 0);
1354                 break;
1355         case B_NEWEFFECT:
1356                 if(ob) {
1357                         if (BLI_countlist(&ob->effect)==MAX_EFFECT)
1358                                 error("Unable to add: effect limit reached");
1359                         else
1360                                 copy_act_effect(ob);
1361                 }
1362                 BIF_undo_push("New effect");
1363                 allqueue(REDRAWBUTSOBJECT, 0);
1364                 break;
1365         case B_DELEFFECT:
1366                 if(ob==0 || ob->type!=OB_MESH) break;
1367                 eff= ob->effect.first;
1368                 while(eff) {
1369                         effn= eff->next;
1370                         if(eff->flag & SELECT) {
1371                                 BLI_remlink(&ob->effect, eff);
1372                                 free_effect(eff);
1373                                 break;
1374                         }
1375                         eff= effn;
1376                 }
1377                 BIF_undo_push("Delete effect");
1378                 allqueue(REDRAWVIEW3D, 0);
1379                 allqueue(REDRAWBUTSOBJECT, 0);
1380                 break;
1381         case B_NEXTEFFECT:
1382                 if(ob==0 || ob->type!=OB_MESH) break;
1383                 eff= ob->effect.first;
1384                 while(eff) {
1385                         if(eff->flag & SELECT) {
1386                                 if(eff->next) {
1387                                         eff->flag &= ~SELECT;
1388                                         eff->next->flag |= SELECT;
1389                                 }
1390                                 break;
1391                         }
1392                         eff= eff->next;
1393                 }
1394                 allqueue(REDRAWBUTSOBJECT, 0);
1395                 break;
1396         case B_PREVEFFECT:
1397                 if(ob==0 || ob->type!=OB_MESH) break;
1398                 eff= ob->effect.first;
1399                 while(eff) {
1400                         if(eff->flag & SELECT) {
1401                                 if(eff->prev) {
1402                                         eff->flag &= ~SELECT;
1403                                         eff->prev->flag |= SELECT;
1404                                 }
1405                                 break;
1406                         }
1407                         eff= eff->next;
1408                 }
1409                 allqueue(REDRAWBUTSOBJECT, 0);
1410                 break;
1411         case B_CHANGEEFFECT:
1412                 if(ob==0 || ob->type!=OB_MESH) break;
1413                 eff= ob->effect.first;
1414                 while(eff) {
1415                         if(eff->flag & SELECT) {
1416                                 if(eff->type!=eff->buttype) {
1417                                         BLI_remlink(&ob->effect, eff);
1418                                         type= eff->buttype;
1419                                         free_effect(eff);
1420                                         eff= add_effect(type);
1421                                         BLI_addtail(&ob->effect, eff);
1422                                 }
1423                                 break;
1424                         }
1425                         eff= eff->next;
1426                 }
1427                 allqueue(REDRAWVIEW3D, 0);
1428                 allqueue(REDRAWBUTSOBJECT, 0);
1429                 break;
1430         case B_CALCEFFECT:
1431                 if(ob==0 || ob->type!=OB_MESH) break;
1432                 eff= ob->effect.first;
1433                 while(eff) {
1434                         if(eff->flag & SELECT) {
1435                                 if(eff->type==EFF_PARTICLE) build_particle_system(ob);
1436                         }
1437                         eff= eff->next;
1438                 }
1439                 allqueue(REDRAWVIEW3D, 0);
1440                 allqueue(REDRAWBUTSOBJECT, 0);
1441                 break;
1442         case B_RECALCAL:
1443                 base= FIRSTBASE;
1444                 while(base) {
1445                         if(base->lay & G.vd->lay) {
1446                                 ob= base->object;
1447                                 eff= ob->effect.first;
1448                                 while(eff) {
1449                                         if(eff->flag & SELECT) {
1450                                                 if(eff->type==EFF_PARTICLE) build_particle_system(ob);
1451                                         }
1452                                         eff= eff->next;
1453                                 }
1454                         }
1455                         base= base->next;
1456                 }
1457                 allqueue(REDRAWVIEW3D, 0);
1458                 break;
1459
1460         default:
1461                 if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
1462                         ob= OBACT;
1463                         if(ob) {
1464                                 int a=B_SELEFFECT;
1465                                 
1466                                 eff= ob->effect.first;
1467                                 while(eff) {
1468                                         if(event==a) eff->flag |= SELECT;
1469                                         else eff->flag &= ~SELECT;
1470                                         
1471                                         a++;
1472                                         eff= eff->next;
1473                                 }
1474                                 allqueue(REDRAWBUTSOBJECT, 0);
1475                         }
1476                 }
1477         }
1478
1479 }
1480
1481 /* Panel for particle interaction settings */
1482 static void object_panel_deflectors(Object *ob)
1483 {
1484         uiBlock *block;
1485
1486         block= uiNewBlock(&curarea->uiblocks, "object_panel_deflectors", UI_EMBOSS, UI_HELV, curarea->win);
1487         uiNewPanelTabbed("Constraints", "Object");
1488         if(uiNewPanel(curarea, block, "Particle Interaction", "Object", 640, 0, 318, 204)==0) return;
1489
1490         /* should become button, option? */
1491         if(ob->pd==NULL) {
1492                 ob->pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
1493                 /* and if needed, init here */
1494                 ob->pd->pdef_sbdamp = 0.1;
1495                 ob->pd->pdef_sbift  = 0.2;
1496                 ob->pd->pdef_sboft  = 0.02;
1497         }
1498         
1499         if(ob->pd) {
1500                 PartDeflect *pd= ob->pd;
1501                 
1502                 uiDefBut(block, LABEL, 0, "Fields",             10,180,140,20, NULL, 0.0, 0, 0, 0, "");
1503                 
1504                 uiBlockBeginAlign(block);
1505                 uiDefButS(block, ROW, REDRAWVIEW3D, "None",                     10,160,50,20, &pd->forcefield, 1.0, 0, 0, 0, "No force");
1506                 uiDefButS(block, ROW, REDRAWVIEW3D, "Force field",      60,160,90,20, &pd->forcefield, 1.0, PFIELD_FORCE, 0, 0, "Object center attracts or repels particles");
1507                 uiDefButS(block, ROW, REDRAWVIEW3D, "Wind",                     10,140,50,20, &pd->forcefield, 1.0, PFIELD_WIND, 0, 0, "Constant force applied in direction of Object Z axis");
1508                 uiDefButS(block, ROW, REDRAWVIEW3D, "Vortex field",     60,140,90,20, &pd->forcefield, 1.0, PFIELD_VORTEX, 0, 0, "Particles swirl around Z-axis of the object");
1509
1510                 uiBlockBeginAlign(block);
1511                 uiDefButF(block, NUM, REDRAWVIEW3D, "Strength: ",       10,110,140,20, &pd->f_strength, -1000, 1000, 1000, 0, "Strength of force field");
1512                 uiDefButF(block, NUM, REDRAWVIEW3D, "Fall-off: ",       10,90,140,20, &pd->f_power, 0, 10, 100, 0, "Falloff power (real gravitational fallof = 2)");
1513                 
1514                 uiBlockBeginAlign(block);
1515                 uiDefButBitS(block, TOG, PFIELD_USEMAX, REDRAWVIEW3D, "Use MaxDist",    10,60,140,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
1516                 uiDefButF(block, NUM, REDRAWVIEW3D, "MaxDist: ",        10,40,140,20, &pd->maxdist, 0, 1000.0, 100, 0, "Maximum distance for the field to work");
1517                 uiBlockEndAlign(block);
1518
1519 //              if(modifiers_isSoftbodyEnabled(ob)) {
1520                 if(0) {
1521                         uiDefBut(block, LABEL, 0, "Object is Softbody,",                160,160,150,20, NULL, 0.0, 0, 0, 0, "");
1522                         uiDefBut(block, LABEL, 0, "no Deflection possible",             160,140,150,20, NULL, 0.0, 0, 0, 0, "");
1523                         pd->deflect= 0;
1524                 }
1525                 else {
1526                         uiDefBut(block, LABEL, 0, "Deflection", 160,180,140,20, NULL, 0.0, 0, 0, 0, "");
1527                         
1528                         /* only meshes collide now */
1529                         if(ob->type==OB_MESH) {
1530                                 uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
1531                                 uiDefBut(block, LABEL, 0, "Particles",                  160,140,150,20, NULL, 0.0, 0, 0, 0, "");
1532                                 
1533                                 uiBlockBeginAlign(block);
1534                                 uiDefButF(block, NUM, B_DIFF, "Damping: ",              160,120,150,20, &pd->pdef_damp, 0.0, 1.0, 10, 0, "Amount of damping during particle collision");
1535                                 uiDefButF(block, NUM, B_DIFF, "Rnd Damping: ",  160,100,150,20, &pd->pdef_rdamp, 0.0, 1.0, 10, 0, "Random variation of damping");
1536                                 uiDefButF(block, NUM, B_DIFF, "Permeability: ", 160,80,150,20, &pd->pdef_perm, 0.0, 1.0, 10, 0, "Chance that the particle will pass through the mesh");
1537                                 uiBlockEndAlign(block);
1538                                 
1539                                 uiDefBut(block, LABEL, 0, "Soft Body",                  160,60,150,20, NULL, 0.0, 0, 0, 0, "");
1540
1541                                 uiBlockBeginAlign(block);
1542                                 uiDefButF(block, NUM, B_DIFF, "Damping:",       160,40,150,20, &pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during softbody collision");
1543                                 uiDefButF(block, NUM, B_DIFF, "Inner:", 160,20,150,20, &pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness");
1544                                 uiDefButF(block, NUM, B_DIFF, "Outer:", 160, 0,150,20, &pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness");
1545                                 uiBlockBeginAlign(block);
1546 /* seems to be working fine .. so we do use modifier stack by default .. code here rests for debugging
1547                             uiDefButBitS(block, TOG, PDEFLE_DEFORM , 0,"UMS or CRASH",  0,0,150,20, &pd->flag, 0, 0, 0, 0, "Let collision object move with armatures/lattices WARNING logical circles will CRASH");
1548 */
1549                         }               
1550                 }       
1551         }
1552 }
1553
1554
1555 /* Panel for softbodies */
1556 static void object_softbodies__enable(void *ob_v, void *arg2)
1557 {
1558         Object *ob = ob_v;
1559         ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
1560
1561         if (modifiers_isSoftbodyEnabled(ob)) {
1562                 if (md) {
1563                         md->mode &= ~(eModifierMode_Render|eModifierMode_Realtime);
1564                 }
1565         } else {
1566                 if (!md) {
1567                         md = modifier_new(eModifierType_Softbody);
1568                         BLI_addhead(&ob->modifiers, md);
1569                 }
1570
1571                 md->mode |= eModifierMode_Render|eModifierMode_Realtime;
1572
1573                 if (!ob->soft) {
1574                         ob->soft= sbNew();
1575                         ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
1576                 }
1577         }
1578
1579         allqueue(REDRAWBUTSEDIT, 0);
1580 }
1581
1582 static void object_softbodies(Object *ob)
1583 {
1584         uiBlock *block;
1585         
1586         block= uiNewBlock(&curarea->uiblocks, "object_softbodies", UI_EMBOSS, UI_HELV, curarea->win);
1587         uiNewPanelTabbed("Constraints", "Object");
1588         if(uiNewPanel(curarea, block, "Softbody", "Object", 640, 0, 318, 204)==0) return;
1589
1590         /* do not allow to combine with force fields */
1591         /* if(ob->pd && ob->pd->deflect) { */
1592         /* no reason for that any more BM */
1593         if(0) {
1594                 uiDefBut(block, LABEL, 0, "Object has Deflection,",             10,160,300,20, NULL, 0.0, 0, 0, 0, "");
1595                 uiDefBut(block, LABEL, 0, "no Softbody possible",               10,140,300,20, NULL, 0.0, 0, 0, 0, "");
1596         } else {
1597                 static int val;
1598                 uiBut *but;
1599
1600                 val = modifiers_isSoftbodyEnabled(ob);
1601                 but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Enable Soft Body",       10,200,150,20, &val, 0, 0, 0, 0, "Sets object to become soft body");
1602                 uiButSetFunc(but, object_softbodies__enable, ob, NULL);
1603                 uiDefBut(block, LABEL, 0, "",   160, 200,150,20, NULL, 0.0, 0.0, 0, 0, "");     // alignment reason
1604         }
1605         
1606         if(modifiers_isSoftbodyEnabled(ob)) {
1607                 SoftBody *sb= ob->soft;
1608                 int defCount;
1609                 char *menustr;
1610                 
1611                 if(sb==NULL) {
1612                         sb= ob->soft= sbNew();
1613                         ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
1614                 }
1615                 
1616                 uiDefButBitS(block, TOG, OB_SB_BAKESET, REDRAWBUTSOBJECT, "Bake settings",      180,200,130,20, &ob->softflag, 0, 0, 0, 0, "To convert simulation into baked (cached) result");
1617                 
1618                 if(sb->keys) uiSetButLock(1, "SoftBody is baked, free it first");
1619                 
1620                 if(ob->softflag & OB_SB_BAKESET) {
1621                         uiBlockBeginAlign(block);
1622                         uiDefButS(block, NUM, B_DIFF, "Start:",                 10, 170,100,20, &sb->sfra, 1.0, 10000.0, 10, 0, "Start frame for baking");
1623                         uiDefButS(block, NUM, B_DIFF, "End:",                   110, 170,100,20, &sb->efra, 1.0, 10000.0, 10, 0, "End frame for baking");
1624                         uiDefButS(block, NUM, B_DIFF, "Interval:",              210, 170,100,20, &sb->interval, 1.0, 10.0, 10, 0, "Interval in frames between baked keys");
1625                         
1626                         uiClearButLock();
1627                         
1628                         uiBlockBeginAlign(block);
1629                         if(sb->keys) {
1630                                 char str[128];
1631                                 uiDefIconTextBut(block, BUT, B_SOFTBODY_BAKE_FREE, ICON_X, "FREE BAKE", 10, 120,300,20, NULL, 0.0, 0.0, 0, 0, "Free baked result");
1632                                 sprintf(str, "Stored %d vertices %d keys %.3f MB", sb->totpoint, sb->totkey, ((float)16*sb->totpoint*sb->totkey)/(1024.0*1024.0));
1633                                 uiDefBut(block, LABEL, 0, str, 10, 100,300,20, NULL, 0.0, 0.0, 00, 0, "");
1634                         }
1635                         else                            
1636                                 uiDefBut(block, BUT, B_SOFTBODY_BAKE, "BAKE",   10, 120,300,20, NULL, 0.0, 0.0, 10, 0, "Start baking. Press ESC to exit without baking");
1637                 }
1638                 else {
1639                         /* GENERAL STUFF */
1640                         uiBlockBeginAlign(block);
1641                         uiDefButF(block, NUM, B_DIFF, "Friction:",              10, 170,150,20, &sb->mediafrict, 0.0, 10.0, 10, 0, "General media friction for point movements");
1642                         uiDefButF(block, NUM, B_DIFF, "Mass:",                  160, 170,150,20, &sb->nodemass , 0.001, 50.0, 10, 0, "Point Mass, the heavier the slower");
1643                         uiDefButF(block, NUM, B_DIFF, "Grav:",                  10,150,150,20, &sb->grav , 0.0, 10.0, 10, 0, "Apply gravitation to point movement");
1644                         uiDefButF(block, NUM, B_DIFF, "Speed:",                 160,150,150,20, &sb->physics_speed , 0.01, 100.0, 10, 0, "Tweak timing for physics to control frequency and speed");
1645                         uiDefButF(block, NUM, B_DIFF, "Error Limit:",   10,130,150,20, &sb->rklimit , 0.01, 1.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision");
1646                         uiBlockEndAlign(block);
1647                         
1648                         /* GOAL STUFF */
1649                         uiBlockBeginAlign(block);
1650                         uiDefButBitS(block, TOG, OB_SB_GOAL, B_SOFTBODY_CHANGE, "Use Goal",     10,100,130,20, &ob->softflag, 0, 0, 0, 0, "Define forces for vertices to stick to animated position");
1651                         
1652                         menustr= get_vertexgroup_menustr(ob);
1653                         defCount=BLI_countlist(&ob->defbase);
1654                         if(defCount==0) sb->vertgroup= 0;
1655                         uiDefButS(block, MENU, B_SOFTBODY_CHANGE, menustr,              140,100,20,20, &sb->vertgroup, 0, defCount, 0, 0, "Browses available vertex groups");
1656                         
1657                         if(sb->vertgroup) {
1658                                 bDeformGroup *defGroup = BLI_findlink(&ob->defbase, sb->vertgroup-1);
1659                                 if(defGroup)
1660                                         uiDefBut(block, BUT, B_DIFF, defGroup->name,    160,100,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group");
1661                                 else
1662                                         uiDefBut(block, BUT, B_DIFF, "(no group)",      160,100,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore");
1663                                 uiDefIconBut(block, BUT, B_SOFTBODY_DEL_VG, ICON_X, 290,100,20,20, 0, 0, 0, 0, 0, "Disable use of vertex group");
1664                         }
1665                         else {
1666                                 uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Goal:",       160,100,150,20, &sb->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used");
1667                         }
1668                         MEM_freeN (menustr);
1669
1670                         uiDefButF(block, NUM, B_DIFF, "G Stiff:",       10,80,150,20, &sb->goalspring, 0.0, 0.999, 10, 0, "Goal (vertex target position) spring stiffness");
1671                         uiDefButF(block, NUM, B_DIFF, "G Damp:",        160,80,150,20, &sb->goalfrict  , 0.0, 10.0, 10, 0, "Goal (vertex target position) friction");
1672                         uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "G Min:",              10,60,150,20, &sb->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range");
1673                         uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "G Max:",              160,60,150,20, &sb->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range");
1674                         uiBlockEndAlign(block);
1675                         
1676                         /* EDGE SPRING STUFF */
1677                         uiBlockBeginAlign(block);
1678                         uiDefButBitS(block, TOG, OB_SB_EDGES, B_SOFTBODY_CHANGE, "Use Edges",           10,30,150,20, &ob->softflag, 0, 0, 0, 0, "Use Edges as springs");
1679                         uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads",         160,30,150,20, &ob->softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons");
1680                         uiDefButF(block, NUM, B_DIFF, "E Stiff:",       10,10,150,20, &sb->inspring, 0.0,  0.999, 10, 0, "Edge spring stiffness");
1681                         uiDefButF(block, NUM, B_DIFF, "E Damp:",        160,10,150,20, &sb->infrict, 0.0,  10.0, 10, 0, "Edge spring friction");
1682                         uiBlockEndAlign(block);
1683                 }
1684         }
1685         uiBlockEndAlign(block);
1686
1687 }
1688
1689 static void object_panel_effects(Object *ob)
1690 {
1691         Effect *eff;
1692         uiBlock *block;
1693         int a;
1694         short x, y;
1695         
1696         block= uiNewBlock(&curarea->uiblocks, "object_panel_effects", UI_EMBOSS, UI_HELV, curarea->win);
1697         uiNewPanelTabbed("Constraints", "Object");
1698         if(uiNewPanel(curarea, block, "Effects", "Object", 640, 0, 418, 204)==0) return;
1699
1700         /* EFFECTS */
1701         
1702         if (ob->type == OB_MESH) {
1703                 uiBlockBeginAlign(block);
1704                 uiDefBut(block, BUT, B_NEWEFFECT, "NEW Effect", 550,187,124,27, 0, 0, 0, 0, 0, "Create a new effect");
1705                 uiDefBut(block, BUT, B_DELEFFECT, "Delete", 676,187,62,27, 0, 0, 0, 0, 0, "Delete the effect");
1706                 uiBlockEndAlign(block);
1707         }
1708
1709         /* select effs */
1710         eff= ob->effect.first;
1711         a= 0;
1712         while(eff) {
1713                 
1714                 x= 15 * a + 550;
1715                 y= 172; // - 12*( abs(a/10) ) ;
1716                 uiDefButBitS(block, TOG, SELECT, B_SELEFFECT+a, "", x, y, 15, 12, &eff->flag, 0, 0, 0, 0, "");
1717                 
1718                 a++;
1719                 if(a==MAX_EFFECT) break;
1720                 eff= eff->next;
1721         }
1722         
1723         eff= ob->effect.first;
1724         while(eff) {
1725                 if(eff->flag & SELECT) break;
1726                 eff= eff->next;
1727         }
1728         
1729         if(eff) {
1730                 uiDefButS(block, MENU, B_CHANGEEFFECT, "Particles %x1", 895,187,107,27, &eff->buttype, 0, 0, 0, 0, "Set effect type");
1731                 
1732                 if(eff->type==EFF_PARTICLE) {
1733                         PartEff *paf;
1734                         
1735                         paf= (PartEff *)eff;
1736                         
1737                         uiDefBut(block, BUT, B_RECALCAL, "RecalcAll", 741,187,67,27, 0, 0, 0, 0, 0, "Update the particle system");
1738                         uiBlockBeginAlign(block);
1739                         uiDefButBitS(block, TOG, PAF_STATIC, B_CALCEFFECT, "Static",    825,187,67,27, &paf->flag, 0, 0, 0, 0, "Make static particles (deform only works with SubSurf)");
1740                         if(paf->flag & PAF_STATIC)
1741                                 uiDefButBitS(block, TOG, PAF_ANIMATED, B_DIFF, "Animated",825,167,67,20, &paf->flag, 0, 0, 0, 0, "Static particles are recalculated each rendered frame");
1742                         
1743                         uiBlockBeginAlign(block);
1744                         uiDefButI(block, NUM, B_CALCEFFECT, "Tot:",                     550,146,91,20, &paf->totpart, 1.0, 100000.0, 0, 0, "Set the total number of particles");
1745                         if(paf->flag & PAF_STATIC) {
1746                                 uiDefButS(block, NUM, REDRAWVIEW3D, "Step:",    644,146,84+97,20, &paf->staticstep, 1.0, 100.0, 10, 0, "For static duplicators, the Step value skips particles");
1747                         }
1748                         else {
1749                                 uiDefButF(block, NUM, B_CALCEFFECT, "Sta:",             644,146,84,20, &paf->sta, -250.0, MAXFRAMEF, 100, 0, "Specify the startframe");
1750                                 uiDefButF(block, NUM, B_CALCEFFECT, "End:",             731,146,97,20, &paf->end, 1.0, MAXFRAMEF, 100, 0, "Specify the endframe");
1751                         }
1752                         uiDefButF(block, NUM, B_CALCEFFECT, "Life:",            831,146,88,20, &paf->lifetime, 1.0, MAXFRAMEF, 100, 0, "Specify the life span of the particles");
1753                         uiDefButI(block, NUM, B_CALCEFFECT, "Keys:",            922,146,80,20, &paf->totkey, 1.0, 100.0, 0, 0, "Specify the number of key positions");
1754                         
1755                         uiDefButS(block, NUM, B_REDR,           "CurMul:",              550,124,91,20, &paf->curmult, 0.0, 3.0, 0, 0, "Multiply the particles");
1756                         uiDefButS(block, NUM, B_CALCEFFECT, "Mat:",                     644,124,84,20, paf->mat+paf->curmult, 1.0, 8.0, 0, 0, "Specify the material used for the particles");
1757                         uiDefButF(block, NUM, B_CALCEFFECT, "Mult:",            730,124,98,20, paf->mult+paf->curmult, 0.0, 1.0, 10, 0, "Probability \"dying\" particle spawns a new one.");
1758                         uiDefButF(block, NUM, B_CALCEFFECT, "Life:",            831,124,89,20, paf->life+paf->curmult, 1.0, 600.0, 100, 0, "Specify the lifespan of the next generation particles");
1759                         uiDefButS(block, NUM, B_CALCEFFECT, "Child:",           922,124,80,20, paf->child+paf->curmult, 1.0, 600.0, 100, 0, "Specify the number of children of a particle that multiply itself");
1760                         
1761                         uiBlockBeginAlign(block);
1762                         uiDefButF(block, NUM, B_CALCEFFECT, "Randlife:",        550,96,96,20, &paf->randlife, 0.0, 2.0, 10, 0, "Give the particlelife a random variation");
1763                         uiDefButI(block, NUM, B_CALCEFFECT, "Seed:",            652,96,80,20, &paf->seed, 0.0, 255.0, 0, 0, "Set an offset in the random table");
1764
1765                         uiDefButBitS(block, TOG, PAF_FACE, B_CALCEFFECT, "Face",                735,96,46,20, &paf->flag, 0, 0, 0, 0, "Emit particles also from faces");
1766                         uiDefButBitS(block, TOG, PAF_BSPLINE, B_CALCEFFECT, "Bspline",  782,96,54,20, &paf->flag, 0, 0, 0, 0, "Use B spline formula for particle interpolation");
1767                         uiDefButS(block, TOG, REDRAWVIEW3D, "Vect",                             837,96,45,20, &paf->stype, 0, 0, 0, 0, "Give the particles a rotation direction");
1768                         uiDefButF(block, NUM, B_DIFF,                   "VectSize",             885,96,116,20, &paf->vectsize, 0.0, 1.0, 10, 0, "Set the speed for Vect");      
1769
1770                         uiBlockBeginAlign(block);
1771                         uiBlockSetCol(block, TH_BUT_SETTING2);
1772                         uiDefButF(block, NUM, B_CALCEFFECT, "Norm:",            550,67,96,20, &paf->normfac, -2.0, 2.0, 10, 0, "Let the mesh give the particle a starting speed");
1773                         uiDefButF(block, NUM, B_CALCEFFECT, "Ob:",              649,67,86,20, &paf->obfac, -1.0, 1.0, 10, 0, "Let the object give the particle a starting speed");
1774                         uiDefButF(block, NUM, B_CALCEFFECT, "Rand:",            738,67,86,20, &paf->randfac, 0.0, 2.0, 10, 0, "Give the startingspeed a random variation");
1775                         uiDefButF(block, NUM, B_CALCEFFECT, "Tex:",             826,67,85,20, &paf->texfac, 0.0, 2.0, 10, 0, "Let the texture give the particle a starting speed");
1776                         uiDefButF(block, NUM, B_CALCEFFECT, "Damp:",            913,67,89,20, &paf->damp, 0.0, 1.0, 10, 0, "Specify the damping factor");
1777                         uiBlockSetCol(block, TH_AUTO);
1778                         
1779                         uiBlockBeginAlign(block);
1780                         uiDefButF(block, NUM, B_CALCEFFECT, "X:",               550,31,72,20, paf->force, -1.0, 1.0, 1, 0, "Specify the X axis of a continues force");
1781                         uiDefButF(block, NUM, B_CALCEFFECT, "Y:",               624,31,78,20, paf->force+1,-1.0, 1.0, 1, 0, "Specify the Y axis of a continues force");
1782                         uiDefBut(block, LABEL, 0, "Force:",                             550,9,72,20, NULL, 1.0, 0, 0, 0, "");
1783                         uiDefButF(block, NUM, B_CALCEFFECT, "Z:",               623,9,79,20, paf->force+2, -1.0, 1.0, 1, 0, "Specify the Z axis of a continues force");
1784
1785                         uiBlockBeginAlign(block);
1786                         uiDefButF(block, NUM, B_CALCEFFECT, "X:",               722,31,74,20, paf->defvec, -1.0, 1.0, 1, 0, "Specify the X axis of a force, determined by the texture");
1787                         uiDefButF(block, NUM, B_CALCEFFECT, "Y:",               798,31,74,20, paf->defvec+1,-1.0, 1.0, 1, 0, "Specify the Y axis of a force, determined by the texture");
1788                         uiDefBut(block, LABEL, 0, "Texture:",                   722,9,74,20, NULL, 1.0, 0, 0, 0, "");
1789                         uiDefButF(block, NUM, B_CALCEFFECT, "Z:",               797,9,75,20, paf->defvec+2, -1.0, 1.0, 1, 0, "Specify the Z axis of a force, determined by the texture");
1790                         uiBlockEndAlign(block);
1791
1792                         uiDefButS(block, ROW, B_CALCEFFECT, "Int",              875,9,32,43, &paf->texmap, 14.0, 0.0, 0, 0, "Use texture intensity as a factor for texture force");
1793
1794                         uiBlockBeginAlign(block);
1795                         uiDefButS(block, ROW, B_CALCEFFECT, "RGB",              911,31,45,20, &paf->texmap, 14.0, 1.0, 0, 0, "Use RGB values as a factor for particle speed vector");
1796                         uiDefButS(block, ROW, B_CALCEFFECT, "Grad",             958,31,44,20, &paf->texmap, 14.0, 2.0, 0, 0, "Use texture gradient as a factor for particle speed vector");
1797                         uiDefButF(block, NUM, B_CALCEFFECT, "Nabla:",           911,9,91,20, &paf->nabla, 0.0001f, 1.0, 1, 0, "Specify the dimension of the area for gradient calculation");
1798
1799                 }
1800         }
1801 }
1802
1803 void object_panels()
1804 {
1805         Object *ob;
1806
1807         /* check context here */
1808         ob= OBACT;
1809         if(ob) {
1810                 if(ob->id.lib) uiSetButLock(1, "Can't edit library data");
1811
1812                 object_panel_anim(ob);
1813                 object_panel_draw(ob);
1814                 object_panel_constraint("Object");
1815                 if(ob->type==OB_MESH) {
1816                         object_panel_effects(ob);
1817                 }
1818                 object_panel_deflectors(ob);
1819                 object_softbodies(ob);
1820
1821                 uiClearButLock();
1822         }
1823 }
1824