initial commit of the fluid simulator.
[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 #include "BKE_utildefines.h"
54
55 #include "BLI_blenlib.h"
56 #include "BLI_arithb.h"
57
58 #include "BSE_filesel.h"
59 #include "BSE_headerbuttons.h"
60
61 #include "BIF_butspace.h"
62 #include "BDR_editcurve.h"
63 #include "BIF_gl.h"
64 #include "BIF_glutil.h"
65 #include "BIF_graphics.h"
66 #include "BIF_interface.h"
67 #include "BIF_keyval.h"
68 #include "BIF_mainqueue.h"
69 #include "BIF_mywindow.h"
70 #include "BIF_poseobject.h"
71 #include "BIF_resources.h"
72 #include "BIF_screen.h"
73 #include "BIF_space.h"
74 #include "BIF_toolbox.h"
75
76 #include "BDR_drawobject.h"
77
78 #include "mydevice.h"
79 #include "blendef.h"
80
81 /* -----includes for this file specific----- */
82
83
84 #include "DNA_action_types.h"
85 #include "DNA_armature_types.h"
86 #include "DNA_camera_types.h"
87 #include "DNA_constraint_types.h"
88 #include "DNA_curve_types.h"
89 #include "DNA_effect_types.h"
90 #include "DNA_group_types.h"
91 #include "DNA_image_types.h"
92 #include "DNA_key_types.h"
93 #include "DNA_lamp_types.h"
94 #include "DNA_lattice_types.h"
95 #include "DNA_material_types.h"
96 #include "DNA_meta_types.h"
97 #include "DNA_mesh_types.h"
98 #include "DNA_modifier_types.h"
99 #include "DNA_object_types.h"
100 #include "DNA_object_force.h"
101 #include "DNA_object_fluidsim.h"
102 #include "DNA_radio_types.h"
103 #include "DNA_screen_types.h"
104 #include "DNA_sound_types.h"
105 #include "DNA_texture_types.h"
106 #include "DNA_userdef_types.h"
107 #include "DNA_vfont_types.h"
108 #include "DNA_view3d_types.h"
109 #include "DNA_world_types.h"
110
111 #include "BKE_anim.h"
112 #include "BKE_armature.h"
113 #include "BKE_constraint.h"
114 #include "BKE_curve.h"
115 #include "BKE_depsgraph.h"
116 #include "BKE_displist.h"
117 #include "BKE_effect.h"
118 #include "BKE_font.h"
119 #include "BKE_image.h"
120 #include "BKE_ipo.h"
121 #include "BKE_lattice.h"
122 #include "BKE_material.h"
123 #include "BKE_mball.h"
124 #include "BKE_mesh.h"
125 #include "BKE_modifier.h"
126 #include "BKE_object.h"
127 #include "BKE_sound.h"
128 #include "BKE_texture.h"
129 #include "BKE_utildefines.h"
130 #include "BKE_DerivedMesh.h"
131 #include "LBM_fluidsim.h"
132
133 #include "BIF_editconstraint.h"
134 #include "BSE_editipo.h"
135 #include "BDR_editobject.h"
136
137 #include "butspace.h" // own module
138
139 static float prspeed=0.0;
140 float prlen=0.0;
141
142
143 /* ********************* CONSTRAINT ***************************** */
144
145 static void constraint_active_func(void *ob_v, void *con_v)
146 {
147         Object *ob= ob_v;
148         bConstraint *con;
149         ListBase *lb;
150         
151         /* lets be nice and escape if its active already */
152         if(con_v) {
153                 con= con_v;
154                 if(con->flag & CONSTRAINT_ACTIVE) return;
155         }
156         
157         lb= get_active_constraints(ob);
158         
159         for(con= lb->first; con; con= con->next) {
160                 if(con==con_v) con->flag |= CONSTRAINT_ACTIVE;
161                 else con->flag &= ~CONSTRAINT_ACTIVE;
162         }
163
164         /* make sure ipowin and buttons shows it */
165         if(ob->ipowin==IPO_CO) {
166                 allqueue(REDRAWIPO, IPO_CO);
167                 allspace(REMAKEIPO, 0);
168                 allqueue(REDRAWNLA, 0);
169         }
170         allqueue(REDRAWBUTSOBJECT, 0);
171 }
172
173 static void add_constraint_to_active(Object *ob, bConstraint *con)
174 {
175         ListBase *list;
176         
177         list = get_active_constraints(ob);
178         if (list) {
179                 unique_constraint_name(con, list);
180                 BLI_addtail(list, con);
181                 
182                 con->flag |= CONSTRAINT_ACTIVE;
183                 for(con= con->prev; con; con= con->prev)
184                         con->flag &= ~CONSTRAINT_ACTIVE;
185         }
186 }
187
188 static void enable_constraint_ipo_func (void *ob_v, void *con_v)
189 {
190         Object *ob= ob_v;
191         bConstraint *con = con_v;
192         bConstraintChannel *chan;
193         ListBase *conbase;
194
195         conbase = get_active_constraint_channels(ob, 1);        // 1 == create
196
197         if (!conbase)
198                 return;
199
200         /* See if this list already has an appropriate channel */
201         chan = find_constraint_channel(conbase, con->name);
202
203         if (!chan){
204                 /* Add a new constraint channel */
205                 chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
206                 strcpy(chan->name, con->name);
207                 BLI_addtail(conbase, chan);
208         }
209
210         /* Ensure there is an ipo to display */
211         if (!chan->ipo){
212                 chan->ipo = add_ipo(con->name, IPO_CO);
213         }
214
215         /* make sure ipowin shows it */
216         ob->ipowin= IPO_CO;
217         allqueue(REDRAWIPO, IPO_CO);
218         allspace(REMAKEIPO, 0);
219         allqueue(REDRAWNLA, 0);
220 }
221
222
223 static void add_influence_key_to_constraint_func (void *ob_v, void *con_v)
224 {
225         Object *ob= ob_v;
226         bConstraint *con = con_v;
227         bConstraintChannel *chan;
228         ListBase *conbase;
229         IpoCurve *icu;
230         
231         conbase = get_active_constraint_channels(ob, 1);        // 1=make
232         
233         if (!conbase)
234                 return;
235         
236         /* See if this list already has an appropriate channel */
237         chan = find_constraint_channel(conbase, con->name);
238         
239         if (!chan){
240                 /* Add a new constraint channel */
241                 chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
242                 strcpy(chan->name, con->name);
243                 BLI_addtail(conbase, chan);
244         }
245         
246         /* Ensure there is an ipo to display */
247         if (!chan->ipo){
248                 chan->ipo = add_ipo(con->name, IPO_CO);
249         }
250         
251         /* now insert an ipo key */
252         icu= get_ipocurve(NULL, IPO_CO, CO_ENFORCE, chan->ipo);
253         insert_vert_ipo(icu, CFRA, con->enforce);
254         
255         /* make sure ipowin shows it */
256         ob->ipowin= IPO_CO;
257         allqueue(REDRAWIPO, IPO_CO);
258         allspace(REMAKEIPO, 0);
259         allqueue(REDRAWNLA, 0);
260         
261         BIF_undo_push("Insert Influence Key");
262 }
263
264
265 static void del_constraint_func (void *ob_v, void *con_v)
266 {
267         bConstraint *con= con_v;
268         bConstraintChannel *chan;
269         ListBase *lb;
270         
271         /* remove ipo channel */
272         lb= get_active_constraint_channels(ob_v, 0);
273         if(lb) {
274                 chan = find_constraint_channel(lb, con->name);
275                 if(chan) {
276                         if(chan->ipo) chan->ipo->id.us--;
277                         BLI_freelinkN(lb, chan);
278                 }
279         }
280         /* remove constraint itself */
281         lb= get_active_constraints(ob_v);
282         free_constraint_data (con);
283         BLI_freelinkN(lb, con);
284         
285         constraint_active_func(ob_v, NULL);
286
287         BIF_undo_push("Delete constraint");
288         allqueue(REDRAWBUTSOBJECT, 0);
289         allqueue(REDRAWIPO, 0); 
290
291 }
292
293 static void verify_constraint_name_func (void *ob_v, void *con_v)
294 {
295         ListBase *conlist;
296         bConstraint *con= con_v;
297         
298         if (!con)
299                 return;
300         
301         conlist = get_active_constraints(ob_v);
302         unique_constraint_name (con, conlist);
303         constraint_active_func(ob_v, con);
304
305 }
306
307 static void get_constraint_typestring (char *str, bConstraint *con)
308 {
309         switch (con->type){
310         case CONSTRAINT_TYPE_CHILDOF:
311                 strcpy (str, "Child Of");
312                 return;
313         case CONSTRAINT_TYPE_NULL:
314                 strcpy (str, "Null");
315                 return;
316         case CONSTRAINT_TYPE_TRACKTO:
317                 strcpy (str, "Track To");
318                 return;
319         case CONSTRAINT_TYPE_MINMAX:
320                 strcpy (str, "Floor");
321                 return;
322         case CONSTRAINT_TYPE_KINEMATIC:
323                 strcpy (str, "IK Solver");
324                 return;
325         case CONSTRAINT_TYPE_ROTLIKE:
326                 strcpy (str, "Copy Rotation");
327                 return;
328         case CONSTRAINT_TYPE_LOCLIKE:
329                 strcpy (str, "Copy Location");
330                 return;
331         case CONSTRAINT_TYPE_ACTION:
332                 strcpy (str, "Action");
333                 return;
334         case CONSTRAINT_TYPE_LOCKTRACK:
335                 strcpy (str, "Locked Track");
336                 return;
337         case CONSTRAINT_TYPE_FOLLOWPATH:
338                 strcpy (str, "Follow Path");
339                 return;
340         case CONSTRAINT_TYPE_STRETCHTO:
341                 strcpy (str, "Stretch To");
342                 return;
343         default:
344                 strcpy (str, "Unknown");
345                 return;
346         }
347 }
348
349 static int get_constraint_col(bConstraint *con)
350 {
351         switch (con->type) {
352         case CONSTRAINT_TYPE_NULL:
353                 return TH_BUT_NEUTRAL;
354         case CONSTRAINT_TYPE_KINEMATIC:
355                 return TH_BUT_SETTING2;
356         case CONSTRAINT_TYPE_TRACKTO:
357                 return TH_BUT_SETTING;
358         case CONSTRAINT_TYPE_ROTLIKE:
359                 return TH_BUT_SETTING1;
360         case CONSTRAINT_TYPE_LOCLIKE:
361                 return TH_BUT_POPUP;
362         case CONSTRAINT_TYPE_MINMAX:
363                 return TH_BUT_POPUP;
364         case CONSTRAINT_TYPE_ACTION:
365                 return TH_BUT_ACTION;
366         case CONSTRAINT_TYPE_LOCKTRACK:
367                 return TH_BUT_SETTING;
368         case CONSTRAINT_TYPE_FOLLOWPATH:
369                 return TH_BUT_SETTING2;
370         case CONSTRAINT_TYPE_STRETCHTO:
371                 return TH_BUT_SETTING;
372         default:
373                 return TH_REDALERT;
374         }
375 }
376
377 static void constraint_moveUp(void *ob_v, void *con_v)
378 {
379         bConstraint *con, *constr= con_v;
380         ListBase *conlist;
381         
382         if(constr->prev) {
383                 conlist = get_active_constraints(ob_v);
384                 for(con= conlist->first; con; con= con->next) {
385                         if(con==constr) {
386                                 BLI_remlink(conlist, con);
387                                 BLI_insertlink(conlist, con->prev->prev, con);
388                                 break;
389                         }
390                 }
391         }
392         BIF_undo_push("Move constraint");
393 }
394
395 static void constraint_moveDown(void *ob_v, void *con_v)
396 {
397         bConstraint *con, *constr= con_v;
398         ListBase *conlist;
399         
400         if(constr->next) {
401                 conlist = get_active_constraints(ob_v);
402                 for(con= conlist->first; con; con= con->next) {
403                         if(con==constr) {
404                                 BLI_remlink(conlist, con);
405                                 BLI_insertlink(conlist, con->next, con);
406                                 break;
407                         }
408                 }
409         }
410         BIF_undo_push("Move constraint");
411 }
412
413
414 static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, short *xco, short *yco)
415 {
416         Object *ob= OBACT;
417         uiBut *but;
418         char typestr[64];
419         short height, width = 265;
420         int curCol, rb_col;
421
422         /* unless button has own callback, it adds this callback to button */
423         uiBlockSetFunc(block, constraint_active_func, ob, con);
424         
425         get_constraint_typestring (typestr, con);
426
427         curCol = get_constraint_col(con);
428
429         /* Draw constraint header */
430         uiBlockSetEmboss(block, UI_EMBOSSN);
431         
432         /* rounded header */
433         rb_col= (con->flag & CONSTRAINT_ACTIVE)?10:-10;
434         uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-1, width+40, 22, NULL, 5.0, 0.0, 
435                          (con->flag & CONSTRAINT_EXPAND)?3:15 , rb_col-20, ""); 
436         
437         /* open/close */
438         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");
439         
440         /* up down */
441         uiBlockSetEmboss(block, UI_EMBOSS);
442         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");
443         uiButSetFunc(but, constraint_moveUp, ob, con);
444         
445         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");
446         uiButSetFunc(but, constraint_moveDown, ob, con);
447         
448         if (con->flag & CONSTRAINT_EXPAND) {
449                 
450                 if (con->flag & CONSTRAINT_DISABLE) {
451                         BIF_ThemeColor(TH_REDALERT);
452                         uiBlockSetCol(block, TH_REDALERT);
453                 }
454                 else
455                         BIF_ThemeColor(curCol);
456
457                 /*if (type==TARGET_BONE)
458                         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"); 
459                 else
460                         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"); 
461                 */
462                 uiBlockSetEmboss(block, UI_EMBOSS);
463                 
464                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, *xco+10, *yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
465                 
466                 but = uiDefBut(block, TEX, B_CONSTRAINT_TEST, "", *xco+120, *yco, 85, 18, con->name, 0.0, 29.0, 0.0, 0.0, "Constraint name"); 
467                 uiButSetFunc(but, verify_constraint_name_func, ob, con);
468         }       
469         else{
470                 uiBlockSetEmboss(block, UI_EMBOSSN);
471
472                 if (con->flag & CONSTRAINT_DISABLE) {
473                         uiBlockSetCol(block, TH_REDALERT);
474                         BIF_ThemeColor(TH_REDALERT);
475                 }
476                 else
477                         BIF_ThemeColor(curCol);
478                 
479                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, *xco+10, *yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
480                 
481                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, con->name, *xco+120, *yco-1, 135, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
482         }
483
484         uiBlockSetCol(block, TH_AUTO);  
485         
486         uiBlockSetEmboss(block, UI_EMBOSSN);
487         
488         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");
489         uiButSetFunc(but, del_constraint_func, ob, con);
490
491         uiBlockSetEmboss(block, UI_EMBOSS);
492
493
494         /* Draw constraint data*/
495         if (!(con->flag & CONSTRAINT_EXPAND)) {
496                 (*yco)-=21;
497         }
498         else {
499                 switch (con->type){
500                 case CONSTRAINT_TYPE_ACTION:
501                         {
502                                 bActionConstraint *data = con->data;
503                                 bArmature *arm;
504
505                                 height = 88;
506                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
507                                 
508                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
509
510                                 /* Draw target parameters */
511                                 uiBlockBeginAlign(block);
512                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
513
514                                 arm = get_armature(data->tar);
515                                 if (arm){
516                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
517                                 }
518                                 else
519                                         strcpy (data->subtarget, "");
520                                 uiBlockEndAlign(block);
521
522                                 /* Draw action button */
523                                 uiBlockBeginAlign(block);
524                                 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");
525                                 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"); 
526                                 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");
527
528                                 uiBlockBeginAlign(block);
529                                 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"); 
530                                 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"); 
531                                 
532                                 uiBlockBeginAlign(block);
533                                 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");
534                                 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");
535                                 uiBlockEndAlign(block);
536                         }
537                         break;
538                 case CONSTRAINT_TYPE_LOCLIKE:
539                         {
540                                 bLocateLikeConstraint *data = con->data;
541                                 bArmature *arm;
542                                 
543                                 height = 66;
544                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
545
546                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
547
548                                 /* Draw target parameters */
549                                 uiBlockBeginAlign(block);
550                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
551
552                                 arm = get_armature(data->tar);
553                                 if (arm){
554                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
555                                 }
556                                 else
557                                         strcpy (data->subtarget, "");
558                                 uiBlockEndAlign(block);
559                                 
560                                 /* Draw XYZ toggles */
561                                 uiBlockBeginAlign(block);
562                                 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");
563                                 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");
564                                 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");
565                                 uiBlockEndAlign(block);
566                         }
567                         break;
568                 case CONSTRAINT_TYPE_ROTLIKE:
569                         {
570                                 bRotateLikeConstraint *data = con->data;
571                                 bArmature *arm;
572                                 
573                                 height = 46;
574                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
575                                 
576                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
577
578                                 /* Draw target parameters */
579                                 uiBlockBeginAlign(block);
580                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
581
582                                 arm = get_armature(data->tar);
583                                 if (arm){
584                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
585                                 }
586                                 else
587                                         strcpy (data->subtarget, "");
588                                 uiBlockEndAlign(block);
589                         }
590                         break;
591                 case CONSTRAINT_TYPE_KINEMATIC:
592                         {
593                                 bKinematicConstraint *data = con->data;
594                                 bArmature *arm;
595                                 
596                                 height = 108;
597                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
598                                 
599                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
600
601                                 /* Draw target parameters */
602                                 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");
603                                 
604                                 uiBlockBeginAlign(block);
605                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 19, &data->tar, "Target Object"); 
606
607                                 arm = get_armature(data->tar);
608                                 if (arm)
609                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,19, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
610                                 else
611                                         strcpy (data->subtarget, "");
612         
613                                 uiBlockBeginAlign(block);
614                                 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");
615                                 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");
616                                 
617                                 uiBlockBeginAlign(block);
618                                 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");
619                                 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");
620                                 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"); 
621                                 uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+142, *yco-106, 143, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations"); 
622                                 
623                         }
624                         break;
625                 case CONSTRAINT_TYPE_TRACKTO:
626                         {
627                                 bTrackToConstraint *data = con->data;
628                                 bArmature *arm;
629
630                                 height = 66;
631                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
632                                 
633                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
634
635                                 /* Draw target parameters */
636                                 uiBlockBeginAlign(block);
637                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
638
639                                 arm = get_armature(data->tar);
640                                 if (arm){
641                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
642                                 }
643                                 else
644                                         strcpy (data->subtarget, "");
645                                 uiBlockEndAlign(block);
646
647                                 uiBlockBeginAlign(block);
648                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "To:", *xco+12, *yco-64, 25, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
649                                 
650                                 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");
651                                 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");
652                                 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");
653                                 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");
654                                 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");
655                                 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");
656                                 uiBlockEndAlign(block);
657                                 
658                                 uiBlockBeginAlign(block);
659                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Up:", *xco+174, *yco-64, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
660                                 
661                                 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");
662                                 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");
663                                 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");
664                                 uiBlockEndAlign(block);
665                         }
666                         break;
667                 case CONSTRAINT_TYPE_MINMAX:
668                         {
669                                 bMinMaxConstraint *data = con->data;
670                                 bArmature *arm;
671
672                                 height = 66;
673                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
674                                 
675                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
676
677                                 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"); 
678
679                                 /* Draw target parameters */
680                                 uiBlockBeginAlign(block);
681                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
682
683                                 arm = get_armature(data->tar);
684                                 if (arm){
685                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
686                                 }
687                                 else
688                                         strcpy (data->subtarget, "");
689                                 uiBlockEndAlign(block);
690
691                                 but=uiDefButBitS(block, TOG, 1, B_CONSTRAINT_TEST, "Sticky", *xco, *yco-24, 54, 18, &data->sticky, 0, 24, 0, 0, "Immobilize object while constrained");
692                                 
693                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Max/Min:", *xco-8, *yco-64, 54, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
694
695                                 uiBlockBeginAlign(block);                       
696                                 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");
697                                 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");
698                                 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");
699                                 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");
700                                 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");
701                                 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");
702                                 uiBlockEndAlign(block);
703                         }
704                         break;
705                 case CONSTRAINT_TYPE_LOCKTRACK:
706                         {
707                                 bLockTrackConstraint *data = con->data;
708                                 bArmature *arm;
709                                 height = 66;
710                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
711
712                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
713
714                                 /* Draw target parameters */
715                                 uiBlockBeginAlign(block);
716                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
717
718                                 arm = get_armature(data->tar);
719                                 if (arm){
720                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
721                                 }
722                                 else
723                                         strcpy (data->subtarget, "");
724                                 uiBlockEndAlign(block);
725                                 
726                                 uiBlockBeginAlign(block);
727                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "To:", *xco+12, *yco-64, 25, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
728                                 
729                                 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");
730                                 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");
731                                 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");
732                                 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");
733                                 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");
734                                 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");
735                                 uiBlockEndAlign(block);
736                                 
737                                 uiBlockBeginAlign(block);
738                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Lock:", *xco+166, *yco-64, 38, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
739                                 
740                                 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");
741                                 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");
742                                 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");
743                                 uiBlockEndAlign(block);
744                         }
745                         break;
746                 case CONSTRAINT_TYPE_FOLLOWPATH:
747                         {
748                                 bFollowPathConstraint *data = con->data;
749
750                                 height = 66;
751                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
752                                 
753                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
754
755                                 /* Draw target parameters */
756                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
757                                 
758                                 /* Draw Curve Follow toggle */
759                                 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");
760
761                                 /* Draw Offset number button */
762                                 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"); 
763
764                                 uiBlockBeginAlign(block);
765                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Fw:", *xco+12, *yco-64, 27, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
766                                 
767                                 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");
768                                 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");
769                                 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");
770                                 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");
771                                 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");
772                                 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");
773                                 uiBlockEndAlign(block);
774                                 
775                                 uiBlockBeginAlign(block);
776                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Up:", *xco+174, *yco-64, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
777                                 
778                                 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");
779                                 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");
780                                 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");
781                                 uiBlockEndAlign(block);
782                         }
783                         break;
784                 case CONSTRAINT_TYPE_STRETCHTO:
785                         {
786                                 bStretchToConstraint *data = con->data;
787                                 bArmature *arm;
788                                 
789                                 height = 105;
790                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
791                                 
792                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
793
794
795                                 /* Draw target parameters */
796                                 uiBlockBeginAlign(block);
797                                 uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
798
799                                 arm = get_armature(data->tar);
800                                 if (arm){
801                                         but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
802                                 }
803                                 else
804                                         strcpy (data->subtarget, "");
805                                 uiBlockEndAlign(block);
806
807                                 
808                                 uiBlockBeginAlign(block);
809                                 uiDefButF(block,BUTM,B_CONSTRAINT_TEST,"R",*xco, *yco-60,20,18,&(data->orglength),0.0,0,0,0,"Recalculate RLenght");
810                                 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");
811                                 uiBlockEndAlign(block);
812
813                                 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");
814
815                                 uiBlockBeginAlign(block);
816                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Vol:",*xco+14, *yco-104,30,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
817                                 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");
818                                 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");
819                                 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");
820                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"NONE", *xco+114, *yco-104,50,18, &data->volmode, 12.0, 3.0, 0, 0, "Ignore Volume");
821                                 uiBlockEndAlign(block);
822
823                                 
824                                 uiBlockBeginAlign(block);
825                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Plane:",*xco+175, *yco-104,40,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
826                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X",       *xco+215, *yco-104,20,18, &data->plane, 12.0, 0.0, 0, 0, "Keep X axis");
827                                 uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z",       *xco+235, *yco-104,20,18, &data->plane, 12.0, 2.0, 0, 0, "Keep Z axis");
828                                 uiBlockEndAlign(block);
829                                 }
830                         break;
831                 case CONSTRAINT_TYPE_NULL:
832                         {
833                                 height = 17;
834                                 uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
835                                 
836                         }
837                         break;
838                 default:
839                         height = 0;
840                         break;
841                 }
842
843                 (*yco)-=(24+height);
844         }
845
846         if (con->type!=CONSTRAINT_TYPE_NULL) {
847                 uiBlockBeginAlign(block);
848                 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");
849                 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");
850                 /* If this is on an object or bone, add ipo channel the constraint */
851                 uiButSetFunc (but, enable_constraint_ipo_func, ob, con);
852                 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");
853                 /* Add a keyframe to the influence IPO */
854                 uiButSetFunc (but, add_influence_key_to_constraint_func, ob, con);
855                 uiBlockEndAlign(block);
856                 (*yco)-=24;
857         } else {
858                 (*yco)-=3;
859         }
860         
861 }
862
863 static uiBlock *add_constraintmenu(void *arg_unused)
864 {
865         Object *ob= OBACT;
866         uiBlock *block;
867         ListBase *conlist;
868         short yco= 0;
869         
870         conlist = get_active_constraints(ob);
871         
872         block= uiNewBlock(&curarea->uiblocks, "add_constraintmenu", UI_EMBOSSP, UI_HELV, curarea->win);
873
874         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIKE,"Copy Location",         0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
875         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIKE,"Copy Rotation",         0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
876         
877         uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
878         
879         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_TRACKTO,"Track To",              0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
880         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_MINMAX,"Floor",          0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
881         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK,"Locked Track",                0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
882         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH,"Follow Path",                0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
883         
884         uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
885         
886         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_STRETCHTO,"Stretch To",          0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
887
888         if (ob->flag & OB_POSEMODE) {
889                 uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
890                 
891                 uiDefBut(block, BUTM, B_CONSTRAINT_ADD_KINEMATIC,"IK Solver",           0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
892                 uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ACTION,"Action",         0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
893                 
894         }
895         uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
896
897         uiDefBut(block, BUTM, B_CONSTRAINT_ADD_NULL,"Null",             0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
898         
899         uiTextBoundsBlock(block, 50);
900         uiBlockSetDirection(block, UI_DOWN);
901                 
902         return block;
903 }
904
905 void do_constraintbuts(unsigned short event)
906 {
907         Object *ob= OBACT;
908         
909         switch(event) {
910         case B_CONSTRAINT_TEST:
911                 break;  // no handling
912                 
913         case B_CONSTRAINT_CHANGETARGET:
914                 if(ob->pose) ob->pose->flag |= POSE_RECALC;     // checks & sorts pose channels
915                 DAG_scene_sort(G.scene);
916                 break;
917                 
918         case B_CONSTRAINT_ADD_NULL:
919                 {
920                         bConstraint *con;
921                         
922                         con = add_new_constraint(CONSTRAINT_TYPE_NULL);
923                         add_constraint_to_active(ob, con);
924
925                         BIF_undo_push("Add constraint");
926                 }
927                 break;
928         case B_CONSTRAINT_ADD_KINEMATIC:
929                 {
930                         bConstraint *con;
931                         
932                         con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
933                         add_constraint_to_active(ob, con);
934
935                         BIF_undo_push("Add constraint");
936                 }
937                 break;
938         case B_CONSTRAINT_ADD_TRACKTO:
939                 {
940                         bConstraint *con;
941
942                         con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
943                         add_constraint_to_active(ob, con);
944
945                         BIF_undo_push("Add constraint");
946                 }
947                 break;
948         case B_CONSTRAINT_ADD_MINMAX:
949                 {
950                         bConstraint *con;
951
952                         con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
953                         add_constraint_to_active(ob, con);
954
955                         BIF_undo_push("Add constraint");
956                 }
957                 break;
958         case B_CONSTRAINT_ADD_ROTLIKE:
959                 {
960                         bConstraint *con;
961
962                         con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
963                         add_constraint_to_active(ob, con);
964
965                         BIF_undo_push("Add constraint");
966                 }
967                 break;
968         case B_CONSTRAINT_ADD_LOCLIKE:
969                 {
970                         bConstraint *con;
971
972                         con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
973                         add_constraint_to_active(ob, con);
974
975                         BIF_undo_push("Add constraint");
976                 }
977                 break;
978         case B_CONSTRAINT_ADD_ACTION:
979                 {
980                         bConstraint *con;
981
982                         con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
983                         add_constraint_to_active(ob, con);
984
985                         BIF_undo_push("Add constraint");
986                 }
987                 break;
988         case B_CONSTRAINT_ADD_LOCKTRACK:
989                 {
990                         bConstraint *con;
991
992                         con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
993                         add_constraint_to_active(ob, con);
994
995                         BIF_undo_push("Add constraint");
996                 }
997                 break;
998         case B_CONSTRAINT_ADD_FOLLOWPATH:
999                 {
1000                         bConstraint *con;
1001
1002                         con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
1003                         add_constraint_to_active(ob, con);
1004
1005                 }
1006                 break;
1007         case B_CONSTRAINT_ADD_STRETCHTO:
1008                 {
1009                         bConstraint *con;
1010                         con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
1011                         add_constraint_to_active(ob, con);
1012                                 
1013                         BIF_undo_push("Add constraint");
1014                 }
1015                 break;
1016
1017         default:
1018                 break;
1019         }
1020
1021         object_test_constraints(ob);
1022         
1023         if(ob->pose) update_pose_constraint_flags(ob->pose);
1024         
1025         if(ob->type==OB_ARMATURE) DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1026         else DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
1027         
1028         allqueue (REDRAWVIEW3D, 0);
1029         allqueue (REDRAWBUTSOBJECT, 0);
1030 }
1031
1032 void object_panel_constraint(char *context)
1033 {
1034         uiBlock *block;
1035         Object *ob= OBACT;
1036         ListBase *conlist;
1037         bConstraint *curcon;
1038         short xco, yco;
1039         char str[64];
1040         
1041         block= uiNewBlock(&curarea->uiblocks, "object_panel_constraint", UI_EMBOSS, UI_HELV, curarea->win);
1042         if(uiNewPanel(curarea, block, "Constraints", context, 640, 0, 318, 204)==0) return;
1043
1044         /* this is a variable height panel, newpanel doesnt force new size on existing panels */
1045         /* so first we make it default height */
1046         uiNewPanelHeight(block, 204);
1047
1048         if(G.obedit==OBACT) return;     // ??
1049         
1050         conlist = get_active_constraints(OBACT);
1051         
1052         if (conlist) {
1053                  
1054                 uiDefBlockBut(block, add_constraintmenu, NULL, "Add Constraint", 0, 190, 130, 20, "Add a new constraint");
1055                 
1056                 /* print active object or bone */
1057                 str[0]= 0;
1058                 if (ob->flag & OB_POSEMODE){
1059                         bPoseChannel *pchan= get_active_posechannel(ob);
1060                         if(pchan) sprintf(str, "To Bone: %s", pchan->name);
1061                 }
1062                 else {
1063                         sprintf(str, "To Object: %s", ob->id.name+2);
1064                 }
1065                 uiDefBut(block, LABEL, 1, str,  150, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Displays Active Object or Bone name");
1066                 
1067                 /* Go through the list of constraints and draw them */
1068                 xco = 10;
1069                 yco = 160;
1070                 
1071                 for (curcon = conlist->first; curcon; curcon=curcon->next) {
1072                         /* Draw default constraint header */                    
1073                         draw_constraint(block, conlist, curcon, &xco, &yco);    
1074                 }
1075                 
1076                 if(yco < 0) uiNewPanelHeight(block, 204-yco);
1077                 
1078         }
1079 }
1080
1081 static void object_panel_draw(Object *ob)
1082 {
1083         uiBlock *block;
1084         int xco, a, dx, dy;
1085         
1086         block= uiNewBlock(&curarea->uiblocks, "object_panel_draw", UI_EMBOSS, UI_HELV, curarea->win);
1087         if(uiNewPanel(curarea, block, "Draw", "Object", 320, 0, 318, 204)==0) return;
1088
1089         /* LAYERS */
1090         xco= 120;
1091         dx= 35;
1092         dy= 30;
1093
1094         uiDefBut(block, LABEL, 0, "Layers",                             10,170,100,20, NULL, 0, 0, 0, 0, "");
1095         
1096         uiBlockBeginAlign(block);
1097         for(a=0; a<5; a++)
1098                 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, "");
1099         for(a=0; a<5; a++)
1100                 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, "");
1101                 
1102         xco+= 7;
1103         uiBlockBeginAlign(block);
1104         for(a=5; a<10; a++)
1105                 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, "");
1106         for(a=5; a<10; a++)
1107                 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, "");
1108
1109         uiBlockEndAlign(block);
1110
1111         uiDefBut(block, LABEL, 0, "Drawtype",                                           10,120,100,20, NULL, 0, 0, 0, 0, "");
1112         
1113         uiBlockBeginAlign(block);
1114         uiDefButC(block, ROW, REDRAWVIEW3D, "Shaded",   10,100,100, 20, &ob->dt, 0, OB_SHADED, 0, 0, "Draw active object shaded or textured");
1115         uiDefButC(block, ROW, REDRAWVIEW3D, "Solid",    10,80,100, 20, &ob->dt, 0, OB_SOLID, 0, 0, "Draw active object in solid");
1116         uiDefButC(block, ROW, REDRAWVIEW3D, "Wire",             10,60, 100, 20, &ob->dt, 0, OB_WIRE, 0, 0, "Draw active object in wireframe");
1117         uiDefButC(block, ROW, REDRAWVIEW3D, "Bounds",   10,40, 100, 20, &ob->dt, 0, OB_BOUNDBOX, 0, 0, "Only draw object with bounding box");
1118         uiBlockEndAlign(block);
1119         
1120         uiDefBut(block, LABEL, 0, "Draw Extra",                                                 120,120,90,20, NULL, 0, 0, 0, 0, "");
1121         
1122         uiBlockBeginAlign(block);
1123         uiDefButBitC(block, TOG, OB_BOUNDBOX, REDRAWVIEW3D, "Bounds",                           120, 100, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's bounds");
1124         uiDefButBitC(block, TOG, OB_DRAWNAME, REDRAWVIEW3D, "Name",             210, 100, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's name");
1125         
1126         uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Polyheder%x4",
1127                                                                                                                                         120, 80, 90, 20, &ob->boundtype, 0, 0, 0, 0, "Selects the boundary display type");
1128         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");
1129         
1130         uiDefButBitC(block, TOG, OB_TEXSPACE, REDRAWVIEW3D, "TexSpace", 120, 60, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's texture space");
1131         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");
1132         
1133         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)");
1134         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");
1135
1136 }
1137
1138 static void softbody_bake(Object *ob)
1139 {
1140         SoftBody *sb= ob->soft;
1141         ScrArea *sa;
1142         float frameleno= G.scene->r.framelen;
1143         int cfrao= CFRA;
1144         unsigned short event=0;
1145         short val;
1146         
1147         G.scene->r.framelen= 1.0;               // baking has to be in uncorrected time
1148         CFRA= sb->sfra;
1149         update_for_newframe_muted();    // put everything on this frame
1150         sbObjectToSoftbody(ob); // put softbody in restposition
1151         ob->softflag |= OB_SB_BAKEDO;
1152         
1153         curarea->win_swap= 0;           // clean swapbuffers
1154         
1155         for(; CFRA <= sb->efra; CFRA++) {
1156                 set_timecursor(CFRA);
1157                 
1158                 update_for_newframe_muted();
1159                 
1160                 for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1161                         if(sa->spacetype == SPACE_VIEW3D) {
1162                                 scrarea_do_windraw(sa);
1163                         }
1164                 }
1165                 screen_swapbuffers();
1166                 
1167                 while(qtest()) {
1168                         
1169                         event= extern_qread(&val);
1170                         if(event==ESCKEY) break;
1171                 }
1172                 if(event==ESCKEY) break;
1173         }
1174         
1175         if(event==ESCKEY) sbObjectToSoftbody(ob);       // clears all
1176         
1177         /* restore */
1178         waitcursor(0);
1179         ob->softflag &= ~OB_SB_BAKEDO;
1180         CFRA= cfrao;
1181         G.scene->r.framelen= frameleno;
1182         update_for_newframe_muted();
1183         allqueue(REDRAWVIEW3D, 0);
1184         allqueue(REDRAWBUTSOBJECT, 0);
1185 }
1186
1187
1188 // NT store processed path & file prefix for fluidsim bake directory
1189 void fluidsimFilesel(char *selection)
1190 {
1191         Object *ob = OBACT;
1192         char srcDir[FILE_MAXDIR], srcFile[FILE_MAXFILE];
1193         char prefix[FILE_MAXFILE];
1194         char *srch, *srchSub, *srchExt, *lastFound;
1195         int isElbeemSurf = 0;
1196
1197         strcpy(srcDir, selection);
1198         BLI_splitdirstring(srcDir, srcFile);
1199
1200         // make prefix
1201         strcpy(prefix, srcFile);
1202         // check if this is a previously generated surface mesh file
1203         srch = strstr(prefix, "_surface_");
1204         if(srch) {
1205                 srchSub = strstr(prefix,"_preview_");
1206                 if(!srchSub) srchSub = strstr(prefix,"_final_");
1207                 srchExt = strstr(prefix,".gz.bobj");
1208                 if(!srchExt) srchExt = strstr(prefix,".bobj");
1209                 if(srchSub && srchExt) {
1210                         *srch = '\0';
1211                         isElbeemSurf = 1;
1212                 }
1213         }
1214         if(!isElbeemSurf) {
1215                 // try to remove suffix
1216                 lastFound = NULL;
1217                 srch = strchr(prefix, '.'); // search last . from extension
1218                 while(srch) {
1219                         lastFound = srch;
1220                         if(srch) {
1221                                 srch++;
1222                                 srch = strchr(srch, '.');
1223                         }
1224                 }
1225                 if(lastFound) {
1226                         *lastFound = '\0';
1227                 } 
1228         }
1229
1230         // TODO check srcDir for file path from sce?
1231         
1232         
1233                 strcpy(ob->fluidsimSettings->surfdataDir, srcDir);
1234                 strcpy(ob->fluidsimSettings->surfdataPrefix, prefix);
1235                 //fprintf(stderr,"fluidsimFilesel: Using surfdata path '%s', prefix '%s' \n", ob->fluidsimSettings->surfdataDir,ob->fluidsimSettings->surfdataPrefix); // DEBUG
1236         
1237 }
1238
1239 void do_object_panels(unsigned short event)
1240 {
1241         Object *ob;
1242         Effect *eff;
1243         
1244         ob= OBACT;
1245
1246         switch(event) {
1247         case B_TRACKBUTS:
1248                 ob= OBACT;
1249                 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
1250                 allqueue(REDRAWVIEW3D, 0);
1251                 break;
1252         case B_RECALCPATH:
1253                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1254                 allqueue(REDRAWVIEW3D, 0);
1255                 break;
1256         case B_PRINTSPEED:
1257                 ob= OBACT;
1258                 if(ob) {
1259                         float vec[3];
1260                         CFRA++;
1261                         do_ob_ipo(ob);
1262                         where_is_object(ob);
1263                         VECCOPY(vec, ob->obmat[3]);
1264                         CFRA--;
1265                         do_ob_ipo(ob);
1266                         where_is_object(ob);
1267                         VecSubf(vec, vec, ob->obmat[3]);
1268                         prspeed= Normalise(vec);
1269                         scrarea_queue_winredraw(curarea);
1270                 }
1271                 break;
1272         case B_PRINTLEN:
1273                 ob= OBACT;
1274                 if(ob && ob->type==OB_CURVE) {
1275                         Curve *cu=ob->data;
1276                         
1277                         if(cu->path) prlen= cu->path->totdist; else prlen= -1.0;
1278                         scrarea_queue_winredraw(curarea);
1279                 } 
1280                 break;
1281         case B_RELKEY:
1282                 allspace(REMAKEIPO, 0);
1283                 allqueue(REDRAWBUTSOBJECT, 0);
1284                 allqueue(REDRAWIPO, 0);
1285                 break;
1286         case B_CURVECHECK:
1287                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1288                 allqueue(REDRAWVIEW3D, 0);
1289                 break;
1290         
1291         case B_SOFTBODY_CHANGE:
1292                 ob= OBACT;
1293                 if(ob) {
1294                         ob->softflag |= OB_SB_REDO;
1295                         allqueue(REDRAWBUTSOBJECT, 0);
1296                         allqueue(REDRAWVIEW3D, 0);
1297                 }
1298                 break;
1299         case B_SOFTBODY_DEL_VG:
1300                 ob= OBACT;
1301                 if(ob && ob->soft) {
1302                         ob->soft->vertgroup= 0;
1303                         ob->softflag |= OB_SB_REDO;
1304                         allqueue(REDRAWBUTSOBJECT, 0);
1305                         allqueue(REDRAWVIEW3D, 0);
1306                 }
1307                 break;
1308         case B_SOFTBODY_BAKE:
1309                 ob= OBACT;
1310                 if(ob && ob->soft) softbody_bake(ob);
1311                 break;
1312         case B_SOFTBODY_BAKE_FREE:
1313                 ob= OBACT;
1314                 if(ob && ob->soft) sbObjectToSoftbody(ob);
1315                 allqueue(REDRAWBUTSOBJECT, 0);
1316                 allqueue(REDRAWVIEW3D, 0);
1317                 break;
1318
1319         case B_FLUIDSIM_BAKE:
1320                 ob= OBACT;
1321                 /* write config files (currently no simulation) */
1322                 fluidsimBake(ob);
1323                 break;
1324         case B_FLUIDSIM_SELDIR: {
1325                         char str[FILE_MAXDIR+FILE_MAXFILE];
1326                         ScrArea *sa = closest_bigger_area();
1327                         strcpy(str,"//");
1328                         ob= OBACT;
1329                         /* chosse dir for surface files */
1330                         areawinset(sa->win);
1331                         activate_fileselect(FILE_SPECIAL, "Select Directory", str, fluidsimFilesel);
1332                 }
1333                 break;
1334                 
1335         default:
1336                 if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
1337                         ob= OBACT;
1338                         if(ob) {
1339                                 int a=B_SELEFFECT;
1340                                 
1341                                 eff= ob->effect.first;
1342                                 while(eff) {
1343                                         if(event==a) eff->flag |= SELECT;
1344                                         else eff->flag &= ~SELECT;
1345                                         
1346                                         a++;
1347                                         eff= eff->next;
1348                                 }
1349                                 allqueue(REDRAWBUTSOBJECT, 0);
1350                         }
1351                 }
1352         }
1353
1354 }
1355
1356 static void object_panel_anim(Object *ob)
1357 {
1358         uiBlock *block;
1359         char str[32];
1360         
1361         block= uiNewBlock(&curarea->uiblocks, "object_panel_anim", UI_EMBOSS, UI_HELV, curarea->win);
1362         if(uiNewPanel(curarea, block, "Anim settings", "Object", 0, 0, 318, 204)==0) return;
1363         
1364         uiBlockBeginAlign(block);
1365         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");
1366         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");
1367         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");
1368         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");
1369         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");
1370         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");
1371         uiBlockBeginAlign(block);
1372         uiDefButC(block, ROW,REDRAWVIEW3D,"UpX",        226,190,45,19, &ob->upflag, 13.0, 0.0, 0, 0, "Specify the axis that points up");
1373         uiDefButC(block, ROW,REDRAWVIEW3D,"Y",          274,190,20,19, &ob->upflag, 13.0, 1.0, 0, 0, "Specify the axis that points up");
1374         uiDefButC(block, ROW,REDRAWVIEW3D,"Z",          298,190,19,19, &ob->upflag, 13.0, 2.0, 0, 0, "Specify the axis that points up");
1375         uiBlockBeginAlign(block);
1376         uiDefButBitC(block, TOG, OB_DRAWKEY, REDRAWVIEW3D, "Draw Key",          24,160,71,19, &ob->ipoflag, 0, 0, 0, 0, "Draw object as key position");
1377         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");
1378         uiDefButBitC(block, TOG, OB_POWERTRACK, REDRAWVIEW3D, "Powertrack",             180,160,78,19, &ob->transflag, 0, 0, 0, 0, "Switch objects rotation off");
1379         uiDefButBitS(block, TOG, PARSLOW, 0, "SlowPar",                                 260,160,56,19, &ob->partype, 0, 0, 0, 0, "Create a delay in the parent relationship");
1380         uiBlockBeginAlign(block);
1381         uiDefButBitC(block, TOG, OB_DUPLIFRAMES, REDRAWVIEW3D, "DupliFrames",   24,128,89,19, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame");
1382         uiDefButBitC(block, TOG, OB_DUPLIVERTS, REDRAWVIEW3D, "DupliVerts",             114,128,82,19, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices");
1383         uiDefButBitC(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot",              200,128,31,19, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to facenormal");
1384         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");
1385         uiBlockBeginAlign(block);
1386         uiDefButS(block, NUM, REDRAWVIEW3D, "DupSta:",          24,105,141,19, &ob->dupsta, 1.0, (MAXFRAMEF - 1.0f), 0, 0, "Specify startframe for Dupliframes");
1387         uiDefButS(block, NUM, REDRAWVIEW3D, "DupOn:",           170,105,146,19, &ob->dupon, 1.0, 1500.0, 0, 0, "");
1388         uiDefButS(block, NUM, REDRAWVIEW3D, "DupEnd",           24,82,140,19, &ob->dupend, 1.0, MAXFRAMEF, 0, 0, "Specify endframe for Dupliframes");
1389         uiDefButS(block, NUM, REDRAWVIEW3D, "DupOff",           171,82,145,19, &ob->dupoff, 0.0, 1500.0, 0, 0, "");
1390         uiBlockBeginAlign(block);
1391         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");
1392         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");
1393         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");
1394         
1395         uiBlockBeginAlign(block);
1396         uiDefButF(block, NUM, REDRAWALL, "TimeOffset:",                 24,17,115,30, &ob->sf, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify an offset in frames");
1397         uiDefBut(block, BUT, B_AUTOTIMEOFS, "Automatic Time",   139,17,104,31, 0, 0, 0, 0, 0, "Generate automatic timeoffset values for all selected frames");
1398         uiDefBut(block, BUT, B_PRINTSPEED,      "PrSpeed",                      248,17,67,31, 0, 0, 0, 0, 0, "Print objectspeed");
1399         uiBlockEndAlign(block);
1400         
1401         sprintf(str, "%.4f", prspeed);
1402         uiDefBut(block, LABEL, 0, str,                                                  247,40,63,31, NULL, 1.0, 0, 0, 0, "");
1403         
1404 }
1405
1406 void do_effects_panels(unsigned short event)
1407 {
1408         Object *ob;
1409         Base *base;
1410         Effect *eff, *effn;
1411         int type;
1412         
1413         ob= OBACT;
1414
1415         switch(event) {
1416
1417     case B_AUTOTIMEOFS:
1418                 auto_timeoffs();
1419                 break;
1420         case B_FRAMEMAP:
1421                 G.scene->r.framelen= G.scene->r.framapto;
1422                 G.scene->r.framelen/= G.scene->r.images;
1423                 allqueue(REDRAWALL, 0);
1424                 break;
1425         case B_NEWEFFECT:
1426                 if(ob) {
1427                         if (BLI_countlist(&ob->effect)==MAX_EFFECT)
1428                                 error("Unable to add: effect limit reached");
1429                         else
1430                                 copy_act_effect(ob);
1431                 }
1432                 BIF_undo_push("New effect");
1433                 allqueue(REDRAWBUTSOBJECT, 0);
1434                 break;
1435         case B_DELEFFECT:
1436                 if(ob==0 || ob->type!=OB_MESH) break;
1437                 eff= ob->effect.first;
1438                 while(eff) {
1439                         effn= eff->next;
1440                         if(eff->flag & SELECT) {
1441                                 BLI_remlink(&ob->effect, eff);
1442                                 free_effect(eff);
1443                                 break;
1444                         }
1445                         eff= effn;
1446                 }
1447                 BIF_undo_push("Delete effect");
1448                 allqueue(REDRAWVIEW3D, 0);
1449                 allqueue(REDRAWBUTSOBJECT, 0);
1450                 break;
1451         case B_NEXTEFFECT:
1452                 if(ob==0 || ob->type!=OB_MESH) break;
1453                 eff= ob->effect.first;
1454                 while(eff) {
1455                         if(eff->flag & SELECT) {
1456                                 if(eff->next) {
1457                                         eff->flag &= ~SELECT;
1458                                         eff->next->flag |= SELECT;
1459                                 }
1460                                 break;
1461                         }
1462                         eff= eff->next;
1463                 }
1464                 allqueue(REDRAWBUTSOBJECT, 0);
1465                 break;
1466         case B_PREVEFFECT:
1467                 if(ob==0 || ob->type!=OB_MESH) break;
1468                 eff= ob->effect.first;
1469                 while(eff) {
1470                         if(eff->flag & SELECT) {
1471                                 if(eff->prev) {
1472                                         eff->flag &= ~SELECT;
1473                                         eff->prev->flag |= SELECT;
1474                                 }
1475                                 break;
1476                         }
1477                         eff= eff->next;
1478                 }
1479                 allqueue(REDRAWBUTSOBJECT, 0);
1480                 break;
1481         case B_CHANGEEFFECT:
1482                 if(ob==0 || ob->type!=OB_MESH) break;
1483                 eff= ob->effect.first;
1484                 while(eff) {
1485                         if(eff->flag & SELECT) {
1486                                 if(eff->type!=eff->buttype) {
1487                                         BLI_remlink(&ob->effect, eff);
1488                                         type= eff->buttype;
1489                                         free_effect(eff);
1490                                         eff= add_effect(type);
1491                                         BLI_addtail(&ob->effect, eff);
1492                                 }
1493                                 break;
1494                         }
1495                         eff= eff->next;
1496                 }
1497                 allqueue(REDRAWVIEW3D, 0);
1498                 allqueue(REDRAWBUTSOBJECT, 0);
1499                 break;
1500         case B_CALCEFFECT:
1501                 if(ob==0 || ob->type!=OB_MESH) break;
1502                 eff= ob->effect.first;
1503                 while(eff) {
1504                         if(eff->flag & SELECT) {
1505                                 if(eff->type==EFF_PARTICLE) build_particle_system(ob);
1506                         }
1507                         eff= eff->next;
1508                 }
1509                 allqueue(REDRAWVIEW3D, 0);
1510                 allqueue(REDRAWBUTSOBJECT, 0);
1511                 break;
1512         case B_RECALCAL:
1513                 base= FIRSTBASE;
1514                 while(base) {
1515                         if(base->lay & G.vd->lay) {
1516                                 ob= base->object;
1517                                 eff= ob->effect.first;
1518                                 while(eff) {
1519                                         if(eff->flag & SELECT) {
1520                                                 if(eff->type==EFF_PARTICLE) build_particle_system(ob);
1521                                         }
1522                                         eff= eff->next;
1523                                 }
1524                         }
1525                         base= base->next;
1526                 }
1527                 allqueue(REDRAWVIEW3D, 0);
1528                 break;
1529
1530         default:
1531                 if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
1532                         ob= OBACT;
1533                         if(ob) {
1534                                 int a=B_SELEFFECT;
1535                                 
1536                                 eff= ob->effect.first;
1537                                 while(eff) {
1538                                         if(event==a) eff->flag |= SELECT;
1539                                         else eff->flag &= ~SELECT;
1540                                         
1541                                         a++;
1542                                         eff= eff->next;
1543                                 }
1544                                 allqueue(REDRAWBUTSOBJECT, 0);
1545                         }
1546                 }
1547         }
1548
1549 }
1550
1551 /* Panel for particle interaction settings */
1552 static void object_panel_deflectors(Object *ob)
1553 {
1554         uiBlock *block;
1555
1556         block= uiNewBlock(&curarea->uiblocks, "object_panel_deflectors", UI_EMBOSS, UI_HELV, curarea->win);
1557         uiNewPanelTabbed("Constraints", "Object");
1558         if(uiNewPanel(curarea, block, "Particle Interaction", "Object", 640, 0, 318, 204)==0) return;
1559
1560         /* should become button, option? */
1561         if(ob->pd==NULL) {
1562                 ob->pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
1563                 /* and if needed, init here */
1564                 ob->pd->pdef_sbdamp = 0.1;
1565                 ob->pd->pdef_sbift  = 0.2;
1566                 ob->pd->pdef_sboft  = 0.02;
1567         }
1568         
1569         if(ob->pd) {
1570                 PartDeflect *pd= ob->pd;
1571                 
1572                 uiDefBut(block, LABEL, 0, "Fields",             10,180,140,20, NULL, 0.0, 0, 0, 0, "");
1573                 
1574                 uiBlockBeginAlign(block);
1575                 uiDefButS(block, ROW, REDRAWVIEW3D, "None",                     10,160,50,20, &pd->forcefield, 1.0, 0, 0, 0, "No force");
1576                 uiDefButS(block, ROW, REDRAWVIEW3D, "Force field",      60,160,90,20, &pd->forcefield, 1.0, PFIELD_FORCE, 0, 0, "Object center attracts or repels particles");
1577                 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");
1578                 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");
1579
1580                 uiBlockBeginAlign(block);
1581                 uiDefButF(block, NUM, REDRAWVIEW3D, "Strength: ",       10,110,140,20, &pd->f_strength, -1000, 1000, 1000, 0, "Strength of force field");
1582                 uiDefButF(block, NUM, REDRAWVIEW3D, "Fall-off: ",       10,90,140,20, &pd->f_power, 0, 10, 100, 0, "Falloff power (real gravitational fallof = 2)");
1583                 
1584                 uiBlockBeginAlign(block);
1585                 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");
1586                 uiDefButF(block, NUM, REDRAWVIEW3D, "MaxDist: ",        10,40,140,20, &pd->maxdist, 0, 1000.0, 100, 0, "Maximum distance for the field to work");
1587                 uiBlockEndAlign(block);
1588
1589 //              if(modifiers_isSoftbodyEnabled(ob)) {
1590                 if(0) {
1591                         uiDefBut(block, LABEL, 0, "Object is Softbody,",                160,160,150,20, NULL, 0.0, 0, 0, 0, "");
1592                         uiDefBut(block, LABEL, 0, "no Deflection possible",             160,140,150,20, NULL, 0.0, 0, 0, 0, "");
1593                         pd->deflect= 0;
1594                 }
1595                 else {
1596                         uiDefBut(block, LABEL, 0, "Deflection", 160,180,140,20, NULL, 0.0, 0, 0, 0, "");
1597                         
1598                         /* only meshes collide now */
1599                         if(ob->type==OB_MESH) {
1600                                 uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
1601                                 uiDefBut(block, LABEL, 0, "Particles",                  160,140,150,20, NULL, 0.0, 0, 0, 0, "");
1602                                 
1603                                 uiBlockBeginAlign(block);
1604                                 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");
1605                                 uiDefButF(block, NUM, B_DIFF, "Rnd Damping: ",  160,100,150,20, &pd->pdef_rdamp, 0.0, 1.0, 10, 0, "Random variation of damping");
1606                                 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");
1607                                 uiBlockEndAlign(block);
1608                                 
1609                                 uiDefBut(block, LABEL, 0, "Soft Body",                  160,60,150,20, NULL, 0.0, 0, 0, 0, "");
1610
1611                                 uiBlockBeginAlign(block);
1612                                 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");
1613                                 uiDefButF(block, NUM, B_DIFF, "Inner:", 160,20,150,20, &pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness");
1614                                 uiDefButF(block, NUM, B_DIFF, "Outer:", 160, 0,150,20, &pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness");
1615                                 uiBlockBeginAlign(block);
1616 /* seems to be working fine .. so we do use modifier stack by default .. code here rests for debugging
1617                             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");
1618 */
1619                         }               
1620                 }       
1621         }
1622 }
1623
1624
1625 /* Panel for softbodies */
1626 static void object_softbodies__enable(void *ob_v, void *arg2)
1627 {
1628         Object *ob = ob_v;
1629         ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
1630
1631         if (modifiers_isSoftbodyEnabled(ob)) {
1632                 if (md) {
1633                         md->mode &= ~(eModifierMode_Render|eModifierMode_Realtime);
1634                 }
1635         } else {
1636                 if (!md) {
1637                         md = modifier_new(eModifierType_Softbody);
1638                         BLI_addhead(&ob->modifiers, md);
1639                 }
1640
1641                 md->mode |= eModifierMode_Render|eModifierMode_Realtime;
1642
1643                 if (!ob->soft) {
1644                         ob->soft= sbNew();
1645                         ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
1646                 }
1647         }
1648
1649         allqueue(REDRAWBUTSEDIT, 0);
1650 }
1651
1652 static void object_softbodies(Object *ob)
1653 {
1654         uiBlock *block;
1655         
1656         block= uiNewBlock(&curarea->uiblocks, "object_softbodies", UI_EMBOSS, UI_HELV, curarea->win);
1657         uiNewPanelTabbed("Constraints", "Object");
1658         if(uiNewPanel(curarea, block, "Softbody", "Object", 640, 0, 318, 204)==0) return;
1659
1660         /* do not allow to combine with force fields */
1661         /* if(ob->pd && ob->pd->deflect) { */
1662         /* no reason for that any more BM */
1663         if(0) {
1664                 uiDefBut(block, LABEL, 0, "Object has Deflection,",             10,160,300,20, NULL, 0.0, 0, 0, 0, "");
1665                 uiDefBut(block, LABEL, 0, "no Softbody possible",               10,140,300,20, NULL, 0.0, 0, 0, 0, "");
1666         } else {
1667                 static int val;
1668                 uiBut *but;
1669
1670                 val = modifiers_isSoftbodyEnabled(ob);
1671                 but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Enable Soft Body",       10,200,150,20, &val, 0, 0, 0, 0, "Sets object to become soft body");
1672                 uiButSetFunc(but, object_softbodies__enable, ob, NULL);
1673                 uiDefBut(block, LABEL, 0, "",   160, 200,150,20, NULL, 0.0, 0.0, 0, 0, "");     // alignment reason
1674         }
1675         
1676         if(modifiers_isSoftbodyEnabled(ob)) {
1677                 SoftBody *sb= ob->soft;
1678                 int defCount;
1679                 char *menustr;
1680                 
1681                 if(sb==NULL) {
1682                         sb= ob->soft= sbNew();
1683                         ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
1684                 }
1685                 
1686                 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");
1687                 
1688                 if(sb->keys) uiSetButLock(1, "SoftBody is baked, free it first");
1689                 
1690                 if(ob->softflag & OB_SB_BAKESET) {
1691                         uiBlockBeginAlign(block);
1692                         uiDefButS(block, NUM, B_DIFF, "Start:",                 10, 170,100,20, &sb->sfra, 1.0, 10000.0, 10, 0, "Start frame for baking");
1693                         uiDefButS(block, NUM, B_DIFF, "End:",                   110, 170,100,20, &sb->efra, 1.0, 10000.0, 10, 0, "End frame for baking");
1694                         uiDefButS(block, NUM, B_DIFF, "Interval:",              210, 170,100,20, &sb->interval, 1.0, 10.0, 10, 0, "Interval in frames between baked keys");
1695                         
1696                         uiClearButLock();
1697                         
1698                         uiBlockBeginAlign(block);
1699                         if(sb->keys) {
1700                                 char str[128];
1701                                 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");
1702                                 sprintf(str, "Stored %d vertices %d keys %.3f MB", sb->totpoint, sb->totkey, ((float)16*sb->totpoint*sb->totkey)/(1024.0*1024.0));
1703                                 uiDefBut(block, LABEL, 0, str, 10, 100,300,20, NULL, 0.0, 0.0, 00, 0, "");
1704                         }
1705                         else                            
1706                                 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");
1707                 }
1708                 else {
1709                         /* GENERAL STUFF */
1710                         uiBlockBeginAlign(block);
1711                         uiDefButF(block, NUM, B_DIFF, "Friction:",              10, 170,150,20, &sb->mediafrict, 0.0, 10.0, 10, 0, "General media friction for point movements");
1712                         uiDefButF(block, NUM, B_DIFF, "Mass:",                  160, 170,150,20, &sb->nodemass , 0.001, 50.0, 10, 0, "Point Mass, the heavier the slower");
1713                         uiDefButF(block, NUM, B_DIFF, "Grav:",                  10,150,150,20, &sb->grav , 0.0, 10.0, 10, 0, "Apply gravitation to point movement");
1714                         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");
1715                         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");
1716                         uiBlockEndAlign(block);
1717                         
1718                         /* GOAL STUFF */
1719                         uiBlockBeginAlign(block);
1720                         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");
1721                         
1722                         menustr= get_vertexgroup_menustr(ob);
1723                         defCount=BLI_countlist(&ob->defbase);
1724                         if(defCount==0) sb->vertgroup= 0;
1725                         uiDefButS(block, MENU, B_SOFTBODY_CHANGE, menustr,              140,100,20,20, &sb->vertgroup, 0, defCount, 0, 0, "Browses available vertex groups");
1726                         
1727                         if(sb->vertgroup) {
1728                                 bDeformGroup *defGroup = BLI_findlink(&ob->defbase, sb->vertgroup-1);
1729                                 if(defGroup)
1730                                         uiDefBut(block, BUT, B_DIFF, defGroup->name,    160,100,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group");
1731                                 else
1732                                         uiDefBut(block, BUT, B_DIFF, "(no group)",      160,100,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore");
1733                                 uiDefIconBut(block, BUT, B_SOFTBODY_DEL_VG, ICON_X, 290,100,20,20, 0, 0, 0, 0, 0, "Disable use of vertex group");
1734                         }
1735                         else {
1736                                 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");
1737                         }
1738                         MEM_freeN (menustr);
1739
1740                         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");
1741                         uiDefButF(block, NUM, B_DIFF, "G Damp:",        160,80,150,20, &sb->goalfrict  , 0.0, 10.0, 10, 0, "Goal (vertex target position) friction");
1742                         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");
1743                         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");
1744                         uiBlockEndAlign(block);
1745                         
1746                         /* EDGE SPRING STUFF */
1747                         uiBlockBeginAlign(block);
1748                         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");
1749                         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");
1750                         uiDefButF(block, NUM, B_DIFF, "E Stiff:",       10,10,150,20, &sb->inspring, 0.0,  0.999, 10, 0, "Edge spring stiffness");
1751                         uiDefButF(block, NUM, B_DIFF, "E Damp:",        160,10,150,20, &sb->infrict, 0.0,  10.0, 10, 0, "Edge spring friction");
1752                         uiBlockEndAlign(block);
1753                 }
1754         }
1755         uiBlockEndAlign(block);
1756
1757 }
1758
1759 static void object_panel_effects(Object *ob)
1760 {
1761         Effect *eff;
1762         uiBlock *block;
1763         int a;
1764         short x, y;
1765         
1766         block= uiNewBlock(&curarea->uiblocks, "object_panel_effects", UI_EMBOSS, UI_HELV, curarea->win);
1767         uiNewPanelTabbed("Constraints", "Object");
1768         if(uiNewPanel(curarea, block, "Effects", "Object", 640, 0, 418, 204)==0) return;
1769
1770         /* EFFECTS */
1771         
1772         if (ob->type == OB_MESH) {
1773                 uiBlockBeginAlign(block);
1774                 uiDefBut(block, BUT, B_NEWEFFECT, "NEW Effect", 550,187,124,27, 0, 0, 0, 0, 0, "Create a new effect");
1775                 uiDefBut(block, BUT, B_DELEFFECT, "Delete", 676,187,62,27, 0, 0, 0, 0, 0, "Delete the effect");
1776                 uiBlockEndAlign(block);
1777         }
1778
1779         /* select effs */
1780         eff= ob->effect.first;
1781         a= 0;
1782         while(eff) {
1783                 
1784                 x= 15 * a + 550;
1785                 y= 172; // - 12*( abs(a/10) ) ;
1786                 uiDefButBitS(block, TOG, SELECT, B_SELEFFECT+a, "", x, y, 15, 12, &eff->flag, 0, 0, 0, 0, "");
1787                 
1788                 a++;
1789                 if(a==MAX_EFFECT) break;
1790                 eff= eff->next;
1791         }
1792         
1793         eff= ob->effect.first;
1794         while(eff) {
1795                 if(eff->flag & SELECT) break;
1796                 eff= eff->next;
1797         }
1798         
1799         if(eff) {
1800                 uiDefButS(block, MENU, B_CHANGEEFFECT, "Particles %x1", 895,187,107,27, &eff->buttype, 0, 0, 0, 0, "Set effect type");
1801                 
1802                 if(eff->type==EFF_PARTICLE) {
1803                         PartEff *paf;
1804                         
1805                         paf= (PartEff *)eff;
1806                         
1807                         uiDefBut(block, BUT, B_RECALCAL, "RecalcAll", 741,187,67,27, 0, 0, 0, 0, 0, "Update the particle system");
1808                         uiBlockBeginAlign(block);
1809                         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)");
1810                         if(paf->flag & PAF_STATIC)
1811                                 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");
1812                         
1813                         uiBlockBeginAlign(block);
1814                         uiDefButI(block, NUM, B_CALCEFFECT, "Tot:",                     550,146,91,20, &paf->totpart, 1.0, 100000.0, 0, 0, "Set the total number of particles");
1815                         if(paf->flag & PAF_STATIC) {
1816                                 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");
1817                         }
1818                         else {
1819                                 uiDefButF(block, NUM, B_CALCEFFECT, "Sta:",             644,146,84,20, &paf->sta, -250.0, MAXFRAMEF, 100, 0, "Specify the startframe");
1820                                 uiDefButF(block, NUM, B_CALCEFFECT, "End:",             731,146,97,20, &paf->end, 1.0, MAXFRAMEF, 100, 0, "Specify the endframe");
1821                         }
1822                         uiDefButF(block, NUM, B_CALCEFFECT, "Life:",            831,146,88,20, &paf->lifetime, 1.0, MAXFRAMEF, 100, 0, "Specify the life span of the particles");
1823                         uiDefButI(block, NUM, B_CALCEFFECT, "Keys:",            922,146,80,20, &paf->totkey, 1.0, 100.0, 0, 0, "Specify the number of key positions");
1824                         
1825                         uiDefButS(block, NUM, B_REDR,           "CurMul:",              550,124,91,20, &paf->curmult, 0.0, 3.0, 0, 0, "Multiply the particles");
1826                         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");
1827                         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.");
1828                         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");
1829                         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");
1830                         
1831                         uiBlockBeginAlign(block);
1832                         uiDefButF(block, NUM, B_CALCEFFECT, "Randlife:",        550,96,96,20, &paf->randlife, 0.0, 2.0, 10, 0, "Give the particlelife a random variation");
1833                         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");
1834
1835                         uiDefButBitS(block, TOG, PAF_FACE, B_CALCEFFECT, "Face",                735,96,46,20, &paf->flag, 0, 0, 0, 0, "Emit particles also from faces");
1836                         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");
1837                         uiDefButS(block, TOG, REDRAWVIEW3D, "Vect",                             837,96,45,20, &paf->stype, 0, 0, 0, 0, "Give the particles a rotation direction");
1838                         uiDefButF(block, NUM, B_DIFF,                   "VectSize",             885,96,116,20, &paf->vectsize, 0.0, 1.0, 10, 0, "Set the speed for Vect");      
1839
1840                         uiBlockBeginAlign(block);
1841                         uiBlockSetCol(block, TH_BUT_SETTING2);
1842                         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");
1843                         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");
1844                         uiDefButF(block, NUM, B_CALCEFFECT, "Rand:",            738,67,86,20, &paf->randfac, 0.0, 2.0, 10, 0, "Give the startingspeed a random variation");
1845                         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");
1846                         uiDefButF(block, NUM, B_CALCEFFECT, "Damp:",            913,67,89,20, &paf->damp, 0.0, 1.0, 10, 0, "Specify the damping factor");
1847                         uiBlockSetCol(block, TH_AUTO);
1848                         
1849                         uiBlockBeginAlign(block);
1850                         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");
1851                         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");
1852                         uiDefBut(block, LABEL, 0, "Force:",                             550,9,72,20, NULL, 1.0, 0, 0, 0, "");
1853                         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");
1854
1855                         uiBlockBeginAlign(block);
1856                         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");
1857                         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");
1858                         uiDefBut(block, LABEL, 0, "Texture:",                   722,9,74,20, NULL, 1.0, 0, 0, 0, "");
1859                         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");
1860                         uiBlockEndAlign(block);
1861
1862                         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");
1863
1864                         uiBlockBeginAlign(block);
1865                         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");
1866                         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");
1867                         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");
1868
1869                 }
1870         }
1871 }
1872
1873 /* NT - Panel for fluidsim settings */
1874 static void object_panel_fluidsim(Object *ob)
1875 {
1876         uiBlock *block;
1877         int yline = 160;
1878         const int lineHeight = 20;
1879         const int objHeight = 20;
1880         
1881         block= uiNewBlock(&curarea->uiblocks, "object_fluidsim", UI_EMBOSS, UI_HELV, curarea->win);
1882         uiNewPanelTabbed("Constraints", "Object");
1883         if(uiNewPanel(curarea, block, "Fluidsim", "Object", 640, 0, 318, 204)==0) return;
1884
1885         uiDefButBitS(block, TOG, OB_FLUIDSIM_ENABLE, REDRAWBUTSOBJECT, "Enable",         0,yline, 75,objHeight, 
1886                         &ob->fluidsimFlag, 0, 0, 0, 0, "Sets object to participate in fluid simulation");
1887
1888         if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
1889                 FluidsimSettings *fss= ob->fluidsimSettings;
1890                 
1891                 if(fss==NULL) {
1892                         fss = ob->fluidsimSettings = fluidsimSettingsNew(ob); // sbNew();
1893                 }
1894
1895                 if(ob->type==OB_MESH) {
1896
1897                         uiBlockBeginAlign(block);
1898                         uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Domain",           90, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_DOMAIN,   0.0, 0.0, "Bounding box of this object represents the computational domain of the fluid simulation.");
1899                         uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Fluid",           160, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_FLUID,    0.0, 0.0, "Object represents a volume of fluid in the simulation.");
1900                         uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Obstacle",      230, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_OBSTACLE, 0.0, 0.0, "Object is a fixed obstacle.");
1901                         yline -= lineHeight;
1902                         yline -= 5;
1903
1904                         /* display specific settings for each type */
1905                         if(fss->type == OB_FLUIDSIM_DOMAIN) {
1906                                 const int maxRes = 200;
1907
1908                                 uiDefButS(block, NUM, B_DIFF, "Resolution:", 0, yline,150,objHeight, &fss->resolutionxyz, 1, maxRes, 10, 0, "Domain resolution in X,Y and Z direction");
1909                                 uiDefButS(block, NUM, B_DIFF, "Preview-Res.:", 150, yline,150,objHeight, &fss->previewresxyz, 1, 100, 10, 0, "Resolution of the preview meshes to generate, also in X,Y and Z direction");
1910                                 yline -= lineHeight;
1911                                 uiDefButF(block, NUM, B_DIFF, "Real-size:",   0, yline,150,objHeight, &fss->realsize, 0.0, 1.0, 10, 0, "Size of the simulation domain in meters.");
1912                                 yline -= lineHeight;
1913
1914                                 uiDefButF(block, NUM, B_DIFF, "GravX:",   0, yline, 100,objHeight, &fss->gravx, -1000.1, 1000.1, 10, 0, "Gravity in X direction");
1915                                 uiDefButF(block, NUM, B_DIFF, "GravY:", 100, yline, 100,objHeight, &fss->gravy, -1000.1, 1000.1, 10, 0, "Gravity in Y direction");
1916                                 uiDefButF(block, NUM, B_DIFF, "GravZ:", 200, yline, 100,objHeight, &fss->gravz, -1000.1, 1000.1, 10, 0, "Gravity in Z direction");
1917                                 yline -= lineHeight;
1918                                 uiDefButF(block, NUM, B_DIFF, "Start time:",   0, yline,150,objHeight, &fss->animStart, 0.0, 100.0, 10, 0, "Simulation time of the first blender frame.");
1919                                 uiDefButF(block, NUM, B_DIFF, "End time:",   150, yline,150,objHeight, &fss->animEnd  , 0.0, 100.0, 10, 0, "Simulation time of the last blender frame.");
1920                                 yline -= lineHeight;
1921
1922                                 /* "advanced" settings */
1923                                 yline -= 5;
1924
1925                                 /* could also be char? */
1926                                 uiDefButS(block, MENU, REDRAWVIEW3D, "Viscosity%t|Manual %x1|Water %x2|Oil %x3|Honey %x4",      
1927                                                 0,yline,100,objHeight, &fss->viscosityMode, 0, 0, 0, 0, "Set viscosity of the fluid to a preset value, or use manual input.");
1928                                 if(fss->viscosityMode==1) {
1929                                         uiDefButF(block, NUM, B_DIFF, "Value:", 100, yline, 100,objHeight, &fss->viscosityValue,       0.0, 1.0, 10, 0, "Viscosity setting, value that is multiplied by 10 to the power of (exponent*-1).");
1930                                         uiDefButS(block, NUM, B_DIFF, "Neg-Exp.:", 200, yline, 100,objHeight, &fss->viscosityExponent, 0, 10, 10, 0, "Negative exponent for the viscosity value (to simplify entering small values e.g. 5*10^-6.");
1931                                 } else {
1932                                         // display preset values
1933                                         uiDefBut(block, LABEL,   0, fluidsimViscosityPresetString[fss->viscosityMode], 100,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
1934                                 }
1935                                 yline -= lineHeight;
1936
1937                                 uiDefBut(block, LABEL,   0, "Gui:",              0,yline,50,objHeight, NULL, 0.0, 0, 0, 0, "");
1938                                 uiDefButS(block, MENU, REDRAWVIEW3D, "GuiDisplayMode%t|Geometry %x1|Preview %x2|Final %x3",     
1939                                                  50,yline,100,objHeight, &fss->guiDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh in the blender gui.");
1940                                 uiDefBut(block, LABEL,   0, "Rend:", 150,yline,50,objHeight, NULL, 0.0, 0, 0, 0, "");
1941                                 uiDefButS(block, MENU, REDRAWVIEW3D, "RenderDisplayMode%t|Geometry %x1|Preview %x2|Final %x3",  
1942                                                 200,yline,100,objHeight, &fss->renderDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh for rendering.");
1943                                 yline -= lineHeight;
1944
1945                                 uiDefBut(block, BUT, B_FLUIDSIM_SELDIR, "Select Output Directory",      0, yline,100,objHeight, NULL, 0.0, 0.0, 10, 0, "Select Directory (and/or filenames) to store baked fluid simulation files in");
1946                                 uiDefBut(block, LABEL, 0, fss->surfdataDir,    100,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
1947                                 uiDefBut(block, LABEL, 0, fss->surfdataPrefix, 200,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
1948                                 yline -= lineHeight;
1949
1950                                 uiDefBut(block, BUT, B_FLUIDSIM_BAKE, "BAKE",   0, yline,300,objHeight, NULL, 0.0, 0.0, 10, 0, "Perform simulation and output and surface&preview meshes for each frame.");
1951                         }
1952                         else if(fss->type == OB_FLUIDSIM_FLUID) {
1953                                 yline -= lineHeight + 5;
1954                                 uiDefBut(block, LABEL, 0, "Initial velocity:",          0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
1955                                 yline -= lineHeight;
1956                                 uiDefButF(block, NUM, B_DIFF, "X:",   0, yline, 100,objHeight, &fss->iniVelx, -1000.1, 1000.1, 10, 0, "Initial fluid velocity in X direction");
1957                                 uiDefButF(block, NUM, B_DIFF, "Y:", 100, yline, 100,objHeight, &fss->iniVely, -1000.1, 1000.1, 10, 0, "Initial fluid velocity in Y direction");
1958                                 uiDefButF(block, NUM, B_DIFF, "Z:", 200, yline, 100,objHeight, &fss->iniVelz, -1000.1, 1000.1, 10, 0, "Initial fluid velocity in Z direction");
1959                                 yline -= lineHeight;
1960                         }
1961                         else if(fss->type == OB_FLUIDSIM_OBSTACLE) {
1962                                 yline -= lineHeight + 5;
1963                                 uiDefBut(block, LABEL, 0, "No additional settings as of now...",                0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
1964                                 yline -= lineHeight;
1965                         }
1966                         else {
1967                                 yline -= lineHeight + 5;
1968                                 /* not yet set */
1969                                 uiDefBut(block, LABEL, 0, "Select object type for simulation",          0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
1970                                 yline -= lineHeight;
1971                         }
1972
1973                 } else {
1974                         yline -= lineHeight + 5;
1975                         uiDefBut(block, LABEL, 0, "Sorry - only meshes supported", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
1976                         yline -= lineHeight;
1977                 }
1978         } else {
1979                 yline -= lineHeight + 5;
1980                 uiDefBut(block, LABEL, 0, "Object not enabled for fluid simulation...", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
1981                 yline -= lineHeight;
1982         }
1983         uiBlockEndAlign(block);
1984 }
1985
1986 void object_panels()
1987 {
1988         Object *ob;
1989
1990         /* check context here */
1991         ob= OBACT;
1992         if(ob) {
1993                 if(ob->id.lib) uiSetButLock(1, "Can't edit library data");
1994
1995                 object_panel_anim(ob);
1996                 object_panel_draw(ob);
1997                 object_panel_constraint("Object");
1998                 if(ob->type==OB_MESH) {
1999                         object_panel_effects(ob);
2000                 }
2001                 object_panel_deflectors(ob);
2002                 object_softbodies(ob);
2003                 object_panel_fluidsim(ob);
2004
2005                 uiClearButLock();
2006         }
2007 }
2008