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