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