5a8a7cef119e9b7d2c0ffc789d036445510d04a0
[blender.git] / source / blender / editors / space_logic / logic_window.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_logic/logic_window.c
28  *  \ingroup splogic
29  */
30
31
32 #include <string.h>
33 #include <stdio.h>
34 #include <stddef.h>
35 #include <float.h>
36
37 #include "DNA_actuator_types.h"
38 #include "DNA_controller_types.h"
39 #include "DNA_property_types.h"
40 #include "DNA_space_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_screen_types.h"
43 #include "DNA_sensor_types.h"
44 #include "DNA_constraint_types.h"
45 #include "DNA_windowmanager_types.h"
46 #include "DNA_object_types.h"
47
48 #include "MEM_guardedalloc.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_utildefines.h"
52
53 #include "BKE_action.h"
54 #include "BKE_context.h"
55 #include "BKE_global.h"
56 #include "BKE_library.h"
57 #include "BKE_main.h"
58 #include "BKE_sca.h"
59 #include "BKE_screen.h"
60
61 #include "ED_util.h"
62
63 #include "WM_types.h"
64
65 #include "BIF_gl.h"
66
67 #include "BLF_translation.h"
68
69 #include "UI_interface.h"
70 #include "UI_view2d.h"
71
72 #include "RNA_access.h"
73
74 /* XXX BAD BAD */
75 #include "../interface/interface_intern.h"
76
77 #include "logic_intern.h"
78
79 #define B_REDR          1
80
81 #define B_ADD_SENS              2703
82 #define B_CHANGE_SENS           2704
83 #define B_DEL_SENS              2705
84
85 #define B_ADD_CONT              2706
86 #define B_CHANGE_CONT           2707
87 #define B_DEL_CONT              2708
88
89 #define B_ADD_ACT               2709
90 #define B_CHANGE_ACT            2710
91 #define B_DEL_ACT               2711
92
93 #define B_SOUNDACT_BROWSE       2712
94
95 #define B_SETPROP               2714
96 #define B_SETACTOR              2715
97 #define B_SETMAINACTOR          2716
98 #define B_SETDYNA               2717
99 #define B_SET_STATE_BIT 2718
100 #define B_INIT_STATE_BIT        2719
101
102 /* proto */
103 static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisflag);
104
105 static int vergname(const void *v1, const void *v2)
106 {
107         char **x1, **x2;
108         
109         x1 = (char **)v1;
110         x2 = (char **)v2;
111         
112         return BLI_natstrcmp(*x1, *x2);
113 }
114
115 void make_unique_prop_names(bContext *C, char *str)
116 {
117         Object *ob;
118         bProperty *prop;
119         bSensor *sens;
120         bController *cont;
121         bActuator *act;
122         ID **idar;
123         short a, obcount, propcount=0, nr;
124         char **names;
125         
126         /* this function is called by a Button, and gives the current
127          * stringpointer as an argument, this is the one that can change
128          */
129         
130         idar= get_selected_and_linked_obs(C, &obcount, BUTS_SENS_SEL|BUTS_SENS_ACT|BUTS_ACT_SEL|BUTS_ACT_ACT|BUTS_CONT_SEL|BUTS_CONT_ACT);
131         
132         /* for each object, make properties and sca names unique */
133         
134         /* count total names */
135         for (a=0; a<obcount; a++) {
136                 ob= (Object *)idar[a];
137                 propcount+= BLI_countlist(&ob->prop);
138                 propcount+= BLI_countlist(&ob->sensors);
139                 propcount+= BLI_countlist(&ob->controllers);
140                 propcount+= BLI_countlist(&ob->actuators);
141         }
142         if (propcount==0) {
143                 if (idar) MEM_freeN(idar);
144                 return;
145         }
146         
147         /* make names array for sorting */
148         names= MEM_callocN(propcount*sizeof(void *), "names");
149         
150         /* count total names */
151         nr= 0;
152         for (a=0; a<obcount; a++) {
153                 ob= (Object *)idar[a];
154                 prop= ob->prop.first;
155                 while (prop) {
156                         names[nr++] = prop->name;
157                         prop= prop->next;
158                 }
159                 sens= ob->sensors.first;
160                 while (sens) {
161                         names[nr++] = sens->name;
162                         sens= sens->next;
163                 }
164                 cont= ob->controllers.first;
165                 while (cont) {
166                         names[nr++] = cont->name;
167                         cont= cont->next;
168                 }
169                 act= ob->actuators.first;
170                 while (act) {
171                         names[nr++] = act->name;
172                         act= act->next;
173                 }
174         }
175         
176         qsort(names, propcount, sizeof(void *), vergname);
177         
178         /* now we check for double names, and change them */
179         
180         for (nr=0; nr<propcount; nr++) {
181                 if (names[nr]!=str && strcmp( names[nr], str )==0 ) {
182                         BLI_newname(str, +1);
183                 }
184         }
185         
186         MEM_freeN(idar);
187         MEM_freeN(names);
188 }
189
190 static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
191 {
192         Main *bmain= CTX_data_main(C);
193         bSensor *sens;
194         bController *cont;
195         bActuator *act;
196         Object *ob;
197         int didit, bit;
198         
199         ob= CTX_data_active_object(C);
200         if (ob==NULL) return;
201         
202         switch (event) {
203
204         case B_SETPROP:
205                 /* check for inconsistent types */
206                 ob->gameflag &= ~(OB_SECTOR|OB_MAINACTOR|OB_DYNAMIC|OB_ACTOR);
207                 break;
208
209         case B_SETACTOR:
210         case B_SETDYNA:
211         case B_SETMAINACTOR:
212                 ob->gameflag &= ~(OB_SECTOR|OB_PROP);
213                 break;
214         
215         case B_ADD_SENS:
216                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
217                         if (ob->scaflag & OB_ADDSENS) {
218                                 ob->scaflag &= ~OB_ADDSENS;
219                                 sens= new_sensor(SENS_ALWAYS);
220                                 BLI_addtail(&(ob->sensors), sens);
221                                 make_unique_prop_names(C, sens->name);
222                                 ob->scaflag |= OB_SHOWSENS;
223                         }
224                 }
225                 
226                 ED_undo_push(C, "Add sensor");
227                 break;
228
229         case B_CHANGE_SENS:
230                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
231                         sens= ob->sensors.first;
232                         while (sens) {
233                                 if (sens->type != sens->otype) {
234                                         init_sensor(sens);
235                                         sens->otype= sens->type;
236                                         break;
237                                 }
238                                 sens= sens->next;
239                         }
240                 }
241                 break;
242         
243         case B_DEL_SENS:
244                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
245                         sens= ob->sensors.first;
246                         while (sens) {
247                                 if (sens->flag & SENS_DEL) {
248                                         BLI_remlink(&(ob->sensors), sens);
249                                         free_sensor(sens);
250                                         break;
251                                 }
252                                 sens= sens->next;
253                         }
254                 }
255                 ED_undo_push(C, "Delete sensor");
256                 break;
257         
258         case B_ADD_CONT:
259                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
260                         if (ob->scaflag & OB_ADDCONT) {
261                                 ob->scaflag &= ~OB_ADDCONT;
262                                 cont= new_controller(CONT_LOGIC_AND);
263                                 make_unique_prop_names(C, cont->name);
264                                 ob->scaflag |= OB_SHOWCONT;
265                                 BLI_addtail(&(ob->controllers), cont);
266                                 /* set the controller state mask from the current object state.
267                                  * A controller is always in a single state, so select the lowest bit set
268                                  * from the object state */
269                                 for (bit=0; bit<32; bit++) {
270                                         if (ob->state & (1<<bit))
271                                                 break;
272                                 }
273                                 cont->state_mask = (1<<bit);
274                                 if (cont->state_mask == 0) {
275                                         /* shouldn't happen, object state is never 0 */
276                                         cont->state_mask = 1;
277                                 }
278                         }
279                 }
280                 ED_undo_push(C, "Add controller");
281                 break;
282
283         case B_SET_STATE_BIT:
284                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
285                         if (ob->scaflag & OB_ALLSTATE) {
286                                 ob->scaflag &= ~OB_ALLSTATE;
287                                 ob->state = 0x3FFFFFFF;
288                         }
289                 }
290                 break;
291
292         case B_INIT_STATE_BIT:
293                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
294                         if (ob->scaflag & OB_INITSTBIT) {
295                                 ob->scaflag &= ~OB_INITSTBIT;
296                                 ob->state = ob->init_state;
297                                 if (!ob->state)
298                                         ob->state = 1;
299                         }
300                 }
301                 break;
302
303         case B_CHANGE_CONT:
304                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
305                         cont= ob->controllers.first;
306                         while (cont) {
307                                 if (cont->type != cont->otype) {
308                                         init_controller(cont);
309                                         cont->otype= cont->type;
310                                         break;
311                                 }
312                                 cont= cont->next;
313                         }
314                 }
315                 break;
316         
317
318         case B_DEL_CONT:
319                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
320                         cont= ob->controllers.first;
321                         while (cont) {
322                                 if (cont->flag & CONT_DEL) {
323                                         BLI_remlink(&(ob->controllers), cont);
324                                         unlink_controller(cont);
325                                         free_controller(cont);
326                                         break;
327                                 }
328                                 cont= cont->next;
329                         }
330                 }
331                 ED_undo_push(C, "Delete controller");
332                 break;
333
334         case B_ADD_ACT:
335                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
336                         if (ob->scaflag & OB_ADDACT) {
337                                 ob->scaflag &= ~OB_ADDACT;
338                                 act= new_actuator(ACT_OBJECT);
339                                 make_unique_prop_names(C, act->name);
340                                 BLI_addtail(&(ob->actuators), act);
341                                 ob->scaflag |= OB_SHOWACT;
342                         }
343                 }
344                 ED_undo_push(C, "Add actuator");
345                 break;
346
347         case B_CHANGE_ACT:
348                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
349                         act= ob->actuators.first;
350                         while (act) {
351                                 if (act->type != act->otype) {
352                                         init_actuator(act);
353                                         act->otype= act->type;
354                                         break;
355                                 }
356                                 act= act->next;
357                         }
358                 }
359                 break;
360
361         case B_DEL_ACT:
362                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
363                         act= ob->actuators.first;
364                         while (act) {
365                                 if (act->flag & ACT_DEL) {
366                                         BLI_remlink(&(ob->actuators), act);
367                                         unlink_actuator(act);
368                                         free_actuator(act);
369                                         break;
370                                 }
371                                 act= act->next;
372                         }
373                 }
374                 ED_undo_push(C, "Delete actuator");
375                 break;
376         
377         case B_SOUNDACT_BROWSE:
378                 /* since we don't know which... */
379                 didit= 0;
380                 for (ob=bmain->object.first; ob; ob=ob->id.next) {
381                         act= ob->actuators.first;
382                         while (act) {
383                                 if (act->type==ACT_SOUND) {
384                                         bSoundActuator *sa= act->data;
385                                         if (sa->sndnr) {
386                                                 ID *sound= bmain->sound.first;
387                                                 int nr= 1;
388
389                                                 if (sa->sndnr == -2) {
390 // XXX                                                  activate_databrowse((ID *)bmain->sound.first, ID_SO, 0, B_SOUNDACT_BROWSE,
391 //                                                                                      &sa->sndnr, do_logic_buts);
392                                                         break;
393                                                 }
394
395                                                 while (sound) {
396                                                         if (nr==sa->sndnr)
397                                                                 break;
398                                                         nr++;
399                                                         sound= sound->next;
400                                                 }
401                                                 
402                                                 if (sa->sound)
403                                                         ((ID *)sa->sound)->us--;
404                                                 
405                                                 sa->sound= (struct bSound *)sound;
406                                                 
407                                                 if (sound)
408                                                         sound->us++;
409                                                 
410                                                 sa->sndnr= 0;
411                                                 didit= 1;
412                                         }
413                                 }
414                                 act= act->next;
415                         }
416                         if (didit)
417                                 break;
418                 }
419
420                 break;
421         }
422 }
423
424
425 static const char *sensor_name(int type)
426 {
427         switch (type) {
428         case SENS_ALWAYS:
429                 return "Always";
430         case SENS_TOUCH:
431                 return "Touch";
432         case SENS_NEAR:
433                 return "Near";
434         case SENS_KEYBOARD:
435                 return "Keyboard";
436         case SENS_PROPERTY:
437                 return "Property";
438         case SENS_ARMATURE:
439                 return "Armature";
440         case SENS_ACTUATOR:
441                 return "Actuator";
442         case SENS_DELAY:
443                 return "Delay";
444         case SENS_MOUSE:
445                 return "Mouse";
446         case SENS_COLLISION:
447                 return "Collision";
448         case SENS_RADAR:
449                 return "Radar";
450         case SENS_RANDOM:
451                 return "Random";
452         case SENS_RAY:
453                 return "Ray";
454         case SENS_MESSAGE:
455                 return "Message";
456         case SENS_JOYSTICK:
457                 return "Joystick";
458         }
459         return "unknown";
460 }
461
462 static const char *controller_name(int type)
463 {
464         switch (type) {
465         case CONT_LOGIC_AND:
466                 return "And";
467         case CONT_LOGIC_OR:
468                 return "Or";
469         case CONT_LOGIC_NAND:
470                 return "Nand";
471         case CONT_LOGIC_NOR:
472                 return "Nor";
473         case CONT_LOGIC_XOR:
474                 return "Xor";
475         case CONT_LOGIC_XNOR:
476                 return "Xnor";
477         case CONT_EXPRESSION:
478                 return "Expression";
479         case CONT_PYTHON:
480                 return "Python";
481         }
482         return "unknown";
483 }
484
485 static const char *actuator_name(int type)
486 {
487         switch (type) {
488         case ACT_SHAPEACTION:
489                 return "Shape Action";
490         case ACT_ACTION:
491                 return "Action";
492         case ACT_OBJECT:
493                 return "Motion";
494         case ACT_IPO:
495                 return "F-Curve";
496         case ACT_LAMP:
497                 return "Lamp";
498         case ACT_CAMERA:
499                 return "Camera";
500         case ACT_MATERIAL:
501                 return "Material";
502         case ACT_SOUND:
503                 return "Sound";
504         case ACT_PROPERTY:
505                 return "Property";
506         case ACT_EDIT_OBJECT:
507                 return "Edit Object";
508         case ACT_CONSTRAINT:
509                 return "Constraint";
510         case ACT_SCENE:
511                 return "Scene";
512         case ACT_GROUP:
513                 return "Group";
514         case ACT_RANDOM:
515                 return "Random";
516         case ACT_MESSAGE:
517                 return "Message";
518         case ACT_GAME:
519                 return "Game";
520         case ACT_VISIBILITY:
521                 return "Visibility";
522         case ACT_2DFILTER:
523                 return "Filter 2D";
524         case ACT_PARENT:
525                 return "Parent";
526         case ACT_STATE:
527                 return "State";
528         case ACT_ARMATURE:
529                 return "Armature";
530         case ACT_STEERING:
531                 return "Steering";
532         }
533         return "unknown";
534 }
535
536 static void set_sca_ob(Object *ob)
537 {
538         bController *cont;
539         bActuator *act;
540
541         cont= ob->controllers.first;
542         while (cont) {
543                 cont->mynew= (bController *)ob;
544                 cont= cont->next;
545         }
546         act= ob->actuators.first;
547         while (act) {
548                 act->mynew= (bActuator *)ob;
549                 act= act->next;
550         }
551 }
552
553 static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisflag)
554 {
555         Base *base;
556         Main *bmain= CTX_data_main(C);
557         Scene *scene= CTX_data_scene(C);
558         Object *ob, *obt, *obact= CTX_data_active_object(C);
559         ID **idar;
560         bSensor *sens;
561         bController *cont;
562         unsigned int lay;
563         int a, nr, do_it;
564         
565         /* we need a sorted object list */
566         /* set scavisflags flags in Objects to indicate these should be evaluated */
567         /* also hide ob pointers in ->new entries of controllerss/actuators */
568         
569         *count= 0;
570         
571         if (scene==NULL) return NULL;
572         
573         ob= bmain->object.first;
574         while (ob) {
575                 ob->scavisflag= 0;
576                 set_sca_ob(ob);
577                 ob= ob->id.next;
578         }
579         
580         /* XXX here it checked 3d lay */
581         lay= scene->lay;
582         
583         base= FIRSTBASE;
584         while (base) {
585                 if (base->lay & lay) {
586                         if (base->flag & SELECT) {
587                                 if (scavisflag & BUTS_SENS_SEL) base->object->scavisflag |= OB_VIS_SENS;
588                                 if (scavisflag & BUTS_CONT_SEL) base->object->scavisflag |= OB_VIS_CONT;
589                                 if (scavisflag & BUTS_ACT_SEL) base->object->scavisflag |= OB_VIS_ACT;
590                         }
591                 }
592                 base= base->next;
593         }
594
595         if (obact) {
596                 if (scavisflag & BUTS_SENS_ACT) obact->scavisflag |= OB_VIS_SENS;
597                 if (scavisflag & BUTS_CONT_ACT) obact->scavisflag |= OB_VIS_CONT;
598                 if (scavisflag & BUTS_ACT_ACT) obact->scavisflag |= OB_VIS_ACT;
599         }
600         
601         /* BUTS_XXX_STATE are similar to BUTS_XXX_LINK for selecting the object */
602         if (scavisflag & (BUTS_SENS_LINK|BUTS_CONT_LINK|BUTS_ACT_LINK|BUTS_SENS_STATE|BUTS_ACT_STATE)) {
603                 do_it = TRUE;
604                 while (do_it) {
605                         do_it = FALSE;
606                         
607                         ob= bmain->object.first;
608                         while (ob) {
609                         
610                                 /* 1st case: select sensor when controller selected */
611                                 if ((scavisflag & (BUTS_SENS_LINK|BUTS_SENS_STATE)) && (ob->scavisflag & OB_VIS_SENS)==0) {
612                                         sens= ob->sensors.first;
613                                         while (sens) {
614                                                 for (a=0; a<sens->totlinks; a++) {
615                                                         if (sens->links[a]) {
616                                                                 obt= (Object *)sens->links[a]->mynew;
617                                                                 if (obt && (obt->scavisflag & OB_VIS_CONT)) {
618                                                                         do_it = TRUE;
619                                                                         ob->scavisflag |= OB_VIS_SENS;
620                                                                         break;
621                                                                 }
622                                                         }
623                                                 }
624                                                 if (do_it) break;
625                                                 sens= sens->next;
626                                         }
627                                 }
628                                 
629                                 /* 2nd case: select cont when act selected */
630                                 if ((scavisflag & BUTS_CONT_LINK) && (ob->scavisflag & OB_VIS_CONT)==0) {
631                                         cont= ob->controllers.first;
632                                         while (cont) {
633                                                 for (a=0; a<cont->totlinks; a++) {
634                                                         if (cont->links[a]) {
635                                                                 obt= (Object *)cont->links[a]->mynew;
636                                                                 if (obt && (obt->scavisflag & OB_VIS_ACT)) {
637                                                                         do_it = TRUE;
638                                                                         ob->scavisflag |= OB_VIS_CONT;
639                                                                         break;
640                                                                 }
641                                                         }
642                                                 }
643                                                 if (do_it) break;
644                                                 cont= cont->next;
645                                         }
646                                 }
647                                 
648                                 /* 3rd case: select controller when sensor selected */
649                                 if ((scavisflag & BUTS_CONT_LINK) && (ob->scavisflag & OB_VIS_SENS)) {
650                                         sens= ob->sensors.first;
651                                         while (sens) {
652                                                 for (a=0; a<sens->totlinks; a++) {
653                                                         if (sens->links[a]) {
654                                                                 obt= (Object *)sens->links[a]->mynew;
655                                                                 if (obt && (obt->scavisflag & OB_VIS_CONT)==0) {
656                                                                         do_it = TRUE;
657                                                                         obt->scavisflag |= OB_VIS_CONT;
658                                                                 }
659                                                         }
660                                                 }
661                                                 sens= sens->next;
662                                         }
663                                 }
664                                 
665                                 /* 4th case: select actuator when controller selected */
666                                 if ((scavisflag & (BUTS_ACT_LINK|BUTS_ACT_STATE)) && (ob->scavisflag & OB_VIS_CONT)) {
667                                         cont= ob->controllers.first;
668                                         while (cont) {
669                                                 for (a=0; a<cont->totlinks; a++) {
670                                                         if (cont->links[a]) {
671                                                                 obt= (Object *)cont->links[a]->mynew;
672                                                                 if (obt && (obt->scavisflag & OB_VIS_ACT)==0) {
673                                                                         do_it = TRUE;
674                                                                         obt->scavisflag |= OB_VIS_ACT;
675                                                                 }
676                                                         }
677                                                 }
678                                                 cont= cont->next;
679                                         }
680                                         
681                                 }
682                                 ob= ob->id.next;
683                         }
684                 }
685         }
686         
687         /* now we count */
688         ob= bmain->object.first;
689         while (ob) {
690                 if ( ob->scavisflag ) (*count)++;
691                 ob= ob->id.next;
692         }
693
694         if (*count == 0) return NULL;
695         if (*count > 24) *count = 24;  /* temporal */
696         
697         idar= MEM_callocN((*count)*sizeof(void *), "idar");
698         
699         ob= bmain->object.first;
700         nr= 0;
701
702         /* make the active object always the first one of the list */
703         if (obact) {
704                 idar[0] = (ID *)obact;
705                 nr++;
706         }
707
708         while (ob) {
709                 if ((ob->scavisflag) && (ob != obact)) {
710                         idar[nr] = (ID *)ob;
711                         nr++;
712                 }
713                 if (nr >= 24) break;
714                 ob= ob->id.next;
715         }
716         
717         /* just to be sure... these were set in set_sca_done_ob() */
718         clear_sca_new_poins();
719         
720         return idar;
721 }
722
723 static void get_armature_bone_constraint(Object *ob, const char *posechannel, const char *constraint_name, bConstraint **constraint)
724 {
725         /* check that bone exist in the active object */
726         if (ob->type == OB_ARMATURE && ob->pose) {
727                 bPoseChannel *pchan= BKE_pose_channel_find_name(ob->pose, posechannel);
728                 if (pchan) {
729                         bConstraint *con= BLI_findstring(&pchan->constraints, constraint_name, offsetof(bConstraint, name));
730                         if (con) {
731                                 *constraint= con;
732                         }
733                 }
734         }
735         /* didn't find any */
736 }
737
738 static void do_sensor_menu(bContext *C, void *UNUSED(arg), int event)
739 {       
740         SpaceLogic *slogic= CTX_wm_space_logic(C);
741         ID **idar;
742         Object *ob;
743         bSensor *sens;
744         short count, a;
745         
746         idar= get_selected_and_linked_obs(C, &count, slogic->scaflag);
747         
748         for (a=0; a<count; a++) {
749                 ob= (Object *)idar[a];
750                 if (event==0 || event==2) ob->scaflag |= OB_SHOWSENS;
751                 else if (event==1) ob->scaflag &= ~OB_SHOWSENS;
752         }
753                 
754         for (a=0; a<count; a++) {
755                 ob= (Object *)idar[a];
756                 sens= ob->sensors.first;
757                 while (sens) {
758                         if (event==2) sens->flag |= SENS_SHOW;
759                         else if (event==3) sens->flag &= ~SENS_SHOW;
760                         sens= sens->next;
761                 }
762         }
763
764         if (idar) MEM_freeN(idar);
765 }
766
767 static uiBlock *sensor_menu(bContext *C, ARegion *ar, void *UNUSED(arg))
768 {
769         uiBlock *block;
770         int yco=0;
771         
772         block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP);
773         uiBlockSetButmFunc(block, do_sensor_menu, NULL);
774         
775         uiDefBut(block, BUTM, 1, IFACE_("Show Objects"),        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
776         uiDefBut(block, BUTM, 1, IFACE_("Hide Objects"),        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
777         uiDefBut(block, SEPR, 0, "",    0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
778         uiDefBut(block, BUTM, 1, IFACE_("Show Sensors"),        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
779         uiDefBut(block, BUTM, 1, IFACE_("Hide Sensors"),        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
780
781         uiBlockSetDirection(block, UI_TOP);
782         uiEndBlock(C, block);
783         
784         return block;
785 }
786
787 static void do_controller_menu(bContext *C, void *UNUSED(arg), int event)
788 {       
789         SpaceLogic *slogic= CTX_wm_space_logic(C);
790         ID **idar;
791         Object *ob;
792         bController *cont;
793         short count, a;
794         
795         idar= get_selected_and_linked_obs(C, &count, slogic->scaflag);
796         
797         for (a=0; a<count; a++) {
798                 ob= (Object *)idar[a];
799                 if (event==0 || event==2) ob->scaflag |= OB_SHOWCONT;
800                 else if (event==1) ob->scaflag &= ~OB_SHOWCONT;
801         }
802
803         for (a=0; a<count; a++) {
804                 ob= (Object *)idar[a];
805                 cont= ob->controllers.first;
806                 while (cont) {
807                         if (event==2) cont->flag |= CONT_SHOW;
808                         else if (event==3) cont->flag &= ~CONT_SHOW;
809                         cont= cont->next;
810                 }
811         }
812
813         if (idar) MEM_freeN(idar);
814 }
815
816 static uiBlock *controller_menu(bContext *C, ARegion *ar, void *UNUSED(arg))
817 {
818         uiBlock *block;
819         int yco=0;
820         
821         block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP);
822         uiBlockSetButmFunc(block, do_controller_menu, NULL);
823         
824         uiDefBut(block, BUTM, 1, IFACE_("Show Objects"),        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
825         uiDefBut(block, BUTM, 1, IFACE_("Hide Objects"),        0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
826         uiDefBut(block, SEPR, 0, "",                                    0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
827         uiDefBut(block, BUTM, 1, IFACE_("Show Controllers"),    0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 2, 2, "");
828         uiDefBut(block, BUTM, 1, IFACE_("Hide Controllers"),    0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 3, 3, "");
829
830         uiBlockSetDirection(block, UI_TOP);
831         uiEndBlock(C, block);
832         
833         return block;
834 }
835
836 static void do_actuator_menu(bContext *C, void *UNUSED(arg), int event)
837 {       
838         SpaceLogic *slogic= CTX_wm_space_logic(C);
839         ID **idar;
840         Object *ob;
841         bActuator *act;
842         short count, a;
843         
844         idar= get_selected_and_linked_obs(C, &count, slogic->scaflag);
845         
846         for (a=0; a<count; a++) {
847                 ob= (Object *)idar[a];
848                 if (event==0 || event==2) ob->scaflag |= OB_SHOWACT;
849                 else if (event==1) ob->scaflag &= ~OB_SHOWACT;
850         }
851
852         for (a=0; a<count; a++) {
853                 ob= (Object *)idar[a];
854                 act= ob->actuators.first;
855                 while (act) {
856                         if (event==2) act->flag |= ACT_SHOW;
857                         else if (event==3) act->flag &= ~ACT_SHOW;
858                         act= act->next;
859                 }
860         }
861
862         if (idar) MEM_freeN(idar);
863 }
864
865 static uiBlock *actuator_menu(bContext *C, ARegion *ar, void *UNUSED(arg))
866 {
867         uiBlock *block;
868         int xco=0;
869         
870         block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP);
871         uiBlockSetButmFunc(block, do_actuator_menu, NULL);
872         
873         uiDefBut(block, BUTM, 1, IFACE_("Show Objects"),        0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
874         uiDefBut(block, BUTM, 1, IFACE_("Hide Objects"),        0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
875         uiDefBut(block, SEPR, 0, "",    0, (short)(xco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
876         uiDefBut(block, BUTM, 1, IFACE_("Show Actuators"),      0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
877         uiDefBut(block, BUTM, 1, IFACE_("Hide Actuators"),      0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
878
879         uiBlockSetDirection(block, UI_TOP);
880         uiEndBlock(C, block);
881         
882         return block;
883 }
884
885 static void check_controller_state_mask(bContext *UNUSED(C), void *arg1_but, void *arg2_mask)
886 {
887         unsigned int *cont_mask = arg2_mask;
888         uiBut *but = arg1_but;
889         
890         /* a controller is always in a single state */
891         *cont_mask = (1<<but->retval);
892         but->retval = B_REDR;
893 }
894
895 static uiBlock *controller_state_mask_menu(bContext *C, ARegion *ar, void *arg_cont)
896 {
897         uiBlock *block;
898         uiBut *but;
899         bController *cont = arg_cont;
900
901         short yco = 12, xco = 0, stbit, offset;
902
903         block= uiBeginBlock(C, ar, __func__, UI_EMBOSS);
904
905         /* use this for a fake extra empy space around the buttons */
906         uiDefBut(block, LABEL, 0, "",                   -5, -5, 200, 34, NULL, 0, 0, 0, 0, "");
907         
908         for (offset=0; offset<15; offset += 5) {
909                 uiBlockBeginAlign(block);
910                 for (stbit=0; stbit<5; stbit++) {
911                         but = uiDefButBitI(block, TOG, (1<<(stbit+offset)), (stbit+offset), "", (short)(xco+12*stbit+13*offset), yco, 12, 12, (int *)&(cont->state_mask), 0, 0, 0, 0, "");
912                         uiButSetFunc(but, check_controller_state_mask, but, &(cont->state_mask));
913                 }
914                 for (stbit=0; stbit<5; stbit++) {
915                         but = uiDefButBitI(block, TOG, (1<<(stbit+offset+15)), (stbit+offset+15), "",   (short)(xco+12*stbit+13*offset), yco-12, 12, 12, (int *)&(cont->state_mask), 0, 0, 0, 0, "");
916                         uiButSetFunc(but, check_controller_state_mask, but, &(cont->state_mask));
917                 }
918         }
919         uiBlockEndAlign(block);
920
921         uiBlockSetDirection(block, UI_TOP);
922         uiEndBlock(C, block);
923
924         return block;
925 }
926
927 static int is_sensor_linked(uiBlock *block, bSensor *sens)
928 {
929         bController *cont;
930         int i;
931
932         for (i=0; i<sens->totlinks; i++) {
933                 cont = sens->links[i];
934                 if (uiFindInlink(block, cont) != NULL)
935                         return 1;
936         }
937         return 0;
938 }
939
940 /* Sensors code */
941
942 static void draw_sensor_header(uiLayout *layout, PointerRNA *ptr, PointerRNA *logic_ptr)
943 {
944         uiLayout *box, *row, *sub;
945         bSensor *sens= (bSensor *)ptr->data;
946         
947         box = uiLayoutBox(layout);
948         row = uiLayoutRow(box, FALSE);
949         
950         uiItemR(row, ptr, "show_expanded", UI_ITEM_R_NO_BG, "", ICON_NONE);
951         if (RNA_boolean_get(ptr, "show_expanded")) {
952                 uiItemR(row, ptr, "type", 0, "", ICON_NONE);
953                 uiItemR(row, ptr, "name", 0, "", ICON_NONE);
954         }
955         else {
956                 uiItemL(row, sensor_name(sens->type), ICON_NONE);
957                 uiItemL(row, sens->name, ICON_NONE);
958         }
959
960         sub = uiLayoutRow(row, FALSE);
961         uiLayoutSetActive(sub, ((RNA_boolean_get(logic_ptr, "show_sensors_active_states") &&
962                                  RNA_boolean_get(ptr, "show_expanded")) || RNA_boolean_get(ptr, "pin")));
963         uiItemR(sub, ptr, "pin", UI_ITEM_R_NO_BG, "", ICON_NONE);
964
965         if (RNA_boolean_get(ptr, "show_expanded")==0) {
966                 sub = uiLayoutRow(row, TRUE);
967                 uiItemEnumO(sub, "LOGIC_OT_sensor_move", "", ICON_TRIA_UP, "direction", 1); // up
968                 uiItemEnumO(sub, "LOGIC_OT_sensor_move", "", ICON_TRIA_DOWN, "direction", 2); // down
969         }
970
971         uiItemO(row, "", ICON_X, "LOGIC_OT_sensor_remove");
972 }
973
974 static void draw_sensor_internal_header(uiLayout *layout, PointerRNA *ptr)
975 {
976         uiLayout *box, *split, *sub, *row;
977
978         box = uiLayoutBox(layout);
979         split = uiLayoutSplit(box, 0.45f, FALSE);
980         
981         row = uiLayoutRow(split, TRUE);
982         uiItemR(row, ptr, "use_pulse_true_level", 0, "", ICON_DOTSUP);
983         uiItemR(row, ptr, "use_pulse_false_level", 0, "", ICON_DOTSDOWN);
984
985         sub = uiLayoutRow(row, FALSE);
986         uiLayoutSetActive(sub, (RNA_boolean_get(ptr, "use_pulse_true_level") ||
987                                 RNA_boolean_get(ptr, "use_pulse_false_level")));
988         uiItemR(sub, ptr, "frequency", 0, IFACE_("Freq"), ICON_NONE);
989         
990         row = uiLayoutRow(split, TRUE);
991         uiItemR(row, ptr, "use_level", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
992         uiItemR(row, ptr, "use_tap", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
993         
994         uiItemR(split, ptr, "invert", UI_ITEM_R_TOGGLE, IFACE_("Invert"), ICON_NONE);
995 }
996 /* sensors in alphabetical order */
997
998 static void draw_sensor_actuator(uiLayout *layout, PointerRNA *ptr)
999 {
1000         Object *ob = (Object *)ptr->id.data;
1001         PointerRNA settings_ptr;
1002
1003         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
1004         uiItemPointerR(layout, ptr, "actuator", &settings_ptr, "actuators", NULL, ICON_LOGIC);
1005 }
1006
1007 static void draw_sensor_armature(uiLayout *layout, PointerRNA *ptr)
1008 {
1009         bSensor *sens = (bSensor*)ptr->data;
1010         bArmatureSensor *as = (bArmatureSensor *) sens->data;
1011         Object *ob = (Object *)ptr->id.data;
1012         PointerRNA pose_ptr, pchan_ptr;
1013         PropertyRNA *bones_prop= NULL;
1014         uiLayout *row;
1015
1016         if (ob->type != OB_ARMATURE) {
1017                 uiItemL(layout, IFACE_("Sensor only available for armatures"), ICON_NONE);
1018                 return;
1019         }
1020
1021         if (ob->pose) {
1022                 RNA_pointer_create((ID *)ob, &RNA_Pose, ob->pose, &pose_ptr);
1023                 bones_prop = RNA_struct_find_property(&pose_ptr, "bones");
1024         }
1025
1026         if (&pose_ptr.data) {
1027                 uiItemPointerR(layout, ptr, "bone", &pose_ptr, "bones", NULL, ICON_BONE_DATA);
1028
1029                 if (RNA_property_collection_lookup_string(&pose_ptr, bones_prop, as->posechannel, &pchan_ptr))
1030                         uiItemPointerR(layout, ptr, "constraint", &pchan_ptr, "constraints", NULL, ICON_CONSTRAINT_BONE);
1031         }
1032         row = uiLayoutRow(layout, TRUE);
1033         uiItemR(row, ptr, "test_type", 0, NULL, ICON_NONE);
1034         if (RNA_enum_get(ptr, "test_type") != SENS_ARM_STATE_CHANGED)
1035                 uiItemR(row, ptr, "value", 0, NULL, ICON_NONE);
1036 }
1037
1038 static void draw_sensor_collision(uiLayout *layout, PointerRNA *ptr, bContext *C)
1039 {
1040         uiLayout *row, *split;
1041         PointerRNA main_ptr;
1042
1043         RNA_main_pointer_create(CTX_data_main(C), &main_ptr);
1044
1045         split = uiLayoutSplit(layout, 0.3f, FALSE);
1046         row = uiLayoutRow(split, TRUE);
1047         uiItemR(row, ptr, "use_pulse", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1048         uiItemR(row, ptr, "use_material", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1049
1050         switch (RNA_boolean_get(ptr, "use_material")) {
1051                 case SENS_COLLISION_PROPERTY:
1052                         uiItemR(split, ptr, "property", 0, NULL, ICON_NONE);
1053                         break;
1054                 case SENS_COLLISION_MATERIAL:
1055                         uiItemPointerR(split, ptr, "material", &main_ptr, "materials", NULL, ICON_MATERIAL_DATA);
1056                         break;
1057         }
1058 }
1059
1060 static void draw_sensor_delay(uiLayout *layout, PointerRNA *ptr)
1061 {
1062         uiLayout *row;
1063         
1064         row = uiLayoutRow(layout, FALSE);
1065
1066         uiItemR(row, ptr, "delay", 0, NULL, ICON_NONE);
1067         uiItemR(row, ptr, "duration", 0, NULL, ICON_NONE);
1068         uiItemR(row, ptr, "use_repeat", 0, NULL, ICON_NONE);
1069 }
1070
1071 static void draw_sensor_joystick(uiLayout *layout, PointerRNA *ptr)
1072 {
1073         uiLayout *col, *row;
1074
1075         uiItemR(layout, ptr, "joystick_index", 0, NULL, ICON_NONE);
1076         uiItemR(layout, ptr, "event_type", 0, NULL, ICON_NONE);
1077
1078         switch (RNA_enum_get(ptr, "event_type")) {
1079                 case SENS_JOY_BUTTON:
1080                         uiItemR(layout, ptr, "use_all_events", 0, NULL, ICON_NONE);
1081
1082                         col = uiLayoutColumn(layout, FALSE);
1083                         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_all_events") == FALSE);
1084                         uiItemR(col, ptr, "button_number", 0, NULL, ICON_NONE);
1085                         break;
1086                 case SENS_JOY_AXIS:
1087                         row = uiLayoutRow(layout, FALSE);
1088                         uiItemR(row, ptr, "axis_number", 0, NULL, ICON_NONE);
1089                         uiItemR(row, ptr, "axis_threshold", 0, NULL, ICON_NONE);
1090
1091                         uiItemR(layout, ptr, "use_all_events", 0, NULL, ICON_NONE);
1092                         col = uiLayoutColumn(layout, FALSE);
1093                         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_all_events") == FALSE);
1094                         uiItemR(col, ptr, "axis_direction", 0, NULL, ICON_NONE);
1095                         break;
1096                 case SENS_JOY_HAT:
1097                         uiItemR(layout, ptr, "hat_number", 0, NULL, ICON_NONE);
1098                         uiItemR(layout, ptr, "use_all_events", 0, NULL, ICON_NONE);
1099
1100                         col = uiLayoutColumn(layout, FALSE);
1101                         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_all_events") == FALSE);
1102                         uiItemR(col, ptr, "hat_direction", 0, NULL, ICON_NONE);
1103                         break;
1104                 case SENS_JOY_AXIS_SINGLE:
1105                         row = uiLayoutRow(layout, FALSE);
1106                         uiItemR(row, ptr, "single_axis_number", 0, NULL, ICON_NONE);
1107                         uiItemR(row, ptr, "axis_threshold", 0, NULL, ICON_NONE);
1108                         break;
1109         }
1110 }
1111
1112 static void draw_sensor_keyboard(uiLayout *layout, PointerRNA *ptr)
1113 {
1114         Object *ob = (Object *)ptr->id.data;
1115         PointerRNA settings_ptr;
1116         uiLayout *row, *col;
1117
1118         row = uiLayoutRow(layout, FALSE);
1119         uiItemL(row, IFACE_("Key:"), ICON_NONE);
1120         col = uiLayoutColumn(row, FALSE);
1121         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_all_keys") == FALSE);
1122         uiItemR(col, ptr, "key", UI_ITEM_R_EVENT, "", ICON_NONE);
1123         col = uiLayoutColumn(row, FALSE);
1124         uiItemR(col, ptr, "use_all_keys", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1125         
1126         col = uiLayoutColumn(layout, FALSE);
1127         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_all_keys") == FALSE);
1128         row = uiLayoutRow(col, FALSE);
1129         uiItemL(row, IFACE_("First Modifier:"), ICON_NONE);
1130         uiItemR(row, ptr, "modifier_key_1", UI_ITEM_R_EVENT, "", ICON_NONE);
1131         
1132         row = uiLayoutRow(col, FALSE);
1133         uiItemL(row, IFACE_("Second Modifier:"), ICON_NONE);
1134         uiItemR(row, ptr, "modifier_key_2", UI_ITEM_R_EVENT, "", ICON_NONE);
1135
1136         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
1137         uiItemPointerR(layout, ptr, "log", &settings_ptr, "properties", NULL, ICON_NONE);
1138         uiItemPointerR(layout, ptr, "target", &settings_ptr, "properties", NULL, ICON_NONE);
1139 }
1140
1141 static void draw_sensor_message(uiLayout *layout, PointerRNA *ptr)
1142 {
1143         uiItemR(layout, ptr, "subject", 0, NULL, ICON_NONE);
1144 }
1145
1146 static void draw_sensor_mouse(uiLayout *layout, PointerRNA *ptr)
1147 {
1148         uiLayout *split;
1149
1150         split = uiLayoutSplit(layout, 0.8f, FALSE);
1151         uiItemR(split, ptr, "mouse_event", 0, NULL, ICON_NONE);
1152
1153         if (RNA_enum_get(ptr, "mouse_event") == BL_SENS_MOUSE_MOUSEOVER_ANY)
1154                 uiItemR(split, ptr, "use_pulse", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1155 }
1156
1157 static void draw_sensor_near(uiLayout *layout, PointerRNA *ptr)
1158 {
1159         uiLayout *row;
1160
1161         uiItemR(layout, ptr, "property", 0, NULL, ICON_NONE);
1162
1163         row = uiLayoutRow(layout, TRUE);
1164         uiItemR(row, ptr, "distance", 0, NULL, ICON_NONE);
1165         uiItemR(row, ptr, "reset_distance", 0, NULL, ICON_NONE);
1166 }
1167
1168 static void draw_sensor_property(uiLayout *layout, PointerRNA *ptr)
1169 {
1170         Object *ob = (Object *)ptr->id.data;
1171         PointerRNA settings_ptr;
1172
1173         uiLayout *row;
1174         uiItemR(layout, ptr, "evaluation_type", 0, NULL, ICON_NONE);
1175
1176         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
1177         uiItemPointerR(layout, ptr, "property", &settings_ptr, "properties", NULL, ICON_NONE);
1178
1179         switch (RNA_enum_get(ptr, "evaluation_type")) {
1180                 case SENS_PROP_INTERVAL:
1181                         row = uiLayoutRow(layout, FALSE);
1182                         uiItemR(row, ptr, "value_min", 0, NULL, ICON_NONE);
1183                         uiItemR(row, ptr, "value_max", 0, NULL, ICON_NONE);
1184                         break;
1185                 case SENS_PROP_EQUAL:
1186                         uiItemR(layout, ptr, "value", 0, NULL, ICON_NONE);
1187                         break;
1188                 case SENS_PROP_NEQUAL:
1189                         uiItemR(layout, ptr, "value", 0, NULL, ICON_NONE);
1190                         break;
1191                 case SENS_PROP_CHANGED:
1192                         break;
1193         }
1194 }
1195
1196 static void draw_sensor_radar(uiLayout *layout, PointerRNA *ptr)
1197 {
1198         uiLayout *row;
1199
1200         uiItemR(layout, ptr, "property", 0, NULL, ICON_NONE);
1201         uiItemR(layout, ptr, "axis", 0, NULL, ICON_NONE);
1202
1203         row = uiLayoutRow(layout, FALSE);
1204         uiItemR(row, ptr, "angle", 0, NULL, ICON_NONE);
1205         uiItemR(row, ptr, "distance", 0, NULL, ICON_NONE);
1206 }
1207
1208 static void draw_sensor_random(uiLayout *layout, PointerRNA *ptr)
1209 {
1210         uiItemR(layout, ptr, "seed", 0, NULL, ICON_NONE);
1211 }
1212
1213 static void draw_sensor_ray(uiLayout *layout, PointerRNA *ptr, bContext *C)
1214 {
1215         uiLayout *split, *row;
1216         PointerRNA main_ptr;
1217
1218         RNA_main_pointer_create(CTX_data_main(C), &main_ptr);
1219         split = uiLayoutSplit(layout, 0.3f, FALSE);
1220         uiItemR(split, ptr, "ray_type", 0, "", ICON_NONE);
1221         switch (RNA_enum_get(ptr, "ray_type")) {
1222                 case SENS_RAY_PROPERTY:
1223                         uiItemR(split, ptr, "property", 0, "", ICON_NONE);
1224                         break;
1225                 case SENS_RAY_MATERIAL:
1226                         uiItemPointerR(split, ptr, "material", &main_ptr, "materials", "", ICON_MATERIAL_DATA);
1227                         break;
1228         }
1229
1230         split = uiLayoutSplit(layout, 0.3, FALSE);
1231         uiItemR(split, ptr, "axis", 0, "", ICON_NONE);
1232         row = uiLayoutRow(split, FALSE);
1233         uiItemR(row, ptr, "range", 0, NULL, ICON_NONE);
1234         uiItemR(row, ptr, "use_x_ray", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1235 }
1236
1237 static void draw_sensor_touch(uiLayout *layout, PointerRNA *ptr)
1238 {
1239         uiItemR(layout, ptr, "material", 0, NULL, ICON_NONE);
1240 }
1241
1242 static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C)
1243 {
1244         uiLayout *box;
1245         
1246         if (!RNA_boolean_get(ptr, "show_expanded"))
1247                 return;
1248
1249         draw_sensor_internal_header(layout, ptr);
1250         
1251         box = uiLayoutBox(layout);
1252
1253         switch (RNA_enum_get(ptr, "type")) {
1254
1255                 case SENS_ACTUATOR:
1256                         draw_sensor_actuator(box, ptr);
1257                         break;
1258                 case SENS_ALWAYS:
1259                         break;
1260                 case SENS_ARMATURE:
1261                         draw_sensor_armature(box, ptr);
1262                         break;
1263                 case SENS_COLLISION:
1264                         draw_sensor_collision(box, ptr, C);
1265                         break;
1266                 case SENS_DELAY:
1267                         draw_sensor_delay(box, ptr);
1268                         break;
1269                 case SENS_JOYSTICK:
1270                         draw_sensor_joystick(box, ptr);
1271                         break;
1272                 case SENS_KEYBOARD:
1273                         draw_sensor_keyboard(box, ptr);
1274                         break;
1275                 case SENS_MESSAGE:
1276                         draw_sensor_message(box, ptr);
1277                         break;
1278                 case SENS_MOUSE:
1279                         draw_sensor_mouse(box, ptr);
1280                         break;
1281                 case SENS_NEAR:
1282                         draw_sensor_near(box, ptr);
1283                         break;
1284                 case SENS_PROPERTY:
1285                         draw_sensor_property(box, ptr);
1286                         break;
1287                 case SENS_RADAR:
1288                         draw_sensor_radar(box, ptr);
1289                         break;
1290                 case SENS_RANDOM:
1291                         draw_sensor_random(box, ptr);
1292                         break;
1293                 case SENS_RAY:
1294                         draw_sensor_ray(box, ptr, C);
1295                         break;
1296                 case SENS_TOUCH:
1297                         draw_sensor_touch(box, ptr);
1298                         break;
1299         }
1300 }
1301
1302 /* Controller code */
1303 static void draw_controller_header(uiLayout *layout, PointerRNA *ptr, int xco, int width, int yco)
1304 {
1305         uiLayout *box, *row, *sub;
1306         bController *cont= (bController *)ptr->data;
1307
1308         char state[3];
1309         BLI_snprintf(state, sizeof(state), "%d", RNA_int_get(ptr, "states"));
1310         
1311         box = uiLayoutBox(layout);
1312         row = uiLayoutRow(box, FALSE);
1313         
1314         uiItemR(row, ptr, "show_expanded", UI_ITEM_R_NO_BG, "", ICON_NONE);
1315         if (RNA_boolean_get(ptr, "show_expanded")) {
1316                 uiItemR(row, ptr, "type", 0, "", ICON_NONE);
1317                 uiItemR(row, ptr, "name", 0, "", ICON_NONE);
1318                 /* XXX provisory for Blender 2.50Beta */
1319                 uiDefBlockBut(uiLayoutGetBlock(layout), controller_state_mask_menu, cont, state, (short)(xco+width-44), yco, 22+22, UI_UNIT_Y, IFACE_("Set controller state index (from 1 to 30)"));
1320         }
1321         else {
1322                 uiItemL(row, controller_name(cont->type), ICON_NONE);
1323                 uiItemL(row, cont->name, ICON_NONE);
1324                 uiItemL(row, state, ICON_NONE);
1325         }
1326
1327         uiItemR(row, ptr, "use_priority", 0, "", ICON_NONE);
1328
1329         if (RNA_boolean_get(ptr, "show_expanded")==0) {
1330                 sub = uiLayoutRow(row, TRUE);
1331                 uiItemEnumO(sub, "LOGIC_OT_controller_move", "", ICON_TRIA_UP, "direction", 1); // up
1332                 uiItemEnumO(sub, "LOGIC_OT_controller_move", "", ICON_TRIA_DOWN, "direction", 2); // down
1333         }
1334         uiItemO(row, "", ICON_X, "LOGIC_OT_controller_remove");
1335 }
1336
1337 static void draw_controller_expression(uiLayout *layout, PointerRNA *ptr)
1338 {
1339         uiItemR(layout, ptr, "expression", 0, "", ICON_NONE);
1340 }
1341
1342 static void draw_controller_python(uiLayout *layout, PointerRNA *ptr)
1343 {
1344         uiLayout *split, *sub;
1345
1346         split = uiLayoutSplit(layout, 0.3, TRUE);
1347         uiItemR(split, ptr, "mode", 0, "", ICON_NONE);
1348         if (RNA_enum_get(ptr, "mode") == CONT_PY_SCRIPT) {
1349                 uiItemR(split, ptr, "text", 0, "", ICON_NONE);
1350         }
1351         else {
1352                 sub = uiLayoutSplit(split, 0.8f, FALSE);
1353                 uiItemR(sub, ptr, "module", 0, "", ICON_NONE);
1354                 uiItemR(sub, ptr, "use_debug", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1355         }
1356 }
1357
1358 static void draw_controller_state(uiLayout *UNUSED(layout), PointerRNA *UNUSED(ptr))
1359 {
1360
1361 }
1362
1363 static void draw_brick_controller(uiLayout *layout, PointerRNA *ptr)
1364 {
1365         uiLayout *box;
1366         
1367         if (!RNA_boolean_get(ptr, "show_expanded"))
1368                 return;
1369         
1370         box = uiLayoutBox(layout);
1371
1372         draw_controller_state(box, ptr);
1373         
1374         switch (RNA_enum_get(ptr, "type")) {
1375                 case CONT_LOGIC_AND:
1376                         break;
1377                 case CONT_LOGIC_OR:
1378                         break;
1379                 case CONT_EXPRESSION:
1380                         draw_controller_expression(box, ptr);
1381                         break;
1382                 case CONT_PYTHON:
1383                         draw_controller_python(box, ptr);
1384                         break;
1385                 case CONT_LOGIC_NAND:
1386                         break;
1387                 case CONT_LOGIC_NOR:
1388                         break;
1389                 case CONT_LOGIC_XOR:
1390                         break;
1391                 case CONT_LOGIC_XNOR:
1392                         break;
1393         }
1394 }
1395
1396 /* Actuator code */
1397 static void draw_actuator_header(uiLayout *layout, PointerRNA *ptr, PointerRNA *logic_ptr)
1398 {
1399         uiLayout *box, *row, *sub;
1400         bActuator *act= (bActuator *)ptr->data;
1401         
1402         box = uiLayoutBox(layout);
1403         row = uiLayoutRow(box, FALSE);
1404         
1405         uiItemR(row, ptr, "show_expanded", UI_ITEM_R_NO_BG, "", ICON_NONE);
1406         if (RNA_boolean_get(ptr, "show_expanded")) {
1407                 uiItemR(row, ptr, "type", 0, "", ICON_NONE);
1408                 uiItemR(row, ptr, "name", 0, "", ICON_NONE);
1409         }
1410         else {
1411                 uiItemL(row, actuator_name(act->type), ICON_NONE);
1412                 uiItemL(row, act->name, ICON_NONE);
1413         }
1414
1415         sub = uiLayoutRow(row, FALSE);
1416         uiLayoutSetActive(sub, ((RNA_boolean_get(logic_ptr, "show_actuators_active_states") &&
1417                                  RNA_boolean_get(ptr, "show_expanded")) || RNA_boolean_get(ptr, "pin")));
1418         uiItemR(sub, ptr, "pin", UI_ITEM_R_NO_BG, "", ICON_NONE);
1419
1420         if (RNA_boolean_get(ptr, "show_expanded")==0) {
1421                 sub = uiLayoutRow(row, TRUE);
1422                 uiItemEnumO(sub, "LOGIC_OT_actuator_move", "", ICON_TRIA_UP, "direction", 1); // up
1423                 uiItemEnumO(sub, "LOGIC_OT_actuator_move", "", ICON_TRIA_DOWN, "direction", 2); // down
1424         }
1425         uiItemO(row, "", ICON_X, "LOGIC_OT_actuator_remove");
1426 }
1427
1428 static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
1429 {
1430         Object *ob = (Object *)ptr->id.data;
1431         PointerRNA settings_ptr;
1432         uiLayout *row, *sub;
1433
1434         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
1435
1436         row = uiLayoutRow(layout, FALSE);
1437         uiItemR(row, ptr, "play_mode", 0, "", ICON_NONE);
1438
1439         sub = uiLayoutRow(row, TRUE);
1440         uiItemR(sub, ptr, "use_force", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1441         uiItemR(sub, ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1442
1443         row = uiLayoutColumn(sub, FALSE);
1444         uiLayoutSetActive(row, (RNA_boolean_get(ptr, "use_additive") || RNA_boolean_get(ptr, "use_force")));
1445         uiItemR(row, ptr, "use_local", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1446
1447         row = uiLayoutRow(layout, FALSE);
1448         uiItemR(row, ptr, "action", 0, "", ICON_NONE);
1449         uiItemR(row, ptr, "use_continue_last_frame", 0, NULL, ICON_NONE);
1450
1451         row = uiLayoutRow(layout, FALSE);
1452         if ((RNA_enum_get(ptr, "play_mode") == ACT_ACTION_FROM_PROP))
1453                 uiItemPointerR(row, ptr, "property", &settings_ptr, "properties", NULL, ICON_NONE);
1454
1455         else {
1456                 uiItemR(row, ptr, "frame_start", 0, NULL, ICON_NONE);
1457                 uiItemR(row, ptr, "frame_end", 0, NULL, ICON_NONE);
1458         }
1459
1460         uiItemR(row, ptr, "apply_to_children", 0, NULL, ICON_NONE);
1461
1462         row = uiLayoutRow(layout, FALSE);
1463         uiItemR(row, ptr, "frame_blend_in", 0, NULL, ICON_NONE);
1464         uiItemR(row, ptr, "priority", 0, NULL, ICON_NONE);
1465
1466         row = uiLayoutRow(layout, FALSE);
1467         uiItemR(row, ptr, "layer", 0, NULL, ICON_NONE);
1468         uiItemR(row, ptr, "layer_weight", 0, NULL, ICON_NONE);
1469
1470         uiItemPointerR(layout, ptr, "frame_property", &settings_ptr, "properties", NULL, ICON_NONE);
1471
1472 #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
1473         uiItemR(layout, "stride_length", 0, NULL, ICON_NONE);
1474 #endif
1475 }
1476
1477 static void draw_actuator_armature(uiLayout *layout, PointerRNA *ptr)
1478 {
1479         bActuator *act = (bActuator*)ptr->data;
1480         bArmatureActuator *aa = (bArmatureActuator *) act->data;
1481         Object *ob = (Object *)ptr->id.data;
1482         bConstraint *constraint = NULL;
1483         PointerRNA pose_ptr, pchan_ptr;
1484         PropertyRNA *bones_prop = NULL;
1485
1486         if (ob->type != OB_ARMATURE) {
1487                 uiItemL(layout, IFACE_("Actuator only available for armatures"), ICON_NONE);
1488                 return;
1489         }
1490         
1491         if (ob->pose) {
1492                 RNA_pointer_create((ID *)ob, &RNA_Pose, ob->pose, &pose_ptr);
1493                 bones_prop = RNA_struct_find_property(&pose_ptr, "bones");
1494         }
1495         
1496         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1497         
1498         switch (RNA_enum_get(ptr, "mode")) {
1499                 case ACT_ARM_RUN:
1500                         break;
1501                 case ACT_ARM_ENABLE:
1502                 case ACT_ARM_DISABLE:
1503                         if (ob->pose) {
1504                                 uiItemPointerR(layout, ptr, "bone", &pose_ptr, "bones", NULL, ICON_BONE_DATA);
1505
1506                                 if (RNA_property_collection_lookup_string(&pose_ptr, bones_prop, aa->posechannel, &pchan_ptr))
1507                                         uiItemPointerR(layout, ptr, "constraint", &pchan_ptr, "constraints", NULL, ICON_CONSTRAINT_BONE);
1508                         }
1509                         break;
1510                 case ACT_ARM_SETTARGET:
1511                         if (ob->pose) {
1512                                 uiItemPointerR(layout, ptr, "bone", &pose_ptr, "bones", NULL, ICON_BONE_DATA);
1513                                 
1514                                 if (RNA_property_collection_lookup_string(&pose_ptr, bones_prop, aa->posechannel, &pchan_ptr))
1515                                         uiItemPointerR(layout, ptr, "constraint", &pchan_ptr, "constraints", NULL, ICON_CONSTRAINT_BONE);
1516                         }
1517
1518                         uiItemR(layout, ptr, "target", 0, NULL, ICON_NONE);
1519
1520                         /* show second target only if the constraint supports it */
1521                         get_armature_bone_constraint(ob, aa->posechannel, aa->constraint, &constraint);
1522                         if (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) {
1523                                 uiItemR(layout, ptr, "secondary_target", 0, NULL, ICON_NONE);
1524                         }
1525                         break;
1526                 case ACT_ARM_SETWEIGHT:
1527                         if (ob->pose) {
1528                                 uiItemPointerR(layout, ptr, "bone", &pose_ptr, "bones", NULL, ICON_BONE_DATA);
1529                                 
1530                                 if (RNA_property_collection_lookup_string(&pose_ptr, bones_prop, aa->posechannel, &pchan_ptr))
1531                                         uiItemPointerR(layout, ptr, "constraint", &pchan_ptr, "constraints", NULL, ICON_CONSTRAINT_BONE);
1532                         }
1533
1534                         uiItemR(layout, ptr, "weight", 0, NULL, ICON_NONE);
1535                         break;
1536                 case ACT_ARM_SETINFLUENCE:
1537                         if (ob->pose) {
1538                                 uiItemPointerR(layout, ptr, "bone", &pose_ptr, "bones", NULL, ICON_BONE_DATA);
1539                                 
1540                                 if (RNA_property_collection_lookup_string(&pose_ptr, bones_prop, aa->posechannel, &pchan_ptr))
1541                                         uiItemPointerR(layout, ptr, "constraint", &pchan_ptr, "constraints", NULL, ICON_CONSTRAINT_BONE);
1542                         }
1543
1544                         uiItemR(layout, ptr, "influence", 0, NULL, ICON_NONE);
1545                         break;
1546         }
1547 }
1548
1549 static void draw_actuator_camera(uiLayout *layout, PointerRNA *ptr)
1550 {
1551         uiLayout *row;
1552         uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
1553
1554         row = uiLayoutRow(layout, FALSE);
1555         uiItemR(row, ptr, "height", 0, NULL, ICON_NONE);
1556         uiItemR(row, ptr, "axis", 0, NULL, ICON_NONE);
1557
1558         row = uiLayoutRow(layout, TRUE);
1559         uiItemR(row, ptr, "min", 0, NULL, ICON_NONE);
1560         uiItemR(row, ptr, "max", 0, NULL, ICON_NONE);
1561
1562         uiItemR(layout, ptr, "damping", 0, NULL, ICON_NONE);
1563 }
1564
1565 static void draw_actuator_constraint(uiLayout *layout, PointerRNA *ptr, bContext *C)
1566 {
1567         uiLayout *row, *col, *sub, *split;
1568         PointerRNA main_ptr;
1569
1570         RNA_main_pointer_create(CTX_data_main(C), &main_ptr);
1571
1572         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1573         switch (RNA_enum_get(ptr, "mode")) {
1574                 case ACT_CONST_TYPE_LOC:
1575                         uiItemR(layout, ptr, "limit", 0, NULL, ICON_NONE);
1576
1577                         row = uiLayoutRow(layout, TRUE);
1578                         uiItemR(row, ptr, "limit_min", 0, NULL, ICON_NONE);
1579                         uiItemR(row, ptr, "limit_max", 0, NULL, ICON_NONE);
1580
1581                         uiItemR(layout, ptr, "damping", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1582                         break;
1583
1584                 case ACT_CONST_TYPE_DIST:
1585                         split = uiLayoutSplit(layout, 0.8, FALSE);
1586                         uiItemR(split, ptr, "direction", 0, NULL, ICON_NONE);
1587                         row = uiLayoutRow(split, TRUE);
1588                         uiItemR(row, ptr, "use_local", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1589                         uiItemR(row, ptr, "use_normal", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1590
1591                         row = uiLayoutRow(layout, FALSE);
1592                         col = uiLayoutColumn(row, TRUE);
1593                         uiItemL(col, IFACE_("Range:"), ICON_NONE);
1594                         uiItemR(col, ptr, "range", 0, "", ICON_NONE);
1595
1596                         col = uiLayoutColumn(row, TRUE);
1597                         uiItemR(col, ptr, "use_force_distance", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1598                         sub = uiLayoutColumn(col, FALSE);
1599                         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_force_distance") == TRUE);
1600                         uiItemR(sub, ptr, "distance", 0, "", ICON_NONE);
1601
1602                         uiItemR(layout, ptr, "damping", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1603
1604                         split = uiLayoutSplit(layout, 0.15f, FALSE);
1605                         uiItemR(split, ptr, "use_material_detect", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1606                         if (RNA_boolean_get(ptr, "use_material_detect"))
1607                                 uiItemPointerR(split, ptr, "material", &main_ptr, "materials", NULL, ICON_MATERIAL_DATA);
1608                         else
1609                                 uiItemR(split, ptr, "property", 0, NULL, ICON_NONE);
1610
1611                         split = uiLayoutSplit(layout, 0.15, FALSE);
1612                         uiItemR(split, ptr, "use_persistent", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1613
1614                         row = uiLayoutRow(split, TRUE);
1615                         uiItemR(row, ptr, "time", 0, NULL, ICON_NONE);
1616                         uiItemR(row, ptr, "damping_rotation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1617                         break;
1618
1619                 case ACT_CONST_TYPE_ORI:
1620                         uiItemR(layout, ptr, "direction_axis_pos", 0, NULL, ICON_NONE);
1621
1622                         row=uiLayoutRow(layout, TRUE);
1623                         uiItemR(row, ptr, "damping", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1624                         uiItemR(row, ptr, "time", 0, NULL, ICON_NONE);
1625
1626                         row=uiLayoutRow(layout, FALSE);
1627                         uiItemR(row, ptr, "rotation_max", 0, NULL, ICON_NONE);
1628
1629                         row=uiLayoutRow(layout, TRUE);
1630                         uiItemR(row, ptr, "angle_min", 0, NULL, ICON_NONE);
1631                         uiItemR(row, ptr, "angle_max", 0, NULL, ICON_NONE);
1632                         break;
1633
1634                 case ACT_CONST_TYPE_FH:
1635                         split = uiLayoutSplit(layout, 0.75, FALSE);
1636                         row = uiLayoutRow(split, FALSE);
1637                         uiItemR(row, ptr, "fh_damping", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1638
1639                         uiItemR(row, ptr, "fh_height", 0, NULL, ICON_NONE);
1640                         uiItemR(split, ptr, "use_fh_paralel_axis", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1641
1642                         row = uiLayoutRow(layout, FALSE);
1643                         uiItemR(row, ptr, "direction_axis", 0, NULL, ICON_NONE);
1644                         split = uiLayoutSplit(row, 0.9f, FALSE);
1645                         uiItemR(split, ptr, "fh_force", 0, NULL, ICON_NONE);
1646                         uiItemR(split, ptr, "use_fh_normal", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1647
1648                         split = uiLayoutSplit(layout, 0.15, FALSE);
1649                         uiItemR(split, ptr, "use_material_detect", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1650                         if (RNA_boolean_get(ptr, "use_material_detect"))
1651                                 uiItemPointerR(split, ptr, "material", &main_ptr, "materials", NULL, ICON_MATERIAL_DATA);
1652                         else
1653                                 uiItemR(split, ptr, "property", 0, NULL, ICON_NONE);
1654
1655                         split = uiLayoutSplit(layout, 0.15, FALSE);
1656                         uiItemR(split, ptr, "use_persistent", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1657
1658                         row = uiLayoutRow(split, FALSE);
1659                         uiItemR(row, ptr, "time", 0, NULL, ICON_NONE);
1660                         uiItemR(row, ptr, "damping_rotation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1661                         break;
1662         }
1663 }
1664
1665 static void draw_actuator_edit_object(uiLayout *layout, PointerRNA *ptr)
1666 {
1667         Object *ob = (Object *)ptr->id.data;
1668         uiLayout *row, *split, *sub;
1669         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1670
1671         switch (RNA_enum_get(ptr, "mode")) {
1672                 case ACT_EDOB_ADD_OBJECT:
1673                         row = uiLayoutRow(layout, FALSE);
1674                         uiItemR(row, ptr, "object", 0, NULL, ICON_NONE);
1675                         uiItemR(row, ptr, "time", 0, NULL, ICON_NONE);
1676
1677                         split = uiLayoutSplit(layout, 0.9, FALSE);
1678                         row = uiLayoutRow(split, FALSE);
1679                         uiItemR(row, ptr, "linear_velocity", 0, NULL, ICON_NONE);
1680                         uiItemR(split, ptr, "use_local_linear_velocity", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1681
1682                         split = uiLayoutSplit(layout, 0.9, FALSE);
1683                         row = uiLayoutRow(split, FALSE);
1684                         uiItemR(row, ptr, "angular_velocity", 0, NULL, ICON_NONE);
1685                         uiItemR(split, ptr, "use_local_angular_velocity", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1686                         break;
1687                 case ACT_EDOB_END_OBJECT:
1688                         break;
1689                 case ACT_EDOB_REPLACE_MESH:
1690                         if (ob->type != OB_MESH) {
1691                                 uiItemL(layout, IFACE_("Mode only available for mesh objects"), ICON_NONE);
1692                                 break;
1693                         }
1694                         split = uiLayoutSplit(layout, 0.6, FALSE);
1695                         uiItemR(split, ptr, "mesh", 0, NULL, ICON_NONE);
1696                         row = uiLayoutRow(split, FALSE);
1697                         uiItemR(row, ptr, "use_replace_display_mesh", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1698                         uiItemR(row, ptr, "use_replace_physics_mesh", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1699                         break;
1700                 case ACT_EDOB_TRACK_TO:
1701                         split = uiLayoutSplit(layout, 0.5, FALSE);
1702                         uiItemR(split, ptr, "track_object", 0, NULL, ICON_NONE);
1703                         sub = uiLayoutSplit(split, 0.7f, FALSE);
1704                         uiItemR(sub, ptr, "time", 0, NULL, ICON_NONE);
1705                         uiItemR(sub, ptr, "use_3d_tracking", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1706                         break;
1707                 case ACT_EDOB_DYNAMICS:
1708                         if (ob->type != OB_MESH) {
1709                                 uiItemL(layout, IFACE_("Mode only available for mesh objects"), ICON_NONE);
1710                                 break;
1711                         }
1712                         uiItemR(layout, ptr, "dynamic_operation", 0, NULL, ICON_NONE);
1713                         if (RNA_enum_get(ptr, "dynamic_operation") == ACT_EDOB_SET_MASS)
1714                                 uiItemR(layout, ptr, "mass", 0, NULL, ICON_NONE);
1715                         break;
1716         }
1717 }
1718
1719 static void draw_actuator_filter_2d(uiLayout *layout, PointerRNA *ptr)
1720 {
1721         uiLayout *row, *split;
1722
1723         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1724         switch (RNA_enum_get(ptr, "mode")) {
1725                 case ACT_2DFILTER_CUSTOMFILTER:
1726                         uiItemR(layout, ptr, "filter_pass", 0, NULL, ICON_NONE);
1727                         uiItemR(layout, ptr, "glsl_shader", 0, NULL, ICON_NONE);
1728                         break;
1729                 case ACT_2DFILTER_MOTIONBLUR:
1730                         split=uiLayoutSplit(layout, 0.75f, TRUE);
1731                         row = uiLayoutRow(split, FALSE);
1732                         uiLayoutSetActive(row, RNA_boolean_get(ptr, "use_motion_blur") == TRUE);
1733                         uiItemR(row, ptr, "motion_blur_factor", 0, NULL, ICON_NONE);
1734                         uiItemR(split, ptr, "use_motion_blur", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1735                         break;
1736                 default: // all other 2D Filters
1737                         uiItemR(layout, ptr, "filter_pass", 0, NULL, ICON_NONE);
1738                         break;
1739         }
1740 }
1741
1742 static void draw_actuator_game(uiLayout *layout, PointerRNA *ptr)
1743 {
1744         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1745         if (RNA_enum_get(ptr, "mode") == ACT_GAME_LOAD)
1746                 uiItemR(layout, ptr, "filename", 0, NULL, ICON_NONE);
1747 }
1748
1749 static void draw_actuator_message(uiLayout *layout, PointerRNA *ptr, bContext *C)
1750 {
1751         Object *ob;
1752         PointerRNA main_ptr, settings_ptr;
1753         uiLayout *row;
1754
1755         RNA_main_pointer_create(CTX_data_main(C), &main_ptr);
1756
1757         ob = (Object *)ptr->id.data;
1758         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
1759
1760         uiItemPointerR(layout, ptr, "to_property", &main_ptr, "objects", NULL, ICON_OBJECT_DATA);
1761         uiItemR(layout, ptr, "subject", 0, NULL, ICON_NONE);
1762
1763         row = uiLayoutRow(layout, TRUE);
1764         uiItemR(row, ptr, "body_type", 0, NULL, ICON_NONE);
1765
1766         if (RNA_enum_get(ptr, "body_type") == ACT_MESG_MESG)
1767                 uiItemR(row, ptr, "body_message", 0, "", ICON_NONE);
1768         else // mode == ACT_MESG_PROP
1769                 uiItemPointerR(row, ptr, "body_property", &settings_ptr, "properties", "", ICON_NONE);
1770 }
1771
1772 static void draw_actuator_motion(uiLayout *layout, PointerRNA *ptr)
1773 {
1774         Object *ob;
1775         PointerRNA settings_ptr;
1776         uiLayout *split, *row, *col, *sub;
1777         int physics_type;
1778
1779         ob = (Object *)ptr->id.data;
1780         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
1781         physics_type = RNA_enum_get(&settings_ptr, "physics_type");
1782         
1783         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1784         
1785         switch (RNA_enum_get(ptr, "mode")) {
1786                 case ACT_OBJECT_NORMAL:
1787                         split = uiLayoutSplit(layout, 0.9, FALSE);
1788                         row = uiLayoutRow(split, FALSE);
1789                         uiItemR(row, ptr, "offset_location", 0, NULL, ICON_NONE);
1790                         uiItemR(split, ptr, "use_local_location", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1791
1792                         split = uiLayoutSplit(layout, 0.9, FALSE);
1793                         row = uiLayoutRow(split, FALSE);
1794                         uiItemR(row, ptr, "offset_rotation", 0, NULL, ICON_NONE);
1795                         uiItemR(split, ptr, "use_local_rotation", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1796                         
1797                         if (ELEM3(physics_type, OB_BODY_TYPE_DYNAMIC, OB_BODY_TYPE_RIGID, OB_BODY_TYPE_SOFT)) {
1798                                 uiItemL(layout, IFACE_("Dynamic Object Settings:"), ICON_NONE);
1799                                 split = uiLayoutSplit(layout, 0.9, FALSE);
1800                                 row = uiLayoutRow(split, FALSE);
1801                                 uiItemR(row, ptr, "force", 0, NULL, ICON_NONE);
1802                                 uiItemR(split, ptr, "use_local_force", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1803
1804                                 split = uiLayoutSplit(layout, 0.9, FALSE);
1805                                 row = uiLayoutRow(split, FALSE);
1806                                 uiItemR(row, ptr, "torque", 0, NULL, ICON_NONE);
1807                                 uiItemR(split, ptr, "use_local_torque", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1808
1809                                 split = uiLayoutSplit(layout, 0.9, FALSE);
1810                                 row = uiLayoutRow(split, FALSE);
1811                                 uiItemR(row, ptr, "linear_velocity", 0, NULL, ICON_NONE);
1812                                 row = uiLayoutRow(split, TRUE);
1813                                 uiItemR(row, ptr, "use_local_linear_velocity", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1814                                 uiItemR(row, ptr, "use_add_linear_velocity", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1815
1816                                 split = uiLayoutSplit(layout, 0.9, FALSE);
1817                                 row = uiLayoutRow(split, FALSE);
1818                                 uiItemR(row, ptr, "angular_velocity", 0, NULL, ICON_NONE);
1819                                 uiItemR(split, ptr, "use_local_angular_velocity", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1820
1821                                 uiItemR(layout, ptr, "damping", 0, NULL, ICON_NONE);
1822                         }
1823                         break;
1824                 case ACT_OBJECT_SERVO:
1825                         uiItemR(layout, ptr, "reference_object", 0, NULL, ICON_NONE);
1826
1827                         split = uiLayoutSplit(layout, 0.9, FALSE);
1828                         row = uiLayoutRow(split, FALSE);
1829                         uiItemR(row, ptr, "linear_velocity", 0, NULL, ICON_NONE);
1830                         uiItemR(split, ptr, "use_local_linear_velocity", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1831
1832                         row = uiLayoutRow(layout, FALSE);
1833                         col = uiLayoutColumn(row, FALSE);
1834                         uiItemR(col, ptr, "use_servo_limit_x", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1835                         sub = uiLayoutColumn(col, TRUE);
1836                         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_servo_limit_x") == TRUE);
1837                         uiItemR(sub, ptr, "force_max_x", 0, NULL, ICON_NONE);
1838                         uiItemR(sub, ptr, "force_min_x", 0, NULL, ICON_NONE);
1839
1840                         col = uiLayoutColumn(row, FALSE);
1841                         uiItemR(col, ptr, "use_servo_limit_y", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1842                         sub = uiLayoutColumn(col, TRUE);
1843                         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_servo_limit_y") == TRUE);
1844                         uiItemR(sub, ptr, "force_max_y", 0, NULL, ICON_NONE);
1845                         uiItemR(sub, ptr, "force_min_y", 0, NULL, ICON_NONE);
1846
1847                         col = uiLayoutColumn(row, FALSE);
1848                         uiItemR(col, ptr, "use_servo_limit_z", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1849                         sub = uiLayoutColumn(col, TRUE);
1850                         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_servo_limit_z") == TRUE);
1851                         uiItemR(sub, ptr, "force_max_z", 0, NULL, ICON_NONE);
1852                         uiItemR(sub, ptr, "force_min_z", 0, NULL, ICON_NONE);
1853
1854                         //XXXACTUATOR missing labels from original 2.49 ui (e.g. Servo, Min, Max, Fast)
1855                         //Layout designers willing to help on that, please compare with 2.49 ui
1856                         // (since the old code is going to be deleted ... soon)
1857
1858                         col = uiLayoutColumn(layout, TRUE);
1859                         uiItemR(col, ptr, "proportional_coefficient", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1860                         uiItemR(col, ptr, "integral_coefficient", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1861                         uiItemR(col, ptr, "derivate_coefficient", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1862                         break;
1863         }
1864 }
1865
1866 static void draw_actuator_parent(uiLayout *layout, PointerRNA *ptr)
1867 {
1868         uiLayout *row, *sub;
1869
1870         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1871
1872         if (RNA_enum_get(ptr, "mode") == ACT_PARENT_SET) {
1873                 uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
1874
1875                 row = uiLayoutRow(layout, FALSE);
1876                 uiItemR(row, ptr, "use_compound", 0, NULL, ICON_NONE);
1877                 sub = uiLayoutRow(row, FALSE);
1878                 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_compound") == TRUE);
1879                 uiItemR(sub, ptr, "use_ghost", 0, NULL, ICON_NONE);
1880         }
1881 }
1882
1883 static void draw_actuator_property(uiLayout *layout, PointerRNA *ptr)
1884 {
1885         Object *ob = (Object *)ptr->id.data;
1886         bActuator *act = (bActuator *)ptr->data;
1887         bPropertyActuator *pa = (bPropertyActuator *) act->data;
1888         Object *ob_from= pa->ob;
1889         PointerRNA settings_ptr, obj_settings_ptr;
1890
1891         uiLayout *row, *sub;
1892
1893         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
1894
1895         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1896         uiItemPointerR(layout, ptr, "property", &settings_ptr, "properties", NULL, ICON_NONE);
1897
1898         switch (RNA_enum_get(ptr, "mode")) {
1899                 case ACT_PROP_TOGGLE:
1900                         break;
1901                 case ACT_PROP_ADD:
1902                         uiItemR(layout, ptr, "value", 0, NULL, ICON_NONE);
1903                         break;
1904                 case ACT_PROP_ASSIGN:
1905                         uiItemR(layout, ptr, "value", 0, NULL, ICON_NONE);
1906                         break;
1907                 case ACT_PROP_COPY:
1908                         row = uiLayoutRow(layout, FALSE);
1909                         uiItemR(row, ptr, "object", 0, NULL, ICON_NONE);
1910                         if (ob_from) {
1911                                 RNA_pointer_create((ID *)ob_from, &RNA_GameObjectSettings, ob_from, &obj_settings_ptr);
1912                                 uiItemPointerR(row, ptr, "object_property", &obj_settings_ptr, "properties", NULL, ICON_NONE);
1913                         }
1914                         else {
1915                                 sub = uiLayoutRow(row, FALSE);
1916                                 uiLayoutSetActive(sub, FALSE);
1917                                 uiItemR(sub, ptr, "object_property", 0, NULL, ICON_NONE);
1918                         }
1919                         break;
1920         }
1921 }
1922
1923 static void draw_actuator_random(uiLayout *layout, PointerRNA *ptr)
1924 {
1925         Object *ob;
1926         PointerRNA settings_ptr;
1927         uiLayout *row;
1928
1929         ob = (Object *)ptr->id.data;
1930         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
1931
1932         row = uiLayoutRow(layout, FALSE);
1933
1934         uiItemR(row, ptr, "seed", 0, NULL, ICON_NONE);
1935         uiItemR(row, ptr, "distribution", 0, NULL, ICON_NONE);
1936
1937         row = uiLayoutRow(layout, FALSE);
1938         uiItemPointerR(row, ptr, "property", &settings_ptr, "properties", NULL, ICON_NONE);
1939
1940         row = uiLayoutRow(layout, FALSE);
1941
1942         switch (RNA_enum_get(ptr, "distribution")) {
1943                 case ACT_RANDOM_BOOL_CONST:
1944                         uiItemR(row, ptr, "use_always_true", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
1945                         break;
1946
1947                 case ACT_RANDOM_BOOL_UNIFORM:
1948                         uiItemL(row, IFACE_("Choose between true and false, 50% chance each"), ICON_NONE);
1949                         break;
1950
1951                 case ACT_RANDOM_BOOL_BERNOUILLI:
1952                         uiItemR(row, ptr, "chance", 0, NULL, ICON_NONE);
1953                         break;
1954
1955                 case ACT_RANDOM_INT_CONST:
1956                         uiItemR(row, ptr, "int_value", 0, NULL, ICON_NONE);
1957                         break;
1958
1959                 case ACT_RANDOM_INT_UNIFORM:
1960                         uiItemR(row, ptr, "int_min", 0, NULL, ICON_NONE);
1961                         uiItemR(row, ptr, "int_max", 0, NULL, ICON_NONE);
1962                         break;
1963
1964                 case ACT_RANDOM_INT_POISSON:
1965                         uiItemR(row, ptr, "int_mean", 0, NULL, ICON_NONE);
1966                         break;
1967
1968                 case ACT_RANDOM_FLOAT_CONST:
1969                         uiItemR(row, ptr, "float_value", 0, NULL, ICON_NONE);
1970                         break;
1971
1972                 case ACT_RANDOM_FLOAT_UNIFORM:
1973                         uiItemR(row, ptr, "float_min", 0, NULL, ICON_NONE);
1974                         uiItemR(row, ptr, "float_max", 0, NULL, ICON_NONE);
1975                         break;
1976
1977                 case ACT_RANDOM_FLOAT_NORMAL:
1978                         uiItemR(row, ptr, "float_mean", 0, NULL, ICON_NONE);
1979                         uiItemR(row, ptr, "standard_derivation", 0, NULL, ICON_NONE);
1980                         break;
1981
1982                 case ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL:
1983                         uiItemR(row, ptr, "half_life_time", 0, NULL, ICON_NONE);
1984                         break;
1985         }
1986 }
1987
1988 static void draw_actuator_scene(uiLayout *layout, PointerRNA *ptr)
1989 {
1990         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1991
1992         switch (RNA_enum_get(ptr, "mode")) {
1993                 case ACT_SCENE_CAMERA:
1994                         uiItemR(layout, ptr, "camera", 0, NULL, ICON_NONE);
1995                         break;
1996                 case ACT_SCENE_RESTART:
1997                         break;
1998                 default: // ACT_SCENE_SET|ACT_SCENE_ADD_FRONT|ACT_SCENE_ADD_BACK|ACT_SCENE_REMOVE|ACT_SCENE_SUSPEND|ACT_SCENE_RESUME
1999                         uiItemR(layout, ptr, "scene", 0, NULL, ICON_NONE);
2000                         break;
2001         }
2002 }
2003
2004 static void draw_actuator_shape_action(uiLayout *layout, PointerRNA *ptr)
2005 {
2006         Object *ob = (Object *)ptr->id.data;
2007         PointerRNA settings_ptr;
2008         uiLayout *row;
2009
2010         if (ob->type != OB_MESH) {
2011                 uiItemL(layout, IFACE_("Actuator only available for mesh objects"), ICON_NONE);
2012                 return;
2013         }
2014
2015         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
2016
2017         row = uiLayoutRow(layout, FALSE);
2018         uiItemR(row, ptr, "mode", 0, "", ICON_NONE);
2019         uiItemR(row, ptr, "action", 0, "", ICON_NONE);
2020         uiItemR(row, ptr, "use_continue_last_frame", 0, NULL, ICON_NONE);
2021
2022         row = uiLayoutRow(layout, FALSE);
2023         if ((RNA_enum_get(ptr, "mode") == ACT_ACTION_FROM_PROP))
2024                 uiItemPointerR(row, ptr, "property", &settings_ptr, "properties", NULL, ICON_NONE);
2025
2026         else {
2027                 uiItemR(row, ptr, "frame_start", 0, NULL, ICON_NONE);
2028                 uiItemR(row, ptr, "frame_end", 0, NULL, ICON_NONE);
2029         }
2030
2031         row = uiLayoutRow(layout, FALSE);
2032         uiItemR(row, ptr, "frame_blend_in", 0, NULL, ICON_NONE);
2033         uiItemR(row, ptr, "priority", 0, NULL, ICON_NONE);
2034
2035         row = uiLayoutRow(layout, FALSE);
2036         uiItemPointerR(row, ptr, "frame_property", &settings_ptr, "properties", NULL, ICON_NONE);
2037
2038 #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
2039         uiItemR(row, "stride_length", 0, NULL, ICON_NONE);
2040 #endif
2041 }
2042
2043 static void draw_actuator_sound(uiLayout *layout, PointerRNA *ptr, bContext *C)
2044 {
2045         uiLayout *row, *col;
2046
2047         uiTemplateID(layout, C, ptr, "sound", NULL, "SOUND_OT_open", NULL);
2048         if (!RNA_pointer_get(ptr, "sound").data) {
2049                 uiItemL(layout, IFACE_("Select a sound from the list or load a new one"), ICON_NONE);
2050                 return;
2051         }
2052         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
2053
2054         row = uiLayoutRow(layout, FALSE);
2055         uiItemR(row, ptr, "volume", 0, NULL, ICON_NONE);
2056         uiItemR(row, ptr, "pitch", 0, NULL, ICON_NONE);
2057
2058         uiItemR(layout, ptr, "use_sound_3d", 0, NULL, ICON_NONE);
2059         
2060         col = uiLayoutColumn(layout, FALSE);
2061         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_sound_3d") == TRUE);
2062
2063         row = uiLayoutRow(col, FALSE);
2064         uiItemR(row, ptr, "gain_3d_min", 0, NULL, ICON_NONE);
2065         uiItemR(row, ptr, "gain_3d_max", 0, NULL, ICON_NONE);
2066
2067         row = uiLayoutRow(col, FALSE);
2068         uiItemR(row, ptr, "distance_3d_reference", 0, NULL, ICON_NONE);
2069         uiItemR(row, ptr, "distance_3d_max", 0, NULL, ICON_NONE);
2070
2071         row = uiLayoutRow(col, FALSE);
2072         uiItemR(row, ptr, "rolloff_factor_3d", 0, NULL, ICON_NONE);
2073         uiItemR(row, ptr, "cone_outer_gain_3d", 0, NULL, ICON_NONE);
2074
2075         row = uiLayoutRow(col, FALSE);
2076         uiItemR(row, ptr, "cone_outer_angle_3d", 0, NULL, ICON_NONE);
2077         uiItemR(row, ptr, "cone_inner_angle_3d", 0, NULL, ICON_NONE);
2078 }
2079
2080 static void draw_actuator_state(uiLayout *layout, PointerRNA *ptr)
2081 {
2082         uiLayout *split;
2083         Object *ob = (Object *)ptr->id.data;
2084         PointerRNA settings_ptr;
2085         RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
2086
2087         split = uiLayoutSplit(layout, 0.35, FALSE);
2088         uiItemR(split, ptr, "operation", 0, NULL, ICON_NONE);
2089
2090         uiTemplateLayers(split, ptr, "states", &settings_ptr, "used_states", 0);
2091 }
2092
2093 static void draw_actuator_visibility(uiLayout *layout, PointerRNA *ptr)
2094 {
2095         uiLayout *row;
2096         row = uiLayoutRow(layout, FALSE);
2097
2098         uiItemR(row, ptr, "use_visible", 0, NULL, ICON_NONE);
2099         uiItemR(row, ptr, "use_occlusion", 0, NULL, ICON_NONE);
2100         uiItemR(row, ptr, "apply_to_children", 0, NULL, ICON_NONE);
2101 }
2102
2103 static void draw_actuator_steering(uiLayout *layout, PointerRNA *ptr)
2104 {
2105         uiLayout *row;
2106         uiLayout *col;
2107
2108         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
2109         uiItemR(layout, ptr, "target", 0, NULL, ICON_NONE);
2110         uiItemR(layout, ptr, "navmesh", 0, NULL, ICON_NONE);
2111
2112         row = uiLayoutRow(layout, FALSE);
2113         uiItemR(row, ptr, "distance", 0, NULL, ICON_NONE);
2114         uiItemR(row, ptr, "velocity", 0, NULL, ICON_NONE);
2115         row = uiLayoutRow(layout, FALSE);
2116         uiItemR(row, ptr, "acceleration", 0, NULL, ICON_NONE);
2117         uiItemR(row, ptr, "turn_speed", 0, NULL, ICON_NONE);
2118
2119         row = uiLayoutRow(layout, FALSE);
2120         col = uiLayoutColumn(row, FALSE);
2121         uiItemR(col, ptr, "facing", 0, NULL, ICON_NONE);
2122         col = uiLayoutColumn(row, FALSE);
2123         uiItemR(col, ptr, "facing_axis", 0, NULL, ICON_NONE);
2124         if (!RNA_boolean_get(ptr, "facing")) {
2125                 uiLayoutSetActive(col, FALSE);
2126         }
2127         col = uiLayoutColumn(row, FALSE);
2128         uiItemR(col, ptr, "normal_up", 0, NULL, ICON_NONE);
2129         if (!RNA_pointer_get(ptr, "navmesh").data) {
2130                 uiLayoutSetActive(col, FALSE);
2131         }
2132
2133         row = uiLayoutRow(layout, FALSE);
2134         uiItemR(row, ptr, "self_terminated", 0, NULL, ICON_NONE);
2135         if (RNA_enum_get(ptr, "mode")==ACT_STEERING_PATHFOLLOWING) {
2136                 uiItemR(row, ptr, "update_period", 0, NULL, ICON_NONE);
2137                 row = uiLayoutRow(layout, FALSE);
2138         }
2139         uiItemR(row, ptr, "show_visualization", 0, NULL, ICON_NONE);
2140 }
2141
2142 static void draw_brick_actuator(uiLayout *layout, PointerRNA *ptr, bContext *C)
2143 {
2144         uiLayout *box;
2145         
2146         if (!RNA_boolean_get(ptr, "show_expanded"))
2147                 return;
2148         
2149         box = uiLayoutBox(layout);
2150         
2151         switch (RNA_enum_get(ptr, "type")) {
2152                 case ACT_ACTION:
2153                         draw_actuator_action(box, ptr);
2154                         break;
2155                 case ACT_ARMATURE:
2156                         draw_actuator_armature(box, ptr);
2157                         break;
2158                 case ACT_CAMERA:
2159                         draw_actuator_camera(box, ptr);
2160                         break;
2161                 case ACT_CONSTRAINT:
2162                         draw_actuator_constraint(box, ptr, C);
2163                         break;
2164                 case ACT_EDIT_OBJECT:
2165                         draw_actuator_edit_object(box, ptr);
2166                         break;
2167                 case ACT_2DFILTER:
2168                         draw_actuator_filter_2d(box, ptr);
2169                         break;
2170                 case ACT_GAME:
2171                         draw_actuator_game(box, ptr);
2172                         break;
2173                 case ACT_MESSAGE:
2174                         draw_actuator_message(box, ptr, C);
2175                         break;
2176                 case ACT_OBJECT:
2177                         draw_actuator_motion(box, ptr);
2178                         break;
2179                 case ACT_PARENT:
2180                         draw_actuator_parent(box, ptr);
2181                         break;
2182                 case ACT_PROPERTY:
2183                         draw_actuator_property(box, ptr);
2184                         break;
2185                 case ACT_RANDOM:
2186                         draw_actuator_random(box, ptr);
2187                         break;
2188                 case ACT_SCENE:
2189                         draw_actuator_scene(box, ptr);
2190                         break;
2191                 case ACT_SHAPEACTION:
2192                         draw_actuator_shape_action(box, ptr);
2193                         break;
2194                 case ACT_SOUND:
2195                         draw_actuator_sound(box, ptr, C);
2196                         break;
2197                 case ACT_STATE:
2198                         draw_actuator_state(box, ptr);
2199                         break;
2200                 case ACT_VISIBILITY:
2201                         draw_actuator_visibility(box, ptr);
2202                         break;
2203                 case ACT_STEERING:
2204                         draw_actuator_steering(box, ptr);
2205         }
2206 }
2207
2208 void logic_buttons(bContext *C, ARegion *ar)
2209 {
2210         SpaceLogic *slogic= CTX_wm_space_logic(C);
2211         Object *ob= CTX_data_active_object(C);
2212         ID **idar;
2213         PointerRNA logic_ptr, settings_ptr, object_ptr;
2214         uiLayout *layout, *row, *box;
2215         uiBlock *block;
2216         uiBut *but;
2217         char uiblockstr[32];
2218         short a, count;
2219         int xco, yco, width, height;
2220         
2221         if (ob==NULL) return;
2222         
2223         RNA_pointer_create(NULL, &RNA_SpaceLogicEditor, slogic, &logic_ptr);
2224         idar= get_selected_and_linked_obs(C, &count, slogic->scaflag);
2225         
2226         BLI_snprintf(uiblockstr, sizeof(uiblockstr), "buttonswin %p", (void *)ar);
2227         block= uiBeginBlock(C, ar, uiblockstr, UI_EMBOSS);
2228         uiBlockSetHandleFunc(block, do_logic_buts, NULL);
2229         
2230         /* loop over all objects and set visible/linked flags for the logic bricks */
2231         for (a=0; a<count; a++) {
2232                 bActuator *act;
2233                 bSensor *sens;
2234                 bController *cont;
2235                 int iact;
2236                 short flag;
2237
2238                 ob= (Object *)idar[a];
2239                 
2240                 /* clean ACT_LINKED and ACT_VISIBLE of all potentially visible actuators so that we can determine which is actually linked/visible */
2241                 act = ob->actuators.first;
2242                 while (act) {
2243                         act->flag &= ~(ACT_LINKED|ACT_VISIBLE);
2244                         act = act->next;
2245                 }
2246                 /* same for sensors */
2247                 sens= ob->sensors.first;
2248                 while (sens) {
2249                         sens->flag &= ~(SENS_VISIBLE);
2250                         sens = sens->next;
2251                 }
2252
2253                 /* mark the linked and visible actuators */
2254                 cont= ob->controllers.first;
2255                 while (cont) {
2256                         flag = ACT_LINKED;
2257
2258                         /* this controller is visible, mark all its actuator */
2259                         if ((ob->scaflag & OB_ALLSTATE) || (ob->state & cont->state_mask))
2260                                 flag |= ACT_VISIBLE;
2261
2262                         for (iact=0; iact<cont->totlinks; iact++) {
2263                                 act = cont->links[iact];
2264                                 if (act)
2265                                         act->flag |= flag;
2266                         }
2267                         cont = cont->next;
2268                 }
2269         }
2270         
2271         /* ****************** Controllers ****************** */
2272         
2273         xco= 420; yco= -10; width= 300;
2274         layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, UI_GetStyle());
2275         row = uiLayoutRow(layout, TRUE);
2276         
2277         uiDefBlockBut(block, controller_menu, NULL, IFACE_("Controllers"), xco-10, yco, 300, UI_UNIT_Y, "");            /* replace this with uiLayout stuff later */
2278         
2279         uiItemR(row, &logic_ptr, "show_controllers_selected_objects", 0, IFACE_("Sel"), ICON_NONE);
2280         uiItemR(row, &logic_ptr, "show_controllers_active_object", 0, IFACE_("Act"), ICON_NONE);
2281         uiItemR(row, &logic_ptr, "show_controllers_linked_controller", 0, IFACE_("Link"), ICON_NONE);
2282
2283         for (a=0; a<count; a++) {
2284                 bController *cont;
2285                 PointerRNA ptr;
2286                 uiLayout *split, *subsplit, *col;
2287
2288                 
2289                 ob= (Object *)idar[a];
2290
2291                 /* only draw the controller common header if "use_visible" */
2292                 if ( (ob->scavisflag & OB_VIS_CONT) == 0) {
2293                         continue;
2294                 }
2295         
2296                 /* Drawing the Controller Header common to all Selected Objects */
2297
2298                 RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
2299
2300                 split = uiLayoutSplit(layout, 0.05f, FALSE);
2301                 uiItemR(split, &settings_ptr, "show_state_panel", UI_ITEM_R_NO_BG, "", ICON_DISCLOSURE_TRI_RIGHT);
2302
2303                 row = uiLayoutRow(split, TRUE);
2304                 uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers"));
2305
2306                 RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
2307                 uiLayoutSetContextPointer(row, "object", &object_ptr);
2308                 uiItemMenuEnumO(row, "LOGIC_OT_controller_add", "type", IFACE_("Add Controller"), ICON_NONE);
2309
2310                 if (RNA_boolean_get(&settings_ptr, "show_state_panel")) {
2311
2312                         box = uiLayoutBox(layout);
2313                         split = uiLayoutSplit(box, 0.2f, FALSE);
2314
2315                         col = uiLayoutColumn(split, FALSE);
2316                         uiItemL(col, IFACE_("Visible"), ICON_NONE);
2317                         uiItemL(col, IFACE_("Initial"), ICON_NONE);
2318
2319                         subsplit = uiLayoutSplit(split, 0.85f, FALSE);
2320                         col = uiLayoutColumn(subsplit, FALSE);
2321                         row = uiLayoutRow(col, FALSE);
2322                         uiLayoutSetActive(row, RNA_boolean_get(&settings_ptr, "use_all_states") == FALSE);
2323                         uiTemplateGameStates(row, &settings_ptr, "states_visible", &settings_ptr, "used_states", 0);
2324                         row = uiLayoutRow(col, FALSE);
2325                         uiTemplateGameStates(row, &settings_ptr, "states_initial", &settings_ptr, "used_states", 0);
2326
2327                         col = uiLayoutColumn(subsplit, FALSE);
2328                         uiItemR(col, &settings_ptr, "use_all_states", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
2329                         uiItemR(col, &settings_ptr, "show_debug_state", 0, "", ICON_NONE);
2330                 }
2331
2332                 /* End of Drawing the Controller Header common to all Selected Objects */
2333
2334                 if ((ob->scaflag & OB_SHOWCONT) == 0) continue;
2335                 
2336
2337                 uiItemS(layout);
2338                 
2339                 for (cont= ob->controllers.first; cont; cont=cont->next) {
2340                         RNA_pointer_create((ID *)ob, &RNA_Controller, cont, &ptr);
2341                         
2342                         if (!(ob->scaflag & OB_ALLSTATE) && !(ob->state & cont->state_mask))
2343                                 continue;
2344                         
2345                         /* use two nested splits to align inlinks/links properly */
2346                         split = uiLayoutSplit(layout, 0.05f, FALSE);
2347                         
2348                         /* put inlink button to the left */
2349                         col = uiLayoutColumn(split, FALSE);
2350                         uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_LEFT);
2351                         uiDefIconBut(block, INLINK, 0, ICON_INLINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, cont, LINK_CONTROLLER, 0, 0, 0, "");
2352                         
2353                         //col = uiLayoutColumn(split, TRUE);
2354                         /* nested split for middle and right columns */
2355                         subsplit = uiLayoutSplit(split, 0.95f, FALSE);
2356                         
2357                         col = uiLayoutColumn(subsplit, TRUE);
2358                         uiLayoutSetContextPointer(col, "controller", &ptr);
2359                         
2360                         /* should make UI template for controller header.. function will do for now */
2361 //                      draw_controller_header(col, &ptr);
2362                         draw_controller_header(col, &ptr, xco, width, yco); //provisory for 2.50 beta
2363
2364                         /* draw the brick contents */
2365                         draw_brick_controller(col, &ptr);
2366                         
2367                         
2368                         /* put link button to the right */
2369                         col = uiLayoutColumn(subsplit, FALSE);
2370                         uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_LEFT);
2371                         but = uiDefIconBut(block, LINK, 0, ICON_LINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
2372                         uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR);
2373                 }
2374         }
2375         uiBlockLayoutResolve(block, NULL, &yco);        /* stores final height in yco */
2376         height = yco;
2377         
2378         /* ****************** Sensors ****************** */
2379         
2380         xco= 10; yco= -10; width= 340;
2381         layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, UI_GetStyle());
2382         row = uiLayoutRow(layout, TRUE);
2383         
2384         uiDefBlockBut(block, sensor_menu, NULL, IFACE_("Sensors"), xco-10, yco, 300, UI_UNIT_Y, "");            /* replace this with uiLayout stuff later */
2385         
2386         uiItemR(row, &logic_ptr, "show_sensors_selected_objects", 0, IFACE_("Sel"), ICON_NONE);
2387         uiItemR(row, &logic_ptr, "show_sensors_active_object", 0, IFACE_("Act"), ICON_NONE);
2388         uiItemR(row, &logic_ptr, "show_sensors_linked_controller", 0, IFACE_("Link"), ICON_NONE);
2389         uiItemR(row, &logic_ptr, "show_sensors_active_states", 0, IFACE_("State"), ICON_NONE);
2390         
2391         for (a=0; a<count; a++) {
2392                 bSensor *sens;
2393                 PointerRNA ptr;
2394                 
2395                 ob= (Object *)idar[a];
2396
2397                 /* only draw the sensor common header if "use_visible" */
2398                 if ((ob->scavisflag & OB_VIS_SENS) == 0) continue;
2399
2400                 row = uiLayoutRow(layout, TRUE);
2401                 uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors"));
2402
2403                 RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
2404                 uiLayoutSetContextPointer(row, "object", &object_ptr);
2405                 uiItemMenuEnumO(row, "LOGIC_OT_sensor_add", "type", IFACE_("Add Sensor"), ICON_NONE);
2406                 
2407                 if ((ob->scaflag & OB_SHOWSENS) == 0) continue;
2408                 
2409                 uiItemS(layout);
2410                 
2411                 for (sens= ob->sensors.first; sens; sens=sens->next) {
2412                         RNA_pointer_create((ID *)ob, &RNA_Sensor, sens, &ptr);
2413                         
2414                         if ((ob->scaflag & OB_ALLSTATE) ||
2415                                 !(slogic->scaflag & BUTS_SENS_STATE) ||
2416                                 (sens->totlinks == 0) ||                                                                                        /* always display sensor without links so that is can be edited */
2417                                 (sens->flag & SENS_PIN && slogic->scaflag & BUTS_SENS_STATE) || /* states can hide some sensors, pinned sensors ignore the visible state */
2418                                 (is_sensor_linked(block, sens))
2419                                 )
2420                         {       // gotta check if the current state is visible or not
2421                                 uiLayout *split, *col;
2422                                 
2423                                 /* make as visible, for move operator */
2424                                 sens->flag |= SENS_VISIBLE;
2425
2426                                 split = uiLayoutSplit(layout, 0.95f, FALSE);
2427                                 col = uiLayoutColumn(split, TRUE);
2428                                 uiLayoutSetContextPointer(col, "sensor", &ptr);
2429                                 
2430                                 /* should make UI template for sensor header.. function will do for now */
2431                                 draw_sensor_header(col, &ptr, &logic_ptr);
2432                                 
2433                                 /* draw the brick contents */
2434                                 draw_brick_sensor(col, &ptr, C);
2435                                 
2436                                 /* put link button to the right */
2437                                 col = uiLayoutColumn(split, FALSE);
2438                                 /* use old-school uiButtons for links for now */
2439                                 but = uiDefIconBut(block, LINK, 0, ICON_LINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
2440                                 uiSetButLink(but, NULL, (void ***)&(sens->links), &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER);
2441                         }
2442                 }
2443         }
2444         uiBlockLayoutResolve(block, NULL, &yco);        /* stores final height in yco */
2445         height = MIN2(height, yco);
2446         
2447         /* ****************** Actuators ****************** */
2448         
2449         xco= 800; yco= -10; width= 340;
2450         layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, UI_GetStyle());
2451         row = uiLayoutRow(layout, TRUE);
2452         
2453         uiDefBlockBut(block, actuator_menu, NULL, IFACE_("Actuators"), xco-10, yco, 300, UI_UNIT_Y, "");                /* replace this with uiLayout stuff later */
2454         
2455         uiItemR(row, &logic_ptr, "show_actuators_selected_objects", 0, IFACE_("Sel"), ICON_NONE);
2456         uiItemR(row, &logic_ptr, "show_actuators_active_object", 0, IFACE_("Act"), ICON_NONE);
2457         uiItemR(row, &logic_ptr, "show_actuators_linked_controller", 0, IFACE_("Link"), ICON_NONE);
2458         uiItemR(row, &logic_ptr, "show_actuators_active_states", 0, IFACE_("State"), ICON_NONE);
2459         
2460         for (a=0; a<count; a++) {
2461                 bActuator *act;
2462                 PointerRNA ptr;
2463                 
2464                 ob= (Object *)idar[a];
2465
2466                 /* only draw the actuator common header if "use_visible" */
2467                 if ((ob->scavisflag & OB_VIS_ACT) == 0) {
2468                         continue;
2469                 }
2470
2471                 row = uiLayoutRow(layout, TRUE);
2472                 uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators"));
2473
2474                 RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
2475                 uiLayoutSetContextPointer(row, "object", &object_ptr);
2476                 uiItemMenuEnumO(row, "LOGIC_OT_actuator_add", "type", IFACE_("Add Actuator"), ICON_NONE);
2477
2478                 if ((ob->scaflag & OB_SHOWACT) == 0) continue;
2479                 
2480                 uiItemS(layout);
2481                 
2482                 for (act= ob->actuators.first; act; act=act->next) {
2483                         
2484                         RNA_pointer_create((ID *)ob, &RNA_Actuator, act, &ptr);
2485                         
2486                         if ((ob->scaflag & OB_ALLSTATE) ||
2487                                 !(slogic->scaflag & BUTS_ACT_STATE) ||
2488                                 !(act->flag & ACT_LINKED) ||            /* always display actuators without links so that is can be edited */
2489                                 (act->flag & ACT_VISIBLE) ||            /* this actuator has visible connection, display it */
2490                                 (act->flag & ACT_PIN && slogic->scaflag & BUTS_ACT_STATE)       /* states can hide some sensors, pinned sensors ignore the visible state */
2491                                 )
2492                         {       // gotta check if the current state is visible or not
2493                                 uiLayout *split, *col;
2494                                 
2495                                 /* make as visible, for move operator */
2496                                 act->flag |= ACT_VISIBLE;
2497
2498                                 split = uiLayoutSplit(layout, 0.05f, FALSE);
2499                                 
2500                                 /* put inlink button to the left */
2501                                 col = uiLayoutColumn(split, FALSE);
2502                                 uiDefIconBut(block, INLINK, 0, ICON_INLINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, act, LINK_ACTUATOR, 0, 0, 0, "");
2503
2504                                 col = uiLayoutColumn(split, TRUE);
2505                                 uiLayoutSetContextPointer(col, "actuator", &ptr);
2506                                 
2507                                 /* should make UI template for actuator header.. function will do for now */
2508                                 draw_actuator_header(col, &ptr, &logic_ptr);
2509                                 
2510                                 /* draw the brick contents */
2511                                 draw_brick_actuator(col, &ptr, C);
2512                                 
2513                         }
2514                 }
2515         }
2516         uiBlockLayoutResolve(block, NULL, &yco);        /* stores final height in yco */
2517         height = MIN2(height, yco);
2518
2519         UI_view2d_totRect_set(&ar->v2d, 1150, height);
2520         
2521         /* set the view */
2522         UI_view2d_view_ortho(&ar->v2d);
2523
2524         uiComposeLinks(block);
2525         
2526         uiEndBlock(C, block);
2527         uiDrawBlock(C, block);
2528         
2529         /* restore view matrix */
2530         UI_view2d_view_restore(C);
2531         
2532         if (idar) MEM_freeN(idar);
2533 }
2534