65c4ed42e0312b58097d2e1f6574054f7e8a549d
[blender.git] / source / blender / blenkernel / intern / group.c
1 /*  group.c   sept 2000
2  *  - cleaned up mar-01 nzc 
3  * 
4  * 
5  *  ton roosendaal
6  * $Id$
7  *
8  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version. The Blender
14  * Foundation also sells licenses for use in proprietary software under
15  * the Blender License.  See http://www.blender.org/BL/ for information
16  * about this.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  *
27  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
28  * All rights reserved.
29  *
30  * The Original Code is: all of this file.
31  *
32  * Contributor(s): none yet.
33  *
34  * ***** END GPL/BL DUAL LICENSE BLOCK *****
35  */
36
37 #include <stdio.h>
38 #include <string.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "DNA_ID.h"
43 #include "DNA_group_types.h"
44 #include "DNA_object_types.h"
45 #include "DNA_ipo_types.h"
46
47 #include "BLI_blenlib.h"
48 #include "BKE_global.h"
49 #include "BKE_main.h"
50
51 #include "BKE_library.h"
52 #include "BKE_group.h"
53 #include "BKE_object.h"
54 #include "BKE_ipo.h"
55
56 #ifdef HAVE_CONFIG_H
57 #include <config.h>
58 #endif
59
60 void free_object_key(ObjectKey *ok)
61 {
62         if(ok->ipo) ok->ipo->id.us--;
63         
64         MEM_freeN(ok);
65 }
66
67 void free_group_object(GroupObject *go)
68 {
69         ObjectKey *ok;
70         
71         while(go->okey.first) {
72                 ok= go->okey.first;
73                 BLI_remlink(&go->okey, ok);
74                 free_object_key(ok);
75         }
76         MEM_freeN(go);
77 }
78
79
80 void free_group(Group *group)
81 {
82         /* don't free group itself */
83         GroupObject *go;
84         
85         BLI_freelistN(&group->gkey);
86         
87         while(group->gobject.first) {
88                 go= group->gobject.first;
89                 BLI_remlink(&group->gobject, go);
90                 free_group_object(go);
91         }
92         
93 }
94
95 Group *add_group()
96 {
97         Group *group;
98         
99         group = alloc_libblock(&G.main->group, ID_GR, "Group");
100         return group;
101 }
102
103 /* assumes 'ok' is unitialized */
104 void object_to_obkey(Object *ob, ObjectKey *ok)
105 {
106         ok->partype= ob->partype;
107         ok->par1= ob->par1;
108         ok->par2= ob->par2;
109         ok->par3= ob->par3;
110         
111         ok->parent= ob->parent;
112         ok->track= ob->track;
113         
114         ok->ipo= copy_ipo(ob->ipo);
115         
116         memcpy(ok->loc, ob->loc, 7*3*sizeof(float));
117         memcpy(ok->quat, ob->quat, 2*4*sizeof(float));
118         memcpy(ok->obmat, ob->obmat, 3*4*4*sizeof(float));
119         
120         ok->lay= ob->lay;
121         ok->transflag= ob->transflag;
122         ok->trackflag= ob->transflag;
123         ok->upflag= ob->upflag;
124         ok->sf= ob->sf;
125         ok->ctime= ob->ctime;
126
127         
128 }
129
130 void obkey_to_object(ObjectKey *ok, Object *ob)
131 {
132         ob->partype= ok->partype;
133         ob->par1= ok->par1;
134         ob->par2= ok->par2;
135         ob->par3= ok->par3;
136         
137         ob->parent= ok->parent;
138         ob->track= ok->track;
139         
140         /* pretty tricky, this makes ob->ipo blocks with users 'hanging around' */
141         if(ob->ipo) {
142                 free_libblock_us(&G.main->ipo, ob->ipo);
143         }
144         ob->ipo= copy_ipo(ok->ipo);
145         
146         memcpy(ob->loc, ok->loc, 7*3*sizeof(float));
147         memcpy(ob->quat, ok->quat, 2*4*sizeof(float));
148         memcpy(ob->obmat, ok->obmat, 3*4*4*sizeof(float));
149         
150         ob->lay= ok->lay;
151         ob->transflag= ok->transflag;
152         ob->trackflag= ok->transflag;
153         ob->upflag= ok->upflag;
154         ob->sf= ok->sf;
155         ob->ctime= ok->ctime;
156 }
157
158 /* current ob position */
159 void add_object_key(GroupObject *go, GroupKey *gk)
160 {
161         ObjectKey *ok;
162         
163         /* check if there already is a key */
164         ok= go->okey.first;
165         while(ok) {
166                 if(ok->gkey == gk) break;
167                 ok= ok->next;
168         }
169         
170         if(ok) {
171                 BLI_remlink(&go->okey, ok);
172                 free_object_key(ok);
173         }
174         ok= MEM_mallocN(sizeof(ObjectKey), "objectkey");
175         ok->gkey= gk;
176         
177         object_to_obkey(go->ob, ok);
178         
179         BLI_addtail(&go->okey, ok);
180         
181 }
182
183 /* external */
184 void add_to_group(Group *group, Object *ob)
185 {
186         GroupObject *go;
187         GroupKey *gk;
188         
189         /* check if the object has been added already */
190         go= group->gobject.first;
191         while(go) {
192                 if(go->ob==ob) return;
193                 go= go->next;
194         }
195         
196         go= MEM_callocN(sizeof(GroupObject), "groupobject");
197         BLI_addtail( &group->gobject, go);
198         
199         go->ob= ob;
200         
201         /* keys? */
202         gk= group->gkey.first;
203         while(gk) {
204                 add_object_key(go, gk);
205                 gk= gk->next;
206         }
207 }
208
209 void rem_from_group(Group *group, Object *ob)
210 {
211         GroupObject *go, *gon;
212         ObjectKey *ok;
213         
214         go= group->gobject.first;
215         while(go) {
216                 gon= go->next;
217                 if(go->ob==ob) {
218                         BLI_remlink(&group->gobject, go);
219                         free_group_object(go);
220                 }
221                 else {
222                         ok= go->okey.first;
223                         while(ok) {
224                                 if(ok->parent==ob) ok->parent= NULL;
225                                 if(ok->track==ob) ok->track= NULL;
226                                 ok= ok->next;
227                         }
228                 }
229                 go= gon;
230         }
231 }
232
233 void add_group_key(Group *group)
234 {
235         GroupObject *go;
236         GroupKey *gk;   
237         int nr=10;
238         extern char colname_array[][20]; /* material.c */
239
240         gk= group->gkey.first;
241         while(gk) {
242                 nr++;
243                 gk= gk->next;
244         }
245
246         gk= MEM_callocN(sizeof(GroupKey), "groupkey");
247         BLI_addtail(&group->gkey, gk);
248         strcpy(gk->name, colname_array[ nr % 120 ]);
249         
250         go= group->gobject.first;
251         while(go) {
252                 add_object_key(go, gk);
253                 go= go->next;
254         }
255         
256         group->active= gk;
257 }
258
259 void set_object_key(Object *ob, ObjectKey *ok)
260 {
261         obkey_to_object(ok, ob);        
262 }
263
264 void set_group_key(Group *group)
265 {
266         /* sets active */
267         GroupObject *go;
268         ObjectKey *ok;
269         
270         if(group->active==NULL) return;
271         
272         go= group->gobject.first;
273         while(go) {
274                 ok= go->okey.first;
275                 while(ok) {
276                         if(ok->gkey==group->active) {
277                                 set_object_key(go->ob, ok);
278                                 break;
279                         }
280                         ok= ok->next;
281                 }
282                 go= go->next;
283         }
284         
285 }
286
287 Group *find_group(Object *ob)
288 {
289         Group *group= G.main->group.first;
290         GroupObject *go;
291         
292         while(group) {
293
294                 go= group->gobject.first;
295                 while(go) {
296                         if(go->ob==ob) return group;
297                         go= go->next;
298                 }
299                 group= group->id.next;
300         }
301         return NULL;
302 }
303
304 void set_group_key_name(Group *group, char *name)
305 {
306         GroupKey *gk;
307         
308         if(group==NULL) return;
309         
310         gk= group->gkey.first;
311         while(gk) {
312                 if(strcmp(name, gk->name)==0) break;
313                 gk= gk->next;
314         }
315         
316         if(gk) {
317                 group->active= gk;
318                 set_group_key(group);
319         }
320 }
321
322 void set_group_key_frame(Group *group, float frame)
323 {
324         GroupObject *go;
325         
326         if(group==NULL) return;
327
328         go= group->gobject.first;
329         while(go) {
330                 where_is_object_time(go->ob, frame);
331                 go= go->next;
332         }
333 }