synched with trunk at revision 30597
[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.f;
472                 sta->turnspeed = 120.f;
473                 sta->dist = 1.f;
474                 sta->velocity= 3.f;
475         default:
476                 ; /* this is very severe... I cannot make any memory for this        */
477                 /* logic brick...                                                    */
478         }
479 }
480
481 bActuator *new_actuator(int type)
482 {
483         bActuator *act;
484
485         act= MEM_callocN(sizeof(bActuator), "Actuator");
486         act->type= type;
487         act->flag= ACT_SHOW;
488         
489         init_actuator(act);
490         
491         strcpy(act->name, "act");
492 // XXX  make_unique_prop_names(act->name);
493         
494         return act;
495 }
496
497 /* ******************** GENERAL ******************* */
498 void clear_sca_new_poins_ob(Object *ob)
499 {
500         bSensor *sens;
501         bController *cont;
502         bActuator *act;
503         
504         sens= ob->sensors.first;
505         while(sens) {
506                 sens->flag &= ~SENS_NEW;
507                 sens= sens->next;
508         }
509         cont= ob->controllers.first;
510         while(cont) {
511                 cont->mynew= NULL;
512                 cont->flag &= ~CONT_NEW;
513                 cont= cont->next;
514         }
515         act= ob->actuators.first;
516         while(act) {
517                 act->mynew= NULL;
518                 act->flag &= ~ACT_NEW;
519                 act= act->next;
520         }
521 }
522
523 void clear_sca_new_poins()
524 {
525         Object *ob;
526         
527         ob= G.main->object.first;
528         while(ob) {
529                 clear_sca_new_poins_ob(ob);
530                 ob= ob->id.next;        
531         }
532 }
533
534 void set_sca_new_poins_ob(Object *ob)
535 {
536         bSensor *sens;
537         bController *cont;
538         bActuator *act;
539         int a;
540         
541         sens= ob->sensors.first;
542         while(sens) {
543                 if(sens->flag & SENS_NEW) {
544                         for(a=0; a<sens->totlinks; a++) {
545                                 if(sens->links[a] && sens->links[a]->mynew)
546                                         sens->links[a]= sens->links[a]->mynew;
547                         }
548                 }
549                 sens= sens->next;
550         }
551
552         cont= ob->controllers.first;
553         while(cont) {
554                 if(cont->flag & CONT_NEW) {
555                         for(a=0; a<cont->totlinks; a++) {
556                                 if( cont->links[a] && cont->links[a]->mynew)
557                                         cont->links[a]= cont->links[a]->mynew;
558                         }
559                 }
560                 cont= cont->next;
561         }
562         
563         
564         act= ob->actuators.first;
565         while(act) {
566                 if(act->flag & ACT_NEW) {
567                         if(act->type==ACT_EDIT_OBJECT) {
568                                 bEditObjectActuator *eoa= act->data;
569                                 ID_NEW(eoa->ob);
570                         }
571                         else if(act->type==ACT_SCENE) {
572                                 bSceneActuator *sca= act->data;
573                                 ID_NEW(sca->camera);
574                         }
575                         else if(act->type==ACT_CAMERA) {
576                                 bCameraActuator *ca= act->data;
577                                 ID_NEW(ca->ob);
578                         }
579                         else if(act->type==ACT_OBJECT) {
580                                 bObjectActuator *oa= act->data;
581                                 ID_NEW(oa->reference);
582                         }
583                         else if(act->type==ACT_SCENE) {
584                                 bSceneActuator *sca= act->data;
585                                 ID_NEW(sca->camera);
586                         }
587                 }
588                 act= act->next;
589         }
590 }
591
592
593 void set_sca_new_poins()
594 {
595         Object *ob;
596         
597         ob= G.main->object.first;
598         while(ob) {
599                 set_sca_new_poins_ob(ob);
600                 ob= ob->id.next;        
601         }
602 }
603
604 void sca_remove_ob_poin(Object *obt, Object *ob)
605 {
606         bSensor *sens;
607         bMessageSensor *ms;
608         bActuator *act;
609         bCameraActuator *ca;
610         bObjectActuator *oa;
611         bSceneActuator *sa;
612         bEditObjectActuator *eoa;
613         bPropertyActuator *pa;
614         bMessageActuator *ma;
615         bParentActuator *para;
616         bArmatureActuator *aa;
617         bSteeringActuator *sta;
618
619         sens= obt->sensors.first;
620         while(sens) {
621                 switch(sens->type) {
622                 case SENS_MESSAGE:
623                         ms= sens->data;
624                         if(ms->fromObject==ob) ms->fromObject= NULL;
625                 }
626                 sens= sens->next;
627         }
628
629         act= obt->actuators.first;
630         while(act) {
631                 switch(act->type) {
632                 case ACT_CAMERA:
633                         ca= act->data;
634                         if(ca->ob==ob) ca->ob= NULL;
635                         break;
636                 case ACT_OBJECT:
637                         oa= act->data;
638                         if(oa->reference==ob) oa->reference= NULL;
639                         break;
640                 case ACT_PROPERTY:
641                         pa= act->data;
642                         if(pa->ob==ob) pa->ob= NULL;
643                         break;
644                 case ACT_SCENE:
645                         sa= act->data;
646                         if(sa->camera==ob) sa->camera= NULL;
647                         break;
648                 case ACT_EDIT_OBJECT:
649                         eoa= act->data;
650                         if(eoa->ob==ob) eoa->ob= NULL;
651                         break;
652                 case ACT_MESSAGE:
653                         ma= act->data;
654                         if(ma->toObject==ob) ma->toObject= NULL;
655                         break;
656                 case ACT_PARENT:
657                         para = act->data;
658                         if (para->ob==ob) para->ob = NULL;
659                         break;
660                 case ACT_ARMATURE:
661                         aa = act->data;
662                         if (aa->target == ob) aa->target = NULL;
663                         if (aa->subtarget == ob) aa->subtarget = NULL;
664                         break;
665                 case ACT_STEERING:
666                         sta = act->data;
667                         if (sta->target==ob) sta->target = NULL;
668                         if (sta->navmesh==ob) sta->navmesh = NULL;
669                         break;                  
670                 }
671                 act= act->next;
672         }       
673 }
674
675 /* ******************** INTERFACE ******************* */
676 void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up)
677 {
678         bSensor *sens, *tmp;
679
680         int val;
681         val = move_up ? 1:2;
682
683         /* make sure this sensor belongs to this object */
684         sens= ob->sensors.first;
685         while(sens) {
686                 if(sens == sens_to_move) break;
687                 sens= sens->next;
688         }
689         if(!sens) return;
690
691         /* move up */
692         if( val==1 && sens->prev) {
693                 for (tmp=sens->prev; tmp; tmp=tmp->prev) {
694                         if (tmp->flag & SENS_VISIBLE)
695                                 break;
696                 }
697                 if (tmp) {
698                         BLI_remlink(&ob->sensors, sens);
699                         BLI_insertlinkbefore(&ob->sensors, tmp, sens);
700                 }
701         }
702         /* move down */
703         else if( val==2 && sens->next) {
704                 for (tmp=sens->next; tmp; tmp=tmp->next) {
705                         if (tmp->flag & SENS_VISIBLE)
706                                 break;
707                 }
708                 if (tmp) {
709                         BLI_remlink(&ob->sensors, sens);
710                         BLI_insertlink(&ob->sensors, tmp, sens);
711                 }
712         }
713 }
714
715 void sca_move_controller(bController *cont_to_move, Object *ob, int move_up)
716 {
717         bController *cont, *tmp;
718
719         int val;
720         val = move_up ? 1:2;
721
722         /* make sure this controller belongs to this object */
723         cont= ob->controllers.first;
724         while(cont) {
725                 if(cont == cont_to_move) break;
726                 cont= cont->next;
727         }
728         if(!cont) return;
729
730         /* move up */
731         if( val==1 && cont->prev) {
732                 /* locate the controller that has the same state mask but is earlier in the list */
733                 tmp = cont->prev;
734                 while(tmp) {
735                         if(tmp->state_mask & cont->state_mask) 
736                                 break;
737                         tmp = tmp->prev;
738                 }
739                 if (tmp) {
740                         BLI_remlink(&ob->controllers, cont);
741                         BLI_insertlinkbefore(&ob->controllers, tmp, cont);
742                 }
743         }
744
745         /* move down */
746         else if( val==2 && cont->next) {
747                 tmp = cont->next;
748                 while(tmp) {
749                         if(tmp->state_mask & cont->state_mask) 
750                                 break;
751                         tmp = tmp->next;
752                 }
753                 BLI_remlink(&ob->controllers, cont);
754                 BLI_insertlink(&ob->controllers, tmp, cont);
755         }
756 }
757
758 void sca_move_actuator(bActuator *act_to_move, Object *ob, int move_up)
759 {
760         bActuator *act, *tmp;
761         int val;
762
763         val = move_up ? 1:2;
764
765         /* make sure this actuator belongs to this object */
766         act= ob->actuators.first;
767         while(act) {
768                 if(act == act_to_move) break;
769                 act= act->next;
770         }
771         if(!act) return;
772
773         /* move up */
774         if( val==1 && act->prev) {
775                 /* locate the first visible actuators before this one */
776                 for (tmp = act->prev; tmp; tmp=tmp->prev) {
777                         if (tmp->flag & ACT_VISIBLE)
778                                 break;
779                 }
780                 if (tmp) {
781                         BLI_remlink(&ob->actuators, act);
782                         BLI_insertlinkbefore(&ob->actuators, tmp, act);
783                 }
784         }
785         /* move down */
786         else if( val==2 && act->next) {
787                 /* locate the first visible actuators after this one */
788                 for (tmp=act->next; tmp; tmp=tmp->next) {
789                         if (tmp->flag & ACT_VISIBLE)
790                                 break;
791                 }
792                 if (tmp) {
793                         BLI_remlink(&ob->actuators, act);
794                         BLI_insertlink(&ob->actuators, tmp, act);
795                 }
796         }
797 }
798
799 void link_logicbricks(void **poin, void ***ppoin, short *tot, short size)
800 {
801         void **old_links= NULL;
802         
803         int ibrick;
804
805         /* check if the bricks are already linked */
806         for (ibrick=0; ibrick < *tot; ibrick++) {
807                 if ((*ppoin)[ibrick] == *poin)
808                         return;
809         }
810
811         if (*ppoin) {
812                 old_links= *ppoin;
813
814                 (*tot) ++;
815                 *ppoin = MEM_callocN((*tot)*size, "new link");
816         
817                 for (ibrick=0; ibrick < *(tot) - 1; ibrick++) {
818                         (*ppoin)[ibrick] = old_links[ibrick];
819                 }
820                 (*ppoin)[ibrick] = *poin;
821
822                 if(old_links) MEM_freeN(old_links);
823         }
824         else {
825                 (*tot) = 1;
826                 *ppoin = MEM_callocN((*tot)*size, "new link");
827                 (*ppoin)[0] = *poin;
828         }
829 }
830
831 void unlink_logicbricks(void **poin, void ***ppoin, short *tot)
832 {
833         int ibrick, removed;
834
835         removed= 0;
836         for (ibrick=0; ibrick < *tot; ibrick++) {
837                 if(removed) (*ppoin)[ibrick - removed] = (*ppoin)[ibrick];
838                 else if((*ppoin)[ibrick] == *poin) removed = 1;
839         }
840
841         if (removed) {
842                 (*tot) --;
843
844                 if(*tot == 0) {
845                         MEM_freeN(*ppoin);
846                         (*ppoin)= NULL;
847                 }
848                 return;
849         }
850 }