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