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