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