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