BGE: TrackTo actuator: increasing up & track axis options
[blender.git] / source / blender / blenkernel / intern / sca.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) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * these all are linked to objects (listbase)
27  * all data is 'direct data', not Blender lib data.
28  */
29
30 /** \file blender/blenkernel/intern/sca.c
31  *  \ingroup bke
32  */
33
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <float.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_controller_types.h"
42 #include "DNA_sensor_types.h"
43 #include "DNA_actuator_types.h"
44 #include "DNA_object_types.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_math.h"
48 #include "BKE_global.h"
49 #include "BKE_main.h"
50 #include "BKE_library.h"
51 #include "BKE_sca.h"
52
53 /* ******************* SENSORS ************************ */
54
55 void free_sensor(bSensor *sens)
56 {
57         if (sens->links) MEM_freeN(sens->links);
58         if (sens->data) MEM_freeN(sens->data);
59         MEM_freeN(sens);
60         
61 }
62
63 void free_sensors(ListBase *lb)
64 {
65         bSensor *sens;
66         
67         while ((sens = BLI_pophead(lb))) {
68                 free_sensor(sens);
69         }
70 }
71
72 bSensor *copy_sensor(bSensor *sens)
73 {
74         bSensor *sensn;
75         
76         sensn= MEM_dupallocN(sens);
77         sensn->flag |= SENS_NEW;
78         if (sens->data) {
79                 sensn->data= MEM_dupallocN(sens->data);
80         }
81
82         if (sens->links) sensn->links= MEM_dupallocN(sens->links);
83         
84         return sensn;
85 }
86
87 void copy_sensors(ListBase *lbn, ListBase *lbo)
88 {
89         bSensor *sens, *sensn;
90         
91         lbn->first= lbn->last= NULL;
92         sens= lbo->first;
93         while (sens) {
94                 sensn= copy_sensor(sens);
95                 BLI_addtail(lbn, sensn);
96                 sens= sens->next;
97         }
98 }
99
100 void init_sensor(bSensor *sens)
101 {
102         /* also use when sensor changes type */
103         bNearSensor *ns;
104         bMouseSensor *ms;
105         bJoystickSensor *js;
106         bRaySensor *rs;
107         
108         if (sens->data) MEM_freeN(sens->data);
109         sens->data= NULL;
110         sens->pulse = 0;
111         
112         switch (sens->type) {
113         case SENS_ALWAYS:
114                 sens->pulse = 0;
115                 break;
116         case SENS_NEAR:
117                 ns=sens->data= MEM_callocN(sizeof(bNearSensor), "nearsens");
118                 ns->dist= 1.0;
119                 ns->resetdist= 2.0;
120                 break;
121         case SENS_KEYBOARD:
122                 sens->data= MEM_callocN(sizeof(bKeyboardSensor), "keysens");
123                 break;
124         case SENS_PROPERTY:
125                 sens->data= MEM_callocN(sizeof(bPropertySensor), "propsens");
126                 break;
127         case SENS_ARMATURE:
128                 sens->data= MEM_callocN(sizeof(bArmatureSensor), "armsens");
129                 break;
130         case SENS_ACTUATOR:
131                 sens->data= MEM_callocN(sizeof(bActuatorSensor), "actsens");
132                 break;
133         case SENS_DELAY:
134                 sens->data= MEM_callocN(sizeof(bDelaySensor), "delaysens");
135                 break;
136         case SENS_MOUSE:
137                 ms=sens->data= MEM_callocN(sizeof(bMouseSensor), "mousesens");
138                 ms->type= 1; // LEFTMOUSE workaround because Mouse Sensor types enum starts in 1
139                 break;
140         case SENS_COLLISION:
141                 sens->data= MEM_callocN(sizeof(bCollisionSensor), "colsens");
142                 break;
143         case SENS_RADAR:
144                 sens->data= MEM_callocN(sizeof(bRadarSensor), "radarsens");
145                 break;
146         case SENS_RANDOM:
147                 sens->data= MEM_callocN(sizeof(bRandomSensor), "randomsens");
148                 break;
149         case SENS_RAY:
150                 sens->data= MEM_callocN(sizeof(bRaySensor), "raysens");
151                 rs = sens->data;
152                 rs->range = 0.01f;
153                 break;
154         case SENS_MESSAGE:
155                 sens->data= MEM_callocN(sizeof(bMessageSensor), "messagesens");
156                 break;
157         case SENS_JOYSTICK:
158                 sens->data= MEM_callocN(sizeof(bJoystickSensor), "joysticksens");
159                 js= sens->data;
160                 js->hatf = SENS_JOY_HAT_UP;
161                 js->axis = 1;
162                 js->hat = 1;
163                 break;
164         default:
165                 ; /* this is very severe... I cannot make any memory for this        */
166                 /* logic brick...                                                    */
167         }
168 }
169
170 bSensor *new_sensor(int type)
171 {
172         bSensor *sens;
173
174         sens= MEM_callocN(sizeof(bSensor), "Sensor");
175         sens->type= type;
176         sens->flag= SENS_SHOW;
177         
178         init_sensor(sens);
179         
180         strcpy(sens->name, "sensor");
181 // XXX  make_unique_prop_names(sens->name);
182         
183         return sens;
184 }
185
186 /* ******************* CONTROLLERS ************************ */
187
188 void unlink_controller(bController *cont)
189 {
190         bSensor *sens;
191         Object *ob;
192         
193         /* check for controller pointers in sensors */
194         ob= G.main->object.first;
195         while (ob) {
196                 sens= ob->sensors.first;
197                 while (sens) {
198                         unlink_logicbricks((void **)&cont, (void ***)&(sens->links), &sens->totlinks);
199                         sens= sens->next;
200                 }
201                 ob= ob->id.next;
202         }
203 }
204
205 void unlink_controllers(ListBase *lb)
206 {
207         bController *cont;
208         
209         for (cont= lb->first; cont; cont= cont->next)
210                 unlink_controller(cont);
211 }
212
213 void free_controller(bController *cont)
214 {
215         if (cont->links) MEM_freeN(cont->links);
216
217         /* the controller itself */
218         if (cont->data) MEM_freeN(cont->data);
219         MEM_freeN(cont);
220         
221 }
222
223 void free_controllers(ListBase *lb)
224 {
225         bController *cont;
226         
227         while ((cont = BLI_pophead(lb))) {
228                 if (cont->slinks)
229                         MEM_freeN(cont->slinks);
230                 free_controller(cont);
231         }
232 }
233
234 bController *copy_controller(bController *cont)
235 {
236         bController *contn;
237         
238         cont->mynew=contn= MEM_dupallocN(cont);
239         contn->flag |= CONT_NEW;
240         if (cont->data) {
241                 contn->data= MEM_dupallocN(cont->data);
242         }
243
244         if (cont->links) contn->links= MEM_dupallocN(cont->links);
245         contn->slinks= NULL;
246         contn->totslinks= 0;
247         
248         return contn;
249 }
250
251 void copy_controllers(ListBase *lbn, ListBase *lbo)
252 {
253         bController *cont, *contn;
254         
255         lbn->first= lbn->last= NULL;
256         cont= lbo->first;
257         while (cont) {
258                 contn= copy_controller(cont);
259                 BLI_addtail(lbn, contn);
260                 cont= cont->next;
261         }
262 }
263
264 void init_controller(bController *cont)
265 {
266         /* also use when controller changes type, leave actuators... */
267         
268         if (cont->data) MEM_freeN(cont->data);
269         cont->data= NULL;
270         
271         switch (cont->type) {
272         case CONT_EXPRESSION:
273                 cont->data= MEM_callocN(sizeof(bExpressionCont), "expcont");
274                 break;
275         case CONT_PYTHON:
276                 cont->data= MEM_callocN(sizeof(bPythonCont), "pycont");
277                 break;
278         }
279 }
280
281 bController *new_controller(int type)
282 {
283         bController *cont;
284
285         cont= MEM_callocN(sizeof(bController), "Controller");
286         cont->type= type;
287         cont->flag= CONT_SHOW;
288
289         init_controller(cont);
290         
291         strcpy(cont->name, "cont");
292 // XXX  make_unique_prop_names(cont->name);
293         
294         return cont;
295 }
296
297 /* ******************* ACTUATORS ************************ */
298
299 void unlink_actuator(bActuator *act)
300 {
301         bController *cont;
302         Object *ob;
303         
304         /* check for actuator pointers in controllers */
305         ob= G.main->object.first;
306         while (ob) {
307                 cont= ob->controllers.first;
308                 while (cont) {
309                         unlink_logicbricks((void **)&act, (void ***)&(cont->links), &cont->totlinks);
310                         cont= cont->next;
311                 }
312                 ob= ob->id.next;
313         }
314 }
315
316 void unlink_actuators(ListBase *lb)
317 {
318         bActuator *act;
319         
320         for (act= lb->first; act; act= act->next)
321                 unlink_actuator(act);
322 }
323
324 void free_actuator(bActuator *act)
325 {
326         bSoundActuator *sa;
327
328         if (act->data) {
329                 switch (act->type) {
330                 case ACT_SOUND:
331                         sa = (bSoundActuator *) act->data;
332                         if (sa->sound)
333                                 id_us_min((ID *) sa->sound);
334                         break;
335                 }
336
337                 MEM_freeN(act->data);
338         }
339         MEM_freeN(act);
340 }
341
342 void free_actuators(ListBase *lb)
343 {
344         bActuator *act;
345         
346         while ((act = BLI_pophead(lb))) {
347                 free_actuator(act);
348         }
349 }
350
351 bActuator *copy_actuator(bActuator *act)
352 {
353         bActuator *actn;
354         bSoundActuator *sa;
355         
356         act->mynew=actn= MEM_dupallocN(act);
357         actn->flag |= ACT_NEW;
358         if (act->data) {
359                 actn->data= MEM_dupallocN(act->data);
360         }
361         
362         switch (act->type) {
363                 case ACT_SOUND:
364                         sa= (bSoundActuator *)act->data;
365                         if (sa->sound)
366                                 id_us_plus((ID *) sa->sound);
367                         break;
368         }
369         return actn;
370 }
371
372 void copy_actuators(ListBase *lbn, ListBase *lbo)
373 {
374         bActuator *act, *actn;
375         
376         lbn->first= lbn->last= NULL;
377         act= lbo->first;
378         while (act) {
379                 actn= copy_actuator(act);
380                 BLI_addtail(lbn, actn);
381                 act= act->next;
382         }
383 }
384
385 void init_actuator(bActuator *act)
386 {
387         /* also use when actuator changes type */
388         bCameraActuator *ca;
389         bObjectActuator *oa;
390         bRandomActuator *ra;
391         bSoundActuator *sa;
392         bSteeringActuator *sta;
393         bArmatureActuator *arma;
394         bMouseActuator *ma;
395         bEditObjectActuator *eoa;
396         
397         if (act->data) MEM_freeN(act->data);
398         act->data= NULL;
399         
400         switch (act->type) {
401         case ACT_ACTION:
402         case ACT_SHAPEACTION:
403                 act->data= MEM_callocN(sizeof(bActionActuator), "actionact");
404                 break;
405         case ACT_SOUND:
406                 sa = act->data= MEM_callocN(sizeof(bSoundActuator), "soundact");
407                 sa->volume = 1.0f;
408                 sa->sound3D.rolloff_factor = 1.0f;
409                 sa->sound3D.reference_distance = 1.0f;
410                 sa->sound3D.max_gain = 1.0f;
411                 sa->sound3D.cone_inner_angle = DEG2RADF(360.0f);
412                 sa->sound3D.cone_outer_angle = DEG2RADF(360.0f);
413                 sa->sound3D.max_distance = FLT_MAX;
414                 break;
415         case ACT_OBJECT:
416                 act->data= MEM_callocN(sizeof(bObjectActuator), "objectact");
417                 oa= act->data;
418                 oa->flag= 15;
419                 break;
420         case ACT_IPO:
421                 act->data= MEM_callocN(sizeof(bIpoActuator), "ipoact");
422                 break;
423         case ACT_PROPERTY:
424                 act->data= MEM_callocN(sizeof(bPropertyActuator), "propact");
425                 break;
426         case ACT_CAMERA:
427                 act->data= MEM_callocN(sizeof(bCameraActuator), "camact");
428                 ca = act->data;
429                 ca->axis = OB_POSX;
430                 ca->damping = 1.0/32.0;
431                 break;
432         case ACT_EDIT_OBJECT:
433                 act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact");
434                 eoa = act->data;
435                 eoa->upflag= ACT_TRACK_UP_Z;
436                 eoa->trackflag= ACT_TRACK_TRAXIS_Y;
437                 break;
438         case ACT_CONSTRAINT:
439                 act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act");
440                 break;
441         case ACT_SCENE:
442                 act->data= MEM_callocN(sizeof(bSceneActuator), "scene act");
443                 break;
444         case ACT_GROUP:
445                 act->data= MEM_callocN(sizeof(bGroupActuator), "group act");
446                 break;
447         case ACT_RANDOM:
448                 act->data= MEM_callocN(sizeof(bRandomActuator), "random act");
449                 ra=act->data;
450                 ra->float_arg_1 = 0.1f;
451                 break;
452         case ACT_MESSAGE:
453                 act->data= MEM_callocN(sizeof(bMessageActuator), "message act");
454                 break;
455         case ACT_GAME:
456                 act->data= MEM_callocN(sizeof(bGameActuator), "game act");
457                 break;
458         case ACT_VISIBILITY:
459                 act->data= MEM_callocN(sizeof(bVisibilityActuator), "visibility act");
460                 break;
461         case ACT_2DFILTER:
462                 act->data = MEM_callocN(sizeof( bTwoDFilterActuator ), "2d filter act");
463                 break;
464         case ACT_PARENT:
465                 act->data = MEM_callocN(sizeof( bParentActuator ), "parent act");
466                 break;
467         case ACT_STATE:
468                 act->data = MEM_callocN(sizeof( bStateActuator ), "state act");
469                 break;
470         case ACT_ARMATURE:
471                 act->data = MEM_callocN(sizeof( bArmatureActuator ), "armature act");
472                 arma = act->data;
473                 arma->influence = 1.f;
474                 break;
475         case ACT_STEERING:
476                 act->data = MEM_callocN(sizeof( bSteeringActuator), "steering act");
477                 sta = act->data;
478                 sta->acceleration = 3.f;
479                 sta->turnspeed = 120.f;
480                 sta->dist = 1.f;
481                 sta->velocity= 3.f;
482                 sta->flag = ACT_STEERING_AUTOMATICFACING;
483                 sta->facingaxis = 1;
484                 break;
485         case ACT_MOUSE:
486                 ma = act->data = MEM_callocN(sizeof( bMouseActuator ), "mouse act");
487                 ma->flag = ACT_MOUSE_VISIBLE|ACT_MOUSE_USE_AXIS_X|ACT_MOUSE_USE_AXIS_Y|ACT_MOUSE_RESET_X|ACT_MOUSE_RESET_Y|ACT_MOUSE_LOCAL_Y;
488                 ma->sensitivity[0] = ma->sensitivity[1] = 2.f;
489                 ma->object_axis[0] = ACT_MOUSE_OBJECT_AXIS_Z;
490                 ma->object_axis[1] = ACT_MOUSE_OBJECT_AXIS_X;
491                 ma->limit_y[0] = DEG2RADF(-90.0f);
492                 ma->limit_y[1] = DEG2RADF(90.0f);
493                 break;
494         default:
495                 ; /* this is very severe... I cannot make any memory for this        */
496                 /* logic brick...                                                    */
497         }
498 }
499
500 bActuator *new_actuator(int type)
501 {
502         bActuator *act;
503
504         act= MEM_callocN(sizeof(bActuator), "Actuator");
505         act->type= type;
506         act->flag= ACT_SHOW;
507         
508         init_actuator(act);
509         
510         strcpy(act->name, "act");
511 // XXX  make_unique_prop_names(act->name);
512         
513         return act;
514 }
515
516 /* ******************** GENERAL ******************* */
517 void clear_sca_new_poins_ob(Object *ob)
518 {
519         bSensor *sens;
520         bController *cont;
521         bActuator *act;
522         
523         sens= ob->sensors.first;
524         while (sens) {
525                 sens->flag &= ~SENS_NEW;
526                 sens= sens->next;
527         }
528         cont= ob->controllers.first;
529         while (cont) {
530                 cont->mynew= NULL;
531                 cont->flag &= ~CONT_NEW;
532                 cont= cont->next;
533         }
534         act= ob->actuators.first;
535         while (act) {
536                 act->mynew= NULL;
537                 act->flag &= ~ACT_NEW;
538                 act= act->next;
539         }
540 }
541
542 void clear_sca_new_poins(void)
543 {
544         Object *ob;
545         
546         ob= G.main->object.first;
547         while (ob) {
548                 clear_sca_new_poins_ob(ob);
549                 ob= ob->id.next;
550         }
551 }
552
553 void set_sca_new_poins_ob(Object *ob)
554 {
555         bSensor *sens;
556         bController *cont;
557         bActuator *act;
558         int a;
559         
560         sens= ob->sensors.first;
561         while (sens) {
562                 if (sens->flag & SENS_NEW) {
563                         for (a=0; a<sens->totlinks; a++) {
564                                 if (sens->links[a] && sens->links[a]->mynew)
565                                         sens->links[a] = sens->links[a]->mynew;
566                         }
567                 }
568                 sens= sens->next;
569         }
570
571         cont= ob->controllers.first;
572         while (cont) {
573                 if (cont->flag & CONT_NEW) {
574                         for (a=0; a<cont->totlinks; a++) {
575                                 if ( cont->links[a] && cont->links[a]->mynew)
576                                         cont->links[a] = cont->links[a]->mynew;
577                         }
578                 }
579                 cont= cont->next;
580         }
581         
582         
583         act= ob->actuators.first;
584         while (act) {
585                 if (act->flag & ACT_NEW) {
586                         if (act->type==ACT_EDIT_OBJECT) {
587                                 bEditObjectActuator *eoa= act->data;
588                                 ID_NEW(eoa->ob);
589                         }
590                         else if (act->type==ACT_SCENE) {
591                                 bSceneActuator *sca= act->data;
592                                 ID_NEW(sca->camera);
593                         }
594                         else if (act->type==ACT_CAMERA) {
595                                 bCameraActuator *ca= act->data;
596                                 ID_NEW(ca->ob);
597                         }
598                         else if (act->type==ACT_OBJECT) {
599                                 bObjectActuator *oa= act->data;
600                                 ID_NEW(oa->reference);
601                         }
602                         else if (act->type==ACT_MESSAGE) {
603                                 bMessageActuator *ma= act->data;
604                                 ID_NEW(ma->toObject);
605                         }
606                         else if (act->type==ACT_PARENT) {
607                                 bParentActuator *para = act->data;
608                                 ID_NEW(para->ob);
609                         }
610                         else if (act->type==ACT_ARMATURE) {
611                                 bArmatureActuator *aa = act->data;
612                                 ID_NEW(aa->target);
613                                 ID_NEW(aa->subtarget);
614                         }
615                         else if (act->type==ACT_PROPERTY) {
616                                 bPropertyActuator *pa= act->data;
617                                 ID_NEW(pa->ob);
618                         }
619                         else if (act->type==ACT_STEERING) {
620                                 bSteeringActuator *sta = act->data;
621                                 ID_NEW(sta->navmesh);
622                                 ID_NEW(sta->target);
623                         }
624                 }
625                 act= act->next;
626         }
627 }
628
629
630 void set_sca_new_poins(void)
631 {
632         Object *ob;
633         
634         ob= G.main->object.first;
635         while (ob) {
636                 set_sca_new_poins_ob(ob);
637                 ob= ob->id.next;
638         }
639 }
640
641 void sca_remove_ob_poin(Object *obt, Object *ob)
642 {
643         bSensor *sens;
644         bMessageSensor *ms;
645         bActuator *act;
646         bCameraActuator *ca;
647         bObjectActuator *oa;
648         bSceneActuator *sa;
649         bEditObjectActuator *eoa;
650         bPropertyActuator *pa;
651         bMessageActuator *ma;
652         bParentActuator *para;
653         bArmatureActuator *aa;
654         bSteeringActuator *sta;
655
656
657         sens= obt->sensors.first;
658         while (sens) {
659                 switch (sens->type) {
660                 case SENS_MESSAGE:
661                         ms= sens->data;
662                         if (ms->fromObject==ob) ms->fromObject= NULL;
663                 }
664                 sens= sens->next;
665         }
666
667         act= obt->actuators.first;
668         while (act) {
669                 switch (act->type) {
670                 case ACT_CAMERA:
671                         ca= act->data;
672                         if (ca->ob==ob) ca->ob= NULL;
673                         break;
674                 case ACT_OBJECT:
675                         oa= act->data;
676                         if (oa->reference==ob) oa->reference= NULL;
677                         break;
678                 case ACT_PROPERTY:
679                         pa= act->data;
680                         if (pa->ob==ob) pa->ob= NULL;
681                         break;
682                 case ACT_SCENE:
683                         sa= act->data;
684                         if (sa->camera==ob) sa->camera= NULL;
685                         break;
686                 case ACT_EDIT_OBJECT:
687                         eoa= act->data;
688                         if (eoa->ob==ob) eoa->ob= NULL;
689                         break;
690                 case ACT_MESSAGE:
691                         ma= act->data;
692                         if (ma->toObject==ob) ma->toObject= NULL;
693                         break;
694                 case ACT_PARENT:
695                         para = act->data;
696                         if (para->ob==ob) para->ob = NULL;
697                         break;
698                 case ACT_ARMATURE:
699                         aa = act->data;
700                         if (aa->target == ob) aa->target = NULL;
701                         if (aa->subtarget == ob) aa->subtarget = NULL;
702                         break;
703                 case ACT_STEERING:
704                         sta = act->data;
705                         if (sta->navmesh == ob) sta->navmesh = NULL;
706                         if (sta->target == ob) sta->target = NULL;
707                 }
708                 act= act->next;
709         }
710 }
711
712 /* ******************** INTERFACE ******************* */
713 void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up)
714 {
715         bSensor *sens, *tmp;
716
717         int val;
718         val = move_up ? 1 : 2;
719
720         /* make sure this sensor belongs to this object */
721         sens= ob->sensors.first;
722         while (sens) {
723                 if (sens == sens_to_move) break;
724                 sens= sens->next;
725         }
726         if (!sens) return;
727
728         /* move up */
729         if (val == 1 && sens->prev) {
730                 for (tmp=sens->prev; tmp; tmp=tmp->prev) {
731                         if (tmp->flag & SENS_VISIBLE)
732                                 break;
733                 }
734                 if (tmp) {
735                         BLI_remlink(&ob->sensors, sens);
736                         BLI_insertlinkbefore(&ob->sensors, tmp, sens);
737                 }
738         }
739         /* move down */
740         else if (val == 2 && sens->next) {
741                 for (tmp=sens->next; tmp; tmp=tmp->next) {
742                         if (tmp->flag & SENS_VISIBLE)
743                                 break;
744                 }
745                 if (tmp) {
746                         BLI_remlink(&ob->sensors, sens);
747                         BLI_insertlinkafter(&ob->sensors, tmp, sens);
748                 }
749         }
750 }
751
752 void sca_move_controller(bController *cont_to_move, Object *ob, int move_up)
753 {
754         bController *cont, *tmp;
755
756         int val;
757         val = move_up ? 1 : 2;
758
759         /* make sure this controller belongs to this object */
760         cont= ob->controllers.first;
761         while (cont) {
762                 if (cont == cont_to_move) break;
763                 cont= cont->next;
764         }
765         if (!cont) return;
766
767         /* move up */
768         if (val == 1 && cont->prev) {
769                 /* locate the controller that has the same state mask but is earlier in the list */
770                 tmp = cont->prev;
771                 while (tmp) {
772                         if (tmp->state_mask & cont->state_mask) 
773                                 break;
774                         tmp = tmp->prev;
775                 }
776                 if (tmp) {
777                         BLI_remlink(&ob->controllers, cont);
778                         BLI_insertlinkbefore(&ob->controllers, tmp, cont);
779                 }
780         }
781
782         /* move down */
783         else if (val == 2 && cont->next) {
784                 tmp = cont->next;
785                 while (tmp) {
786                         if (tmp->state_mask & cont->state_mask) 
787                                 break;
788                         tmp = tmp->next;
789                 }
790                 BLI_remlink(&ob->controllers, cont);
791                 BLI_insertlinkafter(&ob->controllers, tmp, cont);
792         }
793 }
794
795 void sca_move_actuator(bActuator *act_to_move, Object *ob, int move_up)
796 {
797         bActuator *act, *tmp;
798         int val;
799
800         val = move_up ? 1 : 2;
801
802         /* make sure this actuator belongs to this object */
803         act= ob->actuators.first;
804         while (act) {
805                 if (act == act_to_move) break;
806                 act= act->next;
807         }
808         if (!act) return;
809
810         /* move up */
811         if (val == 1 && act->prev) {
812                 /* locate the first visible actuators before this one */
813                 for (tmp = act->prev; tmp; tmp=tmp->prev) {
814                         if (tmp->flag & ACT_VISIBLE)
815                                 break;
816                 }
817                 if (tmp) {
818                         BLI_remlink(&ob->actuators, act);
819                         BLI_insertlinkbefore(&ob->actuators, tmp, act);
820                 }
821         }
822         /* move down */
823         else if (val == 2 && act->next) {
824                 /* locate the first visible actuators after this one */
825                 for (tmp=act->next; tmp; tmp=tmp->next) {
826                         if (tmp->flag & ACT_VISIBLE)
827                                 break;
828                 }
829                 if (tmp) {
830                         BLI_remlink(&ob->actuators, act);
831                         BLI_insertlinkafter(&ob->actuators, tmp, act);
832                 }
833         }
834 }
835
836 void link_logicbricks(void **poin, void ***ppoin, short *tot, short size)
837 {
838         void **old_links= NULL;
839         
840         int ibrick;
841
842         /* check if the bricks are already linked */
843         for (ibrick=0; ibrick < *tot; ibrick++) {
844                 if ((*ppoin)[ibrick] == *poin)
845                         return;
846         }
847
848         if (*ppoin) {
849                 old_links= *ppoin;
850
851                 (*tot) ++;
852                 *ppoin = MEM_callocN((*tot)*size, "new link");
853         
854                 for (ibrick=0; ibrick < *(tot) - 1; ibrick++) {
855                         (*ppoin)[ibrick] = old_links[ibrick];
856                 }
857                 (*ppoin)[ibrick] = *poin;
858
859                 if (old_links) MEM_freeN(old_links);
860         }
861         else {
862                 (*tot) = 1;
863                 *ppoin = MEM_callocN((*tot)*size, "new link");
864                 (*ppoin)[0] = *poin;
865         }
866 }
867
868 void unlink_logicbricks(void **poin, void ***ppoin, short *tot)
869 {
870         int ibrick, removed;
871
872         removed= 0;
873         for (ibrick=0; ibrick < *tot; ibrick++) {
874                 if (removed) (*ppoin)[ibrick - removed] = (*ppoin)[ibrick];
875                 else if ((*ppoin)[ibrick] == *poin) removed = 1;
876         }
877
878         if (removed) {
879                 (*tot) --;
880
881                 if (*tot == 0) {
882                         MEM_freeN(*ppoin);
883                         (*ppoin)= NULL;
884                 }
885                 return;
886         }
887 }
888
889 const char *sca_state_name_get(Object *ob, short bit)
890 {
891         bController *cont;
892         unsigned int mask;
893
894         mask = (1<<bit);
895         cont = ob->controllers.first;
896         while (cont) {
897                 if (cont->state_mask & mask) {
898                         return cont->name;
899                 }
900                 cont = cont->next;
901         }
902         return NULL;
903 }
904