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