Initial revision
[blender.git] / source / blender / src / editsca.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 <stdlib.h>
34 #include <math.h>
35
36 #ifndef WIN32
37 #include <unistd.h>
38 #else
39 #include <io.h>
40 #include "BLI_winstuff.h"
41 #endif   
42
43 #include "MEM_guardedalloc.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_arithb.h"
47 #include "BLI_editVert.h"
48
49 #include "DNA_action_types.h"
50 #include "DNA_material_types.h"
51 #include "DNA_sensor_types.h"
52 #include "DNA_actuator_types.h"
53 #include "DNA_controller_types.h"
54 #include "DNA_property_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_screen_types.h"
57 #include "DNA_space_types.h"
58 #include "DNA_scene_types.h"
59 #include "DNA_sound_types.h"
60 #include "DNA_text_types.h"
61 #include "DNA_view3d_types.h"
62 #include "DNA_mesh_types.h"
63
64 #include "BKE_library.h"
65 #include "BKE_global.h"
66 #include "BKE_main.h"
67 #include "BKE_sca.h"
68 #include "BKE_property.h"
69
70 #include "BIF_gl.h"
71 #include "BIF_resources.h"
72 #include "BIF_space.h"
73 #include "BIF_interface.h"
74 #include "BIF_screen.h"
75 #include "BIF_editsca.h"
76 #include "BIF_keyval.h"
77 #include "BIF_editsound.h"
78
79 #include "BDR_editcurve.h"
80 #include "BSE_buttons.h"
81
82 #include "blendef.h"
83 #include "mydevice.h"
84 #include "interface.h"
85 #include "nla.h"        /* For __NLA : Important, do not remove */
86
87 #include "license_key.h"
88 extern int LICENSE_KEY_VALID;
89
90 #define B_DIFF                  1
91 #define B_ADD_PROP      2701
92 #define B_CHANGE_PROP   2702
93
94 #define B_ADD_SENS              2703
95 #define B_CHANGE_SENS   2704
96 #define B_DEL_SENS              2705
97
98 #define B_ADD_CONT              2706
99 #define B_CHANGE_CONT   2707
100 #define B_DEL_CONT              2708
101
102 #define B_ADD_ACT               2709
103 #define B_CHANGE_ACT    2710
104 #define B_DEL_ACT               2711
105
106 #define B_SOUNDACT_BROWSE       2712
107
108 /* internals */
109
110 /****/
111
112 static ID **get_selected_and_linked_obs(short *count, short scavisflag);
113 static char *actuator_pup(Object *owner);
114
115 /****/
116
117 static void del_property(void *selpropv, void *data2_unused)
118 {
119         bProperty *prop, *selprop= selpropv;
120         Object *ob;
121         int a=0;
122                 
123         ob= OBACT;
124         if(ob==NULL) return;
125
126         prop= ob->prop.first;
127         while(prop) {
128                 if(prop==selprop) {
129                         if (strcmp(prop->name,"Text") == 0) {
130                                 allqueue(REDRAWVIEW3D, 0);
131                         }
132                         BLI_remlink(&ob->prop, prop);
133                         free_property(prop);
134                         break;
135                 }
136                 a++;
137                 prop= prop->next;
138         }
139         allqueue(REDRAWBUTSGAME, 0);
140         
141 }
142
143 static int vergname(const void *v1, const void *v2)
144 {
145         char **x1, **x2;
146         
147         x1= (char **)v1;
148         x2= (char **)v2;
149         
150         return strcmp(*x1, *x2);
151 }
152
153 void make_unique_prop_names(char *str)
154 {
155         Object *ob;
156         bProperty *prop;
157         bSensor *sens;
158         bController *cont;
159         bActuator *act;
160         ID **idar;
161         short a, obcount, propcount=0, nr;
162         char **names;
163         
164         /* this function is called by a Button, and gives the current
165          * stringpointer as an argument, this is the one that can change
166          */
167
168         idar= get_selected_and_linked_obs(&obcount, BUTS_SENS_SEL|BUTS_SENS_ACT|BUTS_ACT_SEL|BUTS_ACT_ACT|BUTS_CONT_SEL|BUTS_CONT_ACT);
169         
170         /* for each object, make properties and sca names unique */
171         
172         /* count total names */
173         for(a=0; a<obcount; a++) {
174                 ob= (Object *)idar[a];
175                 propcount+= BLI_countlist(&ob->prop);
176                 propcount+= BLI_countlist(&ob->sensors);
177                 propcount+= BLI_countlist(&ob->controllers);
178                 propcount+= BLI_countlist(&ob->actuators);
179         }       
180         if(propcount==0) {
181                 if(idar) MEM_freeN(idar);
182                 return;
183         }
184         
185         /* make names array for sorting */
186         names= MEM_callocN(propcount*sizeof(void *), "names");
187
188         /* count total names */
189         nr= 0;
190         for(a=0; a<obcount; a++) {
191                 ob= (Object *)idar[a];
192                 prop= ob->prop.first;
193                 while(prop) {
194                         names[nr++]= prop->name;
195                         prop= prop->next;
196                 }
197                 sens= ob->sensors.first;
198                 while(sens) {
199                         names[nr++]= sens->name;
200                         sens= sens->next;
201                 }
202                 cont= ob->controllers.first;
203                 while(cont) {
204                         names[nr++]= cont->name;
205                         cont= cont->next;
206                 }
207                 act= ob->actuators.first;
208                 while(act) {
209                         names[nr++]= act->name;
210                         act= act->next;
211                 }
212         }
213
214         qsort(names, propcount, sizeof(void *), vergname);
215         
216         /* now we check for double names, and change them */
217         
218         for(nr=0; nr<propcount; nr++) {
219                 if(names[nr]!=str && strcmp( names[nr], str )==0 ) {
220                         BLI_newname(str, +1);
221                 }
222         }
223         
224         MEM_freeN(idar);
225         MEM_freeN(names);
226 }
227
228 static void make_unique_prop_names_cb(void *strv, void *redraw_view3d_flagv)
229 {
230         char *str= strv;
231         int redraw_view3d_flag= (int) redraw_view3d_flagv;
232
233         make_unique_prop_names(str);
234         if (redraw_view3d_flag) allqueue(REDRAWVIEW3D, 0);
235 }
236
237 static void sca_move_sensor(void *datav, void *data2_unused)
238 {
239         bSensor *sens_to_delete= datav;
240         int val;
241         Base *base;
242         bSensor *sens;
243         
244         val= pupmenu("Move up%x1|Move down %x2");
245         
246         if(val>0) {
247                 /* now find out which object has this ... */
248                 base= FIRSTBASE;
249                 while(base) {
250                 
251                         sens= base->object->sensors.first;
252                         while(sens) {
253                                 if(sens == sens_to_delete) break;
254                                 sens= sens->next;
255                         }
256                         
257                         if(sens) {
258                                 if( val==1 && sens->prev) {
259                                         BLI_remlink(&base->object->sensors, sens);
260                                         BLI_insertlinkbefore(&base->object->sensors, sens->prev, sens);
261                                 }
262                                 else if( val==2 && sens->next) {
263                                         BLI_remlink(&base->object->sensors, sens);
264                                         BLI_insertlink(&base->object->sensors, sens->next, sens);
265                                 }
266                                 allqueue(REDRAWBUTSGAME, 0);
267                                 break;
268                         }
269                         
270                         base= base->next;
271                 }
272         }
273 }
274
275 static void sca_move_controller(void *datav, void *data2_unused)
276 {
277         bController *controller_to_del= datav;
278         int val;
279         Base *base;
280         bController *cont;
281         
282         val= pupmenu("Move up%x1|Move down %x2");
283         
284         if(val>0) {
285                 /* now find out which object has this ... */
286                 base= FIRSTBASE;
287                 while(base) {
288                 
289                         cont= base->object->controllers.first;
290                         while(cont) {
291                                 if(cont == controller_to_del) break;
292                                 cont= cont->next;
293                         }
294                         
295                         if(cont) {
296                                 if( val==1 && cont->prev) {
297                                         BLI_remlink(&base->object->controllers, cont);
298                                         BLI_insertlinkbefore(&base->object->controllers, cont->prev, cont);
299                                 }
300                                 else if( val==2 && cont->next) {
301                                         BLI_remlink(&base->object->controllers, cont);
302                                         BLI_insertlink(&base->object->controllers, cont->next, cont);
303                                 }
304                                 allqueue(REDRAWBUTSGAME, 0);
305                                 break;
306                         }
307                         
308                         base= base->next;
309                 }
310         }
311 }
312
313 static void sca_move_actuator(void *datav, void *data2_unused)
314 {
315         bActuator *actuator_to_move= datav;
316         int val;
317         Base *base;
318         bActuator *act;
319         
320         val= pupmenu("Move up%x1|Move down %x2");
321         
322         if(val>0) {
323                 /* now find out which object has this ... */
324                 base= FIRSTBASE;
325                 while(base) {
326                 
327                         act= base->object->actuators.first;
328                         while(act) {
329                                 if(act == actuator_to_move) break;
330                                 act= act->next;
331                         }
332                         
333                         if(act) {
334                                 if( val==1 && act->prev) {
335                                         BLI_remlink(&base->object->actuators, act);
336                                         BLI_insertlinkbefore(&base->object->actuators, act->prev, act);
337                                 }
338                                 else if( val==2 && act->next) {
339                                         BLI_remlink(&base->object->actuators, act);
340                                         BLI_insertlink(&base->object->actuators, act->next, act);
341                                 }
342                                 allqueue(REDRAWBUTSGAME, 0);
343                                 break;
344                         }
345                         
346                         base= base->next;
347                 }
348         }
349 }
350
351 void do_gamebuts(unsigned short event)
352 {
353         bProperty *prop;
354         bSensor *sens;
355         bController *cont;
356         bActuator *act;
357         Base *base;
358         Object *ob;
359         int didit;
360         
361         ob= OBACT;
362         if(ob==0) return;
363         
364         switch(event) {
365                 
366         case B_ADD_PROP:
367                 prop= new_property(PROP_FLOAT);
368                 make_unique_prop_names(prop->name);
369                 BLI_addtail(&ob->prop, prop);
370                 allqueue(REDRAWBUTSGAME, 0);
371                 break;
372         
373         case B_CHANGE_PROP:
374                 prop= ob->prop.first;
375                 while(prop) {
376                         if(prop->type!=prop->otype) {
377                                 init_property(prop);
378                                 if (strcmp(prop->name, "Text") == 0) {
379                                         allqueue(REDRAWVIEW3D, 0);
380                                 }
381                         }
382                         prop= prop->next;
383                 }
384                 allqueue(REDRAWBUTSGAME, 0);
385                 break;
386         
387         case B_ADD_SENS:
388                 base= FIRSTBASE;
389                 while(base) {
390                         if(base->object->scaflag & OB_ADDSENS) {
391                                 base->object->scaflag &= ~OB_ADDSENS;
392                                 sens= new_sensor(SENS_ALWAYS);
393                                 BLI_addtail(&(base->object->sensors), sens);
394                                 make_unique_prop_names(sens->name);
395                                 base->object->scaflag |= OB_SHOWSENS;
396                         }
397                         base= base->next;
398                 }
399                 
400                 allqueue(REDRAWBUTSGAME, 0);
401                 break;
402
403         case B_CHANGE_SENS:
404                 base= FIRSTBASE;
405                 while(base) {
406                         sens= base->object->sensors.first;
407                         while(sens) {
408                                 if(sens->type != sens->otype) {
409                                         init_sensor(sens);
410                                         sens->otype= sens->type;
411                                         break;
412                                 }
413                                 sens= sens->next;
414                         }
415                         base= base->next;
416                 }
417                 allqueue(REDRAWBUTSGAME, 0);
418                 break;
419         
420         case B_DEL_SENS:
421                 base= FIRSTBASE;
422                 while(base) {
423                         sens= base->object->sensors.first;
424                         while(sens) {
425                                 if(sens->flag & SENS_DEL) {
426                                         BLI_remlink(&(base->object->sensors), sens);
427                                         free_sensor(sens);
428                                         break;
429                                 }
430                                 sens= sens->next;
431                         }
432                         base= base->next;
433                 }
434                 allqueue(REDRAWBUTSGAME, 0);
435                 break;
436         
437         case B_ADD_CONT:
438                 base= FIRSTBASE;
439                 while(base) {
440                         if(base->object->scaflag & OB_ADDCONT) {
441                                 base->object->scaflag &= ~OB_ADDCONT;
442                                 cont= new_controller(CONT_LOGIC_AND);
443                                 make_unique_prop_names(cont->name);
444                                 base->object->scaflag |= OB_SHOWCONT;
445                                 BLI_addtail(&(base->object->controllers), cont);
446                         }
447                         base= base->next;
448                 }
449                 allqueue(REDRAWBUTSGAME, 0);
450                 break;
451
452         case B_CHANGE_CONT:
453                 base= FIRSTBASE;
454                 while(base) {
455                         cont= base->object->controllers.first;
456                         while(cont) {
457                                 if(cont->type != cont->otype) {
458                                         init_controller(cont);
459                                         cont->otype= cont->type;
460                                         break;
461                                 }
462                                 cont= cont->next;
463                         }
464                         base= base->next;
465                 }
466                 allqueue(REDRAWBUTSGAME, 0);
467                 break;
468         
469
470         case B_DEL_CONT:
471                 base= FIRSTBASE;
472                 while(base) {
473                         cont= base->object->controllers.first;
474                         while(cont) {
475                                 if(cont->flag & CONT_DEL) {
476                                         BLI_remlink(&(base->object->controllers), cont);
477                                         unlink_controller(cont);
478                                         free_controller(cont);
479                                         break;
480                                 }
481                                 cont= cont->next;
482                         }
483                         base= base->next;
484                 }
485                 allqueue(REDRAWBUTSGAME, 0);
486                 break;
487         
488         case B_ADD_ACT:
489                 base= FIRSTBASE;
490                 while(base) {
491                         if(base->object->scaflag & OB_ADDACT) {
492                                 base->object->scaflag &= ~OB_ADDACT;
493                                 act= new_actuator(ACT_OBJECT);
494                                 make_unique_prop_names(act->name);
495                                 BLI_addtail(&(base->object->actuators), act);
496                                 base->object->scaflag |= OB_SHOWACT;
497                         }
498                         base= base->next;
499                 }
500                 allqueue(REDRAWBUTSGAME, 0);
501                 break;
502
503         case B_CHANGE_ACT:
504                 base= FIRSTBASE;
505                 while(base) {
506                         act= base->object->actuators.first;
507                         while(act) {
508                                 if(act->type != act->otype) {
509                                         init_actuator(act);
510                                         act->otype= act->type;
511                                         break;
512                                 }
513                                 act= act->next;
514                         }
515                         base= base->next;
516                 }
517                 allqueue(REDRAWBUTSGAME, 0);
518                 break;
519
520         case B_DEL_ACT:
521                 base= FIRSTBASE;
522                 while(base) {
523                         act= base->object->actuators.first;
524                         while(act) {
525                                 if(act->flag & ACT_DEL) {
526                                         BLI_remlink(&(base->object->actuators), act);
527                                         unlink_actuator(act);
528                                         free_actuator(act);
529                                         break;
530                                 }
531                                 act= act->next;
532                         }
533                         base= base->next;
534                 }
535                 allqueue(REDRAWBUTSGAME, 0);
536                 break;
537         
538         case B_SOUNDACT_BROWSE:
539                 /* since we don't know which... */
540                 didit= 0;
541                 base= FIRSTBASE;
542                 while(base)
543                 {
544                         act= base->object->actuators.first;
545                         while(act)
546                         {
547                                 if(act->type==ACT_SOUND)
548                                 {
549                                         bSoundActuator *sa= act->data;
550                                         if(sa->sndnr)
551                                         {
552                                                 bSound *sound= G.main->sound.first;
553                                                 int nr= 1;
554
555                                                 while(sound)
556                                                 {
557                                                         if(nr==sa->sndnr)
558                                                                 break;
559                                                         nr++;
560                                                         sound= sound->id.next;
561                                                 }
562                                                 
563                                                 if(sa->sound)
564                                                         sa->sound->id.us--;
565                                                 
566                                                 sa->sound= sound;
567                                                 
568                                                 if(sound)
569                                                         sound->id.us++;
570                                                 
571                                                 sa->sndnr= 0;
572                                                 didit= 1;
573                                         }
574                                 }
575                                 act= act->next;
576                         }
577                         if(didit)
578                                 break;
579                         base= base->next;
580                 }
581                 allqueue(REDRAWBUTSGAME, 0);
582                 allqueue(REDRAWSOUND, 0);
583
584                 break;
585
586         }
587 }
588
589
590 static char *sensor_name(int type)
591 {
592         switch (type) {
593         case SENS_ALWAYS:
594                 return "Always";
595         case SENS_TOUCH:
596                 return "Touch";
597         case SENS_NEAR:
598                 return "Near";
599         case SENS_KEYBOARD:
600                 return "Keyboard";
601         case SENS_PROPERTY:
602                 return "Property";
603         case SENS_MOUSE:
604                 return "Mouse";
605         case SENS_COLLISION:
606                 return "Collision";
607         case SENS_RADAR:
608                 return "Radar";
609         case SENS_RANDOM:
610                 return "Random";
611         case SENS_RAY:
612                 return "Ray";
613         case SENS_MESSAGE:
614                 return "Message";
615         }
616         return "unknown";
617 }
618
619 static char *sensor_pup(void)
620 {
621         /* the number needs to match defines in game.h */
622         return "Sensors %t|Always %x0|Keyboard %x3|Mouse %x5|"
623                 "Touch %x1|Collision %x6|Near %x2|Radar %x7|"
624                 "Property %x4|Random %x8|Ray %x9|Message %x10";
625 }
626
627 static char *controller_name(int type)
628 {
629         switch (type) {
630         case CONT_LOGIC_AND:
631                 return "AND";
632         case CONT_LOGIC_OR:
633                 return "OR";
634         case CONT_EXPRESSION:
635                 return "Expression";
636         case CONT_PYTHON:
637                 return "Python";
638         }
639         return "unknown";
640 }
641
642 static char *controller_pup(void)
643 {
644         return "Controllers   %t|AND %x0|OR %x1|Expression %x2|Python %x3";
645 }
646
647 static char *actuator_name(int type)
648 {
649         switch (type) {
650         case ACT_ACTION:
651                 return "Action";
652         case ACT_OBJECT:
653                 return "Motion";
654         case ACT_IPO:
655                 return "Ipo";
656         case ACT_LAMP:
657                 return "Lamp";
658         case ACT_CAMERA:
659                 return "Camera";
660         case ACT_MATERIAL:
661                 return "Material";
662         case ACT_SOUND:
663                 return "Sound";
664         case ACT_CD:
665                 return "CD";
666         case ACT_PROPERTY:
667                 return "Property";
668         case ACT_EDIT_OBJECT:
669                 return "Edit Object";
670         case ACT_CONSTRAINT:
671                 return "Constraint";
672         case ACT_SCENE:
673                 return "Scene";
674         case ACT_GROUP:
675                 return "Group";
676         case ACT_RANDOM:
677                 return "Random";
678         case ACT_MESSAGE:
679                 return "Message";
680         case ACT_GAME:
681                 return "Game";
682         case ACT_VISIBILITY:
683                 return "Game";
684         }
685         return "unknown";
686 }
687
688
689
690
691 static char *actuator_pup(Object *owner)
692 {
693         if (LICENSE_KEY_VALID)
694         {
695                 switch (owner->type)
696                 {
697                 case OB_ARMATURE:
698                         return "Actuators  %t|Action %x15|Motion %x0|Constraint %x9|Ipo %x1"
699                                 "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
700                                 "|Scene %x11|Random %x13|Message %x14|CD %x16|Game %x17"
701                                 "|Visibility %x18";
702                         break;
703                 default:
704                         return "Actuators  %t|Motion %x0|Constraint %x9|Ipo %x1"
705                                 "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
706                                 "|Scene %x11|Random %x13|Message %x14|CD %x16|Game %x17"
707                                 "|Visibility %x18";
708                 }
709         }
710         else
711         {
712                 switch (owner->type)
713                 {
714                 case OB_ARMATURE:
715                         return "Actuators  %t|Action %x15|Motion %x0|Constraint %x9|Ipo %x1"
716                                 "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
717                                 "|Scene %x11|Random %x13|Message %x14|Visibility %x18";
718                         break;
719                 default:
720                         return "Actuators  %t|Motion %x0|Constraint %x9|Ipo %x1"
721                                 "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
722                                 "|Scene %x11|Random %x13|Message %x14|Visibility %x18";
723                 }
724         }
725         
726 }
727
728
729
730 static void set_sca_ob(Object *ob)
731 {
732         bController *cont;
733         bActuator *act;
734
735         cont= ob->controllers.first;
736         while(cont) {
737                 cont->mynew= (bController *)ob;
738                 cont= cont->next;
739         }
740         act= ob->actuators.first;
741         while(act) {
742                 act->mynew= (bActuator *)ob;
743                 act= act->next;
744         }
745 }
746
747 static ID **get_selected_and_linked_obs(short *count, short scavisflag)
748 {
749         Base *base;
750         Object *ob, *obt;
751         ID **idar;
752         bSensor *sens;
753         bController *cont;
754         unsigned int lay;
755         int a, nr, doit;
756         
757         /* we need a sorted object list */
758         /* set scavisflags flags in Objects to indicate these should be evaluated */
759         /* also hide ob pointers in ->new entries of controllerss/actuators */
760         
761         *count= 0;
762         
763         if(G.scene==NULL) return NULL;
764         
765         ob= G.main->object.first;
766         while(ob) {
767                 ob->scavisflag= 0;
768                 set_sca_ob(ob);
769                 ob= ob->id.next;
770         }
771         
772         if(G.vd) lay= G.vd->lay;
773         else lay= G.scene->lay;
774         
775         base= FIRSTBASE;
776         while(base) {
777                 if(base->lay & lay) {
778                         if(base->flag & SELECT) {
779                                 if(scavisflag & BUTS_SENS_SEL) base->object->scavisflag |= OB_VIS_SENS;
780                                 if(scavisflag & BUTS_CONT_SEL) base->object->scavisflag |= OB_VIS_CONT;
781                                 if(scavisflag & BUTS_ACT_SEL) base->object->scavisflag |= OB_VIS_ACT;
782                         }
783                 }
784                 base= base->next;
785         }
786
787         if(OBACT) {
788                 if(scavisflag & BUTS_SENS_ACT) OBACT->scavisflag |= OB_VIS_SENS;
789                 if(scavisflag & BUTS_CONT_ACT) OBACT->scavisflag |= OB_VIS_CONT;
790                 if(scavisflag & BUTS_ACT_ACT) OBACT->scavisflag |= OB_VIS_ACT;
791         }
792         
793         if(scavisflag & (BUTS_SENS_LINK|BUTS_CONT_LINK|BUTS_ACT_LINK)) {
794                 doit= 1;
795                 while(doit) {
796                         doit= 0;
797                         
798                         ob= G.main->object.first;
799                         while(ob) {
800                         
801                                 /* 1st case: select sensor when controller selected */
802                                 if((scavisflag & BUTS_SENS_LINK) && (ob->scavisflag & OB_VIS_SENS)==0) {
803                                         sens= ob->sensors.first;
804                                         while(sens) {
805                                                 for(a=0; a<sens->totlinks; a++) {
806                                                         if(sens->links[a]) {
807                                                                 obt= (Object *)sens->links[a]->mynew;
808                                                                 if(obt && (obt->scavisflag & OB_VIS_CONT)) {
809                                                                         doit= 1;
810                                                                         ob->scavisflag |= OB_VIS_SENS;
811                                                                         break;
812                                                                 }
813                                                         }
814                                                 }
815                                                 if(doit) break;
816                                                 sens= sens->next;
817                                         }
818                                 }
819                                 
820                                 /* 2nd case: select cont when act selected */
821                                 if((scavisflag & BUTS_CONT_LINK)  && (ob->scavisflag & OB_VIS_CONT)==0) {
822                                         cont= ob->controllers.first;
823                                         while(cont) {
824                                                 for(a=0; a<cont->totlinks; a++) {
825                                                         if(cont->links[a]) {
826                                                                 obt= (Object *)cont->links[a]->mynew;
827                                                                 if(obt && (obt->scavisflag & OB_VIS_ACT)) {
828                                                                         doit= 1;
829                                                                         ob->scavisflag |= OB_VIS_CONT;
830                                                                         break;
831                                                                 }
832                                                         }
833                                                 }
834                                                 if(doit) break;
835                                                 cont= cont->next;
836                                         }
837                                 }
838                                 
839                                 /* 3rd case: select controller when sensor selected */
840                                 if((scavisflag & BUTS_CONT_LINK) && (ob->scavisflag & OB_VIS_SENS)) {
841                                         sens= ob->sensors.first;
842                                         while(sens) {
843                                                 for(a=0; a<sens->totlinks; a++) {
844                                                         if(sens->links[a]) {
845                                                                 obt= (Object *)sens->links[a]->mynew;
846                                                                 if(obt && (obt->scavisflag & OB_VIS_CONT)==0) {
847                                                                         doit= 1;
848                                                                         obt->scavisflag |= OB_VIS_CONT;
849                                                                 }
850                                                         }
851                                                 }
852                                                 sens= sens->next;
853                                         }
854                                 }
855                                 
856                                 /* 4th case: select actuator when controller selected */
857                                 if( (scavisflag & BUTS_ACT_LINK)  && (ob->scavisflag & OB_VIS_CONT)) {
858                                         cont= ob->controllers.first;
859                                         while(cont) {
860                                                 for(a=0; a<cont->totlinks; a++) {
861                                                         if(cont->links[a]) {
862                                                                 obt= (Object *)cont->links[a]->mynew;
863                                                                 if(obt && (obt->scavisflag & OB_VIS_ACT)==0) {
864                                                                         doit= 1;
865                                                                         obt->scavisflag |= OB_VIS_ACT;
866                                                                 }
867                                                         }
868                                                 }
869                                                 cont= cont->next;
870                                         }
871                                         
872                                 }
873                                 ob= ob->id.next;
874                         }
875                 }
876         } 
877         
878         /* now we count */
879         ob= G.main->object.first;
880         while(ob) {
881                 if( ob->scavisflag ) (*count)++;
882                 ob= ob->id.next;
883         }
884
885         if(*count==0) return NULL;
886         if(*count>24) *count= 24;               /* temporal */
887         
888         idar= MEM_callocN( (*count)*sizeof(void *), "idar");
889         
890         ob= G.main->object.first;
891         nr= 0;
892         while(ob) {
893                 if( ob->scavisflag ) {
894                         idar[nr]= (ID *)ob;
895                         nr++;
896                 }
897                 if(nr>=24) break;
898                 ob= ob->id.next;
899         }
900         
901         /* just to be sure... these were set in set_sca_done_ob() */
902         clear_sca_new_poins();
903         
904         return idar;
905 }
906
907
908 static BIFColorID get_col_sensor(int type)
909 {
910         switch(type) {
911         case SENS_ALWAYS:               return BUTACTION;
912         case SENS_TOUCH:                return BUTCAMERA;
913         case SENS_COLLISION:    return BUTCAMERA;
914         case SENS_NEAR:                 return BUTRANDOM; 
915         case SENS_KEYBOARD:             return BUTIPO;
916         case SENS_PROPERTY:             return BUTPROPERTY;
917         case SENS_MOUSE:                return BUTAUDIO;
918         case SENS_RADAR:                return BUTEDITOBJECT;
919         case SENS_RANDOM:               return BUTSCENE;
920         case SENS_RAY:                  return BUTMOTION;
921         case SENS_MESSAGE:              return BUTMESSAGE;
922         default:                                return BUTGREY;
923         }
924 }
925 static void set_col_sensor(int type, int medium)
926 {
927         BIFColorID col= get_col_sensor(type);
928         BIF_set_color(col, medium?COLORSHADE_MEDIUM:COLORSHADE_GREY);
929 }
930
931 /**
932  * Draws a toggle for pulse mode, a frequency fiels and a toggle to invert
933  * the value of this sensor. Operates on the shared data block of sensors.
934  */
935 static void draw_default_sensor_header(bSensor *sens,
936                                                                 uiBlock *block,
937                                                                 short x,
938                                                                 short y,
939                                                                 short w) 
940 {
941         /* Pulsing and frequency */
942         uiDefIconButS(block, TOG|BIT|0, 1, ICON_DOTSUP,
943                          (short)(x + 10), (short)(y - 19), (short)(0.15 * (w-20)), 19,
944                          &sens->pulse, 0.0, 0.0, 0, 0,
945                          "Activate TRUE pulse mode");
946         uiDefIconButS(block, TOG|BIT|2, 1, ICON_DOTSDOWN,
947                          (short)(x + 10 + 0.15 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19,
948                          &sens->pulse, 0.0, 0.0, 0, 0,
949                          "Activate FALSE pulse mode");
950         uiDefButS(block, NUM, 1, "f:",
951                          (short)(x + 10 + 0.3 * (w-20)), (short)(y - 19), (short)(0.275 * (w-20)), 19,
952                          &sens->freq, 0.0, 10000.0, 0, 0,
953                          "Frequency of pulses (in 1/50 sec)");
954         
955         /* value or shift? */
956         uiDefButS(block, TOG, 1, "Inv",
957                          (short)(x + 10 + 0.85 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19,
958                          &sens->invert, 1.0, SENS_NOT, 0, 0,
959                          "Invert the output of this sensor");
960 }
961
962 static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname)
963 {
964         bNearSensor      *ns           = NULL;
965         bTouchSensor     *ts           = NULL;
966         bKeyboardSensor  *ks           = NULL;
967         bPropertySensor  *ps           = NULL;
968         bMouseSensor     *ms           = NULL;
969         bCollisionSensor *cs           = NULL;
970         bRadarSensor     *rs           = NULL;
971         bRandomSensor    *randomSensor = NULL;
972         bRaySensor       *raySens      = NULL;
973         bMessageSensor   *mes          = NULL;
974         short ysize;
975         char *str;
976         
977         /* yco is at the top of the rect, draw downwards */
978         
979         uiBlockSetEmboss(block, UI_EMBOSSW);
980         
981         set_col_sensor(sens->type, 0);
982         
983         switch (sens->type)
984         {
985         case SENS_ALWAYS:
986                 {
987                         ysize= 24;
988                         
989                         glRects(xco, yco-ysize, xco+width, yco);
990                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
991                         
992                         draw_default_sensor_header(sens, block, xco, yco, width);
993                         
994                         yco-= ysize;
995                         
996                         break;
997                 }
998         case SENS_TOUCH:
999                 {
1000                         ysize= 48; 
1001                         
1002                         glRects(xco, yco-ysize, xco+width, yco); 
1003                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1004                         
1005                         draw_default_sensor_header(sens, block, xco, yco, width);
1006                         
1007                         ts= sens->data; 
1008                         
1009                         /* uiDefBut(block, TEX, 1, "Property:", xco,yco-22,width, 19, &ts->name, 0, 31, 0, 0, "Only look for Objects with this property"); */
1010                         uiDefIDPoinBut(block, test_matpoin_but, 1, "MA:",(short)(xco + 10),(short)(yco-44), (short)(width - 20), 19, &ts->ma,  "Only look for floors with this Material"); 
1011                         ///* uiDefButF(block, NUM, 1, "Margin:",        xco+width/2,yco-44,width/2, 19, &ts->dist, 0.0, 10.0, 100, 0, "Extra margin (distance) for larger sensitivity"); 
1012                         yco-= ysize; 
1013                         break; 
1014                 }
1015         case SENS_COLLISION:
1016                 {
1017                         ysize= 48;
1018                         
1019                         glRects(xco, yco-ysize, xco+width, yco);
1020                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1021                         
1022                         draw_default_sensor_header(sens, block, xco, yco, width);
1023                         cs= sens->data;
1024                         
1025                         /* The collision sensor will become a generic collision (i.e. it     */
1026                         /* absorb the old touch sensor).                                     */
1027                         uiDefButS(block, TOG|BIT|0, B_REDR, "M/P",(short)(xco + 10),(short)(yco - 44),
1028                                 (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0,
1029                                 "Toggle collision on material or property.");
1030                         
1031                         if (cs->mode & SENS_COLLISION_MATERIAL) {
1032                                 uiDefBut(block, TEX, 1, "Material:", (short)(xco + 10 + 0.20 * (width-20)),
1033                                         (short)(yco-44), (short)(0.8*(width-20)), 19, &cs->materialName, 0, 31, 0, 0,
1034                                         "Only look for Objects with this material");
1035                         } else {
1036                                 uiDefBut(block, TEX, 1, "Property:", (short)(xco + 10 + 0.20 * (width-20)), (short)(yco-44),
1037                                         (short)(0.8*(width-20)), 19, &cs->name, 0, 31, 0, 0,
1038                                         "Only look for Objects with this property");
1039                         }
1040         
1041                         /*              uiDefButS(block, NUM, 1, "Damp:",       xco+10+width-90,yco-24, 70, 19, &cs->damp, 0, 250, 0, 0, "For 'damp' time don't detect another collision"); */
1042                         
1043                         yco-= ysize;
1044                         break;
1045                 }
1046         case SENS_NEAR:
1047                 {
1048                         ysize= 72;
1049                         
1050                         glRects(xco, yco-ysize, xco+width, yco);
1051                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1052                         
1053                         draw_default_sensor_header(sens, block, xco, yco, width);
1054                         ns= sens->data;
1055                         
1056                         uiDefBut(block, TEX, 1, "Property:",(short)(10+xco),(short)(yco-44), (short)(width-20), 19,
1057                                 &ns->name, 0, 31, 0, 0, "Only look for Objects with this property");
1058                         uiDefButF(block, NUM, 1, "Dist",(short)(10+xco),(short)(yco-68),(short)((width-22)/2), 19,
1059                                 &ns->dist, 0.0, 1000.0, 1000, 0, "Trigger distance");
1060                         uiDefButF(block, NUM, 1, "Reset",(short)(10+xco+(width-22)/2), (short)(yco-68), (short)((width-22)/2), 19,
1061                                 &ns->resetdist, 0.0, 1000.0, 1000, 0, "Reset distance"); 
1062                         yco-= ysize;
1063                         break;
1064                 }
1065         case SENS_RADAR:
1066                 {
1067                         ysize= 72; 
1068                         
1069                         glRects(xco, yco-ysize, xco+width, yco);
1070                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1071                         
1072                         draw_default_sensor_header(sens, block, xco, yco, width);
1073                         
1074                         rs= sens->data;
1075                         
1076                         uiDefBut(block, TEX, 1, "Prop:",
1077                                          (short)(10+xco),(short)(yco-44), (short)(0.7 * (width-20)), 19,
1078                                          &rs->name, 0, 31, 0, 0,
1079                                          "Only look for Objects with this property");
1080                         uiDefButS(block, ROW, 1, "X",
1081                                          (short)(10+xco+0.7 * (width-20)),(short)(yco-44), (short)(0.1 * (width-22)),19,
1082                                          &rs->axis, 2.0, 0, 0, 0,
1083                                          "Cast the cone along the object's positive x-axis");
1084                         uiDefButS(block, ROW, 1, "Y",
1085                                          (short)(10+xco+0.8 * (width-20)),(short)(yco-44),(short)(0.1 * (width-22)), 19,
1086                                          &rs->axis, 2.0, 1, 0, 0,
1087                                          "Cast the cone along the object's positive y-axis");
1088                         uiDefButS(block, ROW, 1, "Z",
1089                                          (short)(10+xco+0.9 * (width-20)), (short)(yco-44), (short)(0.1 * (width-22)), 19,
1090                                          &rs->axis, 2.0, 2, 0, 0,
1091                                          "Cast the cone along the object's positive z-axis");
1092                         uiDefButF(block, NUM, 1, "Ang:",
1093                                          (short)(10+xco), (short)(yco-68), (short)((width-20)/2), 19,
1094                                          &rs->angle, 0.0, 179.9, 10, 0,
1095                                          "Opening angle of the radar cone.");
1096                         uiDefButF(block, NUM, 1, "Dist:",
1097                                          (short)(xco+10 + (width-20)/2), (short)(yco-68), (short)((width-20)/2), 19,
1098                                          &rs->range, 0.01, 10000.0, 100, 0,
1099                                          "Depth of the radar cone");
1100                         yco-= ysize;
1101                         break;
1102                 }
1103         case SENS_KEYBOARD:
1104                 {
1105                         /* 5 lines: 120 height */
1106                         ysize= 120;
1107                         
1108                         glRects(xco, yco-ysize, xco+width, yco);
1109                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1110                         
1111                         /* header line */
1112                         draw_default_sensor_header(sens, block, xco, yco, width);
1113                         ks= sens->data;
1114                         
1115                         /* line 2: hotkey and allkeys toggle */
1116                         uiDefKeyevtButS(block, B_DIFF, "", xco+40, yco-44, (width)/2, 19, &ks->key, "Key code");
1117                         
1118                         /* line 3: two key modifyers (qual1, qual2) */
1119                         uiDefKeyevtButS(block, B_DIFF, "", xco+40, yco-68, (width-50)/2, 19, &ks->qual, "Modifier key code");
1120                         uiDefKeyevtButS(block, B_DIFF, "", xco+40+(width-50)/2, yco-68, (width-50)/2, 19, &ks->qual2, "Second Modifier key code");
1121                         
1122                         /* labels for line 1 and 2 */
1123                         uiDefBut(block, LABEL, 0, "Key",          xco, yco-44, 40, 19, NULL, 0, 0, 0, 0, "");
1124                         uiDefBut(block, LABEL, 0, "Hold",         xco, yco-68, 40, 19, NULL, 0, 0, 0, 0, "");
1125                         
1126                         /* part of line 1 */
1127                         uiBlockSetCol(block, BUTPURPLE);
1128                         uiDefButS(block, TOG|BIT|0, 0, "All keys",        xco+40+(width/2), yco-44, (width/2)-50, 19,
1129                                 &ks->type, 0, 0, 0, 0, "");
1130                         
1131                         /* line 4: toggle property for string logging mode */
1132                         uiDefBut(block, TEX, 1, "LogToggle: ",
1133                                 xco+10, yco-92, (width-20), 19,
1134                                 ks->toggleName, 0, 31, 0, 0,
1135                                 "Property that indicates whether to log "
1136                                 "keystrokes as a string.");
1137                         
1138                         /* line 5: target property for string logging mode */
1139                         uiDefBut(block, TEX, 1, "Target: ",
1140                                 xco+10, yco-116, (width-20), 19,
1141                                 ks->targetName, 0, 31, 0, 0,
1142                                 "Property that receives the keystrokes in case "
1143                                 "a string is logged.");
1144                         
1145                         yco-= ysize;
1146                         break;
1147                 }
1148         case SENS_PROPERTY:
1149                 {
1150                         ysize= 96;
1151                         
1152                         glRects(xco, yco-ysize, xco+width, yco);
1153                         uiEmboss((float)xco, (float)yco-ysize,
1154                                 (float)xco+width, (float)yco, 1);
1155                         
1156                         draw_default_sensor_header(sens, block, xco, yco, width);
1157                         ps= sens->data;
1158                         
1159                         str= "Type %t|Equal %x0|Not Equal %x1|Interval %x2|Changed %x3"; 
1160                         /* str= "Type %t|Equal %x0|Not Equal %x1"; */
1161                         uiDefButI(block, MENU, B_REDR, str,                     xco+30,yco-44,width-60, 19,
1162                                 &ps->type, 0, 31, 0, 0, "Type");
1163                         
1164                         if (ps->type != SENS_PROP_EXPRESSION)
1165                         {
1166                                 uiDefBut(block, TEX, 1, "Prop: ",                       xco+30,yco-68,width-60, 19,
1167                                         ps->name, 0, 31, 0, 0,  "Property name");
1168                         }
1169                         
1170                         if(ps->type == SENS_PROP_INTERVAL)
1171                         {
1172                                 uiDefBut(block, TEX, 1, "Min: ",                xco,yco-92,width/2, 19,
1173                                         ps->value, 0, 31, 0, 0, "test for value");
1174                                 uiDefBut(block, TEX, 1, "Max: ",                xco+width/2,yco-92,width/2, 19,
1175                                         ps->maxvalue, 0, 31, 0, 0, "test for max value");
1176                         }
1177                         else if(ps->type == SENS_PROP_CHANGED);
1178                         else
1179                         {
1180                                 uiDefBut(block, TEX, 1, "Value: ",              xco+30,yco-92,width-60, 19,
1181                                         ps->value, 0, 31, 0, 0, "test for value");
1182                         }
1183                         
1184                         yco-= ysize;
1185                         break;
1186                 }
1187         case SENS_MOUSE:
1188                 {
1189                         ms= sens->data;
1190                         /* Two lines: 48 pixels high. */
1191                         ysize = 48;
1192                         
1193                         glRects(xco, yco-ysize, xco+width, yco);
1194                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1195                         
1196                         /* line 1: header */
1197                         draw_default_sensor_header(sens, block, xco, yco, width);
1198                         
1199                         /* Line 2: type selection. The number are a bit mangled to get
1200                         * proper compatibility with older .blend files. */
1201                         str= "Type %t|Left button %x1|Middle button %x2|"
1202                                 "Right button %x4|Movement %x8|Mouse over %x16"; 
1203                         uiDefButS(block, MENU, B_REDR, str, xco+10, yco-44, width-20, 19,
1204                                 &ms->type, 0, 31, 0, 0,
1205                                 "Specify the type of event this mouse sensor should trigger on.");
1206                         
1207                         yco-= ysize;
1208                         break;
1209                 }
1210         case SENS_RANDOM:
1211                 {
1212                         ysize = 48;
1213                         
1214                         glRects(xco, yco-ysize, xco+width, yco);
1215                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1216                         
1217                         draw_default_sensor_header(sens, block, xco, yco, width);
1218                         randomSensor = sens->data;
1219                         /* some files were wrongly written, avoid crash now */
1220                         if (randomSensor)
1221                         {
1222                                 uiDefButI(block, NUM, 1, "Seed: ",              xco+10,yco-44,(width-20), 19,
1223                                         &randomSensor->seed, 0, 1000, 0, 0,
1224                                         "Initial seed of the generator. (Choose 0 for not random)");
1225                         }
1226                         yco-= ysize;
1227                         break;
1228                 }
1229         case SENS_RAY:
1230                 {
1231                         ysize = 72;
1232                         glRects(xco, yco-ysize, xco+width, yco);
1233                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1234                         
1235                         draw_default_sensor_header(sens, block, xco, yco, width);
1236                         raySens = sens->data;
1237                         
1238                         /* 1. property or material */
1239                         uiDefButS(block, TOG|BIT|0, B_REDR, "M/P",
1240                                 xco + 10,yco - 44, 0.20 * (width-20), 19,
1241                                 &raySens->mode, 0.0, 0.0, 0, 0,
1242                                 "Toggle collision on material or property.");
1243                         
1244                         if (raySens->mode & SENS_COLLISION_MATERIAL)
1245                         {
1246                                 uiDefBut(block, TEX, 1, "Material:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19,
1247                                         &raySens->matname, 0, 31, 0, 0,
1248                                         "Only look for Objects with this material");
1249                         }
1250                         else
1251                         {
1252                                 uiDefBut(block, TEX, 1, "Property:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19,
1253                                         &raySens->propname, 0, 31, 0, 0,
1254                                         "Only look for Objects with this property");
1255                         }
1256                         
1257                         /* 2. sensing range */
1258                         uiDefButF(block, NUM, 1, "Range", xco+10, yco-68, 0.6 * (width-20), 19,
1259                                 &raySens->range, 0.01, 10000.0, 100, 0,
1260                                 "Sense objects no farther than this distance");
1261                         
1262                         /* 3. axis choice */
1263                         str = "Type %t|+ X axis %x1|+ Y axis %x0|+ Z axis %x2|- X axis %x3|- Y axis %x4|- Z axis %x5"; 
1264                         uiDefButI(block, MENU, B_REDR, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19,
1265                                 &raySens->axisflag, 2.0, 31, 0, 0,
1266                                 "Specify along which axis the ray is cast.");
1267                         
1268                         yco-= ysize;            
1269                         break;
1270                 }
1271         case SENS_MESSAGE:
1272                 {
1273                         mes = sens->data;
1274                         ysize = 2 * 24; /* total number of lines * 24 pixels/line */
1275                         
1276                         glRects(xco, yco-ysize, xco+width, yco);
1277                         uiEmboss((float)xco, (float)yco-ysize,
1278                                 (float)xco+width, (float)yco, 1);
1279                         
1280                         /* line 1: header line */
1281                         draw_default_sensor_header(sens, block, xco, yco, width);
1282                         
1283                         /* line 2: Subject filter */
1284                         uiDefBut(block, TEX, 1, "Subject: ",
1285                                 (xco+10), (yco-44), (width-20), 19,
1286                                 mes->subject, 0, 31, 0, 0,
1287                                 "Optional subject filter: only accept messages with this subject"
1288                                 ", or empty for all");
1289                         
1290                         yco -= ysize;
1291                         break;
1292                 }
1293         }
1294         
1295         uiBlockSetEmboss(block, UI_EMBOSSM);
1296         uiBlockSetCol(block, BUTGREY);
1297         
1298         return yco-4;
1299 }
1300
1301
1302
1303 static short draw_controllerbuttons(bController *cont, uiBlock *block, short xco, short yco, short width)
1304 {
1305         bExpressionCont *ec;
1306         bPythonCont *pc;
1307         short ysize;
1308         
1309         uiBlockSetEmboss(block, UI_EMBOSSW);
1310         
1311         switch (cont->type) {
1312         case CONT_EXPRESSION:
1313                 ysize= 28;
1314
1315                 BIF_set_color(BUTPROPERTY, COLORSHADE_GREY);
1316                 glRects(xco, yco-ysize, xco+width, yco);
1317                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1318                 
1319                 /* uiDefBut(block, LABEL, 1, "Not yet...", xco,yco-24,80, 19, NULL, 0, 0, 0, 0, ""); */
1320                 ec= cont->data; 
1321                 /* uiDefBut(block, BUT, 1, "Variables", xco,yco-24,80, 19, NULL, 0, 0, 0, 0, "Available variables for expression"); */
1322                 uiDefBut(block, TEX, 1, "Exp:",         xco + 10 , yco-21, width-20, 19,
1323                                  ec->str, 0, 127, 0, 0,
1324                                  "Expression"); 
1325                 
1326                 yco-= ysize;
1327                 break;
1328         case CONT_PYTHON:
1329                 ysize= 28;
1330                 
1331                 if(cont->data==NULL) init_controller(cont);
1332                 pc= cont->data;
1333                 
1334                 BIF_set_color(BUTMESSAGE, COLORSHADE_GREY);
1335                 glRects(xco, yco-ysize, xco+width, yco);
1336                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1337
1338                 uiDefIDPoinBut(block, test_scriptpoin_but, 1, "Script: ", xco+45,yco-24,width-90, 19, &pc->text, "");
1339                 
1340                 yco-= ysize;
1341                 break;
1342                 
1343         default:
1344                 ysize= 4;
1345
1346                 BIF_set_color(BUTIPO, COLORSHADE_GREY);
1347                 glRects(xco, yco-ysize, xco+width, yco);
1348                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1349                 
1350                 yco-= ysize;
1351         }
1352         
1353         uiBlockSetEmboss(block, UI_EMBOSSM);
1354         uiBlockSetCol(block, BUTGREY);
1355
1356         return yco;
1357 }
1358
1359 static BIFColorID get_col_actuator(int type)
1360 {
1361         switch(type) {
1362         case ACT_ACTION:                return BUTACTION;
1363         case ACT_OBJECT:                return BUTMOTION;
1364         case ACT_IPO:                   return BUTIPO;
1365         case ACT_PROPERTY:              return BUTPROPERTY;
1366         case ACT_SOUND:                 return BUTAUDIO;
1367         case ACT_CD:                    return BUTCD;
1368         case ACT_CAMERA:                return BUTCAMERA;
1369         case ACT_EDIT_OBJECT:   return BUTEDITOBJECT;
1370         case ACT_GROUP:                 return BUTYELLOW;
1371         case ACT_RANDOM:                return BUTRANDOM;
1372         case ACT_SCENE:                 return BUTSCENE;
1373         case ACT_MESSAGE:               return BUTMESSAGE;
1374         case ACT_GAME:                  return BUTGAME;
1375         case ACT_VISIBILITY:                    return BUTVISIBILITY;
1376         default:                                return BUTGREY;
1377         }
1378 }
1379 static void set_col_actuator(int item, int medium) 
1380 {
1381         if (item==ACT_CONSTRAINT) {
1382                 BIF_set_color(BUTRUST, medium?COLORSHADE_HILITE:COLORSHADE_MEDIUM);
1383         } else {
1384                 BIFColorID col= get_col_actuator(item);
1385                 BIF_set_color(col, medium?COLORSHADE_MEDIUM:COLORSHADE_GREY);
1386         }
1387 }
1388
1389 static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, short yco, short width)
1390 {
1391         bSoundActuator      *sa      = NULL;
1392         bCDActuator                     *cda     = NULL;
1393         bObjectActuator     *oa      = NULL;
1394         bIpoActuator        *ia      = NULL;
1395         bPropertyActuator   *pa      = NULL;
1396         bCameraActuator     *ca      = NULL;
1397         bEditObjectActuator *eoa     = NULL;
1398         bConstraintActuator *coa     = NULL;
1399         bSceneActuator      *sca     = NULL;
1400         bGroupActuator      *ga      = NULL;
1401         bRandomActuator     *randAct = NULL;
1402         bMessageActuator    *ma      = NULL;
1403         bActionActuator     *aa      = NULL;
1404         bGameActuator       *gma     = NULL;
1405         bVisibilityActuator *visAct  = NULL;
1406         
1407         float *fp;
1408         short ysize = 0, wval;
1409         char *str;
1410         int myline;
1411
1412         /* yco is at the top of the rect, draw downwards */
1413         uiBlockSetEmboss(block, UI_EMBOSSW);
1414         set_col_actuator(act->type, 0);
1415         
1416         switch (act->type)
1417         {
1418         case ACT_OBJECT:
1419                 {
1420                         ysize= 129;
1421                         
1422                         glRects(xco, yco-ysize, xco+width, yco);
1423                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1424                         uiBlockSetCol(block, BUTGREY);
1425                         
1426                         oa = act->data;
1427                         wval = (width-100)/3;
1428                         
1429                         uiDefBut(block, LABEL, 0, "Force",      xco, yco-22, 55, 19, NULL, 0, 0, 0, 0, "Sets the force");
1430                         uiDefButF(block, NUM, 0, "",            xco+45, yco-22, wval, 19, oa->forceloc, -10000.0, 10000.0, 10, 0, "");
1431                         uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-22, wval, 19, oa->forceloc+1, -10000.0, 10000.0, 10, 0, "");
1432                         uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-22, wval, 19, oa->forceloc+2, -10000.0, 10000.0, 10, 0, "");
1433                         
1434                         uiDefBut(block, LABEL, 0, "Torque", xco, yco-41, 55, 19, NULL, 0, 0, 0, 0, "Sets the torque");
1435                         uiDefButF(block, NUM, 0, "",            xco+45, yco-41, wval, 19, oa->forcerot, -10000.0, 10000.0, 10, 0, "");
1436                         uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-41, wval, 19, oa->forcerot+1, -10000.0, 10000.0, 10, 0, "");
1437                         uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-41, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, "");
1438                         
1439                         uiDefBut(block, LABEL, 0, "dLoc",       xco, yco-64, 45, 19, NULL, 0, 0, 0, 0, "Sets the dLoc");
1440                         uiDefButF(block, NUM, 0, "",            xco+45, yco-64, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, "");
1441                         uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-64, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, "");
1442                         uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-64, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, "");
1443                         
1444                         uiDefBut(block, LABEL, 0, "dRot",       xco, yco-83, 45, 19, NULL, 0, 0, 0, 0, "Sets the dRot");
1445                         uiDefButF(block, NUM, 0, "",            xco+45, yco-83, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, "");
1446                         uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-83, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, "");
1447                         uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-83, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, "");
1448                         
1449                         uiDefBut(block, LABEL, 0, "linV",       xco, yco-106, 45, 19, NULL, 0, 0, 0, 0, "Sets the linear velocity");
1450                         uiDefButF(block, NUM, 0, "",            xco+45, yco-106, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, "");
1451                         uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-106, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, "");
1452                         uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-106, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, "");
1453                         
1454                         uiDefBut(block, LABEL, 0, "angV",       xco, yco-125, 45, 19, NULL, 0, 0, 0, 0, "Sets the angular velocity");
1455                         uiDefButF(block, NUM, 0, "",            xco+45, yco-125, wval, 19, oa->angularvelocity, -10000.0, 10000.0, 10, 0, "");
1456                         uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-125, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, "");
1457                         uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-125, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, "");
1458                         
1459                         uiBlockSetCol(block, BUTGREEN);
1460                         uiDefButI(block, TOG|BIT|0, 0, "L",             xco+45+3*wval, yco-22, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
1461                         uiDefButI(block, TOG|BIT|1, 0, "L",             xco+45+3*wval, yco-41, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
1462                         uiDefButI(block, TOG|BIT|2, 0, "L",             xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
1463                         uiDefButI(block, TOG|BIT|3, 0, "L",             xco+45+3*wval, yco-83, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
1464                         uiDefButI(block, TOG|BIT|4, 0, "L",             xco+45+3*wval, yco-106, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
1465                         uiDefButI(block, TOG|BIT|5, 0, "L",             xco+45+3*wval, yco-125, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
1466                         
1467                         uiBlockSetCol(block, BUTGREEN);
1468                         uiDefButI(block, TOG|BIT|6, 0, "add",xco+45+3*wval+15, yco-106, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV");
1469                         uiBlockSetCol(block, BUTGREY);
1470                         
1471                         yco-= ysize;
1472                         break;
1473                 }
1474         case ACT_ACTION:
1475                 {
1476                         /* DrawAct */
1477 #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
1478                         ysize = 112;
1479 #else
1480                         ysize= 92;
1481 #endif
1482                         
1483                         glRects(xco, yco-ysize, xco+width, yco);
1484                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1485                         
1486                         aa = act->data;
1487                         wval = (width-60)/3;
1488                         
1489                         uiBlockSetCol(block, BUTGREY);
1490                         //              str= "Action types   %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
1491 #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
1492                         str= "Action types   %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6|Displacement %x7";
1493 #else
1494                         str= "Action types   %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
1495 #endif
1496                         uiDefButS(block, MENU, B_REDR, str, xco+30, yco-24, width-60, 19, &aa->type, 0.0, 0.0, 0.0, 0.0, "Action playback type");
1497                         uiDefIDPoinBut(block, test_actionpoin_but, 1, "AC: ", xco+30, yco-44, width-60, 19, &aa->act, "Action name");
1498                         
1499                         if(aa->type == ACT_ACTION_FROM_PROP)
1500                         {
1501                                 uiDefBut(block, TEX, 0, "Prop: ",xco+30, yco-64, width-60, 19, aa->name, 0.0, 31.0, 0, 0, "Use this property to define the Action position");
1502                         }
1503                         else
1504                         {
1505                                 uiDefButS(block, NUM, 0, "Sta: ",xco+30, yco-64, (width-60)/2, 19, &aa->sta, 0.0, 18000.0, 0, 0, "Start frame");
1506                                 uiDefButS(block, NUM, 0, "End: ",xco+30+(width-60)/2, yco-64, (width-60)/2, 19, &aa->end, 0.0, 18000.0, 0, 0, "End frame");
1507                         }
1508                         
1509                         
1510                         
1511                         uiDefButS(block, NUM, 0, "Blendin: ", xco+30, yco-84, (width-60)/2, 19, &aa->blendin, 0.0, 18000.0, 0.0, 0.0, "Number of frames of motion blending");
1512                         uiDefButS(block, NUM, 0, "Priority: ", xco+30+(width-60)/2, yco-84, (width-60)/2, 19, &aa->priority, 0.0, 100.0, 0.0, 0.0, "Execution priority - lower numbers will override actions with higher numbers");
1513                         
1514 #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
1515                         if(aa->type == ACT_ACTION_MOTION)
1516                         {
1517                                 uiDefButF(block, NUM, 0, "Cycle: ",xco+30, yco-104, (width-60)/2, 19, &aa->stridelength, 0.0, 2500.0, 0, 0, "Distance covered by a single cycle of the action");
1518                         }
1519 #endif
1520                         
1521                         yco-=ysize;
1522                         break;
1523                 }
1524         case ACT_IPO:
1525                 {
1526                         ia= act->data;
1527                         
1528                         if(ia->type==ACT_IPO_KEY2KEY)
1529                                 ysize= 72; 
1530                         else
1531                                 ysize= 52;
1532                         
1533                         glRects(xco, yco-ysize, xco+width, yco);
1534                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1535                         
1536                         str = "Ipo types   %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
1537                         
1538                         uiDefButS(block, MENU, B_REDR, str,             xco+20, yco-24, width-40 - (width-40)/3, 19, &ia->type, 0, 0, 0, 0, "");
1539                         uiBlockSetCol(block, BUTGREEN);
1540                         uiDefButS(block, TOG|BIT|ACT_IPOCHILD_BIT, B_REDR, 
1541                                 "Child",        xco+20+0.666*(width-40), yco-24, (width-40)/3, 19, 
1542                                 &ia->flag, 0, 0, 0, 0, 
1543                                 "Add all children Objects as well");
1544                         uiBlockSetCol(block, BUTGREY);
1545                         /* 
1546                         Key2key was disabled.... the settings below should not be reused without 
1547                         thought, because they interfere with other variables.
1548                         
1549                           if(ia->type==ACT_IPO_KEY2KEY) {
1550                           uiBlockSetCol(block, BUTGREEN);
1551                           
1552                                 uiDefButS(block, TOG|BIT|0, 0, "Prev", xco+20, yco-44, (width-40)/3, 19, &ia->flag, 0, 0, 0, 0, "Play backwards");
1553                                 uiDefButS(block, TOG|BIT|1, 0, "Cycl", xco+20+(width-40)/3, yco-44, (width-40)/3, 19, &ia->flag, 0, 0, 0, 0, "Play cyclic");
1554                                 uiDefButS(block, TOG|BIT|3, 0, "Hold", xco+20+2*(width-40)/3, yco-44, (width-40)/3, 19, &ia->flag, 0, 0, 0, 0, "Keep playing while activated");
1555                                 
1556                                   uiDefBut(block, TEX, 0, "Prop: ",             xco+20, yco-66, width-40, 19, ia->name, 0.0, 31.0, 0, 0, "Set property to key position");
1557                                   } else 
1558                         */
1559                         if(ia->type==ACT_IPO_FROM_PROP) {
1560                                 uiDefBut(block, TEX, 0, 
1561                                         "Prop: ",               xco+20, yco-44, width-40, 19, 
1562                                         ia->name, 0.0, 31.0, 0, 0, 
1563                                         "Use this property to define the Ipo position");
1564                         }
1565                         else {
1566                                 uiDefButS(block, NUM, 0, 
1567                                         "Sta",          xco+20, yco-44, (width-100)/2, 19, 
1568                                         &ia->sta, 0.0, 18000.0, 0, 0, 
1569                                         "Start frame");
1570                                 uiDefButS(block, NUM, 0, 
1571                                         "End",          xco+18+(width-90)/2, yco-44, (width-100)/2, 19, 
1572                                         &ia->end, 0.0, 18000.0, 0, 0, 
1573                                         "End frame");
1574                                 
1575                                 uiBlockSetCol(block, BUTGREEN);
1576                                 uiDefButS(block, TOG|BIT|ACT_IPOFORCE_BIT, B_REDR, 
1577                                         "Force", xco+width-78, yco-44, 43, 19, 
1578                                         &ia->flag, 0, 0, 0, 0, 
1579                                         "Convert Ipo to force"); 
1580                                 
1581                                 /* Only show the do-force-local toggle if force is requested */
1582                                 if (ia->flag & ACT_IPOFORCE) {
1583                                         uiDefButS(block, TOG|BIT|ACT_IPOFORCE_LOCAL_BIT, 0, 
1584                                                 "L", xco+width-35, yco-44, 15, 19, 
1585                                                 &ia->flag, 0, 0, 0, 0, 
1586                                                 "Let the force-ipo act in local coordinates."); 
1587                                 }
1588                                 
1589                         }
1590                         yco-= ysize;
1591                         break;
1592                 }
1593         case ACT_PROPERTY:
1594                 {
1595                         ysize= 68;
1596                         
1597                         glRects(xco, yco-ysize, xco+width, yco);
1598                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1599                         
1600                         pa= act->data;
1601                         
1602                         str= "Type   %t|Assign   %x0|Add %x1|Copy %x2";
1603                         uiDefButI(block, MENU, B_REDR, str,             xco+30,yco-24,width-60, 19, &pa->type, 0, 31, 0, 0, "Type");
1604                         
1605                         uiDefBut(block, TEX, 1, "Prop: ",               xco+30,yco-44,width-60, 19, pa->name, 0, 31, 0, 0, "Property name");
1606                         
1607                         if(pa->type==ACT_PROP_COPY) {
1608                                 uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:",        xco+10, yco-64, (width-20)/2, 19, &(pa->ob), "Copy from this Object");
1609                                 uiDefBut(block, TEX, 1, "Prop: ",               xco+10+(width-20)/2, yco-64, (width-20)/2, 19, pa->value, 0, 31, 0, 0, "Copy this property");
1610                         }
1611                         else {
1612                                 uiDefBut(block, TEX, 1, "Value: ",              xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value");
1613                         }
1614                         yco-= ysize;
1615                         
1616                         break;
1617                 }
1618     case ACT_SOUND:
1619                 {
1620                         ysize = 70;
1621                         
1622                         sa = act->data;
1623                         sa->sndnr = 0;
1624                         
1625                         wval = (width-20)/2;
1626                         glRects(xco, yco-ysize, xco+width, yco);
1627                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1628                         
1629                         IDnames_to_pupstring(&str, "Sound files", NULL, &(G.main->sound), (ID *)sa->sound, &(sa->sndnr));
1630
1631                         if(str[0])
1632                         {
1633                                 /* reset this value, it is for handling the event */
1634                                 sa->sndnr = 0;
1635                                 uiDefButS(block, MENU, B_SOUNDACT_BROWSE, str, xco+10,yco-22,20,19, &(sa->sndnr), 0, 0, 0, 0, "");      
1636
1637                                 if(sa->sound)
1638                                 {
1639                                         char dummy_str[] = "Sound mode %t|Play Stop %x0|Play End %x1|Loop Stop %x2|Loop End %x3|Loop Ping Pong Stop %x5|Loop Ping Pong %x4";
1640                                         uiDefBut(block, TEX, B_IDNAME, "SO:",xco+30,yco-22,width-40,19, sa->sound->id.name+2,    0.0, 18.0, 0, 0, "");
1641                                         uiDefButS(block, MENU, 1, dummy_str,xco+10,yco-44,width-20, 19, &sa->type, 0.0, 0.0, 0, 0, "");
1642                                         uiDefButF(block, NUM, 0, "Volume:", xco+10,yco-66,wval, 19, &sa->sound->volume, 0.0,  1.0, 0, 0, "Sets the volume of this sound");
1643                                         uiDefButF(block, NUM, 0, "Pitch:",xco+wval+10,yco-66,wval, 19, &sa->sound->pitch,-12.0, 12.0, 0, 0, "Sets the pitch of this sound");
1644                                 }
1645                         }
1646                         else
1647                         {
1648                                 uiDefBut(block, LABEL, 0, "Use Sound window to load files", xco, yco-24, width, 19, NULL, 0, 0, 0, 0, "");
1649                         }
1650                         
1651                         MEM_freeN(str);
1652                 
1653                         yco-= ysize;
1654                         
1655                         break;
1656                 }
1657         case ACT_CD:
1658                 {
1659                         char cd_type_str[] = "Sound mode %t|Play all tracks %x0|Play one track %x1|"
1660                                 "Volume %x3|Stop %x4|Pause %x5|Resume %x6";
1661                         cda = act->data;
1662
1663                         if (cda)
1664                         {
1665                                 if (cda->track == 0)
1666                                 {
1667                                         cda->track = 1;
1668                                         cda->volume = 1;
1669                                         cda->type = ACT_CD_PLAY_ALL;
1670                                 }
1671                                 
1672                                 if (cda->type == ACT_CD_PLAY_TRACK || cda->type == ACT_CD_LOOP_TRACK)
1673                                 {
1674                                         ysize = 48;
1675                                         glRects(xco, yco-ysize, xco+width, yco);
1676                                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1677                                         uiDefButS(block, NUM, 0, "Track:", xco+10,yco-44,width-20, 19, &cda->track, 1, 99, 0, 0, "Select the track to be played");
1678                                 }
1679                                 else if (cda->type == ACT_CD_VOLUME)
1680                                 {
1681                                         ysize = 48;
1682                                         glRects(xco, yco-ysize, xco+width, yco);
1683                                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1684                                         uiDefButF(block, NUM, 0, "Volume:", xco+10,yco-44,width-20, 19, &cda->volume, 0, 1, 0, 0, "Set the volume for CD playback");
1685                                 }
1686                                 else
1687                                 {
1688                                         ysize = 28;
1689                                         glRects(xco, yco-ysize, xco+width, yco);
1690                                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1691                                 }
1692                                 uiDefButS(block, MENU, B_REDR, cd_type_str,xco+10,yco-22,width-20, 19, &cda->type, 0.0, 0.0, 0, 0, "");
1693                         }
1694                         yco-= ysize;
1695                         break;
1696                 }
1697         case ACT_CAMERA:
1698
1699                 ysize= 48;
1700         
1701                 glRects(xco, yco-ysize, xco+width, yco);
1702                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1703                 
1704                 ca= act->data;
1705         
1706                 uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:",                xco+10, yco-24, (width-20)/2, 19, &(ca->ob), "Look at this Object");
1707                 uiDefButF(block, NUM, 0, "Height:",     xco+10+(width-20)/2, yco-24, (width-20)/2, 19, &ca->height, 0.0, 20.0, 0, 0, "");
1708                 
1709                 uiDefButF(block, NUM, 0, "Min:",        xco+10, yco-44, (width-60)/2, 19, &ca->min, 0.0, 20.0, 0, 0, "");
1710                 
1711                 if(ca->axis==0) ca->axis= 'x';
1712                 uiDefButS(block, ROW, 0, "X",   xco+10+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'x', 0, 0, "Camera tries to get behind the X axis");
1713                 uiDefButS(block, ROW, 0, "Y",   xco+30+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'y', 0, 0, "Camera tries to get behind the Y axis");
1714                 
1715                 uiDefButF(block, NUM, 0, "Max:",        xco+20+(width)/2, yco-44, (width-60)/2, 19, &ca->max, 0.0, 20.0, 0, 0, "");
1716
1717                 yco-= ysize;
1718         
1719          break;
1720                                 
1721         case ACT_EDIT_OBJECT:
1722                 
1723                 eoa= act->data;
1724
1725                 if(eoa->type==ACT_EDOB_ADD_OBJECT) {
1726                         int wval; /* just a temp width */
1727                         ysize = 72;
1728                         glRects(xco, yco-ysize, xco+width, yco);
1729                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1730          
1731                         uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:",                xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Add this Object");
1732                         uiDefButI(block, NUM, 0, "Time:",       xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the new Object lives");
1733
1734                         wval= (width-60)/3;
1735                         uiDefBut(block, LABEL, 0, "linV",       xco,           yco-68,   45, 19,
1736                                          NULL, 0, 0, 0, 0,
1737                                          "Velocity upon creation.");
1738                         uiDefButF(block, NUM, 0, "",            xco+45,        yco-68, wval, 19,
1739                                          eoa->linVelocity, -100.0, 100.0, 10, 0,
1740                                          "Velocity upon creation, x component.");
1741                         uiDefButF(block, NUM, 0, "",            xco+45+wval,   yco-68, wval, 19,
1742                                          eoa->linVelocity+1, -100.0, 100.0, 10, 0,
1743                                          "Velocity upon creation, y component.");
1744                         uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-68, wval, 19,
1745                                          eoa->linVelocity+2, -100.0, 100.0, 10, 0,
1746                                          "Velocity upon creation, z component.");
1747                         uiDefButS(block, TOG|BIT|1, 0, "L", xco+45+3*wval, yco-68, 15, 19,
1748                                          &eoa->localflag, 0.0, 0.0, 0, 0,
1749                                          "Apply the transformation locally");
1750
1751                 }
1752                 else if(eoa->type==ACT_EDOB_END_OBJECT) {
1753                         ysize= 28;
1754                         glRects(xco, yco-ysize, xco+width, yco);
1755                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1756                 }
1757                 else if(eoa->type==ACT_EDOB_REPLACE_MESH) {
1758                         ysize= 48;
1759                         glRects(xco, yco-ysize, xco+width, yco);
1760                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1761          
1762                         uiDefIDPoinBut(block, test_meshpoin_but, 1, "ME:",              xco+40, yco-44, (width-80), 19, &(eoa->me), "Add this Object");
1763                 }
1764                 else if(eoa->type==ACT_EDOB_TRACK_TO) {
1765                         ysize= 48;
1766                         glRects(xco, yco-ysize, xco+width, yco);
1767                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1768          
1769                         uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:",                xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Track to this Object");
1770                         uiDefButI(block, NUM, 0, "Time:",       xco+10+(width-20)/2, yco-44, (width-20)/2-40, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the tracking takes");
1771                         uiBlockSetCol(block, BUTGREEN);
1772                         uiDefButS(block, TOG, 0, "3D",  xco+width-50, yco-44, 40, 19, &eoa->flag, 0.0, 0.0, 0, 0, "Enable 3D tracking");
1773                         uiBlockSetCol(block, BUTGREY);
1774                 }
1775                 
1776                 str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3";
1777                 uiDefButS(block, MENU, B_REDR, str,             xco+40, yco-24, (width-80), 19, &eoa->type, 0.0, 0.0, 0, 0, "");
1778
1779                 yco-= ysize;
1780         
1781         break;
1782  
1783         case ACT_CONSTRAINT:
1784         
1785                 ysize= 44;
1786         
1787                 glRects(xco, yco-ysize, xco+width, yco);
1788                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1789                 
1790                 coa= act->data;
1791                 
1792 /*              str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4|Rot X %x8|Rot Y %x16|Rot Z %x32"; */
1793                 str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4";
1794                 uiDefButS(block, MENU, 1, str,          xco+10, yco-40, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, "");
1795         
1796                 uiDefButS(block, NUM,           0, "Damp:",     xco+10, yco-20, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "");
1797                 uiDefBut(block, LABEL,                  0, "Min",       xco+80, yco-20, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
1798                 uiDefBut(block, LABEL,                  0, "Max",       xco+80+(width-90)/2, yco-20, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
1799
1800                 if(coa->flag & ACT_CONST_LOCX) fp= coa->minloc;
1801                 else if(coa->flag & ACT_CONST_LOCY) fp= coa->minloc+1;
1802                 else if(coa->flag & ACT_CONST_LOCZ) fp= coa->minloc+2;
1803                 else if(coa->flag & ACT_CONST_ROTX) fp= coa->minrot;
1804                 else if(coa->flag & ACT_CONST_ROTY) fp= coa->minrot+1;
1805                 else fp= coa->minrot+2;
1806                 
1807                 uiDefButF(block, NUM, 0, "",            xco+80, yco-40, (width-90)/2, 19, fp, -2000.0, 2000.0, 10, 0, "");
1808                 uiDefButF(block, NUM, 0, "",            xco+80+(width-90)/2, yco-40, (width-90)/2, 19, fp+3, -2000.0, 2000.0, 10, 0, "");
1809
1810                 yco-= ysize;
1811         
1812         break;
1813  
1814         case ACT_SCENE:
1815                 sca= act->data; 
1816                 
1817                 if(sca->type==ACT_SCENE_RESTART) { 
1818                         ysize= 28; 
1819                         glRects(xco, yco-ysize, xco+width, yco); 
1820                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1821                 } 
1822                 else if(sca->type==ACT_SCENE_CAMERA) { 
1823                         
1824                         ysize= 48; 
1825                         glRects(xco, yco-ysize, xco+width, yco); 
1826                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1827          
1828                         uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:",                xco+40, yco-44, (width-80), 19, &(sca->camera), "Set this Camera"); 
1829                 } 
1830                 else if(sca->type==ACT_SCENE_SET) { 
1831                         
1832                         ysize= 48; 
1833                         glRects(xco, yco-ysize, xco+width, yco); 
1834                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1835         
1836                         uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:",            xco+40, yco-44, (width-80), 19, &(sca->scene), "Set this Scene"); 
1837                 } 
1838                 else if(sca->type==ACT_SCENE_ADD_FRONT) { 
1839                         
1840                         ysize= 48; 
1841                         glRects(xco, yco-ysize, xco+width, yco); 
1842                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1843         
1844                         uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:",            xco+40, yco-44, (width-80), 19, &(sca->scene), "Add an Overlay Scene"); 
1845                 } 
1846                 else if(sca->type==ACT_SCENE_ADD_BACK) { 
1847                         
1848                         ysize= 48; 
1849                         glRects(xco, yco-ysize, xco+width, yco); 
1850                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1851         
1852                         uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:",            xco+40, yco-44, (width-80), 19, &(sca->scene), "Add a Background Scene"); 
1853                 } 
1854                 else if(sca->type==ACT_SCENE_REMOVE) { 
1855                         
1856                         ysize= 48; 
1857                         glRects(xco, yco-ysize, xco+width, yco); 
1858                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1859         
1860                         uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:",            xco+40, yco-44, (width-80), 19, &(sca->scene), "Remove a Scene");
1861                 } 
1862                 else if(sca->type==ACT_SCENE_SUSPEND) { 
1863                         
1864                         ysize= 48; 
1865                         glRects(xco, yco-ysize, xco+width, yco); 
1866                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1867         
1868                         uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:",            xco+40, yco-44, (width-80), 19, &(sca->scene), "Pause a Scene");
1869                 } 
1870                 else if(sca->type==ACT_SCENE_RESUME) { 
1871                         
1872                         ysize= 48; 
1873                         glRects(xco, yco-ysize, xco+width, yco); 
1874                         uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1875         
1876                         uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:",            xco+40, yco-44, (width-80), 19, &(sca->scene), "Unpause a Scene");
1877                 } 
1878
1879                 str= "Scene %t|Restart %x0|Set Scene %x1|Set Camera %x2|Add OverlayScene %x3|Add BackgroundScene %x4|Remove Scene %x5|Suspend Scene %x6|Resume Scene %x7";
1880                 uiDefButS(block, MENU, B_REDR, str,             xco+40, yco-24, (width-80), 19, &sca->type, 0.0, 0.0, 0, 0, ""); 
1881
1882                 yco-= ysize; 
1883                 break; 
1884         case ACT_GAME:
1885                 {
1886                         gma = act->data; 
1887                         if (gma->type == ACT_GAME_LOAD)
1888                         {
1889                                 //ysize = 68;
1890                                 ysize = 48;
1891                                 glRects(xco, yco-ysize, xco+width, yco); 
1892                                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1893                                 uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file");
1894 //                              uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation");
1895                         }
1896 /*                      else if (gma->type == ACT_GAME_START)
1897                         {
1898                                 ysize = 68; 
1899                                 glRects(xco, yco-ysize, xco+width, yco); 
1900                                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1901
1902                                 uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file");
1903                                 uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation");
1904                         }
1905 */                      else if (gma->type == ACT_GAME_RESTART)
1906                         {
1907                                 ysize = 28; 
1908                                 glRects(xco, yco-ysize, xco+width, yco); 
1909                                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1910                         }
1911                         else if (gma->type == ACT_GAME_QUIT)
1912                         {
1913                                 ysize = 28; 
1914                                 glRects(xco, yco-ysize, xco+width, yco); 
1915                                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
1916                         }
1917
1918                         //str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3";
1919                         str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3";
1920                         uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, ""); 
1921                         
1922                         yco -= ysize; 
1923                         break; 
1924                 }
1925         case ACT_GROUP:
1926                 ga= act->data;
1927
1928                 ysize= 52;
1929
1930                 glRects(xco, yco-ysize, xco+width, yco);
1931                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
1932                 
1933                 str= "GroupKey types   %t|Set Key %x6|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x5";
1934
1935                 uiDefButS(block, MENU, 1, str,                  xco+20, yco-24, width-40, 19, &ga->type, 0, 0, 0, 0, "");
1936                 if(ga->type==ACT_GROUP_SET) {
1937                         uiDefBut(block, TEX, 0, "Key: ",                xco+20, yco-44, (width-10)/2, 19, ga->name, 0.0, 31.0, 0, 0, "This name defines groupkey to be set");
1938                         uiDefButS(block, NUM, 0, "Frame:",      xco+20+(width-10)/2, yco-44, (width-70)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Set this frame");
1939                 }
1940                 else if(ga->type==ACT_GROUP_FROM_PROP) {
1941                         uiDefBut(block, TEX, 0, "Prop: ",               xco+20, yco-44, width-40, 19, ga->name, 0.0, 31.0, 0, 0, "Use this property to define the Group position");
1942                 }
1943                 else {
1944                         uiDefButS(block, NUM, 0, "Sta",         xco+20, yco-44, (width-40)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Start frame");
1945                         uiDefButS(block, NUM, 0, "End",         xco+20+(width-40)/2, yco-44, (width-40)/2, 19, &ga->end, 0.0, 2500.0, 0, 0, "End frame");
1946                 }
1947                 yco-= ysize;
1948                 break;
1949
1950         case ACT_VISIBILITY:
1951                 ysize = 24;
1952
1953                 glRects(xco, yco-ysize, xco+width, yco);
1954                 uiEmboss((float)xco,
1955                          (float)yco-ysize, (float)xco+width, (float)yco, 1);
1956                 
1957                 visAct = act->data;
1958
1959                 str= "Visibility %t|Visible %x0|Invisible %x1";
1960
1961                 uiDefButI(block, MENU, B_REDR, str,
1962                           xco + 10, yco - 24, width - 20, 19, &visAct->flag,
1963                           0.0, 0.0, 0, 0,
1964                           "Make the object invisible or visible.");
1965 /*
1966                 uiDefButI(block, TOG|BIT|ACT_VISIBILITY_INVISIBLE_BIT, 0,
1967                           "Invisible",
1968                           xco + 10, yco - 24, width - 20, 19, &visAct->flag,
1969                           0.0, 0.0, 0, 0,
1970                           "Make the object invisible or visible.");
1971 */
1972                 yco-= ysize;
1973
1974                 break;
1975                 
1976         case ACT_RANDOM:
1977                 ysize  = 69;
1978
1979                 glRects(xco, yco-ysize, xco+width, yco);
1980                 uiEmboss((float)xco,
1981                                   (float)yco-ysize, (float)xco+width, (float)yco, 1);
1982                 
1983                 randAct = act->data;
1984
1985                 /* 1. seed */
1986                 uiDefButI(block, NUM, 1, "Seed: ",              (xco+10),yco-24, 0.4 *(width-20), 19,
1987                                  &randAct->seed, 0, 1000, 0, 0,
1988                                  "Initial seed of the random generator. Use Python for more freedom. "
1989                                  " (Choose 0 for not random)");
1990
1991                 /* 2. distribution type */
1992                 /* One pick per distribution. These numbers MUST match the #defines  */
1993                 /* in game.h !!!                                                     */
1994                 str= "Distribution %t|Bool Constant %x0|Bool Uniform %x1"
1995                         "|Bool Bernoulli %x2|Int Constant %x3|Int Uniform %x4"
1996                         "|Int Poisson %x5|Float Constant %x6|Float Uniform %x7"
1997                         "|Float Normal %x8|Float Neg. Exp. %x9";
1998                 uiDefButI(block, MENU, B_REDR, str, (xco+10) + 0.4 * (width-20), yco-24, 0.6 * (width-20), 19,
1999                                  &randAct->distribution, 0.0, 0.0, 0, 0,
2000                                  "Choose the type of distribution");
2001
2002                 /* 3. property */
2003                 uiDefBut(block, TEX, 1, "Property:", (xco+10), yco-44, (width-20), 19,
2004                                  &randAct->propname, 0, 31, 0, 0,
2005                                  "Assign the random value to this property"); 
2006
2007                 /*4. and 5. arguments for the distribution*/
2008                 switch (randAct->distribution) {
2009                 case ACT_RANDOM_BOOL_CONST:
2010                         uiDefButI(block, TOG|BIT|0, 1, "Always true", (xco+10), yco-64, (width-20), 19,
2011                                          &randAct->int_arg_1, 2.0, 1, 0, 0,
2012                                          "Always false or always true");                        
2013                         break;
2014                 case ACT_RANDOM_BOOL_UNIFORM:
2015                         uiDefBut(block, LABEL, 0, "     Do a 50-50 pick.",      (xco+10), yco-64, (width-20), 19,
2016                                          NULL, 0, 0, 0, 0,
2017                                          "Choose between true and false, 50%% chance each.");
2018                         break;
2019                 case ACT_RANDOM_BOOL_BERNOUILLI:
2020                         uiDefButF(block, NUM, 1, "Chance", (xco+10), yco-64, (width-20), 19,
2021                                          &randAct->float_arg_1, 0.0, 1.0, 0, 0,
2022                                          "Pick a number between 0 and 1. Success if you stay "
2023                                          "below this value");                   
2024                         break;
2025                 case ACT_RANDOM_INT_CONST:
2026                         uiDefButI(block, NUM, 1, "Value: ",             (xco+10), yco-64, (width-20), 19,
2027                                          &randAct->int_arg_1, -1000, 1000, 0, 0,
2028                                          "Always return this number");
2029                         break;
2030                 case ACT_RANDOM_INT_UNIFORM:
2031                         uiDefButI(block, NUM, 1, "Min: ",               (xco+10), yco-64, (width-20)/2, 19,
2032                                          &randAct->int_arg_1, -1000, 1000, 0, 0,
2033                                          "Choose a number from a range. "
2034                                          "Lower boundary of the range.");
2035                         uiDefButI(block, NUM, 1, "Max: ",               (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19,
2036                                          &randAct->int_arg_2, -1000, 1000, 0, 0,
2037                                          "Choose a number from a range. "
2038                                          "Upper boundary of the range.");
2039                         break;
2040                 case ACT_RANDOM_INT_POISSON:
2041                         uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20), 19,
2042                                          &randAct->float_arg_1, 0.01, 100.0, 0, 0,
2043                                          "Expected mean value of the distribution.");                                           
2044                         break;
2045                 case ACT_RANDOM_FLOAT_CONST:
2046                         uiDefButF(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19,
2047                                          &randAct->float_arg_1, 0.0, 1.0, 0, 0,
2048                                          "Always return this number");
2049                         break;
2050                 case ACT_RANDOM_FLOAT_UNIFORM:
2051                         uiDefButF(block, NUM, 1, "Min: ",               (xco+10), yco-64, (width-20)/2, 19,
2052                                          &randAct->float_arg_1, -10000.0, 10000.0, 0, 0,
2053                                          "Choose a number from a range. "
2054                                          "Lower boundary of the range.");
2055                         uiDefButF(block, NUM, 1, "Max: ",               (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19,
2056                                          &randAct->float_arg_2, -10000.0, 10000.0, 0, 0,
2057                                          "Choose a number from a range. "
2058                                          "Upper boundary of the range.");
2059                         break;
2060                 case ACT_RANDOM_FLOAT_NORMAL:
2061                         uiDefButF(block, NUM, 1, "Mean: ",              (xco+10), yco-64, (width-20)/2, 19,
2062                                          &randAct->float_arg_1, -10000.0, 10000.0, 0, 0,
2063                                          "A normal distribution. Mean of the distribution.");
2064                         uiDefButF(block, NUM, 1, "SD: ",                (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19,
2065                                          &randAct->float_arg_2, 0.0, 10000.0, 0, 0,
2066                                          "A normal distribution. Standard deviation of the "
2067                                          "distribution.");
2068                         break;
2069                 case ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL:
2070                         uiDefButF(block, NUM, 1, "Half-life time: ", (xco+10), yco-64, (width-20), 19,
2071                                          &randAct->float_arg_1, 0.001, 10000.0, 0, 0,
2072                                          "Negative exponential dropoff.");
2073                         break;
2074                 default:
2075                         ; /* don't know what this distro is... can be useful for testing */
2076                         /* though :)                                                     */
2077                 }
2078
2079                 yco-= ysize;
2080                 break;
2081         case ACT_MESSAGE:
2082                 ma = act->data;
2083
2084 #define MESSAGE_SENSOR_TO_FIELD_WORKS   /* Really?  Not really.  Don't remove this ifdef yet */
2085
2086 #ifdef MESSAGE_SENSOR_TO_FIELD_WORKS
2087                 ysize = 4 + (3 * 24); /* footer + number of lines * 24 pixels/line */
2088 #else
2089                 ysize = 4 + (2 * 24); /* footer + number of lines * 24 pixels/line */
2090 #endif
2091                 glRects(xco, yco-ysize, xco+width, yco);
2092                 uiEmboss((float)xco,        (float)yco-ysize,
2093                                  (float)xco+width,  (float)yco, 1);
2094
2095                 myline=1;
2096
2097
2098 #ifdef MESSAGE_SENSOR_TO_FIELD_WORKS
2099                 /* line 1: To */
2100                 uiDefBut(block, TEX, 1, "To: ",
2101                         (xco+10), (yco-(myline++*24)), (width-20), 19,
2102                         &ma->toPropName, 0, 31, 0, 0,
2103                         "Optional send message to objects with this property only"
2104                         ", or empty to broadcast");
2105
2106 #endif
2107
2108                 /* line 2: Message Subject */
2109                 uiDefBut(block, TEX, 1, "Subject: ",
2110                 (xco+10), (yco-(myline++*24)), (width-20), 19,
2111                 &ma->subject, 0, 31, 0, 0,
2112                 "Optional message subject. This is what can be filtered on.");
2113
2114                 /* line 3: Text/Property */
2115                 uiDefButS(block, TOG|BIT|0, B_REDR, "T/P",
2116                         (xco+10),(yco-(myline*24)), (0.20 * (width-20)), 19,
2117                         &ma->bodyType, 0.0, 0.0, 0, 0,
2118                         "Toggle message type: either Text or a PropertyName.");
2119
2120                 if (ma->bodyType == ACT_MESG_MESG)
2121                 {
2122                 /* line 3: Message Body */
2123                 uiDefBut(block, TEX, 1, "Body: ",
2124                 (xco+10+(0.20*(width-20))),(yco-(myline++*24)),(0.8*(width-20)),19,
2125                 &ma->body, 0, 31, 0, 0,
2126                 "Optional message body Text");
2127                 } else
2128                 {
2129                         /* line 3: Property body (set by property) */
2130                         uiDefBut(block, TEX, 1, "Propname: ",
2131                 (xco+10+(0.20*(width-20))),(yco-(myline++*24)),(0.8*(width-20)),19,
2132                         &ma->body, 0, 31, 0, 0,
2133                         "The message body will be set by the Property Value");
2134                 }
2135                 
2136                 yco -= ysize;
2137                 break;
2138         default:
2139                 ysize= 4;
2140
2141                 glRects(xco, yco-ysize, xco+width, yco);
2142                 uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
2143                 
2144                 yco-= ysize;
2145                 break;
2146         }
2147
2148         uiBlockSetEmboss(block, UI_EMBOSSM);
2149         uiBlockSetCol(block, BUTGREY);
2150
2151         return yco-4;
2152 }
2153
2154 static void do_sensor_menu(void *arg, int event)
2155 {       
2156         ID **idar;
2157         Object *ob;
2158         bSensor *sens;
2159         short count, a;
2160         
2161         idar= get_selected_and_linked_obs(&count, G.buts->scaflag);
2162         
2163         for(a=0; a<count; a++) {
2164                 ob= (Object *)idar[a];
2165                 if(event==0 || event==2) ob->scaflag |= OB_SHOWSENS;
2166                 else if(event==1) ob->scaflag &= ~OB_SHOWSENS;
2167         }
2168                 
2169         for(a=0; a<count; a++) {
2170                 ob= (Object *)idar[a];
2171                 sens= ob->sensors.first;
2172                 while(sens) {
2173                         if(event==2) sens->flag |= SENS_SHOW;
2174                         else if(event==3) sens->flag &= ~SENS_SHOW;
2175                         sens= sens->next;
2176                 }
2177         }
2178
2179         if(idar) MEM_freeN(idar);
2180         allqueue(REDRAWBUTSGAME, 0);
2181 }
2182
2183 static uiBlock *sensor_menu(void *arg_unused)
2184 {
2185         uiBlock *block;
2186         int yco=0;
2187         
2188         block= uiNewBlock(&curarea->uiblocks, "filemenu", UI_EMBOSSP, UI_HELV, curarea->win);
2189         uiBlockSetButmFunc(block, do_sensor_menu, NULL);
2190         
2191         uiDefBut(block, BUTM, 1, "Show Objects",        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
2192         uiDefBut(block, BUTM, 1, "Hide Objects",        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
2193         uiDefBut(block, SEPR, 0, "",    0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
2194         uiDefBut(block, BUTM, 1, "Show Sensors",        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
2195         uiDefBut(block, BUTM, 1, "Hide Sensors",        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
2196
2197         uiBlockSetDirection(block, UI_TOP);
2198         
2199         return block;
2200 }
2201
2202 static void do_controller_menu(void *arg, int event)
2203 {       
2204         ID **idar;
2205         Object *ob;
2206         bController *cont;
2207         short count, a;
2208         
2209         idar= get_selected_and_linked_obs(&count, G.buts->scaflag);
2210         
2211         for(a=0; a<count; a++) {
2212                 ob= (Object *)idar[a];
2213                 if(event==0 || event==2) ob->scaflag |= OB_SHOWCONT;
2214                 else if(event==1) ob->scaflag &= ~OB_SHOWCONT;
2215         }
2216
2217         for(a=0; a<count; a++) {
2218                 ob= (Object *)idar[a];
2219                 cont= ob->controllers.first;
2220                 while(cont) {
2221                         if(event==2) cont->flag |= CONT_SHOW;
2222                         else if(event==3) cont->flag &= ~CONT_SHOW;
2223                         cont= cont->next;
2224                 }
2225         }
2226
2227         if(idar) MEM_freeN(idar);
2228         allqueue(REDRAWBUTSGAME, 0);
2229 }
2230
2231 static uiBlock *controller_menu(void *arg_unused)
2232 {
2233         uiBlock *block;
2234         int yco=0;
2235         
2236         block= uiNewBlock(&curarea->uiblocks, "filemenu", UI_EMBOSSP, UI_HELV, curarea->win);
2237         uiBlockSetButmFunc(block, do_controller_menu, NULL);
2238         
2239         uiDefBut(block, BUTM, 1, "Show Objects",        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
2240         uiDefBut(block, BUTM, 1, "Hide Objects",        0,(short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
2241         uiDefBut(block, SEPR, 0, "",                                    0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
2242         uiDefBut(block, BUTM, 1, "Show Controllers",    0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 2, 2, "");
2243         uiDefBut(block, BUTM, 1, "Hide Controllers",    0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 3, 3, "");
2244
2245         uiBlockSetDirection(block, UI_TOP);
2246         
2247         return block;
2248 }
2249
2250 static void do_actuator_menu(void *arg, int event)
2251 {       
2252         ID **idar;
2253         Object *ob;
2254         bActuator *act;
2255         short count, a;
2256         
2257         idar= get_selected_and_linked_obs(&count, G.buts->scaflag);
2258         
2259         for(a=0; a<count; a++) {
2260                 ob= (Object *)idar[a];
2261                 if(event==0 || event==2) ob->scaflag |= OB_SHOWACT;
2262                 else if(event==1) ob->scaflag &= ~OB_SHOWACT;
2263         }
2264
2265         for(a=0; a<count; a++) {
2266                 ob= (Object *)idar[a];
2267                 act= ob->actuators.first;
2268                 while(act) {
2269                         if(event==2) act->flag |= ACT_SHOW;
2270                         else if(event==3) act->flag &= ~ACT_SHOW;
2271                         act= act->next;
2272                 }
2273         }
2274
2275         if(idar) MEM_freeN(idar);
2276         allqueue(REDRAWBUTSGAME, 0);
2277 }
2278
2279 static uiBlock *actuator_menu(void *arg_unused)
2280 {
2281         uiBlock *block;
2282         int xco=0;
2283         
2284         block= uiNewBlock(&curarea->uiblocks, "filemenu", UI_EMBOSSP, UI_HELV, curarea->win);
2285         uiBlockSetButmFunc(block, do_actuator_menu, NULL);
2286         
2287         uiDefBut(block, BUTM, 1, "Show Objects",        0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
2288         uiDefBut(block, BUTM, 1, "Hide Objects",        0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
2289         uiDefBut(block, SEPR, 0, "",    0, (short)(xco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
2290         uiDefBut(block, BUTM, 1, "Show Actuators",      0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
2291         uiDefBut(block, BUTM, 1, "Hide Actuators",      0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
2292
2293         uiBlockSetDirection(block, UI_TOP);
2294         
2295         return block;
2296 }
2297
2298 /* never used, see CVS 1.134 for the code */
2299 /*  static FreeCamera *new_freecamera(void) */
2300
2301 /* never used, see CVS 1.120 for the code */
2302 /*  static uiBlock *freecamera_menu(void) */
2303
2304 void gamebuts(void)
2305 {
2306         ID **idar;
2307         Object *ob;
2308         bProperty *prop;
2309         bSensor *sens;
2310         bController *cont;
2311         bActuator *act;
2312         uiBlock *block;
2313         uiBut *but;
2314         int a;
2315         short xco, yco, count, width, ycoo;
2316         char *pupstr, name[32];
2317         int butreturn = 0;
2318
2319         ob= OBACT;
2320
2321         if(ob==0) return;
2322         uiSetButLock(ob->id.lib!=0, "Can't edit library data");
2323
2324         sprintf(name, "buttonswin %d", curarea->win);
2325         block= uiNewBlock(&curarea->uiblocks, name, UI_EMBOSSX, UI_HELV, curarea->win);
2326         
2327         uiBlockSetCol(block, BUTPURPLE);
2328         // uiDefButI(block, TOG|BIT|0, B_REDR, "X",
2329         //               15,205,10,19, &ob->gameflag2, 0, 0, 0, 0,
2330         //               "Toggle to always ignore activity culling.");
2331         uiDefButI(block, TOG|BIT|2, B_REDR, "Actor",
2332                          25,205,60,19, &ob->gameflag, 0, 0, 0, 0,
2333                          "Objects that are evaluated by the engine ");
2334
2335         if(ob->gameflag & OB_ACTOR) {   
2336                 uiDefButI(block, TOG|BIT|9, B_REDR, "Ghost",                    85,205,65,19, &ob->gameflag, 0, 0, 0, 0, "Objects that don't restitute collisions (like a ghost)");
2337                 uiDefButI(block, TOG|BIT|0, B_REDR, "Dynamic",          150,205,65,19, &ob->gameflag, 0, 0, 0, 0, "Motion defined by laws of physics");
2338         
2339                 if(ob->gameflag & OB_DYNAMIC) {
2340                                 
2341                         uiDefButI(block, TOG|BIT|10, B_REDR, "Rigid Body",      215,205,135,19, &ob->gameflag, 0, 0, 0, 0, "");
2342
2343                         uiDefButI(block, TOG|BIT|6, B_DIFF, "Do Fh",            10,185,50,19, &ob->gameflag, 0, 0, 0, 0, "Use Fh settings in Materials");
2344                         uiDefButI(block, TOG|BIT|7, B_DIFF, "Rot Fh",   60,185,50,19, &ob->gameflag, 0, 0, 0, 0, "Use face normal to rotate Object");
2345         
2346                         uiBlockSetCol(block, BUTGREY);
2347
2348                         uiDefButF(block, NUM, B_DIFF, "Mass:",                  110, 185, 80, 19, &ob->mass, 0.01, 100.0, 10, 0, "The mass of the Object");
2349                         uiDefButF(block, NUM, REDRAWVIEW3D, "Size:",            190, 185, 80, 19, &ob->inertia, 0.01, 10.0, 10, 0, "Bounding sphere size");
2350                         uiDefButF(block, NUM, B_DIFF, "Form:",                  270, 185, 80, 19, &ob->formfactor, 0.01, 100.0, 10, 0, "Form factor");
2351
2352                         uiDefButF(block, NUM, B_DIFF, "Damp:",                  10, 165, 100, 19, &ob->damping, 0.0, 1.0, 10, 0, "General movement damping");
2353                         uiDefButF(block, NUM, B_DIFF, "RotDamp:",               110, 165, 120, 19, &ob->rdamping, 0.0, 1.0, 10, 0, "General rotation damping");
2354                         uiDefButI(block, TOG|BIT|8, B_REDR, "Anisotropic",              230, 165, 120, 19,
2355                                          &ob->gameflag, 0.0, 1.0, 10, 0,
2356                                          "Enable anisotropic friction");                        
2357                 }
2358         }
2359
2360         if (ob->gameflag & OB_ANISOTROPIC_FRICTION) {
2361                 uiDefButF(block, NUM, B_DIFF, "x friction:",                    10, 145, 114, 19,
2362                                  &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0,
2363                                  "Relative friction coefficient in the x-direction.");
2364                 uiDefButF(block, NUM, B_DIFF, "y friction:",                    124, 145, 113, 19,
2365                                  &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0,
2366                                  "Relative friction coefficient in the y-direction.");
2367                 uiDefButF(block, NUM, B_DIFF, "z friction:",                    237, 145, 113, 19,
2368                                  &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0,
2369                                  "Relative friction coefficient in the z-direction.");
2370         }
2371         
2372         uiBlockSetCol(block, BUTSALMON);
2373         uiDefBut(block, BUT, B_ADD_PROP, "ADD property",                10, 110, 340, 24,
2374                          NULL, 0.0, 100.0, 100, 0,
2375                          "");
2376         
2377         pupstr= "Types %t|Bool %x0|Int %x1|Float %x2|String %x3|Timer %x5";
2378         
2379         a= 0;
2380         prop= ob->prop.first;
2381         while(prop) {
2382                 
2383                 uiBlockSetCol(block, BUTSALMON);
2384                 but= uiDefBut(block, BUT, 1, "Del",             10, (short)(90-20*a), 40, 19, NULL, 0.0, 0.0, 1, (float)a, "");
2385                 uiButSetFunc(but, del_property, prop, NULL);
2386                 uiBlockSetCol(block, BUTGREY);
2387                 uiDefButS(block, MENU, B_CHANGE_PROP, pupstr,           50, (short)(90-20*a), 60, 19, &prop->type, 0, 0, 0, 0, "");
2388                 but= uiDefBut(block, TEX, 1, "Name:",                                   110, (short)(90-20*a), 105, 19, prop->name, 0, 31, 0, 0, "");
2389                 uiButSetFunc(but, make_unique_prop_names_cb, prop->name, (void*) 1);
2390                 
2391                 if (strcmp(prop->name, "Text") == 0) {
2392                         butreturn = REDRAWVIEW3D;
2393                 } else {
2394                         butreturn = 0;
2395                 }
2396
2397                 if(prop->type==PROP_BOOL) {
2398                         uiBlockSetCol(block, BUTGREEN);
2399                         uiDefButI(block, TOG|BIT|0, B_REDR, "True",             215, (short)(90-20*a), 55, 19, &prop->data, 0, 0, 0, 0, "");
2400                         uiDefButI(block, TOGN|BIT|0, B_REDR, "False",   270, (short)(90-20*a), 55, 19, &prop->data, 0, 0, 0, 0, "");
2401                         uiBlockSetCol(block, BUTGREY);
2402                 }
2403                 else if(prop->type==PROP_INT) 
2404                         uiDefButI(block, NUM, butreturn, "",                    215, (short)(90-20*a), 110, 19, &prop->data, -10000, 10000, 0, 0, "");
2405                 else if(prop->type==PROP_FLOAT) 
2406                         uiDefButF(block, NUM, butreturn, "",                    215, (short)(90-20*a), 110, 19, (float*) &prop->data, -10000, 10000, 100, 0, "");
2407                 else if(prop->type==PROP_STRING) 
2408                         uiDefBut(block, TEX, butreturn, "",                             215, (short)(90-20*a), 110, 19, prop->poin, 0, 127, 0, 0, "");
2409                 else if(prop->type==PROP_TIME) 
2410                         uiDefButF(block, NUM, butreturn, "",                    215, (short)(90-20*a), 110, 19, (float*) &prop->data, -10000, 10000, 0, 0, "");
2411                 
2412                 uiDefButS(block, TOG|BIT|0, 0, "D",             325, (short)(90-20*a), 20, 19, &prop->flag, 0, 0, 0, 0, "Print Debug info");
2413                 
2414                 a++;
2415                 prop= prop->next;
2416         }
2417         
2418         uiClearButLock();
2419
2420         idar= get_selected_and_linked_obs(&count, G.buts->scaflag);
2421         
2422         /* ******************************* */
2423         xco= 375; yco= 170; width= 230;
2424
2425         uiBlockSetCol(block, BUTGREY);
2426         uiBlockSetEmboss(block, UI_EMBOSSM);
2427         uiDefBlockBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 80, 19, "");
2428         uiBlockSetCol(block, BUTGREEN);
2429         uiBlockSetEmboss(block, UI_EMBOSSX);
2430         uiDefButS(block, TOG|BIT|0, B_REDR, "Sel", xco+110, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects");
2431         uiDefButS(block, TOG|BIT|1, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object");
2432         uiDefButS(block, TOG|BIT|2, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
2433         
2434         for(a=0; a<count; a++) {
2435                 ob= (Object *)idar[a];
2436                 uiClearButLock();
2437                 uiSetButLock(ob->id.lib!=0, "Can't edit library data");
2438                 
2439                 if( (ob->scavisflag & OB_VIS_SENS) == 0) continue;
2440                 
2441                 /* presume it is only objects for now */
2442                 uiBlockSetEmboss(block, UI_EMBOSSX);
2443                 uiBlockSetCol(block, BUTGREY);
2444                 if(ob->sensors.first) uiSetCurFont(block, UI_HELVB);
2445                 uiBlockSetCol(block, MIDGREY);
2446                 uiDefButS(block, TOG|BIT|6, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors");
2447                 if(ob->sensors.first) uiSetCurFont(block, UI_HELV);
2448                 uiBlockSetCol(block, BUTSALMON);
2449                 uiDefButS(block, TOG|BIT|8, B_ADD_SENS, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor");
2450                 yco-=20;
2451                 
2452                 if(ob->scaflag & OB_SHOWSENS) {
2453                         
2454                         sens= ob->sensors.first;
2455                         while(sens) {
2456                                 uiBlockSetEmboss(block, UI_EMBOSSW);
2457                                 uiBlockSetCol(block, BUTSALMON);
2458                                 uiDefIconButS(block, TOG|BIT|1, B_DEL_SENS, ICON_X,     xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor");
2459                                 uiBlockSetCol(block, BUTGREY);
2460                                 uiDefIconButS(block, ICONTOG|BIT|0, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Sensor settings");
2461
2462                                 ycoo= yco;
2463                                 if(sens->flag & SENS_SHOW)
2464                                 {
2465                                         uiBlockSetCol(block, BUTYELLOW);
2466
2467                                         uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(),     (short)(xco+22), yco, 100, 19, &sens->type, 0, 0, 0, 0, "Sensor type");
2468                                         but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, sens->name, 0, 31, 0, 0, "Sensor name");
2469                                         uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0);
2470
2471                                         sens->otype= sens->type;
2472                                         uiBlockSetCol(block, BUTGREY);
2473                                         yco= draw_sensorbuttons(sens, block, xco, yco, width,ob->id.name);
2474                                         if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2;
2475                                 }
2476                                 else {
2477                                         set_col_sensor(sens->type, 1);
2478                                         glRecti(xco+22, yco, xco+width-22,yco+19);
2479                                         but= uiDefBut(block, LABEL, 0, sensor_name(sens->type), (short)(xco+22), yco, 100, 19, sens, 0, 0, 0, 0, "");
2480                                         uiButSetFunc(but, sca_move_sensor, sens, NULL);
2481                                         but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+122), yco, (short)(width-144), 19, sens, 0, 31, 0, 0, "");
2482                                         uiButSetFunc(but, sca_move_sensor, sens, NULL);
2483                                 }
2484
2485                                 but= uiDefIconBut(block, LINK, 0, ICON_LINK,    (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, "");
2486                                 uiSetButLink(but, NULL, (void ***)&(sens->links), &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER);
2487
2488                                 yco-=20;
2489
2490                                 sens= sens->next;
2491                         }
2492                         yco-= 6;
2493                 }
2494         }
2495
2496         /* ******************************* */
2497         xco= 675; yco= 170; width= 230;
2498
2499         uiBlockSetCol(block, BUTGREY);
2500         uiBlockSetEmboss(block, UI_EMBOSSM);
2501         uiDefBlockBut(block, controller_menu, NULL, "Controllers", xco-10, yco+35, 100, 19, "");
2502         uiBlockSetCol(block, BUTGREEN);
2503         uiBlockSetEmboss(block, UI_EMBOSSX);
2504         uiDefButS(block, TOG|BIT|3, B_REDR, "Sel", xco+110, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects");
2505         uiDefButS(block, TOG|BIT|4, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object");
2506         uiDefButS(block, TOG|BIT|5, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Sensor/Actuator");
2507         
2508         ob= OBACT;
2509         
2510         for(a=0; a<count; a++) {
2511                 ob= (Object *)idar[a];
2512                 uiClearButLock();
2513                 uiSetButLock(ob->id.lib!=0, "Can't edit library data");
2514                 if( (ob->scavisflag & OB_VIS_CONT) == 0) continue;
2515
2516                 /* presume it is only objects for now */
2517                 uiBlockSetEmboss(block, UI_EMBOSSX);
2518                 uiBlockSetCol(block, BUTSALMON);
2519                 uiDefButS(block, TOG|BIT|9, B_ADD_CONT, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Controller");
2520                 uiBlockSetCol(block, MIDGREY);
2521                 if(ob->controllers.first) uiSetCurFont(block, UI_HELVB);
2522                 uiDefButS(block, TOG|BIT|11, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 0, 0, 0, "Active Object name");
2523                 if(ob->controllers.first) uiSetCurFont(block, UI_HELV);
2524                 yco-=20;
2525                 
2526                 if(ob->scaflag & OB_SHOWCONT) {
2527                 
2528                         cont= ob->controllers.first;
2529                         while(cont) {
2530                                 uiBlockSetEmboss(block, UI_EMBOSSW);
2531                                 uiBlockSetCol(block, BUTSALMON);
2532                                 uiDefIconButS(block, TOG|BIT|1, B_DEL_CONT, ICON_X,     xco, yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Delete Controller");
2533                                 uiBlockSetCol(block, BUTGREY);
2534                                 uiDefIconButS(block, ICONTOG|BIT|0, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings");
2535                 
2536                                 if(cont->flag & CONT_SHOW) {
2537                                         uiBlockSetCol(block, BUTYELLOW);
2538                                         cont->otype= cont->type;
2539                                         uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 100, 19, &cont->type, 0, 0, 0, 0, "Controller type");
2540                                         but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, cont->name, 0, 31, 0, 0, "Controller name");
2541                                         uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0);
2542                                         uiBlockSetCol(block, BUTGREY);
2543                 
2544                                         ycoo= yco;
2545                                         yco= draw_controllerbuttons(cont, block, xco, yco, width);
2546                                         if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2;
2547                                 }
2548                                 else {
2549                                         cpack(0x999999);
2550                                         glRecti(xco+22, yco, xco+width-22,yco+19);
2551                                         but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 100, 19, cont, 0, 0, 0, 0, "Controller type");
2552                                         uiButSetFunc(but, sca_move_controller, cont, NULL);
2553                                         but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+122), yco,(short)(width-144), 19, cont, 0, 0, 0, 0, "Controller name");
2554                                         uiButSetFunc(but, sca_move_controller, cont, NULL);
2555                                         ycoo= yco;
2556                                 }
2557                 
2558                                 but= uiDefIconBut(block, LINK, 0, ICON_LINK,    (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, "");
2559                                 uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR);
2560                 
2561                                 uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, cont, LINK_CONTROLLER, 0, 0, 0, "");
2562                 
2563                                 yco-=20;
2564                                 
2565                                 cont= cont->next;
2566                         }
2567                         yco-= 6;
2568                 }
2569         }
2570         
2571         /* ******************************* */
2572         xco= 985; yco= 170; width= 280;
2573         
2574         uiBlockSetCol(block, BUTGREY);
2575         uiBlockSetEmboss(block, UI_EMBOSSM);
2576         uiDefBlockBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 100, 19, "");
2577         uiBlockSetCol(block, BUTGREEN);
2578         uiBlockSetEmboss(block, UI_EMBOSSX);
2579         uiDefButS(block, TOG|BIT|6, B_REDR, "Sel", xco+110, yco+35, (width-110)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects");
2580         uiDefButS(block, TOG|BIT|7, B_REDR, "Act", xco+110+(width-110)/3, yco+35, (width-110)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object");
2581         uiDefButS(block, TOG|BIT|8, B_REDR, "Link", xco+110+2*(width-110)/3, yco+35, (width-110)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
2582         
2583         for(a=0; a<count; a++) {
2584                 ob= (Object *)idar[a];
2585                 uiClearButLock();
2586                 uiSetButLock(ob->id.lib!=0, "Can't edit library data");
2587                 if( (ob->scavisflag & OB_VIS_ACT) == 0) continue;
2588
2589                 /* presume it is only objects for now */
2590                 uiBlockSetEmboss(block, UI_EMBOSSX);
2591                 uiBlockSetCol(block, BUTGREY);
2592                 if(ob->actuators.first) uiSetCurFont(block, UI_HELVB);
2593                 uiBlockSetCol(block, MIDGREY);
2594                 uiDefButS(block, TOG|BIT|7, B_REDR, ob->id.name+2,(short)(xco-10), yco,(short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators");
2595                 if(ob->actuators.first) uiSetCurFont(block, UI_HELV);
2596                 uiBlockSetCol(block, BUTSALMON);
2597                 uiDefButS(block, TOG|BIT|10, B_ADD_ACT, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Actuator");
2598                 yco-=20;
2599                 
2600                 if(ob->scaflag & OB_SHOWACT) {
2601                         
2602                         act= ob->actuators.first;
2603                         while(act) {
2604                                 uiBlockSetEmboss(block, UI_EMBOSSW);
2605                                 uiBlockSetCol(block, BUTSALMON);
2606                                 uiDefIconButS(block, TOG|BIT|1, B_DEL_ACT, ICON_X,      xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator");
2607                                 uiBlockSetCol(block, BUTGREY);
2608                                 uiDefIconButS(block, ICONTOG|BIT|0, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Actuator settings");
2609
2610                                 if(act->flag & ACT_SHOW) {
2611                                         uiBlockSetCol(block, BUTYELLOW);
2612                                         act->otype= act->type;
2613                                         uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob),  (short)(xco+22), yco, 100, 19, &act->type, 0, 0, 0, 0, "Actuator type");
2614                                         but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, act->name, 0, 31, 0, 0, "Actuator name");
2615                                         uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0);
2616                                         uiBlockSetCol(block, BUTGREY);
2617
2618                                         ycoo= yco;
2619                                         yco= draw_actuatorbuttons(act, block, xco, yco, width);
2620                                         if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2;
2621                                 }
2622                                 else {
2623                                         set_col_actuator(act->type, 1);
2624                                         glRecti((short)(xco+22), yco, (short)(xco+width-22),(short)(yco+19));
2625                                         but= uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 100, 19, act, 0, 0, 0, 0, "Actuator type");
2626                                         uiButSetFunc(but, sca_move_actuator, act, NULL);
2627                                         but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+122), yco, (short)(width-144), 19, act, 0, 0, 0, 0, "Actuator name");
2628                                         uiButSetFunc(but, sca_move_actuator, act, NULL);
2629                                         ycoo= yco;
2630                                 }
2631
2632                                 uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, act, LINK_ACTUATOR, 0, 0, 0, "");
2633
2634                                 yco-=20;
2635
2636                                 act= act->next;
2637                         }
2638                         yco-= 6;
2639                 }
2640         }
2641
2642         uiComposeLinks(block);
2643         uiDrawBlock(block);
2644
2645         if(idar) MEM_freeN(idar);
2646 }
2647