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