1310162483e3191e1cffa5466e01f969b8ca02bd
[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         
396         if (act->data) MEM_freeN(act->data);
397         act->data= NULL;
398         
399         switch (act->type) {
400         case ACT_ACTION:
401         case ACT_SHAPEACTION:
402                 act->data= MEM_callocN(sizeof(bActionActuator), "actionact");
403                 break;
404         case ACT_SOUND:
405                 sa = act->data= MEM_callocN(sizeof(bSoundActuator), "soundact");
406                 sa->volume = 1.0f;
407                 sa->sound3D.rolloff_factor = 1.0f;
408                 sa->sound3D.reference_distance = 1.0f;
409                 sa->sound3D.max_gain = 1.0f;
410                 sa->sound3D.cone_inner_angle = DEG2RADF(360.0f);
411                 sa->sound3D.cone_outer_angle = DEG2RADF(360.0f);
412                 sa->sound3D.max_distance = FLT_MAX;
413                 break;
414         case ACT_OBJECT:
415                 act->data= MEM_callocN(sizeof(bObjectActuator), "objectact");
416                 oa= act->data;
417                 oa->flag= 15;
418                 break;
419         case ACT_IPO:
420                 act->data= MEM_callocN(sizeof(bIpoActuator), "ipoact");
421                 break;
422         case ACT_PROPERTY:
423                 act->data= MEM_callocN(sizeof(bPropertyActuator), "propact");
424                 break;
425         case ACT_CAMERA:
426                 act->data= MEM_callocN(sizeof(bCameraActuator), "camact");
427                 ca = act->data;
428                 ca->axis = OB_POSX;
429                 ca->damping = 1.0/32.0;
430                 break;
431         case ACT_EDIT_OBJECT:
432                 act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact");
433                 break;
434         case ACT_CONSTRAINT:
435                 act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act");
436                 break;
437         case ACT_SCENE:
438                 act->data= MEM_callocN(sizeof(bSceneActuator), "scene act");
439                 break;
440         case ACT_GROUP:
441                 act->data= MEM_callocN(sizeof(bGroupActuator), "group act");
442                 break;
443         case ACT_RANDOM:
444                 act->data= MEM_callocN(sizeof(bRandomActuator), "random act");
445                 ra=act->data;
446                 ra->float_arg_1 = 0.1f;
447                 break;
448         case ACT_MESSAGE:
449                 act->data= MEM_callocN(sizeof(bMessageActuator), "message act");
450                 break;
451         case ACT_GAME:
452                 act->data= MEM_callocN(sizeof(bGameActuator), "game act");
453                 break;
454         case ACT_VISIBILITY:
455                 act->data= MEM_callocN(sizeof(bVisibilityActuator), "visibility act");
456                 break;
457         case ACT_2DFILTER:
458                 act->data = MEM_callocN(sizeof( bTwoDFilterActuator ), "2d filter act");
459                 break;
460         case ACT_PARENT:
461                 act->data = MEM_callocN(sizeof( bParentActuator ), "parent act");
462                 break;
463         case ACT_STATE:
464                 act->data = MEM_callocN(sizeof( bStateActuator ), "state act");
465                 break;
466         case ACT_ARMATURE:
467                 act->data = MEM_callocN(sizeof( bArmatureActuator ), "armature act");
468                 arma = act->data;
469                 arma->influence = 1.f;
470                 break;
471         case ACT_STEERING:
472                 act->data = MEM_callocN(sizeof( bSteeringActuator), "steering act");
473                 sta = act->data;
474                 sta->acceleration = 3.f;
475                 sta->turnspeed = 120.f;
476                 sta->dist = 1.f;
477                 sta->velocity= 3.f;
478                 sta->flag = ACT_STEERING_AUTOMATICFACING;
479                 sta->facingaxis = 1;
480                 break;
481         case ACT_MOUSE:
482                 ma = act->data = MEM_callocN(sizeof( bMouseActuator ), "mouse act");
483                 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;
484                 ma->sensitivity[0] = ma->sensitivity[1] = 2.f;
485                 ma->object_axis[0] = ACT_MOUSE_OBJECT_AXIS_Z;
486                 ma->object_axis[1] = ACT_MOUSE_OBJECT_AXIS_X;
487                 ma->limit_y[0] = DEG2RADF(-90.0f);
488                 ma->limit_y[1] = DEG2RADF(90.0f);
489                 break;
490         default:
491                 ; /* this is very severe... I cannot make any memory for this        */
492                 /* logic brick...                                                    */
493         }
494 }
495
496 bActuator *new_actuator(int type)
497 {
498         bActuator *act;
499
500         act= MEM_callocN(sizeof(bActuator), "Actuator");
501         act->type= type;
502         act->flag= ACT_SHOW;
503         
504         init_actuator(act);
505         
506         strcpy(act->name, "act");
507 // XXX  make_unique_prop_names(act->name);
508         
509         return act;
510 }
511
512 /* ******************** GENERAL ******************* */
513 void clear_sca_new_poins_ob(Object *ob)
514 {
515         bSensor *sens;
516         bController *cont;
517         bActuator *act;
518         
519         sens= ob->sensors.first;
520         while (sens) {
521                 sens->flag &= ~SENS_NEW;
522                 sens= sens->next;
523         }
524         cont= ob->controllers.first;
525         while (cont) {
526                 cont->mynew= NULL;
527                 cont->flag &= ~CONT_NEW;
528                 cont= cont->next;
529         }
530         act= ob->actuators.first;
531         while (act) {
532                 act->mynew= NULL;
533                 act->flag &= ~ACT_NEW;
534                 act= act->next;
535         }
536 }
537
538 void clear_sca_new_poins(void)
539 {
540         Object *ob;
541         
542         ob= G.main->object.first;
543         while (ob) {
544                 clear_sca_new_poins_ob(ob);
545                 ob= ob->id.next;
546         }
547 }
548
549 void set_sca_new_poins_ob(Object *ob)
550 {
551         bSensor *sens;
552         bController *cont;
553         bActuator *act;
554         int a;
555         
556         sens= ob->sensors.first;
557         while (sens) {
558                 if (sens->flag & SENS_NEW) {
559                         for (a=0; a<sens->totlinks; a++) {
560                                 if (sens->links[a] && sens->links[a]->mynew)
561                                         sens->links[a] = sens->links[a]->mynew;
562                         }
563                 }
564                 sens= sens->next;
565         }
566
567         cont= ob->controllers.first;
568         while (cont) {
569                 if (cont->flag & CONT_NEW) {
570                         for (a=0; a<cont->totlinks; a++) {
571                                 if ( cont->links[a] && cont->links[a]->mynew)
572                                         cont->links[a] = cont->links[a]->mynew;
573                         }
574                 }
575                 cont= cont->next;
576         }
577         
578         
579         act= ob->actuators.first;
580         while (act) {
581                 if (act->flag & ACT_NEW) {
582                         if (act->type==ACT_EDIT_OBJECT) {
583                                 bEditObjectActuator *eoa= act->data;
584                                 ID_NEW(eoa->ob);
585                         }
586                         else if (act->type==ACT_SCENE) {
587                                 bSceneActuator *sca= act->data;
588                                 ID_NEW(sca->camera);
589                         }
590                         else if (act->type==ACT_CAMERA) {
591                                 bCameraActuator *ca= act->data;
592                                 ID_NEW(ca->ob);
593                         }
594                         else if (act->type==ACT_OBJECT) {
595                                 bObjectActuator *oa= act->data;
596                                 ID_NEW(oa->reference);
597                         }
598                         else if (act->type==ACT_MESSAGE) {
599                                 bMessageActuator *ma= act->data;
600                                 ID_NEW(ma->toObject);
601                         }
602                         else if (act->type==ACT_PARENT) {
603                                 bParentActuator *para = act->data;
604                                 ID_NEW(para->ob);
605                         }
606                         else if (act->type==ACT_ARMATURE) {
607                                 bArmatureActuator *aa = act->data;
608                                 ID_NEW(aa->target);
609                                 ID_NEW(aa->subtarget);
610                         }
611                         else if (act->type==ACT_PROPERTY) {
612                                 bPropertyActuator *pa= act->data;
613                                 ID_NEW(pa->ob);
614                         }
615                         else if (act->type==ACT_STEERING) {
616                                 bSteeringActuator *sta = act->data;
617                                 ID_NEW(sta->navmesh);
618                                 ID_NEW(sta->target);
619                         }
620                 }
621                 act= act->next;
622         }
623 }
624
625
626 void set_sca_new_poins(void)
627 {
628         Object *ob;
629         
630         ob= G.main->object.first;
631         while (ob) {
632                 set_sca_new_poins_ob(ob);
633                 ob= ob->id.next;
634         }
635 }
636
637 void sca_remove_ob_poin(Object *obt, Object *ob)
638 {
639         bSensor *sens;
640         bMessageSensor *ms;
641         bActuator *act;
642         bCameraActuator *ca;
643         bObjectActuator *oa;
644         bSceneActuator *sa;
645         bEditObjectActuator *eoa;
646         bPropertyActuator *pa;
647         bMessageActuator *ma;
648         bParentActuator *para;
649         bArmatureActuator *aa;
650         bSteeringActuator *sta;
651
652
653         sens= obt->sensors.first;
654         while (sens) {
655                 switch (sens->type) {
656                 case SENS_MESSAGE:
657                         ms= sens->data;
658                         if (ms->fromObject==ob) ms->fromObject= NULL;
659                 }
660                 sens= sens->next;
661         }
662
663         act= obt->actuators.first;
664         while (act) {
665                 switch (act->type) {
666                 case ACT_CAMERA:
667                         ca= act->data;
668                         if (ca->ob==ob) ca->ob= NULL;
669                         break;
670                 case ACT_OBJECT:
671                         oa= act->data;
672                         if (oa->reference==ob) oa->reference= NULL;
673                         break;
674                 case ACT_PROPERTY:
675                         pa= act->data;
676                         if (pa->ob==ob) pa->ob= NULL;
677                         break;
678                 case ACT_SCENE:
679                         sa= act->data;
680                         if (sa->camera==ob) sa->camera= NULL;
681                         break;
682                 case ACT_EDIT_OBJECT:
683                         eoa= act->data;
684                         if (eoa->ob==ob) eoa->ob= NULL;
685                         break;
686                 case ACT_MESSAGE:
687                         ma= act->data;
688                         if (ma->toObject==ob) ma->toObject= NULL;
689                         break;
690                 case ACT_PARENT:
691                         para = act->data;
692                         if (para->ob==ob) para->ob = NULL;
693                         break;
694                 case ACT_ARMATURE:
695                         aa = act->data;
696                         if (aa->target == ob) aa->target = NULL;
697                         if (aa->subtarget == ob) aa->subtarget = NULL;
698                         break;
699                 case ACT_STEERING:
700                         sta = act->data;
701                         if (sta->navmesh == ob) sta->navmesh = NULL;
702                         if (sta->target == ob) sta->target = NULL;
703                 }
704                 act= act->next;
705         }
706 }
707
708 /* ******************** INTERFACE ******************* */
709 void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up)
710 {
711         bSensor *sens, *tmp;
712
713         int val;
714         val = move_up ? 1 : 2;
715
716         /* make sure this sensor belongs to this object */
717         sens= ob->sensors.first;
718         while (sens) {
719                 if (sens == sens_to_move) break;
720                 sens= sens->next;
721         }
722         if (!sens) return;
723
724         /* move up */
725         if (val == 1 && sens->prev) {
726                 for (tmp=sens->prev; tmp; tmp=tmp->prev) {
727                         if (tmp->flag & SENS_VISIBLE)
728                                 break;
729                 }
730                 if (tmp) {
731                         BLI_remlink(&ob->sensors, sens);
732                         BLI_insertlinkbefore(&ob->sensors, tmp, sens);
733                 }
734         }
735         /* move down */
736         else if (val == 2 && sens->next) {
737                 for (tmp=sens->next; tmp; tmp=tmp->next) {
738                         if (tmp->flag & SENS_VISIBLE)
739                                 break;
740                 }
741                 if (tmp) {
742                         BLI_remlink(&ob->sensors, sens);
743                         BLI_insertlinkafter(&ob->sensors, tmp, sens);
744                 }
745         }
746 }
747
748 void sca_move_controller(bController *cont_to_move, Object *ob, int move_up)
749 {
750         bController *cont, *tmp;
751
752         int val;
753         val = move_up ? 1 : 2;
754
755         /* make sure this controller belongs to this object */
756         cont= ob->controllers.first;
757         while (cont) {
758                 if (cont == cont_to_move) break;
759                 cont= cont->next;
760         }
761         if (!cont) return;
762
763         /* move up */
764         if (val == 1 && cont->prev) {
765                 /* locate the controller that has the same state mask but is earlier in the list */
766                 tmp = cont->prev;
767                 while (tmp) {
768                         if (tmp->state_mask & cont->state_mask) 
769                                 break;
770                         tmp = tmp->prev;
771                 }
772                 if (tmp) {
773                         BLI_remlink(&ob->controllers, cont);
774                         BLI_insertlinkbefore(&ob->controllers, tmp, cont);
775                 }
776         }
777
778         /* move down */
779         else if (val == 2 && cont->next) {
780                 tmp = cont->next;
781                 while (tmp) {
782                         if (tmp->state_mask & cont->state_mask) 
783                                 break;
784                         tmp = tmp->next;
785                 }
786                 BLI_remlink(&ob->controllers, cont);
787                 BLI_insertlinkafter(&ob->controllers, tmp, cont);
788         }
789 }
790
791 void sca_move_actuator(bActuator *act_to_move, Object *ob, int move_up)
792 {
793         bActuator *act, *tmp;
794         int val;
795
796         val = move_up ? 1 : 2;
797
798         /* make sure this actuator belongs to this object */
799         act= ob->actuators.first;
800         while (act) {
801                 if (act == act_to_move) break;
802                 act= act->next;
803         }
804         if (!act) return;
805
806         /* move up */
807         if (val == 1 && act->prev) {
808                 /* locate the first visible actuators before this one */
809                 for (tmp = act->prev; tmp; tmp=tmp->prev) {
810                         if (tmp->flag & ACT_VISIBLE)
811                                 break;
812                 }
813                 if (tmp) {
814                         BLI_remlink(&ob->actuators, act);
815                         BLI_insertlinkbefore(&ob->actuators, tmp, act);
816                 }
817         }
818         /* move down */
819         else if (val == 2 && act->next) {
820                 /* locate the first visible actuators after this one */
821                 for (tmp=act->next; tmp; tmp=tmp->next) {
822                         if (tmp->flag & ACT_VISIBLE)
823                                 break;
824                 }
825                 if (tmp) {
826                         BLI_remlink(&ob->actuators, act);
827                         BLI_insertlinkafter(&ob->actuators, tmp, act);
828                 }
829         }
830 }
831
832 void link_logicbricks(void **poin, void ***ppoin, short *tot, short size)
833 {
834         void **old_links= NULL;
835         
836         int ibrick;
837
838         /* check if the bricks are already linked */
839         for (ibrick=0; ibrick < *tot; ibrick++) {
840                 if ((*ppoin)[ibrick] == *poin)
841                         return;
842         }
843
844         if (*ppoin) {
845                 old_links= *ppoin;
846
847                 (*tot) ++;
848                 *ppoin = MEM_callocN((*tot)*size, "new link");
849         
850                 for (ibrick=0; ibrick < *(tot) - 1; ibrick++) {
851                         (*ppoin)[ibrick] = old_links[ibrick];
852                 }
853                 (*ppoin)[ibrick] = *poin;
854
855                 if (old_links) MEM_freeN(old_links);
856         }
857         else {
858                 (*tot) = 1;
859                 *ppoin = MEM_callocN((*tot)*size, "new link");
860                 (*ppoin)[0] = *poin;
861         }
862 }
863
864 void unlink_logicbricks(void **poin, void ***ppoin, short *tot)
865 {
866         int ibrick, removed;
867
868         removed= 0;
869         for (ibrick=0; ibrick < *tot; ibrick++) {
870                 if (removed) (*ppoin)[ibrick - removed] = (*ppoin)[ibrick];
871                 else if ((*ppoin)[ibrick] == *poin) removed = 1;
872         }
873
874         if (removed) {
875                 (*tot) --;
876
877                 if (*tot == 0) {
878                         MEM_freeN(*ppoin);
879                         (*ppoin)= NULL;
880                 }
881                 return;
882         }
883 }
884
885 const char *sca_state_name_get(Object *ob, short bit)
886 {
887         bController *cont;
888         unsigned int mask;
889
890         mask = (1<<bit);
891         cont = ob->controllers.first;
892         while (cont) {
893                 if (cont->state_mask & mask) {
894                         return cont->name;
895                 }
896                 cont = cont->next;
897         }
898         return NULL;
899 }
900