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